深度拆解 Hy Memory 2.0chat / working / coding 三类记忆如何在一套框架里共存【免费下载链接】Hy-Memory项目地址: https://gitcode.com/gh_mirrors/hy/Hy-Memory2026 年 10 月腾讯混元把 Hy Memory 2.0 整体开源hy-memory2.0.4上架 PyPI配套的 Hy-Memory-30B-A3B 记忆写入模型30B 总参数、仅激活 3B 的 MoE一并放出外加桌面/CLI 产品 MemHub 和 OpenClaw 插件模型、框架、应用三层全开源。社区最感兴趣的一点是它没有做大而全的一把梭记忆系统而是把记忆按任务切成了chat / working / coding三条管线却共用同一个HyMemoryClient入口、同一套写入/检索 API。这三类记忆的形态差异极大——聊天记忆是分层摘要与认知结构生产力记忆是事实经验双层卡片编码记忆还要能追溯被回滚的代码改了什么。它们凭什么能装进一套框架这篇文章基于仓库源码拆解三件事三条管线各自的记忆形态与边界、System 1 / System 2 双系统如何分工、以及官方给开发者留了哪些可编程钩子。一、先说结论三条管线一个入口数据完全分轨Hy Memory 把scene作为路由参数贯穿写入与检索README 中给出的边界定义是scene典型任务记忆形态chat闲聊、个人信息、偏好、一般问答L0–L7 分层记忆working文档、表格、研究、财经分析、内容创作、电脑操作双层记忆会话事实 可复用经验coding编码、调试、测试、构建、API/SDK、脚本、SQL与 working 同构的双层记忆 代码版本演进链关键设计是分轨而非融合working 与 coding复用同一套生产力 pipeline 和 schema但使用不同的抽取规范、独立的 SQLite 文件coding_memory.dbvscoding_memory_cv.db与向量集合数据不会混在一起。这个取舍在 docs/scene_coding_usage.md 中写得很直白两条链共享结构隔离靠存储与规范而不是靠一套万能 prompt。路由是怎么做的一个有界摘要三分类器写入时如果调用方不显式指定scene路由逻辑是输入没有 tool/tool_calls直接进 chat 管线零 LLM 调用输入含 tool 轨迹调用一次场景分类 LLM在chat / working / coding三选一中判定。分类器实现在 hy_memory/coding/judge.py它是一个 single-label 分类器且刻意只看一个有界视图——用户 query 工具名的摘要模块顶部用常量把输入框死_JUDGE_MAX_TURNS 20 _JUDGE_USER_CONTENT_LIMIT 1_000 _JUDGE_USER_CONTENT_HEAD 200 _JUDGE_USER_CONTENT_TAIL 200分类边界也写进了 prompt代码或开发产物是工作对象或实现媒介判 coding有明确生产力交付物但代码不是核心媒介判 working只用了 search/browser 类工具不会自动升格为 working。judge 失败或输出无法解析时回退 chat——这是一个偏保守的失败策略宁可少进一条结构化管线也不把噪声写进工作记忆。检索侧同理search_modedefault单 query 固定走 chat 轻量检索、零 LLMsearch_modeagentic才启用 LLM 三分类 query rewrite 时间范围解析而显式传scene时直接选路跳过一切 judge/rewrite。也就是说路由成本是可按需付费的高频低价值调用可以完全绕开 LLM。二、chat 管线八层记忆与双系统分工L0–L7原始对话如何被逐层抽象chat 管线是典型的长期个人记忆形态。记忆层枚举定义在 hy_memory/models/memory.py 中class MemoryLayer(str, Enum): L0_BASIC_INFO l0_basic_info # 基本信息 L1_RAW l1_raw # 原始对话 (Append-Only) L2_FACT l2_fact # 原子事实 (版本化不可变记录) L3_SUMMARY l3_summary # 会话摘要 ... L6_SCHEMA l6_schema # 心智模型 (抽象叙事模板, Graph 层) L7_INTENTION l7_intention # 前瞻意图 (带过期时间)从只增不改的 L1 原始对话到版本化原子事实 L2、会话摘要 L3再往上到图层的 SCHEMA心智模型与 INTENTION前瞻意图过期后降级为普通事实——每一层服务不同的检索粒度。读取侧也对应设计了分层视图画像摘要L0始终返回、索引视图~100 tokens、摘要视图~500 tokens、完整内容按需懒加载token 预算是显式管理的。System 1 / System 2即时写入与离线演化的双系统这是 Hy Memory 论文EMNLP 2026 收录的Memory Beyond Recall: A Dual-Process Cognitive Memory System的核心主张也是双系统认知架构的落点。代码里的分工非常清晰System 1 跑在add()路径上负责即时。hy_memory/agent/mem_agent.py 中的MemAgent统一调度 Extractor事实/实体提取与 Reflector反思。Reflector 的职责不是简单去重而是把新信息与已有信息的关系分类为OVERRIDE / SUPPLEMENT / TEMPORAL / NEGATE / CONFLICT五类更新类型并做冲突检测与隐式信号推断hy_memory/agent/reflector.py。L7 的意图抽取也是 System 1 在写入时即时完成的。System 2 跑在evolve()上负责慢思考。hy_memory/pipelines/system2_agent.py 的头注释说明了它的设计Phase 1 是硬编码预处理——从 VDB 取未处理事实、DBSCAN 聚类、图正向/反向查找Phase 2 才是 Agent LLM且只在聚类非空时触发散事实冷启动时不烧 LLM。evolve()的 API 语义值得单独看hy_memory/client.pydef evolve(self, user_id, agent_iddefault_agent, max_batchesNone): 手动触发 System 2 认知加工ultra 模式专用同步阻塞直到完成。 非幂等每次 evolve 看到的是当前 VDB 全量连续多次 evolve 有意义 add 一批 → evolve → 再 add 一批 → 再 evolve。 触发时机由调用方控制System 2 不在 add/write 里自动触发也无进程内队列。 仅 ultra 模式可调用。 注意两个工程细节System 2不自动触发节奏完全交给调用方——这把它从后台黑盒变成了可编程的批处理单元evolve是非幂等的每次扫 VDB 全量所以add 一批 → evolve → 再 add 一批 → 再 evolve是推荐的迭代模式。另外 Agent 单次处理的候选事实被_S2_MAX_FACTS_PER_BATCH 24限流防止 LLM 输出预算耗尽产出不可解析的 JSON。三档模式则把双系统做成了可降级的配置lite纯 embedding零 LLMscene/layers全忽略、pro LLM 提取 reconcile图谱可选、ultra System 2 schema 归纳 cross-domain sweeper图谱必开。三、working 管线事实层保证记下来经验层保证用得上working 管线的核心是一次会话 trace 同时产出两层记忆hy_memory/coding/types.py层记录什么数量策略结构Facts(WorkingFact)本次做了什么任务、做法、结果每 session 恰好 1 条无阈值statement,subject,files,detailsExperiences下次遇到同类任务可复用的方法0–N 条必须过价值门槛task,search_keys,solution,boundary_envs,confidence事实层无门槛、必落一条保证干过的事一定有迹可循经验层高门槛、宁缺毋滥boundary_envs记录经验依赖的环境、confidence给出置信度供消费方判断是否仍适用。两层互相链接fact.derived_experience_ids↔experience.source_fact_ids由同批全互链回填被覆盖的事实则通过 task 进展链fact_chain_summary保持可追溯。写入协调器 hy_memory/coding/writer.py 把整条链串起来模块注释本身就是流程文档extractor.extract(...) ← 一次 LLM 产出双层草稿 reconciler.reconcile(经验草稿) ← ADD/UPDATE/DELETE/SKIP fact_reconciler.reconcile(事实草稿) ← INSERT/SUPERSEDE _crosslink(...) ← 同批全互链回填其中有两处设计哲学值得注意。第一抽取时故意不给 LLM 看库里已有记忆writer 的注释解释把已有 task 摆在 extractor 面前它会把一个其实不同的任务往清单里某个措辞上靠随后被 reconciler 误判为 UPDATE 合并掉——措辞对不上顶多多存一条措辞被带偏是直接写错。去重/合并的判定权完全交给 reconcile 阶段抽取只负责忠实记录这一段发生了什么。第二历史窗口与本次输入严格分离store 回读最近 5 个 user-turn 仅作指代消解上下文LAST 5 USER TURNS本次add()的全部消息构成NEW MESSAGES抽取主体且历史在finally块中回写——即使本次没跨过价值门槛上下文也不能丢。四、coding 管线版本演进链一个装饰器不是检索器coding 与 working 的差异可以精确列成三条抽取规范不同subject 必须是代码或决策记录精确坐标而非粘贴代码、存储独立coding_memory_cv.db*_cv集合、以及独有版本演进链。而链的设计是整个 2.0 里最反直觉的一块hy_memory/coding/chain_store.py 的模块文档把它说得很透为什么必须存 diff而不是把 fact 写详细点因为抽取 prompt 是明文要求砍代码的——EXACT COORDINATES, NOT PASTED CODE硬上限约 200 汉字。这个取舍在通用场景下是对的200 字预算里一个feat/x分支 token 的价值远超 30 行 diff而且代码可以回去读。但前提有个洞被撤掉那版的代码读不回来——它不在工作区、不在 HEAD只在某次中间提交里。所以 chain_store 不改抽取 prompt 一个字而是零 LLM 地把每一版的真实 patch 存下来补的不是抽取质量是 LLM 摘要必然丢掉的那一类信息。它是装饰器不是检索器。向量层决定给哪几条 facttop-k、阈值、排序全归它chain 只负责每条 fact 后面跟什么把那条 fact 涉及的代码在这条分支上的全部改动版本每版的用户原话 每版真实 diff按顺序挂上去。不做相似度、不选版本、不猜哪版是最终答案——判定权交给指令本身。数据模型是两张表加一张辅助索引thread(id, owner, branch, file, symbol, lo, hi, n_rounds, updated_at) 一条 thread 某分支某文件某函数的某一块被反复改的历史 owner 隔离键 user_id|workspace_id round(id, thread_id, seq, said, patch, adds, created_at) 一条 round 一次改动seq 第几版 repo_symbol(name, path, line, kind) 全仓 AST 索引只用于定位不参与分链几个值得细看的工程决定seq是 observe() 的第几次调用纯计数。不做 diff 间比对、不推断谁覆盖谁第 1 版就是第一次调用物理事实——不存在猜错的可能。thread 键三级降级hunk header 带函数名 →(owner, branch, file, symbol, 行区间)只有上下文文字 → 降到文件行区间聚类而不是直接降到文件粒度否则同文件所有改动会挤成一条十几版的长链裸 hunk → 文件粒度。且明确不用AST 索引按行号反查补符号因为patch 里的行号是改后的、索引是改前建的会系统性偏一个符号。失败闸门从对话里合成path/old/new替换操作时必须检查编辑是否真的成功AssertionError、old not in、returncode1等正则判失败REPLACED 1等判成功否则agent 只是提议改法但用户拒绝了的失败版本也会进链——链是哪一版赢了的唯一依据掺一个没生效的版本进去agent 可能照着写。注入预算全是显式常量MAX_SAID_CHARS800每版原话、MAX_BLOCK_CHARS14000整块、TOPN_THREADS3、TOPN_FACTS1……注释反复强调一个原则原话是这个机制的核心信息宁可少挂一条链也不把它压短因为同一条链上各版原话的开头往往相同真正区分版本的词常在后段。改动来源只有两个确定性入口本地 Git diff配置MEMORY_CODING_CHAIN_REPO_ROOT或工具 trace 里带path/old/new的确定性替换动作。检索时返回结构里scenecoding会额外带出chain_block与已召回 fact 对齐的版本演进上下文无法挂链时为空串和chain_used字段。五、开发者钩子官方把哪些旋钮留给了你抛开单条管线可编程记忆真正体现在 API 与配置面上。梳理 hy_memory/client.py 的公开接口写入面。add()的参数就是一组正交的隔离/路由维度user_id / agent_id / session_id三级隔离键source如openclaw / cursor / codex与agent_id正交用于隔离不同调用方应用——这是10 款 AI 工具共享同一份记忆但可分源治理的底层支撑检索端用include_sources / exclude_sources过滤scene / workspace_id / branch控制管线路由与 coding 作用域memory_at支持导入历史记忆并指定时间戳meta是业务透传字段不 embed、不参与召回、不作过滤写入时存为 list同一节点多次写入会追加而非覆盖查询时原样返回embed_override支持单次调用级别切换 embedding 端点或用with embed_endpoint_override(...)上下文并发安全切换。读与治理面。search()返回结构按场景分形chat 返回memoriesprofile/normal/proactive 通道 schema_min_score、intention_limit等分层预算working/coding 返回facts/experiences双层 coding 专属chain_block且两层可分别用working_fact_min_score/working_experience_min_score设阈值。get / update / delete / list_memories构成 CRUDevolve()与sweep()仅 ultra 模式可用是显式的 System 2 触发器finalize_session()可以把一个会话固化为一等公民的 episode 叙事opt-in。存储与模型面。向量层兼容 ChromaDB默认/ Qdrant / FAISS图层 Kuzu默认/ Neo4j缓存可换 MySQL全部通过 pip extras 安装hy-memory[qdrant]、hy-memory[graph]……配置只需一对 OpenAI 兼容的 LLM embedding 端点。所有行为细节历史轮数、tool 结果截断字节数、chain 预算等都是环境变量见 docs/env_reference.md 与 docs/scene_coding_usage.md。集成面。仓库里的 plugins/openclaw/ 插件暴露memory_search / memory_add / memory_get / memory_update / memory_delete五个工具并提供 Auto-Recall每轮 agent 前自动注入相关记忆、Auto-Capture每轮后自动存关键事实、自动拉起本地 Python 服务三种托管能力memhub/ 则把 Claude Code、Cursor、Codex、OpenCode、Qwen Code 等应用的会话历史与编码 trace 统一进一个本地数据目录做跨应用受控召回。SDK 内部每个阶段judge/extract/reconcile还有统一的 pipeline log 落库store_pipeline_log记录 prompt、response、token、耗时排查为什么这条记忆没被写进去时有据可查。六、一点观察为什么是分轨而不是大一统把三条管线放在一起看Hy Memory 2.0 的选择其实很克制它没有试图用一套 schema 覆盖所有记忆而是承认三类任务的记忆形态根本不兼容——个人事实要的是演化分层抽象 冲突调和生产力经验要的是复用高门槛 边界环境代码决策要的是可追溯被回滚的版本必须能读回来。框架层真正统一的是一个客户端入口、一套 scene 路由协议、一组隔离键user/agent/session/source/workspace/branch、以及路由与加工成本可按需付费的降级策略lite 模式零 LLMjudge 失败回退 chat。这也解释了它论文层面的两个锚点EMNLP 2026 的双系统认知记忆论文chat 侧和已提交 ICLR 2027 的 CMB benchmarkdocs/papers/ 目录内有全文针对长时程交织编码 agent 的记忆评测coding 侧。配合 30B-A3B 的记忆写入专用模型用归因强化学习训练专注高精度抽取与冲突调和框架开源 专用模型 评测集算是把这条路线的三块拼图都放出来了。对想给 agent 加长期记忆的开发者来说值得动手的不是它的宣传口径而是 docs/usage.md 里那几张路由与返回结构表——它们定义了这个框架真正的能力边界。【免费下载链接】Hy-Memory项目地址: https://gitcode.com/gh_mirrors/hy/Hy-Memory创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?