【LangGraph】运行时上下文(Runtime Context)

📅 发布时间:2026/7/17 18:34:33 👁️ 浏览次数:
【LangGraph】运行时上下文(Runtime Context)
【LangGraph】新篇章LangGraph 运行时上下文Runtime Context前言1、什么是运行时上下文1.1 为什么需要运行时上下文1.2 运行时上下文的本质2、代码详解一个多语言问候助手2.1 定义上下文和状态2.2 编写节点函数访问上下文2.4 调用图并传入上下文2.5 完整代码回顾3、深入理解运行时上下文 vs 状态 vs 存储4、进阶用法与常见场景4.1 在条件边中使用上下文4.2 在子图中传递上下文4.3 与异步流式调用结合4.4 使用 TypedDict 代替 dataclass5、最佳实践与注意事项5.1 最佳实践5.2 常见误区5.3 调试技巧6、总结前言在 LangGraph 中构建多租户 AI 应用时我们经常需要传递一些环境信息—— 比如当前用户的 ID、语言偏好、模型提供商等这些信息不属于对话消息也不是需要持久化的状态但直接影响工作流的行为LangGraph 提供了运行时上下文Runtime Context机制让这类配置信息可以优雅地注入到图的每一个节点中本文将通过一个完整的示例带你彻底掌握运行时上下文的定义、使用和最佳实践1、什么是运行时上下文1.1 为什么需要运行时上下文举个例子啊假设我们正在开发一个支持中英文双语的智能客服系统我们会遇到——不同用户有不同的语言偏好在没有运行时上下文的情况下我们可能需要在每个节点中显式传递 language 参数或者把它塞进 State 中但这会带来几个问题State 污染语言偏好不是对话内容也不是节点间需要累积的数据放在 State 里显得多余重复代码每个节点都要从 State 中取出 language 并处理测试困难每次调用都需要手动构造包含 language 的初始 State更好的做法是将这类静态配置信息与动态 State分离LangGraph 的运行时上下文正是为此设计的1.2 运行时上下文的本质运行时上下文Runtime Context是一次 invoke调用中保持不变的外部配置数据。它的生命周期仅限于单次调用不参与图的持久化不会被 checkpointer保存我们可以把它理解为给图传递的“参数”类似于 HTTP 请求中的 Header在 LangGraph 中使用时需要三个步骤定义上下文的数据结构通常用 dataclass 或 TypedDict在构建 StateGraph 时指定 context_schema在节点函数中通过 Runtime[Context] 参数访问调用图时通过 context 参数传入具体值下面我们用一个完整的、可运行的例子来演示2、代码详解一个多语言问候助手2.1 定义上下文和状态首先导入必要的模块并定义静态上下文 Context和动态状态 StatefromdataclassesimportdataclassfromtypingimportTypedDictfromlanggraph.checkpoint.memoryimportInMemorySaverfromlanggraph.constantsimportEND,STARTfromlanggraph.graphimportStateGraphfromlanggraph.runtimeimportRuntime# 静态上下文单次调用中不变的配置dataclassclassContext:user_id:str# 用户标识可用于日志、审计language:strEn# 语言偏好默认英文# 动态状态会在节点间传递和演化classState(TypedDict):user_name:str# 用户名称可能来自用户输入message:list[str]# 存储生成的消息为什么要用 dataclassdataclass 提供了默认值、类型提示和简洁的语法非常适合定义上下文我们也可以使用 TypedDict但 dataclass 支持默认值更灵活切记两个2.2 编写节点函数访问上下文节点函数需要接收state: State和runtime: Runtime[Context]两个参数Runtime是一个泛型类其.context属性就是我们在调用时传入的上下文对象defnode(state:State,runtime:Runtime[Context]):# 静态运行时上下文语言偏好ifruntime.context.languageEn:greetinghelloelse:greeting你好# 动态运行时上下文从 State 中获取用户名或默认值user_namestate.get(user_name,Guest)return{message:[f{greeting},{user_name}]}注意节点只能读取 runtime.context不能修改它。如果需要修改应该通过 State 传递。### 2.3 构建并编译图在构建 StateGraph 时通过 context_schema 参数绑定上下文类型。 python 运行 builderStateGraph(State,context_schemaContext)builder.add_node(node)builder.add_edge(START,node)builder.add_edge(node,END)graphbuilder.compile()尽管本例没有使用持久化但compile()不加checkpointer也可以正常运行我们不需要持久化上下文因为它每次调用都是新的2.4 调用图并传入上下文resultgraph.invoke({user_name:张三},context{user_id:123,language:中文})print(result)# 输出: {user_name: 张三, message: [你好, 张三]}注意 context 参数接受一个字典其键必须与 Context 的字段匹配这里我们传入 “language”: “中文”节点中的判断条件runtime.context.language En为假因此输出 “你好”2.5 完整代码回顾fromdataclassesimportdataclassfromtypingimportTypedDictfromlanggraph.checkpoint.memoryimportInMemorySaverfromlanggraph.constantsimportEND,STARTfromlanggraph.graphimportStateGraphfromlanggraph.runtimeimportRuntimedataclassclassContext:user_id:strlanguage:strEnclassState(TypedDict):user_name:strmessage:list[str]defnode(state:State,runtime:Runtime[Context]):ifruntime.context.languageEn:greetinghelloelse:greeting你好user_namestate.get(user_name,Guest)return{message:[f{greeting},{user_name}]}builderStateGraph(State,context_schemaContext)builder.add_node(node)builder.add_edge(START,node)builder.add_edge(node,END)graphbuilder.compile()resultgraph.invoke({user_name:张三},context{user_id:123,language:中文})print(result)# {user_name: 张三, message: [你好, 张三]}3、深入理解运行时上下文 vs 状态 vs 存储在 LangGraph 中有三个容易混淆的概念我们可以用一张表彻底区分它们概念可变性生命周期持久化典型用途运行时上下文只读单次调用内不变单次 invoke/stream否每次调用独立用户 ID、语言、租户配置、模型选择图状态State可读写节点间可更新同一 thread_id 下跨节点✅ 由 checkpointer 保存对话消息、累积结果、中间变量跨会话存储Store可读写跨 thread_id 永久✅ 由 Store 持久化用户偏好、历史预定、长期记忆关键结论如果你需要数据在一次调用中保持恒定用运行时上下文如果你需要数据在多轮对话中持续演化用 State如果你需要数据在不同对话之间共享比如用户长期偏好用 Store4、进阶用法与常见场景4.1 在条件边中使用上下文上下文不仅在节点中可用也可以在条件边函数中访问。例如根据上下文中的 model_provider 决定走哪个分支defselect_model_branch(state:State,runtime:Runtime[Context])-str:ifruntime.context.model_provideropenai:returnopenai_nodeelse:returnanthropic_nodebuilder.add_conditional_edges(router,select_model_branch)4.2 在子图中传递上下文当你将子图作为主图的一个节点时上下文会自动传播给子图前提是子图的 context_schema 兼容LangGraph 会在调用子图时自动合并父图的上下文# 子图定义sub_builderStateGraph(SubState,context_schemaSubContext)...sub_graphsub_builder.compile()# 主图main_builderStateGraph(MainState,context_schemaMainContext)main_builder.add_node(sub,sub_graph)# 上下文会自动传递4.3 与异步流式调用结合在astream或astream_events中同样支持context参数asyncforchunkingraph.astream(inputs,contextmy_context)上下文会贯穿整个异步执行过程4.4 使用 TypedDict 代替 dataclass如果你更偏爱 TypedDict也可以fromtypingimportTypedDictclassContext(TypedDict):user_id:strlanguage:str然后在调用时传入字典即可但TypedDict不支持默认值需要手动处理缺失字段5、最佳实践与注意事项5.1 最佳实践将身份、配置类信息放入上下文而不是 State例如user_id、tenant_id、model_name、language为上下文字段提供合理的默认值避免节点中出现大量的空值检查在大型项目中为不同的子图定义不同的上下文类型保持职责清晰在日志和调试信息中打印 runtime.context便于追踪请求5.2 常见误区在节点中修改runtime.context并期待它影响后续节点上下文是不可变的应该在 State 中存储可变数据忘记指定 context_schema导致节点中 runtime.context 为 None 并报错在上下文中放入不可序列化的对象如数据库连接、文件句柄5.3 调试技巧使用print(runtime.context)我们可以在节点中快速查看当前上下文的值6、总结本文通过一个简单的多语言问候示例全面介绍了 LangGraph 运行时上下文的概念、定义方式、节点内访问方法以及在图调用时的传递方式我们还对比了上下文、状态和存储的区别并给出了最佳实践核心要点回顾运行时上下文用于传递单次调用中不变的静态配置使用dataclass定义上下文模式并在构建StateGraph时指定context_schem节点函数中通过runtime: Runtime[Context]参数访问调用时通过context传入上下文与State、Store互补各自解决不同层次的数据需求掌握了运行时上下文你的 LangGraph 工作流将更具模块化和可配置性本次分享就到这里了下一篇我们将在此基础上学习如何在工具Tool内部访问上下文、State 和 Store让工具也能感知运行时环境拜拜~~