Skip to content

Prompt 工程

上一章讲清楚了 LLM 是什么:根据上下文预测下一个 token 的语言系统,不是数据库,不是编译器,输出结果受 prompt、上下文和参数共同影响。

现在的问题是:既然模型输出取决于你给它的"任务描述",怎么把这件事做稳定?

Prompt 工程不是写玄学咒语,是在做任务描述、上下文组织和输出契约设计。

本章目标

  • 能写清角色、目标、上下文、输出格式和边界
  • 知道什么时候该用 Zero-shot、Few-shot 和结构化提示
  • 明白很多问题不是 prompt 不够花,而是本来就需要工具、检索或校验

Prompt 到底是什么

Prompt 可以理解为:

任务说明 + 上下文信息 + 输出要求 + 约束边界

它不只是用户发给模型的一句话,而是你如何把任务讲清楚。

Prompt 定义的是一轮推理的任务接口。你交代什么,模型就按什么理解目标、参考信息、输出格式和行为边界。它不是文案,是控制面。

一个好 Prompt 通常包含什么

五个部分:角色说明(你是谁)、任务目标(做什么)、输入上下文(有哪些材料)、输出要求(格式和长度)、边界和限制(什么不该做)。

不是每个 Prompt 都需要全部写出来,但写不清楚时,通常是其中某一项缺了。常见的情况是任务目标模糊,或者输出格式没说。

一个简单的检查方式:把你写的 Prompt 发给同事,他们能不能只看 Prompt 就知道预期输出长什么样?如果不能,缺的地方就在那里。

为什么 Prompt 有效,但又总会失效

Prompt 有效,是因为模型高度依赖上下文;你把任务描述得更清楚,模型在预测下一个 token 时的约束就更明确。

Prompt 又总会失效,是因为它终究还是自然语言约束,不是硬规则。任务一复杂、上下文一脏、外部资料一混入,模型就可能开始重新分配注意力,把本来该优先遵守的规则放到后面。

所以 Prompt 工程最先要建立的判断就是:Prompt 很重要,但它不能单独扛住全部控制责任。

System Prompt 和 User Prompt 的区别

System Prompt

系统级规则,决定模型这轮任务的大方向和行为边界。

User Prompt

用户这次具体想做什么,是本轮输入的业务请求。

真实系统里,两者通常还会叠加历史对话、检索结果、工具返回。所以 Prompt 工程本质上也包含上下文工程。

拆开来看,它们解决的是不同层级的问题:

  • System Prompt 更像长期策略和行为边界
  • User Prompt 更像这一轮的业务请求
  • 历史对话、检索结果、工具返回则是在补充当前任务状态

把它们混着写,不一定马上出错,但系统一复杂就会很难维护。因为你会逐渐分不清:到底哪些规则是长期稳定的,哪些要求只是这一轮临时需要的。

什么是上下文工程

上下文工程的核心问题不是"写一句更厉害的话",而是决定:

  • 哪些历史消息要保留
  • 检索结果要放几段
  • 工具结果是否原样回传
  • 是否要先总结旧内容

好的上下文是:相关、干净、有结构、成本可控。

Prompt 工程为什么越来越像“上下文分配”

学 Prompt 的人,最开始关注的都是措辞技巧——"你是一个……""请一步一步思考"。有用,但到真实系统里,更关键的问题很快会变成:

  • 哪些信息该放进去
  • 哪些信息必须删掉
  • 哪些信息该放前面
  • 哪些信息该结构化,而不是写成长段自然语言

Prompt 工程的重心,会逐渐从"怎么写一句更好的话"转向"怎么给这一轮推理分配最合适的上下文预算"。

判断"哪些信息该放进去"有一个实用角度:你知道而 AI 不知道的信息,就应该主动写进 Prompt。 比如你们的内部系统规则、私有接口定义、这轮对话的业务背景——这些都不在模型的训练数据里,不补进来它只能猜。关于这个判断视角背后的风险逻辑,在 AI 幻觉 章节里有更完整的四象限分析。

Zero-shot、One-shot、Few-shot

Zero-shot

不给示例,直接描述任务。适合简单任务的第一版尝试。

One-shot / Few-shot

给 1 个或多个输入输出示例,让模型模仿格式和风格。适合:

  • 分类
  • 抽取
  • 固定格式改写
  • 容易跑偏的结构化任务

Few-shot 的底层价值,不只是"给模型举例子",而是在帮助模型更快锁定隐含任务模式。

有些任务你用自然语言规则说半天,模型还是会摇摆;给一个示例,它就突然稳定了。原因通常不是示例更有权威,而是示例把你真正想要的映射关系直接摆在了上下文里。模型不必再从抽象规则里自己猜。

Prompt 常见误区

误区 1:任务太模糊

有问题的写法

text
帮我处理一下这段内容。

