第 17 章 提示词与上下文工程¶
开场问题:为什么同一句要求写进 system message 有效,放进检索文档里却会被忽略,甚至被当成不可信内容?
17.1 Context 不只是“一长段字符串”¶
现代聊天模型看到的是带角色和边界的消息序列。常见优先级是 system/developer > user > tool/data,但具体语义由后训练模板决定。
高权限消息定义目标、规则和可用工具;用户消息表达当前任务;检索文档和工具返回是不可信数据。若把它们全部拼成同一段文本,模型无法可靠区分“要遵守的指令”和“要分析的内容”,prompt injection 就由此产生。
17.2 一个可维护的 Prompt 结构¶
建议分成:
- 角色与任务目标。
- 必须遵守的硬约束。
- 决策流程或边界条件。
- 输出 schema。
- 少量有区分度的示例。
- 当前输入与外部证据。
把最关键的约束放在清晰、稳定的位置;避免十几条互相重叠的“不要”。Prompt 过长不仅贵,还会使规则竞争,模型更难判断优先级。
17.3 Few-shot 示例在做什么¶
示例不是给模型补知识,而是在上下文中定义任务、标签语义和输出风格。高价值示例应覆盖决策边界:一个正例、一个容易混淆的反例、一个信息不足的边界例。
随机堆十个普通例子常不如按当前输入检索两个相似示例。动态 few-shot 本质上是对“示范”的 RAG,检索目标应是决策结构相似,而不只是文本相似。
17.4 结构化输出¶
“请输出 JSON”只是自然语言愿望,不是协议保证。可靠性从弱到强:
- Prompt 要求 + 解析失败重试。
- JSON mode,保证语法合法但不保证 schema 正确。
- constrained decoding,根据 JSON Schema/CFG 限制下一 token。
- 工具调用协议,由模型输出结构化函数名和参数。
结构化约束能保证形状,不能保证语义。amount: -999999 依然是合法 JSON,必须在应用层做类型、范围、权限和业务校验。
17.5 长上下文怎样排布¶
模型对上下文不同位置的利用并不均匀,关键信息埋在中间可能被忽略。常见策略:核心指令置顶;当前问题和输出要求靠近末尾;长证据分块带标题;先压缩低价值历史;为证据编号,要求引用。
不要把“窗口支持 1M token”理解成“放进去都能同等利用”。第一册第 10 章讲的是模型侧能力,这里关注任务侧的信息预算。
17.6 Prompt 版本也是代码版本¶
每次修改都要有版本、变更原因、评测结果和回滚能力。禁止在线上控制台悄悄改一句话而不留记录。Prompt 与模型、模板、工具 schema 共同组成行为制品。
核心问答¶
Q:Context Engineering 与 Prompt Engineering 的区别? 前者不只写指令,还设计哪些证据、示例、历史和工具结果进入上下文,以及它们的权限和位置。
Q:为什么检索文档不能拥有 system 权限? 文档来自外部且可能被攻击者控制。它是待分析数据,不是可信指令。
Q:JSON mode 能保证业务字段正确吗? 不能。它最多保证语法,schema、范围、权限和语义仍需应用层验证。
Q:什么时候 few-shot 比 SFT 合适? 任务仍在变化、示例很少、需要快速试验或每个租户规则不同时;规则稳定且每次都重复占上下文,再考虑 SFT。