上下文工程
上下文工程不是"写更好的 Prompt",而是设计更好的信息系统。 Andrej Karpathy 在 2025 年指出,Prompt Engineering 关注措辞技巧,而 Context Engineering 关注的是:什么信息在什么时候以什么形式出现在上下文窗口中。随着模型能力提升,瓶颈已经从"如何说服模型做事"转移到"给模型提供什么信息"。
上下文窗口是一个有结构的空间
上下文窗口不是一个平铺的文本框,而是有层次的信息架构。 一次典型的 LLM 调用,上下文大致分为几个功能区:
System Prompt(角色、规则、工具定义)
↓
Retrieved Context(RAG 检索结果、长期记忆)
↓
Few-shot Examples(格式示例、行为示范)
↓
Conversation History(对话历史、工具调用结果)
↓
Current User Message(当前输入)
每个区域的作用不同。System Prompt 声明稳定的规则和身份;检索上下文动态注入外部知识;Few-shot 示例校准输出格式和风格;对话历史维持任务状态;当前消息触发本次推理。这个结构是需要主动设计的,而不是随意堆叠的。
信息在上下文中的位置和内容同等重要。 Liu 等人 2023 年的研究证明,当关键信息位于长上下文的开头或结尾时,模型表现最好;位于中间时,表现会显著下降,呈现 U 型曲线——这是 Transformer 注意力机制的结构性特征,不因模型变大而消失。这意味着重要的约束和关键文档,应该放在上下文的头部或紧邻当前消息的位置,而不是随便放在中间。
上下文还存在近因偏差。 模型对最近出现的信息赋予更高权重。在多轮对话中,最近几轮的内容对模型行为影响最大;在提示词里,后出现的指令往往会部分压过前面的约束。这既是风险(早期规则可能被覆盖),也是可以利用的特性(在关键用户消息附近重申约束,效果优于只写在系统提示里)。
Few-shot 的真正作用
Few-shot 示例的核心价值不是"教"模型新任务,而是校准格式、分布和风格。 Min 等人 2022 年的研究发现了一个反直觉结论:Few-shot 示例中标签的正确性对性能影响有限,随机错误标签的 Few-shot 仍然比 Zero-shot 好很多。真正起作用的是三件事:告诉模型期望的输出格式、限定"什么是合理输出"的范围、校准语气和详细程度。
一个好的 Few-shot 示例需要满足:相关性、多样性、格式一致性。 示例应该在语义上接近目标任务,示例集合应该覆盖输入空间的不同情况,所有示例必须使用完全一致的格式标记——格式不统一会让模型在格式选择上消耗额外注意力。示例数量上,1-8 个通常足够,超过 20 个的边际收益快速递减。对于经过指令微调的模型,Zero-shot 通常已经足够,Few-shot 主要用于格式和风格校准。
Chain-of-Thought 的本质是展开计算路径,而不是让模型"思考"。 CoT 让中间推理步骤占据 token,使注意力头在每一步只需做更简单的推理。研究发现,CoT 效果在参数量超过约 100B 的模型上才稳定显现——对于较小模型,强制输出推理链反而可能有害。"Let's think step by step"这类 Zero-shot CoT 触发短语,对经过 RLHF 的大模型效果尤为稳定。
System Prompt 的设计原则
System Prompt 不只是"角色设定",它是整个对话的协议层。 经过 RLHF 训练的模型被训练为"信任"系统提示中的指令,这使得系统提示在权限声明、持久约束和行为规范上比用户消息更有效。一个结构完整的 System Prompt 通常包含:角色与能力边界、工具使用规则、输出格式规范、关键行为示例。
正向声明优于负向禁止,具体示例优于抽象描述。 "回复控制在 200 字以内"优于"不要啰嗦";展示一个真实输出示例,优于用文字描述格式要求。原子化规则——每条规则只声明一件事,避免"规则里的规则"——能减少模型解释歧义的概率。
System Prompt 有一个实际的工程优势:KV Cache。 上下文中的固定前缀部分,在多次请求之间会被 API 缓存复用,不需要重复计算。Anthropic 的 Prompt Caching 在缓存命中后可以将输入 token 成本降低 90%、延迟减少 85%。这意味着 System Prompt 写得详尽在成本上几乎是免费的——但前提是它必须放在上下文的最前面,保持前缀稳定,因为 KV Cache 基于前缀匹配工作。
Persona Prompt 的结构化
陪伴、教练、顾问、编辑这类 Persona Prompt 很容易写成一大段人格设定:真诚、共情、有见识、温和、直接、懂心理学、懂文学、像朋友一样说话。问题在于,这些词单独看都正确,堆在一起却不会稳定改变模型行为。真正有效的 Persona Prompt 要把“像谁”拆成“如何判断、如何回应、哪些边界不能越过”。
一个可维护的 Persona Prompt 至少应分成六层:
- 角色:它在这段关系里扮演什么,不扮演什么。例如朋友、教练、编辑、研究助理、面试官、审稿人。
- 核心价值:它优先保护什么。例如真实、尊重、现实检验、用户主体性、长期成长。
- 回应目标:每次回答要完成什么。例如看见具体线索、区分事实和观点、指出盲点、给出临时判断。
- 语气协议:表达要是什么质感。例如温和但直接、自然对话、有解释链、少标签、多展开。
- 边界禁区:哪些行为禁止。例如读心、廉价安慰、连续追问逃避判断、无依据夸赞、过度保姆式步骤。
- 不确定性处理:信息不足时如何说。例如明确当前不知道什么,基于已知信息给出临时判断,不把推测包装成事实。
这类 prompt 的关键,是让模型在温度和判断之间保持张力。只有共情没有判断,会变成情绪陪聊;只有判断没有共情,会变成说教。稳定的结构应该先从用户文本里的具体线索出发,再分析情绪、认知结构或关系动力,接着说明判断依据,最后给出有边界的认可、提醒或建议。这样既能让用户感觉被看见,也不会把 AI 变成迎合用户偏见的回声室。
Persona Prompt 尤其要警惕“洞察越强越好”的误区。模型可以提出可能的潜台词、情绪流动和关系模式,但必须说明这些判断来自哪些文本线索。涉及他人动机、用户内心、关系动态时,要用“基于你描述的这些细节,我更倾向于理解为……”这类表达保留不确定性。没有依据的深刻感,短期很打动人,长期会损害信任。
如果把这类 prompt 写成可复用模板,可以使用这样的顺序:
Role → Core Value → Response Goal → Tone Protocol
→ Boundaries → Reasoning Rules → Immediate Task
其中 Immediate Task 应该留给当前用户请求,不要把它和长期角色规则混在一起。长期规则负责稳定人格和边界,当前任务负责决定这轮具体做什么。两者分开,prompt 才容易复用、调试和替换。
RAG:把知识检索变成上下文注入
RAG 的本质是动态上下文构建,而不只是"搜索 + 回答"。 模型的参数知识有截止日期、有幻觉风险、无法访问私有数据。RAG 解决这些问题的方式是:把知识存在外部,每次推理前检索相关内容,注入上下文,让模型基于当前上下文生成答案,而不是依赖参数记忆。
Chunk 策略决定检索质量的上限。 文档切分过小,单个 chunk 缺乏上下文导致语义残缺;切分过大,检索到的内容包含太多噪音。层次化切分是当前效果最好的方向:用小 chunk(256-512 tokens)做精确检索,检索命中后返回其父级大 chunk(1024-2048 tokens)提供完整上下文,兼顾检索精度和上下文完整性。Chunk 之间保留 10-20% 的重叠,防止边界信息丢失。
向量检索之后需要精排(Reranking)。 初始向量检索基于语义相似度,容易把"语义相近但答案不相关"的内容检索进来。用 Cross-encoder Reranker 对初始 Top-30 结果精排,取 Top-5 注入上下文,通常能提升系统准确率 5-15%。查询增强同样重要:对复杂查询先让 LLM 生成"假设答案文档"再用它检索(HyDE),或生成 3-5 个改写版本分别检索再合并去重(Multi-Query),都能显著提升召回率。
上下文压缩与多轮管理
随着对话推进,上下文会不断增长,需要主动管理。 早期信息会被"迷失在中间",token 成本随长度线性增长,且模型无法区分哪些历史真正重要。解决方案不是无限扩大上下文窗口,而是分层管理:最近几轮完整保留(工作记忆),更早的历史滚动摘要(压缩为情节记忆),关键事实和决策提取到结构化存储(语义记忆),按需检索注入。
可以丢弃的和必须保留的有明确优先级。 可以优先丢弃:礼貌用语和确认语句、同样信息的重复陈述、CoT 的中间推理步骤(只保留结论)。必须保留:用户明确表达的偏好和约束、已确认的事实和决策、对话的核心目标、错误和纠正记录——后者尤其重要,防止 Agent 在多轮中重复同样的错误。
上下文压缩有损,但有工程手段可以控制损失。 Microsoft Research 的 LLMLingua 通过小型语言模型评估每个 token 的信息量,移除困惑度低的冗余 token,压缩比可达 2-20x,精度损失通常低于 5%。对于需要高效处理极长 Prompt 的场景,这类压缩工具是实用的工程选项。
记忆系统:跨会话的持久化与保鲜
前面讨论的都是单次对话内的上下文管理。但当 AI 应用跨越多个会话甚至多年时,记忆系统就成为新的设计问题——什么信息要被记住、怎么保鲜、怎么被用户审查、怎么避免过期。
上下文是空间,记忆是时间
上下文工程解决的是"一次推理窗口里装什么",记忆系统解决的是"跨多次推理保留什么"。 两者是同一信息架构问题的两个维度:上下文管的是空间,记忆管的是时间。
一个成熟的 AI 应用通常有三层记忆:
- 工作记忆:当前会话的完整上下文,由上下文窗口承载
- 情节记忆:跨会话的历史摘要,按主题或时间组织
- 语义记忆:从历史中提炼出的稳定事实、偏好、约束
工作记忆决定这次回答好不好;情节记忆决定 AI 是否记得"我们上次聊到哪";语义记忆决定 AI 是否知道"你是个素食主义者"。没有稳定设计的记忆系统,AI 每次都要从零开始理解用户。
从主动保存到自动综合
第一代记忆系统依赖用户主动操作:让用户说"记住我 7 月去新加坡",系统把这句话存下来。这是一个简单的记事本模式——写入完全靠用户自觉,触发条件强但覆盖率低。在实践中,用户很少主动说"记住",绝大多数个人信息散落在对话的自然流程里。
第二代记忆系统转向后台自动综合:在会话之外用单独的模型反复阅读对话历史,主动识别值得记住的事实、偏好和事件,然后写入记忆库。这种模式让"自然对话"也能成为记忆来源,不需要用户刻意触发。
后台综合引入了三个新的工程问题:
- 保鲜:信息会过期。"7 月去新加坡"在 7 月之后是过时的;"我现在用 Vim"在用户换编辑器之后是错误的
- 正确性:综合过程会出错。模型可能误判哪些信息重要,或者把推测当事实
- 可扩展性:用户量增长后,每个用户的记忆都需要独立存储和更新,工程量线性增加
记忆的三个评估维度
一个记忆系统是否"好",可以沿三个维度评估:
| 维度 | 衡量什么 | 典型失败 |
|---|---|---|
| 跨会话携带上下文 | 用户说过一次的信息是否被后续会话正确使用 | 用户提到自己是某角色,下次会话 AI 又问一遍 |
| 遵循偏好和约束 | 用户的偏好是否在所有回答中一致执行 | 用户说过喜欢安静的地方,但 AI 总是推荐闹市区 |
| 随时间保持新鲜 | 过时信息是否被及时清理或更新 | 一个月前用户换工作了,AI 仍按旧工作给建议 |
第三个维度最容易被忽视。没有保鲜机制的记忆系统是污染源——它让 AI 越来越偏离用户的真实状态。建议类的回答会基于过期的事实,风格类的偏好会因为旧习惯被强化。保鲜能力直接决定记忆系统的可用性。
记忆应该是可审查的
记忆系统最大的设计陷阱是"用户失去了对 AI 知道什么的控制感"。 当 AI 在后台自动积累了大量记忆,用户会开始怀疑:AI 是怎么知道这些的?它记的是对的吗?它记的是我想让它记的吗?
一个好的记忆系统应该:
- 提供可读的摘要视图:把后台积累的记忆压缩成可阅读、可编辑的卡片
- 允许用户主动修正:发现错误时直接修改或删除,不需要复杂的反馈机制
- 区分来源可信度:用户明确说的、模型推断的、行为观察的应该用不同标记
可审查性同时是信任机制和纠错机制。用户能看见 AI 知道什么,才能信任 AI 的回答;用户能修正错误记忆,才能阻止错误累积。
记忆系统的设计选择
设计一个记忆系统时,几个常见选择会影响最终形态:
主动保存 vs 后台综合——前者简单可控但覆盖率低,后者覆盖率高但需要保鲜机制。成熟的系统通常两者并存:用户主动说的立刻写入,模型后台综合的内容经过评估后再写入。
显式存储 vs 隐式整合——把记忆作为独立存储(数据库、向量库)按需检索注入上下文,还是把记忆融入模型本身(微调、持续预训练)?前者灵活可改,后者更难更新但推理更自然。
单用户隔离 vs 跨用户共享——单用户 AI 助手的记忆是私有的;多用户协作系统可能需要共享某些团队级记忆。这涉及权限管理和隐私边界设计。
上下文工程的第一性原理
理解上下文工程,有三个核心命题:
上下文是程序,不是文本。 每次 LLM 调用的上下文,是在运行时动态组装的程序产物。检索什么文档、选哪些历史轮次、注入什么工具结果,都是需要精心设计的决策,而不是随意拼接的文字。
信息的放置和信息的内容同等重要。 相同的内容放在不同位置会产生显著不同的效果。位置、顺序、格式标记——这些是上下文工程的核心设计变量。
Token 预算是稀缺资源,需要工程化管理。 固定内容前置利用 KV Cache,动态内容后置减少缓存失效,关键信息首尾放置避免注意力洼地,检索内容精排减少噪音——这些是系统层面的设计决策,不是事后优化的细节。