第 4 章:上下文工程 - 提升智能体可靠性的关键
上下文工程不是堆砌信息,而是在正确的时间以正确的格式提供关键信息。
智能体失败的根源:缺少“正确的上下文”
在智能体应用开发中,提升可靠性是最大的挑战。虽然智能体在原型阶段可能表现良好,但在实际场景中常常出现失效。
智能体失败的主要原因有两个:
- 底层大型语言模型(LLM, Large Language Model)的能力有限。
- 没有将“正确的上下文”传递给 LLM。
通常,智能体不可靠的核心障碍是缺少“正确的上下文”。当智能体失败时,往往是因为 LLM 在调用中采取了错误的行动,或未执行预期操作。
上下文工程的哲学:在正确的格式中提供正确的信息
上下文工程(Context Engineering) 是提升智能体可靠性的核心方法,也是 AI 工程师的首要任务。
上下文工程的定义如下:
- 以正确的格式提供正确的信息和工具,使 LLM 能够完成任务。LangChain 的智能体抽象专为促进上下文工程而设计。
LangChain 的 中间件(Middleware) 是实现上下文工程的底层机制。中间件允许开发者介入智能体生命周期的任意步骤:
- 更新上下文:修改状态(State)和存储(Store),以持久化更改、更新对话历史或保存洞察。
- 在生命周期中跳转:根据上下文移动到智能体周期的不同步骤(如满足条件则跳过工具执行,或以修改后的上下文重复模型调用)。
三大上下文控制域
为了构建可靠的智能体,需要在智能体循环的每一步及步骤之间进行精细控制。这些控制点被组织为三大上下文类型:
下表总结了三类上下文的控制范围与特性:
| 上下文类型 | 控制范围 | 瞬态或持久性 |
|---|---|---|
| 模型上下文 (Model Context) | 控制进入模型调用的内容(指令、消息历史、工具、响应格式)。 | 瞬态 (Transient) |
| 工具上下文 (Tool Context) | 控制工具可以访问和产生的内容(读取/写入状态、存储、运行时上下文)。 | 持久性 (Persistent) |
| 生命周期上下文 (Life-cycle Context) | 控制模型调用和工具调用之间发生的事情(摘要、防护栏、日志记录等)。 | 持久性 (Persistent) |
模型上下文(Model Context):瞬态控制
模型上下文控制每次模型调用中包含的内容,直接影响智能体的可靠性和成本。
模型上下文的更改通常是瞬态的——只影响单次模型调用的消息,不会改变状态中保存的内容(除非使用摘要等持久化生命周期钩子)。
- 指令(System Prompt):系统提示设置了 LLM 的行为和能力。成功的智能体应根据记忆、偏好和配置动态提供正确的指令。可通过中间件(如
@dynamic_prompt或@wrap_model_call)基于运行时上下文或状态动态修改系统提示。 - 消息(Messages):消息是发送给 LLM 的提示内容。关键在于管理消息内容,确保 LLM 拥有正确的信息以做出优质响应。
- 工具(Tools):工具的定义(名称、描述、参数)和选择直接影响模型能否有效完成任务。工具过多会导致模型上下文超载并增加错误。可用中间件(如
LLMToolSelector)根据身份验证状态或会话阶段动态选择工具集。 - 响应格式(Response Format):结构化输出将非结构化文本转换为经过验证的结构化数据。可通过
response_format参数提供模式(如 Pydantic 或 dataclass),保证模型响应符合预期结构。
工具上下文(Tool Context):读写控制
工具上下文控制工具执行期间的数据访问和修改。工具既能读取上下文,也能写入上下文。
工具通过 ToolRuntime 参数访问运行时信息:
- 读取(Reads):工具通常需要用户 ID、API 密钥或当前会话状态等信息来决策或查询数据库。工具通过读取状态(State)、存储(Store)和运行时上下文(Runtime Context)来访问这些信息。
- 写入(Writes):工具结果不仅可直接返回给模型,还可通过更新智能体记忆,使重要上下文用于后续步骤。工具可通过返回状态更新实现对智能体状态的修改。
生命周期上下文(Life-cycle Context):持久性控制
生命周期上下文控制模型调用和工具执行之间发生的事情,支持跨领域关注点(cross-cutting concerns),如日志记录、摘要和防护栏。
这些更改通常具有持久性,经常修改状态(State)或存储(Store)。
- 摘要(Summarization):用于对话历史过长时自动压缩。摘要中间件会用单独的 LLM 调用总结旧消息,并永久性地用摘要信息替换状态中的原始消息。
- 防护栏(Guardrails):用于在关键点验证和过滤内容,确保安全合规。例如,PII 检测中间件可在模型调用前检查用户输入,并根据策略(如
redact或block)处理敏感信息。 - 人工参与(Human-in-the-Loop, HITL):允许在执行敏感操作(如工具调用)前暂停智能体,等待人工批准、编辑或拒绝,是高风险决策的有效防护栏。
- 日志记录和监控:可用中间件添加自定义日志记录和监控,或利用 LangChain 内置的 LangSmith 追踪功能。
数据来源分类:运行时上下文、状态与长期存储
在上下文工程过程中,智能体会访问(读取和写入)不同的数据源。理解这些数据源的范围有助于设计持久性和控制流。
下表总结了三类数据来源的范围与示例:
| 数据来源 | 别名 | 范围 | 示例 |
|---|---|---|---|
| 运行时上下文 | 静态配置 | 对话范围(Conversation-scoped) | 用户 ID、API 密钥、数据库连接、应用配置 |
| 状态(State) | 短时记忆 | 对话范围(Conversation-scoped) | 当前消息、上传的文件、身份验证状态、工具结果 |
| 存储(Store) | 长期记忆 | 跨对话(Cross-conversation) | 用户偏好、提取的洞察、历史数据 |
- 运行时上下文(Runtime Context):
- 不可变(Immutable):调用智能体时传入,执行过程中不可更改。
- 用途:依赖注入。通过
context参数传递,可通过ToolRuntime或中间件访问。
- 状态(State)/短时记忆:
- 可变(Mutable):智能体执行过程中可读取和修改。
- 用途:维持单线程或对话内的历史信息。默认用
AgentState管理会话历史消息。工具可通过返回状态更新修改状态。
- 存储(Store)/长期记忆:
- 持久性:跨多个对话或会话持久化数据。
- 结构:LangGraph 将长期记忆存储为 JSON 文档,并用命名空间和键组织。
- 访问:工具和中间件可通过
ToolRuntime.store访问和更新存储。
总结
上下文工程是确保智能体可靠性的首要任务,其核心在于通过 LangChain 的中间件机制,精细控制在智能体执行不同阶段传递给 LLM 和工具的数据与指令。就像一位经验丰富的厨师,只有在正确的时间以正确的形式送达关键食材(上下文),才能确保最终菜肴(智能体输出)的质量始终如一。