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

Agent 记不住上下文?别再手写 history,先把 session_id 设计对

「Regnexe Python 实战系列」第 7 篇(共 10 篇),对应仓库examples/readme/07_three_layer_memory.py。上一篇:06. 能力市场换成数据库要改多少代码?regnexe-py 一个 Marketplace 搞定。

问题的起点

Agent 调用一次完整地回答了问题。下次继续聊,它还记得上次说了什么吗?

这不是一个可以靠"塞进 history 列表"来解决的问题——谁来裁剪?裁多少?超出上下文怎么办?regnexe-py 把这些事情交给了底层架构来处理,而不是在业务代码里手动维护。

Regnexe-py 会话如何挂载到线程

沿用 LangChain(deepagents) 体系,每次ainvoke()都会传三个身份字段:

agent=(RegnexeAgentBuilder().with_default_model(Vendor.DEEPSEEK,"deepseek-v4-flash").with_plugin(WeatherPlugin()).with_event_listener(ConsoleEventListener()).build())result=awaitagent.ainvoke("Check today's weather in Beijing.",app_id="readme",user_id="reader",session_id="07-memory-a",)

内部会把它们拼成 LangGraph 的thread_id

readme:reader:07-memory-a

checkpointer(默认MemorySaver)以这个 thread_id 为键,存取图的完整运行状态。同一个session_id的多次调用落在同一条线程上;换session_id就是全新线程,没有任何历史。

消息是怎么积累的

deepagents 的图状态(DeepAgentState)里有一个messages字段,类型是DeltaChannel——每次图节点执行只写入增量,每 50 次才做一次完整快照,从 O(N²) 降到 O(N) 的存储开销。

同一 session 下连续两次ainvoke(),消息会持续追加:

第 1 次调用(问天气): HumanMessage("Check today's weather in Beijing...") AIMessage(tool_calls=[{name: "get_weather", args: {"city": "Beijing"}}]) ToolMessage("Beijing: sunny, 22 C, excellent air quality.") AIMessage("Yes, today is great for outdoor running.") 第 2 次调用(追问,同 session_id): HumanMessage("Based on the weather you just looked up...") AIMessage("Since it's sunny and 22°C, here are a few tips...")

LangGraph 在第二次调用前自动恢复线程状态,模型拿到的是完整的对话历史,不需要业务层做任何额外处理。

示例里验证这个行为只需保持session_id不变:

# Turn 1: tool is calledresult1=awaitagent.ainvoke("Check today's weather in Beijing and tell me if it's good for outdoor running.",app_id="readme",user_id="reader",session_id="07-memory-a",)# Turn 2: model already knows the weather, no tool re-call neededresult2=awaitagent.ainvoke("Based on the weather you just looked up, what should I keep in mind while running? ""No need to check the weather again.",app_id="readme",user_id="reader",session_id="07-memory-a",)

上下文压缩:SummarizationMiddleware

消息无限积累必然撑爆模型的 context window。deepagents 默认内置了SummarizationMiddleware,它的触发逻辑是:

  • 有模型 profile(知道 max_input_tokens):token 用量达到85%时压缩,保留最近10%的窗口
  • 无 profile:超过170,000 tokens时压缩,保留最近6 条消息

触发后,它做三件事:

  1. 把旧消息用 LLM 压缩成一段摘要
  2. 把原始消息卸载到后端(/conversation_history/{thread_id}.md),方便 agent 之后用read_file查看
  3. 在私有状态字段_summarization_event里记录{cutoff_index, summary_message, file_path}

关键设计state["messages"]里的原始消息永远不会被删除。只有发给 LLM 的那一份视图被替换成[summary_message] + messages[cutoff:]。这样 checkpoint 里的完整日志可以用于 replay 和 eval,不因压缩而丢失。

可替换点

替换 checkpointer——持久化会话

默认的MemorySaver在进程重启后丢失所有会话。换成持久化后端:

fromlanggraph.checkpoint.sqlite.aioimportAsyncSqliteSaverasyncwithAsyncSqliteSaver.from_conn_string("sessions.db")ascheckpointer:agent=(RegnexeAgentBuilder().with_default_model(Vendor.DEEPSEEK,"deepseek-v4-flash").with_plugin(WeatherPlugin()).with_checkpointer(checkpointer).build())

换 checkpointer 不影响业务代码里的app_id / user_id / session_id用法,线程映射逻辑完全不变。

替换 SummarizationMiddleware——控制压缩时机

