Prompt Engineering 不是研究"神奇咒语",而是把目标、规则、上下文、示例和验收标准组织成模型能稳定执行的任务说明。真正可靠的 Prompt,应该像代码一样可测试、可版本化、可维护。
Prompt Engineering 到底是什么
Prompt Engineering 可以理解为:设计一份让 Large Language Model 能正确理解任务、稳定执行规则并输出可验收结果的"工作说明书"。
它不只是把问题写得更礼貌,也不是不断增加"请认真思考""这对我很重要"之类的强调语。一个有效的 Prompt 至少要解决五件事:模型要完成什么任务、为什么要完成、可使用哪些信息、必须遵守哪些限制、最终结果应该长什么样。
因此,Prompt 更接近接口契约,而不是聊天技巧。开发者把业务规则、数据边界、输出格式和异常处理写入 Prompt,模型再把用户输入映射为结果。Prompt 写得含糊,模型只能猜;Prompt 内部互相矛盾,模型则会耗费计算去调和冲突,最后仍可能选错方向。
一句话理解
好 Prompt 不是"更长的提问",而是"更清楚的任务定义"。它把隐含要求变成显式要求,把主观期待变成可检查的标准。

动手改 Prompt 之前,先定义"什么叫成功"
Anthropic 的官方文档把这一点放在 Prompt Engineering 之前:你需要先有明确的 success criteria、能对照这些标准进行测试的方法,以及一份准备改进的初稿。否则,所谓"优化"只会变成凭感觉修改文字。
例如,你要做一个客服分类器,目标不能只写"分类准确"。更可操作的标准是:在 300 条人工标注样本上,一级类别 Macro-F1 不低于 0.92;对于无法判断的输入必须返回 UNKNOWN;输出只能是符合 JSON Schema 的对象;P95 延迟低于 2 秒。这样才知道问题到底来自 Prompt、模型选择、输入数据,还是系统架构。