模型不知道"处理"是什么意思——是总结、翻译、改写、分类,还是抽取字段?这种 Prompt 可能会得到任何形式的输出,也可能得到一堆澄清问题。

改进写法

text
请将以下产品评论分类为"正面"、"负面"或"中性",只输出分类结果,不要解释。

任务、输出格式、范围——三件事都说清楚了。

误区 2:没有输出约束

有问题的写法

text
请从以下简历里提取技能。

模型可能返回一段话、一个列表、一个 JSON,或者一段分析。每次运行结果格式不同,程序没法稳定消费。

改进写法

text
请从以下简历里提取技能,以 JSON 数组格式输出,只输出数组,不要任何额外文字。
示例输出:["React", "Node.js", "PostgreSQL"]

输出契约明确了,格式才会稳定。

误区 3:上下文太多或太杂

把无关内容全塞进去,不会让模型更懂,只会让它更难聚焦。

常见场景:用 RAG 检索了 10 段相关资料,全部塞进 Prompt,希望模型综合所有信息。结果模型被大量资料稀释,反而没抓到最关键的那段。

更好的做法:对检索结果做 rerank,只保留最相关的 2-3 段,而不是"塞越多越好"。

误区 4:把所有问题都归因到 Prompt

很多时候,真正缺的是:

  • 结构化输出(让输出格式可被程序消费)
  • 工具调用(让模型能访问实时数据或执行动作)
  • 检索增强(让模型能查外部知识库)
  • 程序校验(在程序层兜底,不只靠 Prompt 约束)

遇到问题先判断根因,不要默认"把 Prompt 写得更长更详细就能解决"。有时候核心问题是系统设计,而不是提示词措辞。

Prompt 其实是在弥补模型和任务之间的信息落差

模型不知道你的业务目标、字段定义、风险边界,也不知道下游程序怎么消费它的输出。Prompt 工程干的事情,就是把这些只存在于开发者脑子里的信息转译给模型。

Prompt 的本质不是花哨,是信息对齐。对齐做得越好,模型越少靠猜。

一个可复用的 Prompt 模板

text
你是一个信息抽取助手。
请从下面的文本中提取指定字段,并按 JSON 输出。

要求:
1. 只输出 JSON
2. 如果无法确定字段值,返回 null
3. 不要添加未定义字段

字段:
- name: string | null
- role: string | null
- years_of_experience: number | null

文本:
{{input}}

Prompt 优化的正确方法

  1. 先明确失败现象:偏题、漏字段、格式错还是胡说。
  2. 再判断原因:任务不清、上下文不够、约束不够,还是本来需要检索 / 工具。
  3. 针对性修改,不要盲目把 prompt 越写越长。
  4. 用固定样例比较前后效果,避免纯凭感觉。

把验收标准写进 Prompt

Prompt 优化往往集中在"怎么让模型输出更准",但有一个方向经常被忽略:你可以在 Prompt 里就告诉模型,输出应该满足什么交付标准。

这不是让模型自己 QA 自己——模型做不到真正的自我校验。但在 Prompt 里明确验收维度,至少能让模型在生成时把更多注意力放在这些方向上,减少明显的遗漏。

实际操作中,验收标准通常可以从四个维度切入:

样式完整性

输出涉及 UI 或视觉的部分,是否把该有的元素都覆盖了。比如你让模型写一个组件,结果只实现了结构但完全没管样式,或者少了某个状态下的展示——这类遗漏在不加约束的情况下非常常见。

功能覆盖

需求里的功能点是否都有对应实现。接口字段有没有漏掉。如果你在 Prompt 里补充过业务逻辑(比如权限判断、边界处理),模型有没有真的用上。

代码规范

命名是否一致,类型定义是否完整,样式有没有用项目约定的变量而不是硬编码数值。这些细节如果不在 Prompt 里提,模型几乎不会主动考虑。

测试覆盖

是否需要模型同时输出测试代码。如果需要,哪些路径必须覆盖——正常流程、异常流程、边界值。

把这四个维度浓缩成一句话加在 Prompt 末尾,就能覆盖大部分场景:

text
请确保输出满足以下标准:样式完整、功能覆盖、符合项目代码规范、关键路径有测试覆盖。

当然,这句话本身不是万能的。它的作用更像一个 checklist 提醒,让模型在生成过程中不至于只顾逻辑正确而忽略其他维度。真正的验收还是要靠你在输出之后做检查——用程序校验、跑测试、人工 review。

AI 幻觉 章节讲的系统级防控不同,这里的重点是:在 Prompt 层面就尽早把验收期望说清楚,而不是等到输出之后才发现少了什么。两者是互补的。

为什么 Prompt 不能无限增长

优化 Prompt 时,多数人的默认动作是继续加——加规则、加限制、加示例、加解释。短期有时有效,长期往往把问题搞得更复杂。

Prompt 一旦过长,副作用会一起冒出来:

  • 重点被稀释,模型难以抓住真正关键的约束
  • 成本上升,响应变慢
  • 不同规则之间开始互相打架
  • 调整时更难知道到底是哪一句在起作用

