当前位置: 首页 > news >正文

LangGraph 上下文工程权威指南:构建智能、感知、有记忆的 AI 代理

在这里插入图片描述

引言:超越提示词——上下文工程的崛起

在构建高级 AI 代理时,我们很快就会发现,简单的请求-响应循环是远远不够的。为了让代理能够执行复杂、多步骤的任务,它们需要一个“工作记忆”——也就是上下文 (Context)。著名 AI 思想家安德烈·卡帕西 (Andrej Karpathy) 曾将 LLM 比作一个新的操作系统,其中 LLM 是 CPU,而其上下文窗口就是 RAM 。

上下文工程 (Context Engineering) 正是这样一门艺术和科学:构建动态系统,以正确的格式提供正确的信息和工具,从而使 AI 应用能够成功完成任务 。它决定了在代理执行任务的每一步,应该向其有限的“RAM”中加载哪些信息。

LangGraph 为上下文工程提供了一个强大而分层的框架。本教程将深入探讨 LangGraph 管理上下文的三种核心机制,从单次运行的静态配置,到动态演变的短期记忆,再到跨越对话的长期知识库。掌握这些概念是构建真正智能、有感知力代理的关键。

第一部分:理解上下文的维度

在深入 LangGraph 的具体实现之前,我们首先需要建立一个清晰的心智模型。上下文可以沿着两个关键维度进行划分 :

按可变性 (Mutability):

  • 静态上下文 (Static Context):在单次运行期间保持不变的不可变数据。例如,用户信息、数据库连接或在任务开始时就已确定的可用工具集。
  • 动态上下文 (Dynamic Context):随着应用程序运行而演变的可变数据。例如,不断增长的对话历史、工具调用的中间结果或代理的“草稿纸”内容。

按生命周期 (Lifetime):

  • 运行时上下文 (Runtime Context):数据的作用域仅限于单次运行或调用。运行结束后,这些数据就会被丢弃。
  • 跨对话上下文 (Cross-conversation Context):数据在多次对话或会话之间持久存在。

LangGraph 精心设计了三种上下文管理机制,分别对应了这些维度的不同组合,为开发者提供了应对不同场景的精确工具 。

上下文类型描述可变性生命周期访问方法
静态运行时上下文在启动时传入的用户元数据、工具、数据库连接等静态单次运行invoke/stream 的 context 参数
动态运行时上下文 (State)在单次运行中演变的可变数据,如对话历史、中间结果动态单次运行LangGraph 的 State 对象
动态跨对话上下文 (Store)跨对话共享的持久化数据,如用户偏好、历史互动动态跨对话LangGraph 的 Store

导出到 Google 表格

第二部分:静态运行时上下文——为单次运行注入配置

静态运行时上下文代表了那些在任务开始时就已确定,并且在整个执行过程中不会改变的“环境变量” 。这对于向代理传递运行时的特定配置(如用户 ID、API 密钥或要使用的特定模型)至关重要。

实现方式:context 参数

在 LangGraph v0.6 版本之后,传递静态上下文的标准方式是通过 invoke 或 stream 方法的 context 参数。这取代了之前嵌套在 config[‘configurable’] 中的模式,使得 API 更加清晰直观 。

代码示例:
from dataclasses import dataclass# 1. 定义上下文的模式 (Schema)
@dataclass
class ContextSchema:user_name: str# 假设 graph 已经编译好
# 2. 在调用时通过 `context` 参数传入数据
graph.invoke({"messages": [{"role": "user", "content": "hi!"}]}, context={"user_name": "John Smith"} 
)

访问静态上下文

一旦传入,静态上下文就可以在图的各个部分被轻松访问,从而影响代理的行为。

  1. 在代理的提示词 (Prompt) 中访问
    这是个性化代理行为最常见的方式。通过 langgraph.runtime.get_runtime,我们可以访问到当前的运行时上下文,并将其动态地注入到系统提示中。
