Appearance
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 优化的正确方法
- 先明确失败现象:偏题、漏字段、格式错还是胡说。
- 再判断原因:任务不清、上下文不够、约束不够,还是本来需要检索 / 工具。
- 针对性修改,不要盲目把 prompt 越写越长。
- 用固定样例比较前后效果,避免纯凭感觉。
把验收标准写进 Prompt
Prompt 优化往往集中在"怎么让模型输出更准",但有一个方向经常被忽略:你可以在 Prompt 里就告诉模型,输出应该满足什么交付标准。
这不是让模型自己 QA 自己——模型做不到真正的自我校验。但在 Prompt 里明确验收维度,至少能让模型在生成时把更多注意力放在这些方向上,减少明显的遗漏。
实际操作中,验收标准通常可以从四个维度切入:
样式完整性
输出涉及 UI 或视觉的部分,是否把该有的元素都覆盖了。比如你让模型写一个组件,结果只实现了结构但完全没管样式,或者少了某个状态下的展示——这类遗漏在不加约束的情况下非常常见。
功能覆盖
需求里的功能点是否都有对应实现。接口字段有没有漏掉。如果你在 Prompt 里补充过业务逻辑(比如权限判断、边界处理),模型有没有真的用上。
代码规范
命名是否一致,类型定义是否完整,样式有没有用项目约定的变量而不是硬编码数值。这些细节如果不在 Prompt 里提,模型几乎不会主动考虑。
测试覆盖
是否需要模型同时输出测试代码。如果需要,哪些路径必须覆盖——正常流程、异常流程、边界值。
把这四个维度浓缩成一句话加在 Prompt 末尾,就能覆盖大部分场景:
text
请确保输出满足以下标准:样式完整、功能覆盖、符合项目代码规范、关键路径有测试覆盖。当然,这句话本身不是万能的。它的作用更像一个 checklist 提醒,让模型在生成过程中不至于只顾逻辑正确而忽略其他维度。真正的验收还是要靠你在输出之后做检查——用程序校验、跑测试、人工 review。
和 AI 幻觉 章节讲的系统级防控不同,这里的重点是:在 Prompt 层面就尽早把验收期望说清楚,而不是等到输出之后才发现少了什么。两者是互补的。
为什么 Prompt 不能无限增长
优化 Prompt 时,多数人的默认动作是继续加——加规则、加限制、加示例、加解释。短期有时有效,长期往往把问题搞得更复杂。
Prompt 一旦过长,副作用会一起冒出来:
- 重点被稀释,模型难以抓住真正关键的约束
- 成本上升,响应变慢
- 不同规则之间开始互相打架
- 调整时更难知道到底是哪一句在起作用
好的 Prompt 不是信息越多越好,是重要信息层次清楚、各有各的作用。
对你最有价值的 Prompt 能力
- 抽取型 Prompt:为 Structured Output 做准备
- 问答型 Prompt:为 RAG 原理 做准备
- 工具路由型 Prompt:为 Tool Calling 和 Agent 基础原理 做准备
真实产品中 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——把模型输出从"会说话"推进到"能稳定给系统提供结构化数据"。
如果你在用 Cursor 或其他 AI 编程工具,任务描述模板 可以直接复用这一章的结构思路——把 Prompt 工程的原则落到真实开发任务里。