LangGraph状态管理实战,多轮交互中维护Agent状态

发布时间:2026/9/29 23:12:44

LangGraph状态管理实战,多轮交互中维护Agent状态 LangGraph状态管理实战多轮交互中维护Agent状态上一篇讲了LangGraph的核心概念。这一篇深入状态管理。状态管理是LangGraph最有价值的功能。Agent执行复杂任务的时候中间会产生大量信息。搜索结果、中间推理、用户偏好、任务进度。这些信息要在多个节点之间共享和更新。状态管理做不好Agent就会健忘。做了前面忘了后面或者信息在不同步骤之间对不上。状态的设计状态设计是第一步。好的状态设计能让工作流清晰高效。设计状态要考虑几个问题。需要存什么信息。把任务执行过程中需要共享的信息都列出来。对话历史、搜索结果、中间结论、任务进度、用户信息。信息之间有没有层级。简单的用扁平结构就行。复杂的可以嵌套。哪些信息是只读的哪些需要更新。只读的不用管需要更新的要想好更新策略。fromtypingimportTypedDict,List,OptionalclassResearchState(TypedDict):# 用户输入topic:str# 研究主题user_level:str# 用户水平初学者/中级/专家# 搜索相关search_queries:List[str]# 搜索关键词列表search_results:List[str]# 搜索结果search_round:int# 搜索轮次# 分析相关key_findings:List[str]# 关键发现summary:str# 总结# 控制流status:str# 当前状态retry_count:int# 重试次数max_retries:int# 最大重试次数这个状态设计覆盖了一个研究Agent需要的所有信息。用户输入、搜索过程、分析结果、控制流分门别类。状态的更新机制LangGraph的状态更新机制是这样的。每个节点返回一个字典只包含要更新的字段。LangGraph会把这个字典合并到当前状态里。defsearch_node(state:ResearchState)-dict:topicstate[topic]round_numstate.get(search_round,0)1# 执行搜索new_resultf第{round_num}轮搜索{topic}的结果# 只返回要更新的字段return{search_results:state[search_results][new_result],search_round:round_num,status:searched,}对于列表类型的字段更新时要手动拼接旧值和新值。state[search_results] [new_result]把新结果追加到旧列表后面。这样写有点麻烦。LangGraph提供了Annotated类型可以自动处理列表的追加。fromtypingimportAnnotatedfromoperatorimportaddclassResearchState(TypedDict):search_results:Annotated[List[str],add]# 自动追加search_queries:Annotated[List[str],add]# 自动追加topic:strsummary:strstatus:strsearch_round:int用了Annotated和add以后节点返回时直接给新值就行LangGraph会自动追加。defsearch_node(state:ResearchState)-dict:new_resultf搜索{state[topic]}的结果# 直接给新值自动追加到现有列表return{search_results:[new_result],search_round:state.get(search_round,0)1,}消息列表的管理对话型Agent的状态里最常见的是消息列表。用户消息、AI消息、工具调用消息都要存。LangGraph提供了add_messagesreducer专门用来管理消息列表。fromtypingimportAnnotated,TypedDictfromlanggraph.graph.messageimportadd_messagesfromlangchain_core.messagesimportHumanMessage,AIMessageclassChatState(TypedDict):messages:Annotated[list,add_messages]user_id:strdefchat_node(state:ChatState)-dict:# 读取所有消息messagesstate[messages]# 调用大模型fromlangchain_openaiimportChatOpenAI llmChatOpenAI(modelgpt-3.5-turbo,temperature0)responsellm.invoke(messages)# 返回AI的回复自动追加到消息列表return{messages:[response]}add_messages会自动处理消息的追加。如果同一条消息被重复添加它还会自动去重。比手动拼接方便多了。多轮对话的状态管理多轮对话是状态管理的典型场景。用户跟Agent来回对话每轮对话都要参考之前的上下文。fromlanggraph.graphimportStateGraph,ENDfromtypingimportAnnotated,TypedDictfromlanggraph.graph.messageimportadd_messagesfromlangchain_core.messagesimportHumanMessage,AIMessage,SystemMessagefromlangchain_openaiimportChatOpenAIclassConversationState(TypedDict):messages:Annotated[list,add_messages]user_name:strtopic_count:int# 对话节点defchat_node(state:ConversationState)-dict:llmChatOpenAI(modelgpt-3.5-turbo,temperature0.7)messagesstate[messages]# 如果知道用户名字加到系统提示里ifstate.get(user_name):system_msgSystemMessage(contentf你是一个友好的助手。用户叫{state[user_name]}。)messages[system_msg]messages responsellm.invoke(messages)return{messages:[response],topic_count:state.get(topic_count,0)1,}# 判断是否结束defshould_continue(state:ConversationState)-str:ifstate.get(topic_count,0)5:returnENDreturnchat# 构建图workflowStateGraph(ConversationState)workflow.add_node(chat,chat_node)workflow.set_entry_point(chat)workflow.add_conditional_edges(chat,should_continue)appworkflow.compile()# 模拟多轮对话resultapp.invoke({messages:[HumanMessage(content你好我叫张三),HumanMessage(content我想聊聊AI Agent),HumanMessage(contentLangChain和LangGraph有什么区别),],user_name:张三,topic_count:0,})# 查看完整的对话历史formsginresult[messages]:role用户ifisinstance(msg,HumanMessage)else助手print(f{role}:{msg.content[:50]}...)状态持久化默认情况下LangGraph的状态存在内存里。程序结束就没了。要想跨会话保持状态需要用持久化存储。LangGraph支持用SQLite做持久化。fromlanggraph.checkpoint.sqliteimportSqliteSaverimportsqlite3# 创建SQLite持久化存储connsqlite3.connect(agent_state.db,check_same_threadFalse)checkpointerSqliteSaver(conn)# 编译时传入checkpointerappworkflow.compile(checkpointercheckpointer)# 运行时指定thread_id不同对话用不同的idconfig{configurable:{thread_id:user_001_session_1}}# 第一轮对话resultapp.invoke({messages:[HumanMessage(content我叫张三)]},configconfig,)# 第二轮对话同一个thread_id能访问之前的状态resultapp.invoke({messages:[HumanMessage(content我叫什么名字)]},configconfig,)# Agent能回答张三因为状态被持久化了用了持久化以后即使程序重启状态也不会丢。下次用同一个thread_id还能接着之前的对话继续。状态的查看和调试开发的时候经常需要查看中间状态。用stream方法可以看到每一步的状态变化。foreventinapp.stream({messages:[HumanMessage(content什么是RAG)],topic_count:0},configconfig,):fornode_name,state_updateinevent.items():print(f节点{node_name}执行完毕)print(f状态更新:{state_update})print()也可以用get_state方法查看当前状态。# 获取当前状态current_stateapp.get_state(config)print(current_state.values)调试的时候把状态打印出来看比猜来猜去高效得多。状态设计的几个建议状态不要太大。状态在节点之间传递太大会影响性能。特别是消息列表聊久了会很长。定期做摘要压缩。状态字段要有明确的语义。别用data1、data2这种名字。用search_results、key_findings这种一看就懂的名字。控制流字段和业务字段分开。status、retry_count这些是控制流用的。search_results、summary这些是业务数据。分开放逻辑更清晰。给状态加默认值。新建状态时给所有字段初始值。避免节点读到None报错。下一篇讲条件分支与循环。让Agent学会思考和重试处理更复杂的任务流程。
延伸阅读

