3.5 提示词工程与 Agent 工程的边界
一句话结论:提示词工程管"模型怎么想",Agent 工程管"系统怎么转"。用错工具是最大的浪费——很多被当成"提示词写不好"的问题,其实是架构问题;反过来,很多被当成"要改架构"的问题,只要改一句约束就能解决。
读这篇之前
需要先读 3.1–3.4,以及 1.4(复杂度阶梯)。这一篇是第 3 章的收束,也是全系列最重要的一次"工具选择"判断。
一、一个反复出现的浪费
先看两个真实场景:
场景 A:Agent 老是调错工具。于是工程师花了三天,把系统提示从 800 字改到 4000 字,加了无数"请注意"。
真相:工具描述写得含糊(4.2 会讲),或者两个工具职责重叠(4.5)。改提示词只能缓解,不能解决。
场景 B:Agent 回答的质量不稳定。于是工程师决定引入多 Agent 架构、加审查者角色。
真相:检索召回的准确率太低(第 7 章),上下文里给的就是错材料。换架构也没用。
这两个场景的共同点是:问题被归错了类。
二、怎么分清:五个问题定位
当 Agent 表现不达预期时,按顺序问这五个问题:
| # | 问题 | 如果是"是" | 该改哪里 |
|---|---|---|---|
| 1 | 它是否缺少必要信息? | 是 | 补上下文 / 检索(第 5、7 章) |
| 2 | 它是否拿到了错误信息? | 是 | 修数据源 / 加校验(第 7 章) |
| 3 | 它是否不知道该怎么判断? | 是 | 改提示词(本章) |
| 4 | 它是否判断对了但做不到? | 是 | 修工具(第 4 章) |
| 5 | 它是否做对了但这步不该有? | 是 | 改架构(第 11、12 章) |
这个顺序不能变,因为前三个都是"信息与判断"层问题,成本低、修复快;后两个才是"系统"层问题,成本高。
关键统计事实:实践中,绝大多数 Agent 问题落在第 1、2 行(信息问题),而不是第 3 行(提示词问题)。
三、提示词工程能做什么,不能做什么
| 提示词工程能 | 提示词工程不能 |
|---|---|
| 明确任务与边界 | 补齐缺失的知识 |
| 规定输出格式 | 修正错误的数据 |
| 引导推理步骤 | 让模型执行动作 |
| 降低幻觉概率 | 消除幻觉 |
| 统一语气风格 | 提升事实准确率上限 |
| 指定失败策略 | 保证模型一定遵守 |
最后一项最容易被误判:"我在提示词里写了'禁止 XXX',为什么它还是做了?"
因为提示词是"请求",不是"保证"(3.2 讲结构化输出时提过同样的话)。真正的保证来自:
- 格式保证:schema 校验(3.2)
- 行为保证:工具层拦截(2.5、第 14 章)
一句话记住:提示词能提高概率,不能提供保证。需要保证的地方,必须有代码兜底。
四、Agent 工程管什么
把"非提示词"的部分列出来,你就知道边界在哪:
| 领域 | 具体内容 | 章节 |
|---|---|---|
| 上下文供给 | 检索、记忆、压缩、状态外显 | 5、6、7 |
| 工具与执行 | 工具设计、参数校验、副作用分级 | 4、14 |
| 循环与编排 | 运行时、终止条件、多 Agent、工作流 | 10、11、12 |
| 质量保障 | 评测、回归、可观测 | 13 |
| 成本与延迟 | 缓存、批处理、模型选择 | 2.1、5.3 |
这五块里的任何一块缺失,都无法靠提示词补上。
五、一个可操作的升级决策树
flowchart TD
A["Agent 表现不达预期"] --> B{"缺信息吗?"}
B -->|是| C["补上下文或加检索"]
B -->|否| D{"信息是错的吗?"}
D -->|是| E["修数据源 / 加校验"]
D -->|否| F{"判断逻辑不清吗?"}
F -->|是| G["改提示词:明确目标/步骤/约束"]
F -->|否| H{"判断对了但做不到?"}
H -->|是| I["修工具:参数/权限/错误信息"]
H -->|否| J["改架构:拆职责/加层/换编排"]
C --> K["配评测集验证"]
E --> K
G --> K
I --> K
J --> K
注意最后汇聚到 "配评测集验证"——无论改哪一层,都必须有办法证明"改好了"。
没有评测的改动,你无法区分"改好了"和"碰巧这次对了"。
六、把提示词当代码管:PromptOps
原文提到把提示词当代码管理的实践(PromptOps)。四个最低配置:[原文 707]
| 环节 | 做法 |
|---|---|
| 模板化 | 用模板引擎(如 Jinja2)管理变量,而不是字符串拼接 |
| 版本化 | 存文件、进 Git,可 diff 可回滚 |
| 测试化 | 配评测集,改动前后跑对比 |
| 可观测 | 记录每次调用用的提示词版本,便于归因 |
第二条尤其重要,因为 3.1 讲过:提示词改动一个词的后果可能比改一行代码大得多,而且更难定位。 没有版本化,出问题时你连"之前是什么"都查不到。
七、提示词模板化:为什么不能用字符串拼接
一个具体的技术选择,能省掉后面很多麻烦。
# ❌ 字符串拼接
prompt = "你是一个助手。当前资料:" + docs + "。用户问:" + question
# ✅ 模板
prompt = template.render(docs=docs, question=question)
为什么模板更好?三个具体原因:
| 原因 | 说明 |
|---|---|
| 结构显式 | 模板文件里能看清"哪块是变量、哪块是固定约束" |
| 转义安全 | 拼接时如果 docs 里含 {} 或特殊字符,会破坏结构;模板引擎会处理 |
| 可测试 | 模板 + 变量可以分别测试;拼接字符串只能整体测 |
第三条最关键。模板让你能单独验证"渲染出来的提示词本身对不对",而不必等整个 Agent 跑一遍。
原文把这一实践归为 PromptOps 的一部分:把提示词当代码管理,用模板引擎管理变量而不是字符串拼接。[原文 707]
模板化的一个隐藏收益
模板天然把固定部分和变量部分分开了。而 3.4 讲过:固定的部分才有资格放进 system,才有资格被缓存。
所以模板化不只是代码整洁问题,它直接决定了你的缓存能不能命中(5.3),进而决定成本。
八、一个判断练习:这些该改哪里
给五个真实场景,你先自己判断,再看答案。
场景 1:Agent 回答时经常编造不存在的配置项名称。
答案:信息问题(第 1 行)。缺真实文档 → 补检索(第 7 章)。改提示词只能降低概率,不能根治(3.5 第三节)。
场景 2:Agent 每次都输出格式不一致的列表,解析经常失败。
答案:这是提示词 + 机制的交叉问题。用原生 schema(3.2) 一步解决,而不是反复加"请用统一格式"。
场景 3:Agent 在长任务里忘记自己做到第几步。
答案:上下文问题。加状态栏外显进度(2.2)。这不是提示词能解决的,因为它的根源是"模型不会自动数数"。
场景 4:Agent 偶尔会删除不该删的文件。
答案:工具层问题。改提示词写"不要删文件"只是第一道墙,真正可靠的是工具层拦截 + 人工确认(第 14 章)。
场景 5:Agent 处理简单问题时也啰嗦写一大段推理。
答案:提示词问题。任务分类后走不同提示词(路由模式,1.4 第五节),简单任务不要求推理(3.3)。
这五道题的共同规律:
越是"可靠性"问题,越不该只靠提示词;越是"表达"问题,才越该靠提示词。
九、常见误区
误区一:Agent 效果不好,先改提示词。
先查信息和工具。多数问题不在这里(第二节的统计事实)。
误区二:提示词能替代架构。
不能。提示词无法让一个单 Agent 具备它缺失的能力。
误区三:Agent 工程就是"写提示词 + 接工具"。
还差上下文供给、评测、可观测三大块,而且这三大块决定了系统工程质量。
误区四:改架构总比改提示词"更彻底"。
代价也更大。从最便宜的那层开始试(复杂度阶梯,1.4)。
误区五:PromptOps 是大团队才需要的。
个人项目更需要——因为没人帮你记住"上次为什么这么改"。
误区六:模板化只是代码风格问题。
它直接关系到缓存命中率和可测试性,是成本与质量的双重问题。
十、动手:用一个案例走完"改哪里"的判断
把 3.5 的五问定位用到具体案例。
案例:客服 Agent 回答退款规定时经常错
现象:用户问"多久能退款",Agent 答"3-5 个工作日",但实际是"7-15 个工作日"。
按五问排查:
| 问 | 检查 | 结果 |
|---|---|---|
| ① 缺信息吗? | 上下文里有退款政策文档吗 | 没有 ← 命中 |
| ② 信息错吗? | 有的话内容对不对 | 不适用 |
| ③ 判断逻辑不清吗? | 提示词有没有说怎么回答 | 有 |
| ④ 判断对了做不到吗? | 不需要工具 | 不适用 |
| ⑤ 这步不该有吗? | 该有 | 不适用 |
结论:不是提示词问题,是缺上下文。
正确修复:把退款政策放进检索库(第 7 章),或者直接写进系统提示(如果很短)。
错误修复(很多人会这么做):
在提示词里加:「退款时间是 7-15 个工作日,请注意不要说错」
这能修好这一个问题,但下一条政策变了又要改提示词——治标不治本,而且系统提示越来越长(3.4 失败一)。
正确做法是把"事实"放在它能被更新的地方(文档/检索),把"规则"放在提示词。
一条判据
如果这条内容是"会变的事实" → 放文档/检索
如果这条内容是"不变的规则" → 放提示词
这条判据能防止系统提示膨胀成规则条文堆积。
十一、第 3 章小结
五篇讲完,把提示词这一层压缩成一张表:
| 主题 | 核心结论 | 篇 |
|---|---|---|
| 三件套 | 指令 / 上下文 / 示例必须分开,生命周期不同 | 3.1 |
| 结构化输出 | 原生 schema 比提示词请求可靠;六个结构单元 + C.L.E.A.R | 3.2 |
| 推理提示 | 先测"无推理"够不够;推理有成本也有害处 | 3.3 |
| 系统提示 | 每轮重复计费;不变的东西放 system,会变的放后面 | 3.4 |
| 边界 | 提示词提高概率,代码提供保证 | 3.5 |
三条最重要的结论:
- 提示词是"操作系统",不是"咒语"。 它决定模型怎么想,但决定不了它能看见什么。
- 形容词没有约束力。 一切要求都要换成可验证、可计数的事实。
- 需要保证的地方,必须在代码里兜底。 提示词只能提高概率。
十二、第 3 章小结
| 主题 | 一句话 |
|---|---|
| 三件套 | 指令/上下文/示例放不同位置,生命周期不同 |
| 结构化输出 | 原生 schema 是机制保证,提示词只是请求 |
| 推理提示 | 先测"无推理"够不够;推理有成本也有害处 |
| 系统提示 | 每轮都付费;不变放 system,变放后面 |
| 边界 | 提示词提高概率,代码提供保证 |
五个可直接用的判据:
① 形容词 → 换成可计数的事实
② "输出会被程序读" → 必上 schema + 低温度
③ 才测"无推理"→ 够用就不加 CoT
④ 会变的事实 → 放文档;不变的规则 → 放提示词
⑤ 需要保证的事 → 代码兜底,不靠提示词
这五条能解决 80% 的提示词问题。
十三、一个总结性的对照表
| 你以为的问题 | 实际可能是 | 该做什么 |
|---|---|---|
| 模型不够聪明 | 上下文缺信息 | 补检索(7) |
| 提示词写得不好 | 该用 Workflow | 改架构(12) |
| 需要更强的模型 | 需要结构化输出 | 上 schema(3.2) |
| 模型不听话 | 规则写成了形容词 | 换成可计数事实 |
| 需要微调 | 只需给示例 | Few-shot(3.2) |
右列这些,全都比"换模型"或"微调"便宜得多。
十四、下一篇
第 3 章讲完了"怎么让模型想对"。第 4 章进入下一个环节:怎么让模型做到。
这就涉及 Agent 的"手脚"——工具调用。它的本质其实很简单(一次结构化输出),但要写好却极难,因为它决定了 Agent 能力的实际边界。
下一篇从 Function Calling 的机制讲起。