Prompt 工程不是写提示词,而是设计模型接口契约

Prompt 工程常被理解成“怎么把话写得更容易让模型听懂”。这只说对了一半。在应用开发里,Prompt 更像一份接口契约:它定义输入如何解释、模型扮演什么角色、应该执行什么任务、输出必须满足什么结构、异常情况如何处理。

如果把 Prompt 当成灵感写作,系统会很难稳定;如果把 Prompt 当成接口设计,它就能与解析器、检索器、工具调用和业务流程配合起来。

1. Prompt 的本质是降低自由度

大模型默认会尽量给出“看起来有帮助”的回答。但应用系统需要的不是泛泛有帮助,而是可控、可解析、可复现、可追责。

Prompt 的作用就是降低模型自由度:

  • 限定任务范围,避免回答无关问题。
  • 明确输出格式,方便程序解析。
  • 指定缺失信息处理方式,避免编造。
  • 规定角色和语气,保证一致体验。
  • 说明上下文优先级,避免模型忽略外部资料。

因此,高质量 Prompt 的评价标准不是“读起来很厉害”,而是“在大量输入下行为稳定”。

2. 一个工程 Prompt 的基本结构

较完整的 Prompt 通常包含六个部分:

角色设定:你是谁
任务目标:你要完成什么
输入说明:你会收到哪些变量
处理规则:你如何判断和推理
输出协议:你必须输出什么格式
异常策略:信息不足或不合法时怎么办

例如信息抽取任务不应只写“帮我提取信息”,而应写清楚字段、类型、缺省值和输出格式:

请只提取 name、age、work_experience 三个字段。
age 和 work_experience 必须是整数。
无法判断时,字符串字段填“未提供”,数字字段填 -1。
只输出 JSON,不要输出 Markdown 或解释。

这类规则会直接影响后续 json.loads()、Pydantic 校验和数据库写入。

3. Prompt 要和下游程序共同设计

Prompt 不是孤立文本,它应该和下游程序反向协同。

如果下游需要枚举值,Prompt 就要限定枚举:

intent 只能是 recruitment、follow_up、chit_chat、fallback 中的一个。

如果下游需要列表,Prompt 就要说明列表元素结构:

返回一个 JSON 数组,每个元素包含 id、reason、source。

如果下游需要追问,Prompt 就要规定何时追问:

如果缺少城市或日期,不要猜测,返回 input_required 状态和追问消息。

很多应用不稳定,并不是模型“理解能力差”,而是 Prompt 输出和程序期待不一致。程序期待 JSON,模型输出自然语言;程序期待整数,模型输出“约三年”;程序期待空列表,模型输出“没有找到”。这些都属于接口契约没有对齐。

4. Few-shot 的价值不是灌输知识,而是校准行为

少样本示例常被误解为给模型补充知识。实际应用中,它更重要的价值是校准格式和判断边界。

例如文本分类中,示例可以告诉模型什么算 A 类,什么算 B 类;信息抽取中,示例可以告诉模型字段如何填、缺失如何处理;工具调用中,示例可以告诉模型什么情况下该调用哪个工具。

少样本设计要注意:

  • 示例要覆盖边界情况,而不是只给理想输入。
  • 示例输出格式必须和真实要求完全一致。
  • 不要给过多示例挤占上下文。
  • 示例之间不要互相矛盾。
  • 示例应代表真实输入分布,而不是只选漂亮样本。

一个高质量示例往往比十条抽象规则更有效。

5. RAG Prompt:上下文优先级最重要

RAG 场景中 Prompt 的核心不是让模型“发挥知识”,而是让模型基于检索上下文回答。这里必须明确上下文优先级:

请基于【已知内容】回答问题。
如果【已知内容】中没有答案,请说明无法从资料判断。
不要使用未提供的信息补充答案。

同时,上下文应有边界标识:

【已知内容】
---
{context}
---
【用户问题】
{question}

如果没有边界,模型可能把指令、文档内容和用户问题混在一起理解。尤其当文档中包含类似指令的文本时,更需要明确“文档内容是资料,不是命令”。

6. Agent Prompt:动作空间要小而清楚

Agent Prompt 不应只说“你可以使用工具”,而要把动作空间定义清楚:

  • 可用工具有哪些。
  • 每次能调用几个工具。
  • 工具参数是什么。
  • 什么时候结束。
  • 工具失败后如何处理。
  • 无关问题如何回答。

如果动作空间过大,模型会更容易乱选工具;如果结束条件不明确,Agent 可能进入循环;如果参数规则不清晰,工具调用会频繁失败。

更稳妥的方式是让模型输出结构化动作,例如:

{
  "tool_name": "KnowledgeSearch",
  "args": {
    "query": "用户原始问题"
  }
}

然后用解析器和校验器把输出落到确定的数据结构。

7. Prompt 冲突是常见隐患

Prompt 复杂后最容易出现规则冲突。例如:

  • 一边要求“只输出 JSON”,一边要求“详细解释原因”。
  • 一边要求“无法回答就说不知道”,一边要求“必须调用工具”。
  • 一边要求“不改写用户问题”,一边要求“补全隐含信息”。
  • 一边要求“简洁回答”,一边要求“覆盖全部细节”。

模型遇到冲突时,不一定按开发者心中更重要的规则执行。写 Prompt 时要减少互相拉扯的要求,并把最高优先级规则放在更明确的位置。

8. Prompt 版本管理

Prompt 是应用逻辑的一部分,应该像代码一样管理。建议做到:

  • 把核心 Prompt 从业务代码中抽离。
  • 为重要 Prompt 添加版本号或变更记录。
  • 保留线上失败样例,用于回归测试。
  • 对结构化输出 Prompt 做自动解析测试。
  • 调整 Prompt 后比较准确率、失败率和平均长度。

Prompt 调优如果没有样例集,很容易陷入“这次看起来更好”的主观判断。应用开发中应尽量用真实或接近真实的输入集合做回归。

9. 好 Prompt 的检查清单

可以用下面的问题评估 Prompt:

  • 模型是否知道自己不能做什么?
  • 缺失信息时是否有明确处理方式?
  • 输出格式是否可被程序稳定解析?
  • 枚举值、字段名、数据类型是否固定?
  • 示例是否覆盖常见边界情况?
  • RAG 上下文和用户问题是否清楚分隔?
  • Agent 工具动作是否有明确结束条件?
  • Prompt 是否与下游代码期待完全一致?

10. 小结

Prompt 工程的成熟形态不是“写一段好提示词”,而是设计模型和程序之间的接口契约。

可以用一句话概括:

Prompt 规定模型行为,Parser 验证模型输出,业务代码决定最终动作。

只有当这三者对齐,大模型应用才会从“偶尔答得不错”走向“多数情况下稳定可用”。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