好的 Prompt 不是信息越多越好,是重要信息层次清楚、各有各的作用。

对你最有价值的 Prompt 能力

真实产品中 Prompt 是怎么管理的

前面讲的技巧——Zero-shot、Few-shot、结构化模板——都是在"写一段好的 Prompt"。但翻开一个生产级 AI 产品的内部,你会发现落差很大:它们的 Prompt 根本不是"写"出来的,是每次运行时动态拼装出来的

下面用 Claude Code 的实现(来自 v2.1.88 源码)做一次拆解,看看工业级 Prompt 管理到底长什么样。

Prompt 不是一段话,而是一个组装流水线

Claude Code 内部有一个函数 getSystemPrompt(),每次会话启动时,它会依次收集:

  • 当前操作系统类型和版本
  • 当前工作目录(CWD)
  • 当前已加载的工具列表和每个工具的描述
  • 用户的语言偏好设置
  • 已连接的 MCP 服务器指令
  • 多层 CLAUDE.md 记忆文件
  • 当前激活的 Feature Flag 控制的功能段

这些内容被拼接成一个完整的 System Prompt 数组,然后发给模型。不是手写的固定字符串,而是运行时根据当前环境状态计算出来的。

你在聊天框里看到的 AI 回答,背后是一次信息打包过程,不是一句"你是一个编程助手"。

静态段与动态段:Prompt 也要管成本

Claude Code 源码里有一个常量叫 SYSTEM_PROMPT_DYNAMIC_BOUNDARY,它是一条分界线,把 System Prompt 分成两个区域:

[静态段]  角色说明、行为规则、工具使用规范
──── DYNAMIC_BOUNDARY ────
[动态段]  当前环境信息、记忆文件、MCP 指令、会话特有配置

静态段的内容不随用户或会话变化,可以在多个组织之间共享缓存(global cache scope),避免每次请求都重新计费。

动态段包含用户私有信息和运行时状态,每次请求都重新生成,按实际 token 计费。

这不只是"写好 Prompt"的事——真实产品还得管 Prompt 的成本。哪些内容可以缓存、哪些必须每次生成,不能等到账单来了再想。

四层记忆:CLAUDE.md 的优先级系统

Claude Code 的记忆系统不是一个文件,而是四层叠加结构,按优先级从低到高加载:

层级路径用途
1. 托管全局/etc/claude-code/CLAUDE.md企业/组织统一规则
2. 用户个人~/.claude/CLAUDE.md个人跨项目偏好
3. 项目级项目根/CLAUDE.md.claude/rules/*.md项目规范,可提交 Git
4. 本地私有CLAUDE.local.md个人本地配置,不提交 Git

越靠后的层级优先级越高(后加载 = 模型更倾向于遵循)。这意味着你可以在组织层设通用规则,在项目层设代码规范,在个人层覆盖自己的风格偏好——整个系统自动聚合,不需要每次手写。

这就是上下文工程配置化的样子:不用每次往 Prompt 里粘规则,多层来源按优先级自动注入。

工具描述本身就是 Prompt 工程

一个容易忽视的细节:每个工具的 description 字段,直接决定模型什么时候选择调用它。

举个例子,假设你有两个工具,描述不同:

  • 描述 A:在项目中搜索文件
  • 描述 B:在项目文件系统中递归搜索文件,支持通配符,返回匹配路径列表;适合在需要找某个文件位置时使用,不适合搜索文件内容

描述 B 更具体,模型选择时的准确率会更高。"写好工具描述"本身就是在做 Prompt 工程——只是作用域在工具层,而不是对话层。这个认知在后面的 Tool Calling 章节里会继续展开。

对照:初学认知 vs 工业做法

初学阶段生产环境
写一段好的 System Prompt运行时动态拼装多个来源
Prompt 越长越好区分静态缓存段和动态计费段
每次手写上下文多层配置文件自动聚合注入
Tool Calling 只看功能工具描述本身就是路由 Prompt

把 Prompt 管理当成配置管理——哪些固定、哪些动态、哪些来自配置文件、哪些来自运行时状态——想到这一步,就已经离开了"调提示词",进入了系统设计。

优化 Prompt 时,改措辞不如补信息、删噪音、重排上下文。Few-shot 最该用的场景,是自然语言规则怎么写都说不清,但一个示例就能把隐含模式直接摆出来。

Prompt 始终是软约束——涉及事实核查、权限控制和动作执行的地方,要交给工具和程序校验,不能指望一段文本兜底。

到了生产环境,Prompt 管理最终会走向配置化、分层化、动态组装。一段越来越长的固定文本撑不住真实业务。


下一章:Structured Output——把模型输出从"会说话"推进到"能稳定给系统提供结构化数据"。

面向开发者的 AI 实战路线——Vibe Coding 与 AI 应用开发