from langgraph.runtime import get_runtime
from langgraph.prebuilt import create_react_agent
from langgraph.prebuilt.chat_agent_executor import AgentState
from langchain_core.messages import AnyMessagedef personalized_prompt(state: AgentState) -> list[AnyMessage]:# 获取当前运行时并指定其类型runtime = get_runtime(ContextSchema)# 从 context 中提取 user_namesystem_msg = f"You are a helpful assistant. Address the user as {runtime.context.user_name}."return [{"role": "system", "content": system_msg}] + state["messages"]agent = create_react_agent(model="anthropic:claude-3-5-sonnet-latest",tools=[...],prompt=personalized_prompt,context_schema=ContextSchema # 告知代理上下文的模式
)# 调用时传入上下文
agent.invoke({"messages": [{"role": "user", "content": "what is the weather in sf"}]},context={"user_name": "John Smith"}
)

在这个例子中,代理会根据传入的 user_name 调整其称呼,从而实现个性化交互 。

  1. 在工作流的节点 (Node) 中访问
    在自定义的工作流节点中,可以通过在函数签名中指定 Runtime 类型来直接访问上下文。
from langgraph.runtime import Runtimedef my_node(state: State, runtime: Runtime):user_name = runtime.context.user_nameprint(f"Executing node for user: {user_name}")#... 节点逻辑...return {}

这种方式使得节点能够根据运行时配置执行不同的逻辑分支 。

  1. 在工具 (Tool) 中访问
    工具也可以是上下文感知的。这使得工具能够执行依赖于用户身份或特定配置的操作。
from langchain_core.tools import tool
from langgraph.runtime import get_runtime@tool
def get_user_email() -> str:"""根据上下文中的用户名检索用户信息。"""runtime = get_runtime(ContextSchema)# 模拟从数据库中获取邮件email = get_user_email_from_db(runtime.context.user_name) return email

在这里,get_user_email 工具可以根据调用时传入的 user_name 从数据库中查询正确的信息 。

第三部分:动态运行时上下文 (State)——代理的短期记忆

动态运行时上下文是代理在单次运行期间的“工作记忆”或“草稿纸” 。它通过 LangGraph 的核心 State 对象来管理,是可变的,用于存储对话历史、工具调用的中间结果以及代理在推理过程中产生的任何临时数据 。

实现方式:自定义 State 模式

通过扩展 LangGraph 预定义的 AgentState 或 MessagesState,或者创建一个全新的 TypedDict,我们可以为代理的短期记忆定义一个自定义的结构 。

代码示例:
from typing_extensions import TypedDict
from langchain_core.messages import AnyMessage
from langgraph.graph import StateGraph
from langgraph.prebuilt.chat_agent_executor import AgentState# 1. 扩展 AgentState 来添加自定义字段
class CustomState(AgentState):user_name: strscratchpad: str# 2. 在节点中访问和更新 State
def node(state: CustomState):# 读取 state 中的数据messages = state["messages"]current_scratchpad = state.get("scratchpad", "")#... 节点逻辑...# 返回对 state 的更新return {"scratchpad": current_scratchpad + "\n- New thought."}# 3. 构建图时使用自定义 State
builder = StateGraph(CustomState)
builder.add_node("my_node", node)
#...
graph = builder.compile()# 4. 在初次调用时初始化 State
graph.invoke({"messages": [{"role": "user", "content": "hi!"}],"user_name": "John Smith","scratchpad": "Initial thoughts..."
})

在这个例子中,CustomState 不仅包含了对话消息,还有一个 user_name 和一个 scratchpad 字段。节点函数可以直接读取和返回对这些字段的更新,LangGraph 会自动将这些更新合并到主状态中 。

启用记忆以跨越调用

默认情况下,State 对象的生命周期仅限于单次 .invoke() 调用。要让这个“短期记忆”在同一次对话的多次调用之间得以保持,您需要启用持久化,即为图配置一个 Checkpointer。这会将 State 的演变历史保存下来,从而实现真正的对话记忆。更多详情请参阅内存指南 。

第四部分:动态跨对话上下文 (Store)——代理的长期记忆