默认触发阈值对大多数场景够用。如果需要更早压缩(比如控制成本)或调整保留窗口:

fromdeepagents.middleware.summarizationimportSummarizationMiddlewarefromdeepagents.backendsimportStateBackend summ=SummarizationMiddleware(model=my_model,backend=StateBackend(),trigger=("tokens",60_000),# 6 万 token 时就压缩keep=("messages",10),# 保留最近 10 条)agent=(RegnexeAgentBuilder().with_default_model(Vendor.DEEPSEEK,"deepseek-v4-flash").with_plugin(WeatherPlugin()).with_middleware(summ).build())

with_middleware()把自定义 middleware 追加到 deepagents 的 middleware 栈,传给create_deep_agent(middleware=...)。如果同时注册了和默认栈相同类型的 middleware,需要通过 deepagents 的HarnessProfile.excluded_middleware先移除默认的——这属于进阶用法,通常只覆写触发参数就够了。

小结

关注点机制可替换
会话线程映射app_id:user_id:session_idthread_id不需要替换
消息持久化LangGraph checkpointer(默认 MemorySaver)with_checkpointer()
消息存储结构DeltaChannel,只存增量,O(N) 开销内部实现,不暴露
上下文压缩SummarizationMiddleware(内置,按 token 比例触发)with_middleware()
原始消息保留state["messages"]永远不被截断内部设计

regnexe-py 不重新实现这些机制,而是把app_id / user_id / session_id的业务身份体系接到 deepagents / LangGraph 的状态管理上,让架构替你管记忆。


📌 上一篇:06. 能力市场换成数据库要改多少代码?regnexe-py 一个 Marketplace 搞定 | 下一篇:08. Agent 答案错了怎么排查?先把 LLM 和工具调用事件打出来
📌 项目地址:https://github.com/flower-trees/regnexe-py

http://www.jsqmd.com/news/1193415/

相关文章:

  • 臃肿应用变轻量网页!Travelbound应用逆向工程改造记
  • 如何三步快速解密网易云NCM文件:完整免费解决方案
  • 防静电服装体系建设:洁净生产环境的主要防护策略 - 资讯焦点
  • Python浅拷贝与深拷贝本质解析:从内存地址到工程安全
  • 厄尔尼诺现象机制解析:从沃克环流到太平洋东西岸气候影响
  • 暑期本地餐饮商家小红书分阶段营销运营策略 - Redbook_CD
  • 长沙文化创意产业生态观察:从“网红品牌”到“品牌服务体系”的进阶之路 - GrowUME
  • 终极指南:如何使用网盘直链下载助手打破九大网盘下载限制
  • LED驱动失效诊断与电路设计优化指南
  • CH432双串口芯片SPI驱动与寄存器配置实战指南
  • 端到端文件传输终极指南:3分钟掌握安全P2P传输工具
  • 斯坦福四足机器人:如何用1000美元打造智能仿生伙伴
  • 开源实战:如何高效构建720P视频生成系统的3大核心组件
  • 碧蓝航线全自动脚本终极指南:如何让游戏自己玩自己,解放你的双手时间
  • DGUS II数据库存储问题排查与解决方案
  • FreeMoCap:用Python颠覆传统动捕,让三维动作捕捉触手可及
  • 如何深度掌控AMD Ryzen处理器:免费开源调试工具SMUDebugTool完整指南
  • UC3842芯片在电机控制开关电源中的设计与优化
  • 如何快速部署PDF转语音工具:完整实战教程
  • LMK61E0M DCXO模式深度解析:从分数N型PLL原理到70.656MHz时钟实战
  • 【Java 基础篇】Java HashSet 深度解析:从哈希表原理到实战避坑指南
  • 终极指南:如何在Blender中快速实现3D高斯渲染
  • 阻抗匹配原理与高频电路设计实践
  • ThinkPad风扇控制终极指南:告别噪音,掌控性能的完整解决方案
  • 终极SOCD解决方案:Hitboxer键盘重映射工具完全指南
  • 维生素E(VE)含量检测试剂盒,让机体抗氧化评价更高效
  • 51单片机存储器结构详解与编程实践
  • 抖音小程序开发教学系列(2)- 从零构建你的第一个抖音小程序页面
  • MATLAB版VRPTW求解工具包:含双目标蚁群算法、时间窗校验与即用型示例数据
  • 大理云南特产怎么买?品味云南特产超市选购解析 - 百航