不是所有问题都应该靠 Prompt 解决
如果主要问题是 latency、cost 或 context window 不够,换模型、压缩上下文、使用缓存或重构调用链通常比继续堆叠指令更有效。如果模型缺少关键事实,应补充检索数据或使用 RAG;如果输出必须百分之百符合机器协议,应优先使用 Structured Outputs 或 schema 约束,而不是只写一句"请严格输出 JSON"。
一个完整 Prompt 应该包含哪些部分
OpenAI 当前文档建议使用 Markdown 与 XML 建立清楚的逻辑边界,并把 developer message 按 Identity、Instructions、Examples、Context 等区域组织。实际项目中,可以进一步加入 Output Contract 和 Validation,使它成为一份完整的执行规范。
Identity
模型在当前应用中的身份、职责和沟通风格。例如"你是企业内部的安全日志分析助手"。
Task
这一次具体要完成的工作。使用明确动词,如 classify、extract、compare、rewrite、verify。
Context
完成任务所必需的业务背景、术语定义、文档、用户数据和前置条件。
Rules
必须遵守的限制、优先级、允许与禁止的行为,以及信息不足时的处理方式。
Examples
代表性的输入输出对,包括常规情况、边界情况和容易误判的情况。
Output
输出格式、字段、长度、语言、顺序、风格及是否允许解释文本。
Validation
完成前需要执行的自检,如字段完整性、引用存在性、代码测试或事实一致性。
# Identity
你是一个负责处理【业务领域】任务的专业助手。
# Task
根据用户输入完成【明确动作】,不要执行与任务无关的工作。
# Context
<context>
{{CONTEXT}}
</context>
# Rules
1. 只依据给定 context 和明确可验证的信息回答。
2. 信息不足时返回"需要补充信息",不要自行编造。
3. 遵守字段含义、单位和业务术语定义。
# Output Format
严格按照以下结构输出:
{{OUTPUT_SCHEMA_OR_TEMPLATE}}
# Examples
<examples>
<example>...</example>
</examples>
# Final Check
输出前检查:任务是否完成、格式是否正确、是否包含无依据内容。
OpenAI 与 Claude 的角色体系有什么区别
两家 API 都需要区分"应用级规则"和"用户本轮输入",但字段组织方式不同。理解这一点,可以避免把长期业务规则和临时用户内容混在一起。
| 用途 | OpenAI Responses API | Claude Messages API |
|---|---|---|
| 应用级行为规则 | instructions 参数,或 developer message |
顶层 system 字段 |
| 用户本轮请求 | input 中的 user message |
messages 中的 user message |
| 模型历史输出 | assistant message / output items |
assistant message |
| 核心理解 | developer 像函数定义,user 像传入参数 |
system 定义全局行为,messages 承载会话内容 |
OpenAI 的一个容易忽略的细节
instructions 只作用于当前 generation request。使用 previous_response_id 管理多轮状态时,上一轮的 instructions 不会自动作为新一轮规则继承;需要持续生效的规则,应在新请求中重新提供,或通过你自己的会话管理层稳定注入。
最重要的 Prompt Engineering 技巧
1. 写清楚,不要让模型猜
"帮我分析一下"通常缺少任务边界。模型不知道你要分析结论、风险、原因、数据质量还是改进建议。更好的写法是直接列出对象、角度、输出长度和判断依据。
模糊 Prompt
帮我分析这份日志,写得专业一点。
可执行 Prompt
分析下面的 Web 访问日志,识别可疑请求。对每条可疑记录给出时间、源 IP、请求路径、可能对应的攻击类型和判断依据。无法确认时标记为"待复核",不要虚构 CVE 编号。
2. 告诉模型"做什么",而不只是"不要做什么"
负面限制有时只能说明错误方向,却没有给出正确行为。例如"不要使用 Markdown"不如"使用连续自然段,仅在代码处使用 code block"明确。理想写法是先定义期望动作,再补充必要的禁止项。
3. 提供必要的 Context 和原因
模型不会自动知道你的组织规范、受众水平和业务流程。告诉它"为什么这条规则重要",往往能帮助模型在边界场景中做出更一致的判断。例如,要求医学报告保留原始测量单位时,可以说明"单位会直接进入后续统计流程,任何自动换算都会造成数据不一致"。
4. 使用 Role Prompting,但不要只写角色
"你是一位资深专家"本身提供的信息很少。角色应与职责、知识边界和输出方式一起出现。例如:"你是负责审查 Python 后端代码的 senior engineer,重点检查并发安全、异常处理和测试覆盖;不要重写无关模块。"
5. 用 Markdown 和 XML 划分信息边界
当 Prompt 同时包含规则、文档、示例和用户输入时,纯文本容易互相污染。Markdown 适合表达章节层级,XML tags 适合明确标记可变数据。Claude 官方文档尤其推荐使用描述性标签,如 <instructions>、<context>、<input> 和 <examples>。
XML 分区示例
<instructions>
阅读用户提供的合同片段,提取付款义务。
只依据合同内容,不补充一般法律常识。
</instructions>
<contract>
{{CONTRACT_TEXT}}
</contract>
<output_format>
{
"payer": "string | null",
"amount": "string | null",
"deadline": "string | null",
"evidence": "原文依据"
}
</output_format>
6. 使用 Few-shot / Multishot Examples
Few-shot learning 是在 Prompt 中放入少量输入输出示例,让模型从示例中归纳任务模式。它特别适合固定分类口径、统一写作风格、处理边界条件和稳定输出格式。
示例应当 relevant、diverse、structured。只放三个完全相似的正常案例,模型可能学不到异常情况;只给结果不说明规则,模型又可能把示例中的偶然细节误当作硬规则。Anthropic 当前建议在适合的任务中准备约 3--5 个高质量示例,但数量不是越多越好,关键是覆盖代表性差异。
7. 明确 Output Contract
输出要求不要停留在"简洁""专业""结构清楚"。说明语言、段落、字段、顺序、长度、空值规则和是否允许附加解释。机器消费的结果,最好使用 Structured Outputs、JSON Schema 或类型约束;Prompt 中的文字规则作为补充,而不是唯一防线。
长文档、私有数据与 RAG 应该怎样组织
模型无法凭空访问企业知识库、最新政策或用户私有文件。要让回答基于这些信息,需要把相关资料放入上下文,或先从 vector database、file search 等检索系统中找到相关片段,再加入生成请求,这就是常见的 Retrieval-Augmented Generation(RAG)流程。