动态跨对话上下文是代理的长期记忆。它用于存储那些需要在不同对话、不同时间甚至不同用户之间持久化和共享的信息,例如用户偏好、历史互动摘要或核心事实 。

实现方式:LangGraph Store

LangGraph 通过 Store 接口来管理长期记忆。与 State 不同,Store 中的数据是持久化的,并且可以被任何有权访问它的工作流读取或更新 。

核心用例:

  • 用户个性化:一个代理可以在一次对话中通过 store.put() 记住用户的名字或偏好,然后在未来的任何对话中通过 store.get() 或 store.search() 来回忆起这些信息,提供高度个性化的体验 。
  • 知识积累:代理可以通过工具调用将从外部世界学到的新事实存入 Store,从而不断丰富自己的知识库。

由于长期记忆是一个深度话题,我们强烈建议您阅读我们关于内存的完整教程,其中详细介绍了如何配置和使用 Store,包括高级的语义搜索功能 。

结论:构建上下文感知的智能体

LangGraph 的三层上下文管理系统为构建从简单到极其复杂的 AI 代理提供了坚实的基础。通过清晰地分离不同生命周期和可变性的上下文,开发者可以构建出模块化、可维护且功能强大的应用。

决策框架总结:

  • 当您需要传递一次性、不可变的配置(如用户 ID、API 密钥)时,请使用静态运行时上下文 (context)。
  • 当您需要管理代理在单次任务中的动态工作空间(如消息历史、中间步骤)时,请使用动态运行时上下文 (State)。
  • 当您需要让代理永久记住跨越多次对话的信息(如用户偏好、核心事实)时,请使用动态跨对话上下文 (Store)。

掌握上下文工程,就是掌握了赋予 AI 代理感知、记忆和适应能力的关键。通过明智地运用 LangGraph 提供的这些工具,您将能够创造出真正理解并响应其环境的下一代智能体。

http://www.xdnf.cn/news/1434853.html

相关文章:

  • Ubuntu平台查看.gz格式压缩文件内容以及利用grep命令过滤搜索内容
  • 《浪浪山小妖怪》知识竞赛来袭!测测你是几级影迷?
  • RL【1】:Basic Concepts
  • 情况三:已经 add ,并且也 commit 了
  • 机器人控制器开发(整体架构2 Lerobot介绍)
  • 佛山体彩第二届唱享之夜浪漫收官, 七夕音乐派对全场大合唱!
  • 使用 Gulp + Webpack 打造一个完整的 TypeScript 库构建流程
  • 社区医疗健康管理系统的设计与实现-(源码+LW+可部署)
  • Linux92 shell:倒计时,用户分类
  • [re_2] rpc|http|nginx|protobuf|
  • HBuilder X 4.76 开发微信小程序集成 uview-plus
  • 【Linux我做主】进程退出和终止详解
  • C++编程语言:标准库:第37章——正则表达式(Bjarne Stroustrup)
  • 拷打字节面试官之-吃透c语言-哈希算法 如何在3面拷打字节cto 3万行算法源码带你吃透算法面试所有考题
  • 【完整源码+数据集+部署教程】鸡粪病害检测系统源码和数据集:改进yolo11-bifpn-SDI
  • 前端开发中经常提到的iframe、DOM是什么?
  • WPF中的DataContext以及常见的绑定方式
  • windows下wsl2 ubuntu开发配置
  • 破解人事管理非标化困境:启效云低代码如何助力业务突围?
  • 为什么同步是无线通信的灵魂?WiFi 与 5G 帧结构中的关键技术
  • 创建一个只能直接构造和销毁,但不能被复制和移动的基类
  • burpsuite使用之CaA神器使用
  • 2025年企业级数据服务API平台大全和接入指南
  • Text2SQL与DataAgent技术深度对比与实践指南
  • Java集合源码解析之LinkedList
  • 串口服务器技术详解:2025年行业标准与应用指南
  • 今天我们继续学习shell编程语言的内容
  • Vscode + docker + qt 网络监听小工具
  • 方差分析(通俗易理解)
  • Java代码耗时统计的5种方法