
Hindsight 深度指南Agent Memory 到底是什么——从 Retain 到 Recall 的记忆系统设计与源码实现【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight理解Agent 记忆应该从工作流入手而不是从术语入手。Agent memory 一词被用得很松散有时指向量库有时指摘要缓冲区有时只是更长的提示词。Hindsight 给出的定义更简单也更可操作Agent 记忆是决定保留什么、如何结构化、未来任务需要时如何取回的系统。读完本文你将掌握判断记忆系统好坏的评估框架并深入 Hindsight 的 retain/recall 双 API 及其背后的四路并行检索实现理解一个能留存、能取回、能装回上下文的记忆层在源码层面是如何落地的。快速结论Agent Memory 的三句话定义Agent memory 不止是存下来的文本它是保留retain 取回recall的完整闭环。有用的记忆系统会保留事实facts、实体entities、决策decisions和时间timing。目标不是记住一切而是记住对的事情。这三句话是后文所有内容的总纲Hindsight 的 retain API 文档 回答如何保留recall API 文档 回答如何取回而 memory_engine.py 中的retain约 L5179与recall约 L7184两个入口方法则是这套设计的代码实体。为什么这个问题在生产环境中如此重要很多团队在拥有词汇表之前就意识到了这个问题Agent 在单次会话中表现得很有能力到了下一次会话却变得出奇地脆弱。这通常意味着系统依赖的是提示词状态prompt state而不是持久记忆。这也是为什么从演示走向生产工作流时临时上下文与持久记忆的区分如此关键。一个实用的记忆设计让 Agent 能够复用过往工作而不用把整个过去拖进每个提示词。这正是构建者在以下场景选择 Hindsight retain API 来存储持久信号、用 recall API 让系统事后恢复正确上下文的原因——同样的模式也出现在 Claude Code 集成、OpenClaw 集成 等实战示例中例如 为 Codex 添加 Hindsight 记忆 这篇博客演示了记忆如何改变日常开发工作流。常见失败模式什么样的记忆名不副实把检索器retriever叫成记忆即使它只会返回模糊相似的文本块。聊天记录不断变长但事后什么都变得更容易取回不了。系统存了信息但没人能预测它会取回什么。这些失败单独看都不大但会层层叠加一点点的遗忘变成反复的重新教学onboarding反复重新教学变成返工rework返工最终变成信任下降——因为用户不再相信 Agent 能把关键上下文带过去。这三条失败模式恰好对应了 Hindsight 架构中的三个设计决策可以逐条对照失败模式Hindsight 的对应设计仓库证据只返回模糊相似块语义 BM25 图 时间四路并行检索再融合重排而不是单一相似度查找retrieval.py记录增长但不可取回retain 时由 LLM 抽取结构化事实、实体并构建知识图谱而非存原文retain.mdx不知道会取回什么recall 支持按 fact typeworld/experience/observation、tags、时间窗精确控制响应里是结构化事实而非原始文档recall.mdx更好的记忆层应该做什么更好的设计是选择性的它不试图永远保存每个 token而是聚焦那些能改进未来工作的信号并在关键时刻让它们可被恢复。好的系统通常包含四个要素明确的保留规则——什么值得持久化多路检索策略——而不是一次相似度查找实体、关系与时间上下文的支持运维可见性——能看到存了什么、为什么被取回。这就是为什么架构比标签重要一个产品可以宣传记忆却表现得像挂了个搜索的长提示词。有用的系统必须留存得好retain well、取回得好retrieve well、并把结果干净地装回活跃上下文。下面两节用 Hindsight 的真实实现逐条印证这四个要素。要素一明确的保留规则——retain 不是存文本而是抽取记忆Hindsight 的 retain 流程的核心事实是原文不会被逐字存储存的是 LLM 从内容中抽取的结构化事实。一次 retain 调用接收一个或多个 item一段对话、一份文档、一条笔记Hindsight 对内容分块、逐块送 LLM 做事实抽取最终把 unstructured 信息转成可查询的结构化记忆。几个关键参数的设计值得展开完整参数说明见 retain API 文档content唯一必填原始文本。内容量决定产出多少条记忆——一段content可以产生多条记忆。timestamp内容描述的事件实际发生的时间。三种形态缺省/null表示取摄入时间ISO 8601 字符串表示显式时间unset表示不存任何时间戳适合参考文档、书籍等无真实事件时间的材料。时间戳会被注入 LLM 事实抽取提示词让模型能解析上周一这类相对时间引用提供真实时间戳还能让What happened last spring?这类时间性查询正确工作。context来源或场景的短标签如team meeting、slack。它直接注入抽取提示词主动塑造事实抽取结果——同一句话 the project was terminated 在performance review与product roadmap语境下会产出不同的记忆。持续提供 context 是提升记忆质量中杠杆率最高的动作之一。metadata任意字符串键值对如{source: slack, channel: engineering}。它既进抽取提示词辅助 LLM也随每条记忆存储并在每次 recall 时原样返回支持客户端过滤与静态富化如把记忆链回源 URL。document_idupdate_mode这是让 retain幂等的关键。提供document_id时执行 upsert——旧文档及其全部记忆先删除再重新处理因此对话增长后可以用document_id重复 retain 而不积累重复记忆。update_mode有两个值replace默认整删整建与append把新内容拼接到现有文档尾部重新处理delta 机制自动跳过未变化块只有新增部分触发 LLM 抽取——后者正是日志、日记、逐条到达的聊天记录这类增量内容的正确用法。entities/resolve_entities显式指定必须被识别的实体列表与 LLM 自动抽取的实体合并。默认情况下传入的实体会与库中已有实体做解析resolve——基于名称相似度加共现强度做合并这正是Dr. Waller和Dr Waller最终成为同一实体的机制当你传入的名称是权威数据如手工纠错时必须原样存储时可设resolve_entities: false。tags/document_tagstags 控制可见性作用域——记忆只在 tags 与 recall 请求的 tags 过滤有交集时才会被返回。这让单个 memory bank 可以服务多个用户/会话各自只看得到自己的记忆。常见命名约定user:id、session:id、room:id、topic:name。observation_scopes控制这些记忆参与巩固consolidation时生成哪些作用域的 observations。combined默认用全部 tags 做一次巩固产出的 observation 打上完整 tag 集shared则让不同 tags 的记忆汇入同一个无 tag 的全局 observation天然去重易变的 per-call 标签如每次会话唯一的session-id:…。从源码结构看这一整套保留逻辑集中在 memory_engine.py 的retain/retain_async/retain_batch_async方法族中约 L5179 起而巩固阶段由 consolidation 模块 在后台异步完成——这与 recall 文档中observations 在 retain 操作后由后台自动创建和维护的说明相互印证。要素二多路检索 实体/时间支持——recall 的四路并行架构recall 一侧的设计直接回答了多种检索策略而不是一次相似度查找。recall API 文档 明确写道recall 会并行执行四种检索策略——语义相似度、关键词BM25、图遍历、时间感知——然后融合并重排为单一排序列表响应里是结构化事实不是原始文档。这一声明在源码中可以得到逐字印证。retrieval.py 的模块 docstring 就是这份设计清单1. Semantic retrieval (vector similarity) 2. BM25 retrieval (keyword/full-text search) 3. Graph retrieval (via pluggable GraphRetriever interface) 4. Temporal retrieval (time-aware search with spreading)四路结果汇入 fusion.py 做融合再经 reranking.py 用 cross-encoder 重打分——文档中raw query 会被传给 cross-encoder reranker 对每个候选重新打分描述的正是这条链路图检索的时间解析与扩展分别落在 graph_retrieval.py 与 temporal_extraction.py 中。recall 的关键参数同样值得理解其设计意图query唯一必填一条自然语言查询同时驱动全部四路——被向量化用于语义检索、被分词用于 BM25、被用作图遍历种子、被解析出时间表达式超过 500 token 的查询会被拒绝。types控制搜索哪类记忆事实——world客观事实、experience事件与对话、observation从多条记忆巩固出的去重、有证据支撑的信念。每种 type 独立跑完整四路管线因此收窄types既缩小结果集也降低查询成本。prefer_observations同时召回observation与world/experience时同一信息可能以原始事实和已并入 observation两种形态重复出现。开启后由某条原始事实构建的 observation 会取代该原始事实空出的名额由次优结果回填——默认关闭按需开启。budget检索深度与广度low/mid默认/high。max_tokens默认4096。按事实文本的相关性顺序填充直到预算耗尽超长的单条事实会被跳过而不是截断。一个值得注意的边界行为只要查询命中了东西就绝不会返回空列表——哪怕 top 事实超出预算也会整条返回因为空结果会被误读为这个库没有相关记忆而截断的事实则是记忆从未做过的陈述唯一例外是max_tokens0表示有意只要 chunks。query_timestamp查询方视角的现在用于解析查询中的相对时间表达并作为近因recency打分锚点——重放历史对话或构建时间锚定召回时最关键。temporal_window显式{ start: ..., end: ... }时间边界。它是排序信号而非过滤落在窗内、按记忆自身事件日期计算的记忆会被提升排名但窗外结果仍会返回。注意它替代的只是日期抽取query_timestamp仍负责近因打分两者可并存。这里体现的实体、关系与时间支持正好补全了开篇三句话定义中的后两条retain 阶段抽取实体与时间戳recall 阶段用图遍历与时间检索把它们取回来。要素三与四结果装回上下文 运维可见性把结果干净地装回活跃上下文对应的是 recall 的 token 预算设计max_tokens默认 4096只统计事实text字段——Hindsight 是为以 token 思考的 Agent 而设计的你把max_tokens设为你愿意分配给记忆的上下文窗口份额即可而不需要理解返回几条这种人类计数。运维可见性则体现在recall 响应返回的是带 metadata、tags、实体引用的结构化事实因此 retain 时传入的metadata会原样回来供客户端过滤tags 侧银行还提供 list-tags 端点返回全部 tag 及各自的记忆计数可用于 UI 自动补全或通配展开。典型适用工作流以下场景最能体现记忆系统与长提示词搜索的差距需要跨会话连续性的 Agent——下一次会话不重新教学直接取回上次建立的实体、决策与时间线跨工具共享记忆的团队——一个 memory bank 通过 tags 作用域如user:id、topic:name服务多个工具/成员各取所需需要在数周乃至数月尺度上适应用户的助手——这正是observation类型的用武之地偏好、重复模式、持久性学习被巩固为去重的信念并在新证据到来时被精炼而非覆盖。仓库中可深入阅读的实战示例包括 为 Codex 添加 Hindsight 记忆 这篇博客以及 Claude Code 集成 与 OpenClaw 集成 两个集成目录。如何评估你自己的记忆栈五步评估框架原文档给出的评估框架简洁且可直接执行建议在引入任何记忆方案包括 Hindsight之前先跑一遍识别一件事Agent 应该明天记住的、今天学会的信号是什么判断归属这个信号属于个人记忆、项目记忆还是共享记忆验证可保留系统能否有意地intentionally保留它——在 Hindsight 中这意味着选择合适的context、tags、observation_scopes而不是无差别灌入验证可取回它能否在正确的后续工作流中回来——对应 recall 时types、tags 过滤、temporal_window是否能精确命中验证足够简洁召回的上下文是否有帮助而不是干扰——对应max_tokens预算下返回的是精炼的结构化事实而非原始文档转储。记忆系统只有在存储与召回模型清晰到可以检查inspect时才容易建立信任。这正是 retain API 文档 与 recall API 文档 逐参数写明行为含边界情况的价值所在。FAQ向量数据库够格算记忆吗它可以是记忆的一部分但很少是完整系统。单路向量相似度查找解决不了精确实体匹配交给 BM25/图与时间语义交给 temporal 检索——这从 retrieval.py 的四路设计就能看到为什么。记忆是否必须意味着知识图谱不。关键在于系统能否保留并取回有用的结构而不是它使用了哪一种特定存储模型。Hindsight 的图检索通过可插拔的GraphRetriever接口实现见 graph_retrieval.py存储模型是可替换的实现细节。为什么定义本身这么重要因为不同架构解决不同问题含糊的措辞会掩盖真实的权衡。把Agent memory等同于向量库就会在选型时看不到保留规则、取回策略与上下文预算这些真正的差异点。小结Agent memory 保留 取回的闭环不是更长的提示词或单纯的检索器好的记忆层要选择性留存retain 抽事实、建实体与时间锚点、多路取回recall 四路并行 融合重排、并按 token 预算干净地装回上下文用五步评估框架对照自己的栈识别信号 → 判断归属 → 验证可保留 → 验证可取回 → 验证召回足够简洁继续深入retain 参数详解、recall 参数详解、检索实现源码、记忆引擎。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考