news 2026/9/10 2:18:39

Working Memory

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Working Memory

Working Memory

【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

Session Title

简短独特的 5-10 词标题,信息密集

Current State

当前工作状态、待完成任务、下一步

Task & Goals

用户目标、关键设计决策、解释性上下文

Key Facts & Decisions

重要结论、技术选择及理由、用户偏好与约束

Files & Context

重要文件 / 函数 / 模块及路径

Errors & Corrections

遇到的错误及修复、用户纠正、失败方案

Open Issues

未解决问题、阻塞项、后续风险

模板在 [session.py](https://link.gitcode.com/i/a654d680b56087e9f23a2e21dc0456c6) 中由 `WM_SEVEN_SECTIONS` 常量定义,服务端解析与合并均围绕该常量遍历。段与段的「数据性格」不同,决定了 Guard 策略不同: - **锚定型**(Session Title):会话身份标识,不应随意变更; - **易变型**(Current State、Task & Goals):每轮反映当前状态,LLM 可自由 UPDATE; - **累积型**(Key Facts & Decisions):重要结论不断积累,丢失代价高; - **引用型**(Files & Context):文件路径一旦提及不应消失; - **只增型**(Errors & Corrections):错误记录只增不删; - **跟踪型**(Open Issues):未解决项不应被静默丢弃。 从源码看,预算约束还落在 prompt 指引层面:每段上限约 2000 tokens、总 WM 上限约 12000 tokens;服务端定义 `_WM_SECTION_BULLET_THRESHOLD = 25`、`_WM_SECTION_TOKEN_THRESHOLD = 1500`([session.py](https://link.gitcode.com/i/a654d680b56087e9f23a2e21dc0456c6#L4737-L4738)),当单段超过 25 个 bullet 或 1500 tokens 时触发 consolidation 提醒。 --- ## 四、增量更新协议:tool_call + JSON Schema WM 更新通过 **tool_call(function calling)+ JSON schema** 实现:LLM 调用 `update_working_memory` 工具,以结构化 JSON 提交对 7 个段的逐段操作。JSON schema 的强约束保证漏段、多段、格式错误在 schema 层直接拦截。 ### 4.1 tool schema 定义 ```python WM_SEVEN_SECTIONS = [ "Session Title", "Current State", "Task & Goals", "Key Facts & Decisions", "Files & Context", "Errors & Corrections", "Open Issues", ] WM_UPDATE_TOOL = { "type": "function", "function": { "name": "update_working_memory", "parameters": { "type": "object", "required": ["sections"], "additionalProperties": False, "properties": { "sections": { "type": "object", "required": list(WM_SEVEN_SECTIONS), # 7 段全部必填 "additionalProperties": False, "properties": {name: _WM_SECTION_OP_SCHEMA for name in WM_SEVEN_SECTIONS}, } }, }, }, }

每段的操作(_WM_SECTION_OP_SCHEMA)用oneOf约束为三种形状之一:

  • {"op": "KEEP"}— 原样保留
  • {"op": "UPDATE", "content": "..."}— 全段替换
  • {"op": "APPEND", "items": ["...", "..."]}— 追加条目

实现细节上,op字段使用"type": "string", "enum": ["KEEP"]形式,以兼容更多 JSON Schema 版本;additionalProperties: false+required把 LLM 输出严格钉在 schema 里。7 段全部必填的设计,强制 LLM 对每个段落都显式表态,避免「某段被遗忘而隐式丢失」。

4.2 段级合并

服务端_merge_wm_sections(old_wm, ops)WM_SEVEN_SECTIONS常量遍历 7 段执行合并:

  • KEEP→ 原样复制旧内容;
  • UPDATE→ 用 LLM 提供的 content 替换(先经过该段的 guard 校验);
  • APPEND→ 旧内容 + LLM 提供的 items(渲染为- item);
  • 漏段 / 未知 op→ 兜底 KEEP。

配套的_parse_wm_sections()##标题切分 Markdown 为{header: body}字典。关键实现位于 session.py 的_parse_wm_sections()(约 L4715)与_merge_wm_sections()(约 L5367)。


五、服务端 Guards:信息保留的系统级兜底

Guards 是服务端在合并 LLM 提交的操作时按段执行的语义校验函数:即使 LLM 说 UPDATE,服务端也根据段的特性决定是否接受。7 个段的保护策略如下:

数据特点Guard规则
Session Title锚定型_wm_enforce_title_stabilityUPDATE 与旧 title 的 meaningful-word overlap < 1 → 回退 KEEP
Current State易变型LLM 可自由 UPDATE
Task & Goals易变型LLM 可自由 UPDATE
Key Facts & Decisions累积型_wm_enforce_key_facts_consolidation双阈值验证:bullet count ≥ 旧值 15% 且 lexical anchor coverage ≥ 70%;被拒时提取新 items 做 APPEND
Files & Context引用型_wm_enforce_files_no_regressionUPDATE 丢失旧路径 → KEEP + APPEND 新路径
Errors & Corrections只增型_wm_enforce_append_onlyUPDATE 降级为 APPEND,去重后只追加新条目
Open Issues跟踪型_wm_enforce_open_issues_resolvedsilently drop 的 item → 加[restored]标签恢复

从源码看,这些 guard 的工程实现相当细致(session.py):

  • Errors 的 append-only 降级_wm_enforce_append_only()将 UPDATE 的 content 解析为 bullet items,过滤掉旧内容中已存在的条目后,把「真正新增的条目」以 APPEND 形式重新发射,既不让 LLM 重写的内容丢失,也绝不丢弃旧 body 的任何内容;若没有新增条目则整体回退为 KEEP。
  • Key Facts 的受控合并_wm_enforce_key_facts_consolidation()采用双层验证。第一层拒绝明显缩水的 UPDATE(bullet 数 < 旧值 15%);第二层要求至少 70% 的lexical anchor覆盖——_extract_lexical_anchors()会从文本中提取日期(如2024-03-15)、数字短语(如3 months$200)、决策标记词(because / decided / chose / agreed / resolved)以及专有名词(大写 token)作为事实锚点(session.py)。被拒的 UPDATE 会通过_salvage_new_items_from_rejected_update()抢救出真正的新条目做 APPEND,当前轮次的事实不会静默丢失。
  • Key Facts 的反膨胀(anti-bloat)机制:当 Key Facts 已超限(bullet > 25 或 token > 1500)时 APPEND 被节流——1~2 倍阈值区间只接受去重后的新条目且上限 5 条(_WM_OVERSIZED_APPEND_CAP = 5);超过 2 倍阈值(紧急状态)则拒绝一切普通新增,仅插入一条幂等的[⚠ CONSOLIDATION REQUIRED: ...]哨兵,且哨兵已存在时后续轮次不再追加任何内容,形成硬停止(session.py)。
  • Files 的路径回归检测_WM_PATH_LIKE_RE用宽松的 path-like 正则识别旧 Files & Context 中出现过的文件路径(覆盖py/ts/tsx/js/jsx/md/yaml/yml/json/sh/ps1/cmd/bat/toml/ini/cfg/rs/go扩展名及a/b/c型路径),UPDATE 一旦丢失旧路径即回退 KEEP 并追加新路径。
  • Title 的停用词机制_WM_TITLE_STOPWORDS过滤the/a/an/and/session/working/memory等无信息量词汇后,再计算新旧 title 的重叠度判断是否「换了个身份」。

另外,更新 prompt 中还会注入动态的section size warnings_build_wm_section_reminders()扫描当前 overview,统计每段 bullet 数与 token 估算,超过阈值时生成<section_size_warnings>XML 块,明确告知 LLM 哪些段必须用 UPDATE 做合并压缩、并给出目标(≤ 25 bullets、≤ 1500 tokens),从而把「何时必须压缩」的信号从服务端传到模型(session.py)。

这些 guard 均有配套单元测试,集中在 tests/unit/session/test_wm_v2_guards.py(共 107 用例覆盖 5 个 guard + growth + 通用 schema),另有test_working_memory_growth.pytest_working_memory_v2.py等测试文件补充验证。


六、滑动窗口与 pending_tokens

SessionMeta维护pending_tokens: intkeep_recent_count: int两个字段,持久化到.meta.json。其核心语义(session.py):

  • pending_tokens落在最近保留窗口之外、将在下次 commit 被归档的消息的累计 estimated_tokens;
  • keep_recent_count是插件最近一次通过 commit API body 传入的值,被记住后,后续add_message调用可在进程重启后依然一致地维护pending_tokens

运行机制:

  • add_message时:新消息进入保留窗口尾部,窗口头部被挤出的消息 token 累加到pending_tokens
  • commitpending_tokens归零;
  • GET /sessions/{id}直接读 meta,O(1) 获得 pending_tokens。

服务端有防御性 clamp:pending_tokenskeep_recent_count在加载与写入时都执行max(0, ...)(session.py)。CommitRequest.keep_recent_count在 router 层还有ge=0, le=10_000的数值约束,见 routers/sessions.py 的CommitRequest定义。此外从源码看,commit 之后服务端还会通过_rebuild_pending_tokens()依据当前消息列表重算pending_tokens(session.py),保证跨重启、跨异常路径下的账目一致。

关键实现位置:session.pySessionMeta/add_message()routers/sessions.pyCommitRequest


七、保留最近消息:keep_recent_count

commit 归档时并不全量清空消息,而是保留最近 N 条以维持上下文连贯:

  • 参数keep_recent_count由插件在 commit API body 中传入;
  • afterTurn 路径默认 10,compact 路径硬编码 0;
  • OV 存储模型保证tool_use/tool_result配对完整性(ToolPart 自包含),因此归档与保留都不会拆散一次工具调用与其结果。

该值会被持久化到SessionMeta.keep_recent_count,确保跨进程重启后滑动窗口的边界仍与插件侧预期一致。关键实现:session.pycommit_async(keep_recent_count)routers/sessions.pyCommitRequest,以及插件侧的context-engine.tsclient.ts


八、核心流程

8.1 afterTurn 流程(每轮对话后自动归档)

插件端逻辑不变,commit 的耗时工作在服务端完成:

[插件] afterTurn ├── extractNewTurnMessages → 提取新消息 ├── addSessionMessage → 逐条 POST /sessions/{id}/messages │ 服务端: append msg + 滑动窗口更新 pending_tokens + save meta ├── GET /sessions/{id} → 返回 pending_tokens(O(1)) └── pending_tokens >= tokenBudget * commitTokenThresholdRatio? │ YES → commitSession(wait=false, keepRecentCount=cfg.commitKeepRecentCount) │ [服务端 commit_async] │ ├── Phase 1(同步,不阻塞返回) │ ├── split_idx = total - keep_recent_count │ ├── 归档 messages[:split_idx] → archive_NNN/ │ ├── 保留 messages[split_idx:] │ └── pending_tokens = 0, 更新 meta │ └── Phase 2(asyncio.create_task 后台执行,包在 request_wait_tracker.register_request / wait_for_request / cleanup 包络内,确保所有下游 enqueue 都被等待) ├── 读旧 WM: _get_latest_completed_archive_overview() ├── 有旧 WM? │ YES → ov_wm_v2_update prompt + tool_call │ → guards 检查每段决策 │ → _merge_wm_sections 段级合并 │ NO → ov_wm_v2 prompt 全量创建 ├── 写入 archive_NNN/.overview.md + .abstract.md + .meta.json ├── 提取 long-term memory(SessionCompressorV3,需 archive_uri 才能写 memory_diff.json) ├── 等待 embedding / semantic 队列排空(wait_for_request) └── 写入 .done(最后写,标志该 archive 全部状态终结)

Phase 2 的关键细节(均有源码对应):

  • 格式检测:读取旧 overview 后,先检查是否包含 WM 7 段 header(any(f"## {s}" in overview for s in WM_SEVEN_SECTIONS))。若是 legacy 格式,走创建路径而非 tool_call 更新,保证平滑升级。
  • Section reminders:更新路径中_build_wm_section_reminders()从旧 WM 提取每段当前状态摘要与尺寸告警,注入到 update prompt 的wm_section_reminders变量。
  • 完整回退链:tool_call 缺失 →_fallback_generate_wm_creation()重跑(传入旧 WM 作为上下文);JSON parse 失败 → 正则 recovery(_wm_recover_ops_from_raw()针对 VLM 后端包装非 JSON 参数、未转义字符、弯引号、截断 JSON 等场景做逐段恢复)→ 段级 guard 兜底 KEEP;VLM 不可用 → 占位 summary。
  • Phase 2 队列等待register_request+wait_for_request(timeout=_PHASE2_QUEUE_WAIT_TIMEOUT_SECONDS=1800s)是必需的——否则下游compressor/memory_updater通过register_*_root注册的 embedding / semantic 队列无人 await,会让tracker.complete().done在向量化 / 语义入库之前就触发,导致调用方看到 commit 完成但 memory 不可检索。

Phase 2 主循环对应 session.py 的_run_memory_extraction()

8.2 compact 流程(主动上下文压缩)

[插件] compact └── commitSession(wait=true, keepRecentCount=0) ├── Phase 1: 全部消息 → archive, messages.clear() ├── Phase 2: 读旧 WM → 创建/更新 → 写入 └── 返回 → getSessionContext → 回读最新 WM

与 afterTurn 的差异在于:wait=true同步等待完成;keepRecentCount=0表示 Phase 1 全量归档并清空 live messages,实现彻底压缩。

8.3 assemble 流程(上下文组装)

assemble 将上下文组织为 instruction / archive / session 三分区:

┌──────────── System Prompt ────────────────────┐ │ systemPromptAddition(语义示意,非逐字): │ │ 1. [Session History Summary] 是压缩摘要 │ │ 2. Active messages 是最新未压缩上下文 │ │ 3. 二者冲突时优先 active messages │ │ 4. 缺细节时询问用户,不要猜 │ │ + 原始 system prompt │ └────────────────────────────────────────────────┘ ┌──── Layer 1: Archive Memory (≤8K tokens) ─────┐ │ [user] [Session History Summary] │ │ # Working Memory │ │ ## Session Title │ │ ## Current State │ │ ## Task & Goals │ │ ## Key Facts & Decisions │ │ ## Files & Context │ │ ## Errors & Corrections │ │ ## Open Issues │ └────────────────────────────────────────────────┘ ┌──── Layer 2: Session Context ─────────────────┐ │ server 侧合并后的 ctx.messages: │ │ - 未完成 archive 的 pending messages │ │ - 当前 live session messages │ └────────────────────────────────────────────────┘ ┌──── Layer 3: Reserved (≥20K tokens) ──────────┐ │ LLM 回复空间 │ └────────────────────────────────────────────────┘

【免费下载链接】OpenVikingSelf-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.项目地址: https://gitcode.com/GitHub_Trending/op/OpenViking

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 2:18:39

SSM框架云借阅图书管理系统:从数据库设计到云部署实践

简介&#xff1a;一套基于SSM框架的云借阅图书管理系统完整源码包&#xff0c;内含项目源码和MySQL数据库脚本&#xff0c;面向Java Web初中级学习者和毕业设计者&#xff0c;重点解决图书借阅场景中的用户登录注销、新书推荐、图书借阅与借阅记录管理等核心业务&#xff0c;也…

作者头像 李华
网站建设 2026/9/10 2:17:17

多爆破工作面通风风量分配仿真:MATLAB实现多风机与风窗联合调节

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 2:16:34

AI网关:多模型统一接入、智能路由与治理控制中枢

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 2:16:32

用Verilog在FPGA上实现TCP代理:架构、序列号翻译与验证

简介&#xff1a;基于Verilog的TCP代理程序是一份面向FPGA开发与网络功能加速方向的高阶硬件设计资源&#xff0c;适合有Verilog基础并希望深入TCP协议栈硬件化的工程师、研究生或竞赛选手&#xff0c;用于解决软件TCP代理在CPU上的性能瓶颈&#xff0c;实现网络功能硬件加速。…

作者头像 李华
网站建设 2026/9/10 2:16:18

宫颈细胞检测模型:RetinaNet改进版与rank-aware损失实战

简介&#xff1a;本资源是一套面向医学图像分析初学者与AI医疗实践者的宫颈异常细胞检测完整实现方案&#xff0c;聚焦深度学习在早期宫颈疾病筛查中的落地应用。压缩包共25个文件&#xff0c;含20个核心Python源码&#xff08;涵盖RetinaNet、SE-ResNeXt等模型构建、数据增强、…

作者头像 李华
网站建设 2026/9/10 2:15:20

NPN环境下的数据传输安全:方案设计与实操指南

说到数据传输安全&#xff0c;很多朋友第一反应是加密算法、安全网关、权限控制这些零散概念。但真正做项目的人清楚&#xff0c;最怕的不是单项技术不够强&#xff0c;而是整套方案在架构层面就没想清楚。我最近在整理一个围绕NPN&#xff08;Non-Public Network&#xff0c;非…

作者头像 李华