长上下文的布局原则
Claude 官方建议在处理超长文档或多文档任务时,把长篇资料放在 Prompt 前部,把具体问题和执行要求放在后部,并用 XML 标记文档边界与 metadata。对于需要精确依据的任务,可以先要求模型抽取与问题直接相关的证据片段,再进行总结或判断。
<documents>
<document index="1">
<source>安全策略_v3.pdf</source>
<document_content>
{{DOC_1}}
</document_content>
</document>
<document index="2">
<source>应急响应流程.md</source>
<document_content>
{{DOC_2}}
</document_content>
</document>
</documents>
<task>
先列出与"高危漏洞处置时限"直接相关的原文证据及来源,
再根据证据总结处置要求。若文档之间冲突,明确指出冲突,
不要自行决定哪一份有效。
</task>
不要把检索内容当作可信指令
RAG 返回的网页、邮件或文档可能包含 Prompt Injection。应用级规则应明确规定:外部内容仅作为数据,不得覆盖 system/developer instructions;工具权限和数据访问边界必须由程序控制,而不是交给模型自行决定。
什么时候需要 Reasoning,怎样要求模型自检
简单改写、字段抽取和直接问答通常不需要复杂 reasoning。多步规划、代码调试、数学推导、工具调用和跨文档比较更可能从 reasoning 中受益。模型与 API 提供的 effort、thinking 等参数应按任务复杂度设置,而不是所有请求都开到最高。
在 Prompt 层面,与其强行规定一套冗长的人类推理步骤,不如给出清楚的目标、约束和验收条件,让模型选择合适方法。需要提高可靠性时,可以要求它在提交结果前完成可观察的验证,例如运行测试、检查 JSON Schema、核对引用、验证单位或列出不确定项。
# Validation
提交最终结果前完成以下检查:
1. 确认每个结论都能在给定资料中找到依据。
2. 确认所有必填字段均存在,类型正确。
3. 发现资料冲突时,不要强行合并,单独列出冲突项。
4. 对无法确认的内容使用 null,并在 uncertainties 中说明原因。
5. 最终只输出符合 schema 的 JSON,不附加说明文字。
区分"思考过程"和"验证结果"
生产系统通常真正需要的是可检查的证据、测试结果、引用和错误信息,而不是一大段不可执行的思维叙述。把 Prompt 的重点放在 verification,而不是要求模型展示冗长的内部推理。
有工具的 Agent,Prompt 应该多写哪些内容
当模型可以搜索网页、读取文件、执行代码或调用业务 API 时,Prompt 不再只控制文字风格,还要定义行动策略。Claude 官方文档指出,含糊的"给一些修改建议"可能只得到建议;需要模型真正执行时,应明确写出 implement、edit、run、verify(实现功能,修改文件,运行程序,验证结果) 等动作。