更多相关文章

2026/9/29 22:25:26

Transformer推理核心机制拆解:从Attention、GQA、RoPE到KV Cache

1. 从“黑盒”到“骨架”:为什么我们需要拆解Transformer如果你在2024年还在搞AI,尤其是大模型,那么“Transformer”这个词大概已经听得耳朵起茧了。网上铺天盖地的文章都在说它“颠覆了NLP”、“是GPT的基石”、“Attention is all you need…

2026/9/21 22:03:14

过度依赖外部模型,该公司下调 2026 年营收预测三分之一

AI 依赖之痛:营收预测下调三分之一据报道,某公司因过度依赖其他提供商的前沿模型来驱动平台上的 AI 功能,将 2026 年的营收预测下调了三分之一。这一举措反映出公司在 AI 发展战略上的困境。自有模型难产:定价与需求的失衡首席执行…

2026/9/29 23:11:16

特种供电选型之前,先把负载的“致命软肋”问明白

很多做硬件系统、测控平台或特种装备集成的工程师,在选型初期都容易踩进同一个直觉陷阱:把电源当成插线板,觉得只要输入输出电压对得上、额定功率留足余量就万事大吉了。直到样机联调整机上电,现场才开始频繁暴雷——要么是前端极…

2026/9/29 23:11:16

GPON OLT模块B+3dB SC接口 传输20Km

GPONOLT模块B3dB光模块(单模,1490nm-TX/1310nm-RX20km,SC)该GPONOLTSFP光模块支持最高2.5G-TX/1.25G-RX的数据传输速率,适用于单模光纤(单模),最远传输距离可达20km,使用…

2026/9/29 23:11:16

VS2019编译版paho.mqtt.cpp库使用全攻略:配置、示例与排坑

简介:面向需要在VS2019下使用MQTT C客户端的开发者,paho.mqtt.cpp库的VS2019编译成品包源自配套博文教程,可直接对照使用。paho.mqtt.cpp是Eclipse Paho官方的MQTT C客户端库,支持同步/异步API,常用于物联网设备接入、…

2026/9/29 23:06:15

交换芯片控制通路解析:报文解析、查表调度与可编程流水线

写这个系列的时候我一直在想一个比喻:如果把交换芯片的数据通路比作快递分拣中心的传送带和机械臂,那控制通路就是分拣中心的识别台、调度台和一套写好的分拣规则。传送带跑多快、走什么路径,那是数据通路的事;而每个包该不该进、…

2026/9/29 11:07:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 7:00:49

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/29 0:04:04

AI Evals实战指南:从零搭建LLM应用评估体系与CI/CD集成

1. 为什么AI Evals值得你花时间搞明白做LLM应用的人,迟早会撞上同一堵墙:模型输出飘忽不定,今天答得好好的,明天换个问法就胡说八道。你改了一版提示词,感觉好像好了点,但到底好了多少?说不清。…

2026/9/29 0:04:04

Java采购管理系统实战:从数据库设计到事务一致性

简介:这是一套面向Java Web初学者与课程设计者的采购管理系统完整源码,采用JSP技术搭建,配合MySQL数据库,用于解决企业采购信息的管理问题,适合作为毕业设计、课程大作业或进销存类项目的参考模板。系统实现了用户登录…

2026/9/29 3:53:39

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/29 9:46:12

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/29 6:36:14

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