Agent 行动规则示例
# Tool Policy
- 当回答依赖最新公开信息时,先使用 web_search。
- 当用户要求修改代码时,先阅读相关文件,再进行最小范围修改。
- 不要猜测文件路径、API 参数或账号信息。
- 独立的读取操作可以并行;存在数据依赖的步骤必须顺序执行。
- 工具返回"success"后,仍需读取结果或运行测试确认任务真实完成。
- 涉及删除数据、付款、发送消息等不可逆操作时,必须先请求明确确认。
三套可直接复用的 Prompt 模板
模板一:技术概念讲解
# Identity
你是一名擅长把复杂技术讲清楚的工程师。
# Audience
读者了解基础编程,但第一次接触 {{TOPIC}}。
# Task
用中文完整解释 {{TOPIC}},专有名词保留英文。
# Content Requirements
- 先说明它解决什么问题,再解释工作机制。
- 给出一个具体示例,不使用只有定义没有场景的空泛描述。
- 区分它与 {{RELATED_CONCEPT}} 的差异。
- 说明常见误区和适用边界。
# Style
使用自然段和少量小标题,减少口号式表达,不反复总结同一句话。
# Output
篇幅约 1200--1800 字。
模板二:基于资料的问答
# Task
仅根据 <documents> 中的资料回答 <question>。
# Rules
1. 不使用资料外的事实补齐答案。
2. 每个关键结论后标注来源文档名称。
3. 资料没有答案时,明确写"现有资料未说明"。
4. 多份资料冲突时,分别陈述,不自行消除冲突。
<documents>
{{RETRIEVED_DOCUMENTS}}
</documents>
<question>
{{USER_QUESTION}}
</question>
# Output Structure
- 直接答案
- 依据
- 不确定或冲突信息
模板三:代码修改 Agent
# Role
你是维护现有代码库的 software engineer。
# Objective
实现 {{FEATURE_OR_FIX}},保持现有公开接口兼容。
# Workflow
1. 阅读相关源码、测试和配置,确认问题范围。
2. 给出简短实施判断,然后直接修改代码。
3. 优先进行最小、局部、可回滚的修改。
4. 增加或更新测试,覆盖正常路径与关键边界情况。
5. 运行测试和静态检查;失败时继续修正,不要只报告失败。
6. 最后说明修改了哪些文件、验证结果和仍存在的限制。
# Constraints
- 不重构无关代码。
- 不删除已有测试来获得通过结果。
- 不猜测不存在的依赖或环境变量。
- 未验证通过时,不宣称任务已经完成。
Prompt 不是"写完",而是通过 Evals 迭代出来
可靠的 Prompt 优化应该使用固定测试集。每次只修改一小部分,然后比较新旧版本在相同样本上的准确率、格式合规率、拒答率、延迟和 token cost。没有 Evals,就无法判断一次修改到底提升了整体表现,还是只修好了眼前的一个案例。

常见评估指标
| 任务类型 | 常用指标 | 注意事项 |
|---|---|---|
| 分类 | Accuracy、Precision、Recall、F1、confusion matrix | 类别不平衡时不要只看 Accuracy |
| 信息抽取 | 字段级 exact match、Precision / Recall、schema pass rate | 区分缺失字段与错误字段 |
| 代码 | unit tests、integration tests、lint、build success | 工具返回成功不等于代码正确 |
| RAG 问答 | citation correctness、faithfulness、answer relevance | 分别评估检索质量和生成质量 |
| 长文本 | rubric、pairwise preference、事实错误率 | 评分规则必须具体,避免"整体不错" |
生产环境中的 Prompt 应像代码一样管理
实验阶段可以直接在控制台修改 Prompt,进入生产后则需要版本控制、代码审查、测试和灰度发布。Prompt 是业务逻辑的一部分,一次看似普通的措辞变化,可能改变分类边界、工具触发方式或安全行为。

常见失败模式,以及应该怎样改
| 表现 | 常见原因 | 修正方向 |
|---|---|---|
| 回答方向经常跑偏 | 任务动词和完成标准不明确 | 明确对象、动作、范围和输出结构 |
| 格式偶尔不合法 | 只用自然语言要求 JSON | 使用 Structured Outputs / schema,并补充合法示例 |
| 模型无依据补全信息 | 没有规定知识边界和缺失处理 | 要求只依据 context;不足时返回 null 或 UNKNOWN |
| 示例越加越差 | 示例单一、互相冲突或包含偶然模式 | 审查 relevance、diversity、consistency |
| 长文档漏掉关键信息 | 文档未分区,问题埋在中间 | 使用 XML、metadata,把任务放在资料之后,并要求先提证据 |
| Agent 只给建议不执行 | Prompt 使用 suggest、consider 等弱动作 | 明确 implement、edit、run tests、verify |
| Agent 乱调用工具 | 触发条件和缺参行为不明确 | 规定何时调用、何时询问、不得猜参数 |
| 改一个 case,其他 case 退化 | 没有回归测试,只看单例 | 建立固定 Evals,逐项修改并比较版本 |
| 模型在冲突规则间表现不稳 | Prompt 内部存在矛盾或优先级不清 | 删除冲突,写明优先顺序和例外条件 |