ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Hindsight 0.4.15 版本解读:PydanticAI 持久记忆、Observation Scopes 与 Entity Labels 全面指南

Hindsight 0.4.15 版本解读:PydanticAI 持久记忆、Observation Scopes 与 Entity Labels 全面指南 Hindsight 0.4.15 版本解读PydanticAI 持久记忆、Observation Scopes 与 Entity Labels 全面指南【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsightHindsight 是一个会学习的 Agent 记忆系统Agent Memory That Learns核心能力是把对话与文档内容提炼为可检索的事实facts、实体entities与更高层的观察observations。0.4.15 版本带来了 PydanticAI 官方集成、可精细控制事实归并粒度的 Observation Scopes、支持受控词表的 Richer Entity Labels、面向无时间戳内容的 Timestamp Unset以及针对大规模记忆库10 万条记忆、1 亿实体链接级别的数据库级性能优化。读完本文你将掌握这五项新能力的完整配置方式、底层实现原理以及如何在真实业务如教育辅导、客服会话、参考文档管理中落地使用。PydanticAI Integration给 PydanticAI Agent 装上持久记忆0.4.15 的核心亮点是与 PydanticAI安装命令为pip install hindsight-pydantic-ai该包刻意只依赖pydantic-ai-slim不拉取全部模型提供商保持轻量。依赖要求为 Python 3.10、pydantic-ai-slim 1.0.0、hindsight-client 0.4.0且需要一个运行中的 Hindsight API 服务。最小接入示例from hindsight_client import Hindsight from hindsight_pydantic_ai import create_hindsight_tools, memory_instructions from pydantic_ai import Agent client Hindsight(base_urlhttp://localhost:8888) agent Agent( openai:gpt-4o, toolscreate_hindsight_tools(clientclient, bank_iduser-123), instructions[memory_instructions(clientclient, bank_iduser-123)], ) result await agent.run(What do you remember about my preferences?) print(result.output)本地开发时用base_urlhttp://localhost:8888指向本地服务对应仓库脚本scripts/dev/start-api.sh接入 Hindsight Cloud 时改为其 API 地址并传入api_key。create_hindsight_tools会为 Agent 注册三个异步工具在 tools.py 中实现全部基于 Pydantic AI 的 async tool 接口无线程池 hack工具名作用对应 APIhindsight_retain将信息写入长期记忆保存重要事实、用户偏好、决策等aretainhindsight_recall按查询检索相关记忆返回编号列表arecallhindsight_reflect基于记忆综合出有推理的回答而非罗列原始事实areflectmemory_instructions则是另一种注入方式它返回一个异步 callable在每次 Agent 运行时自动执行一次 recall把命中的记忆以Relevant memories:\n1. ... 2. ...的格式注入到系统指令里Agent 无需显式调用工具也能始终拥有相关历史上下文。由于 instructions 每次运行都会重新求值即使复用message_history记忆也保持新鲜且召回失败时静默返回空串不会阻塞 Agent 运行见 tools.py#L224-L245。两个函数可单独使用只想让 Agent 自主决定何时查记忆就只传tools只想自动注入不想暴露工具就只传instructions。按需选择工具与全局配置create_hindsight_tools支持通过include_retain/include_recall/include_reflect三个布尔参数选择工具子集默认全部包含tools create_hindsight_tools( clientclient, bank_iduser-123, include_retainTrue, include_recallTrue, include_reflectFalse, # 不需要 reflect 时省略 )也可以用configure()一次性设置全局默认值之后创建工具无需再传 clientfrom hindsight_pydantic_ai import configure, create_hindsight_tools configure( hindsight_api_urlhttp://localhost:8888, api_keyyour-api-key, # 或设置 HINDSIGHT_API_KEY 环境变量 budgetmid, # Recall 预算low/mid/high max_tokens4096, # Recall 结果的最大 token 数 tags[env:prod], # 写入记忆时附加的标签 recall_tags[scope:global], # 检索时过滤的标签 recall_tags_matchany, # 标签匹配模式any/all/any_strict/all_strict ) # 之后不再传 client使用全局配置 tools create_hindsight_tools(bank_iduser-123)在源码层面configure()的默认值通过 config.py 持有create_hindsight_tools内部用_resolve_client()按显式 client 全局配置的优先级解析客户端tools.py#L29-L50构造时传入的参数会覆盖全局配置。完整的参数默认值表可参见 README.mdcreate_hindsight_tools()budget默认mid、max_tokens默认4096、tags/recall_tags默认None、recall_tags_match默认anymemory_instructions()query默认relevant context about the user、budget默认low、max_results默认5、max_tokens默认4096、prefix默认Relevant memories:\n、tags/tags_match用于过滤召回结果configure()verbose默认False可开启详细日志。配套测试见 hindsight-integrations/pydantic-ai/tests/test_tools.py 与 test_config.py。Observation Scopes控制观察归并的粒度Observation观察是 Hindsight 中由原始事实facts归纳出的高层摘要。在 0.4.15 之前观察总是基于全部标签一次性归并现在可以通过 retain 请求中的observation_scopes参数精确控制每次归并的粒度。为什么这很重要考虑一条教学场景的记忆它带有三个维度的标签student:alice、teacher:bob、session-id:s1。你可能希望分别得到按学生按老师按会话的观察而不是三个标签组合在一起的单一观察——这样Alice 在哪方面吃力和Bob 怎么授课的这类问题才能各自命中正确的观察。下面以一条打了tags: [student:alice, teacher:bob, session-id:s1]的课程记录为例说明四种模式的行为差异。per_tag —— 每个标签单独归并每个标签独立做一次归并是多参与方内容最常用的选择产生观察[student:alice]、[teacher:bob]、[session-id:s1]命中What does Alice struggle with?按学生、How does Bob teach?按老师不命中How does Alice perform specifically with Bob?——没有为该组合建立观察在源码 consolidator.py#L611-L612 中per_tag被展开为[[t] for t in memory.tags]即每个标签对应一个单标签 scope。combined —— 全标签一次归并默认所有标签一起做一次归并这也是未指定参数时的默认行为产生观察[student:alice, teacher:bob, session-id:s1]只有精确的组合才能命中单独的[student:alice]等无法命中all_combinations —— 每个子集各归并一次对全部非空子集各做一次归并。3 个标签意味着 7 次归并3 个单标签 3 个双标签组合 1 个全量组合产生的观察 全部per_tagscope 每一对组合 完整集合源码实现为[list(c) for r in range(1, len(tags) 1) for c in combinations(tags, r)]consolidator.py#L613-L616即标准组合展开。custom —— 显式指定标签集合直接给出一份 tag 集合列表只构建列出的 scope[[student:alice], [teacher:bob], [teacher:bob, session-id:s1]]上面配置只产生这三个 scope不会多建任何其他组合。隔离性与并行安全各 scope 在归并时完全隔离——在[student:alice]下归并出的记忆绝不会泄漏进[student:alice, teacher:bob]的观察。在实现上consolidator.py#L624-L658 的_resolve_write_scopes把每个记忆将要写入的 scope 计算为 frozenset 集合并行调度器据此为每个 scope 获取一把锁使 scope 重叠的分组在重叠观察行上串行执行避免并发竞争。此外shared模式[[]]一个无标签的全局 scope可用来跨易变的每次调用标签如 session-id做去重同时保留源事实上的标签——这也是 0.4.15 新增的取值之一。完整字段定义见 types.py#L149-L151相关测试覆盖了 test_consolidation_write_scopes.py 与 test_consolidation_scope_parallelism.py。Richer Entity Labels受控词表的结构化实体提取entity_labels是新的银行bank级配置项用于定义一个key:value形式的受控分类词表。retain 过程中 LLM 会从每段内容里提取这些标签并存为实体。由于标签本身就是实体它们会自动把相关记忆在知识图谱中互相关联同时提升语义检索和 BM25 检索的效果。三种字段类型类型行为value从固定列表取单个值multi-values从固定列表取一个或多个值text自由文本无固定取值列表字段还可以标记optional: true当内容信息不足时 LLM 会跳过该字段。完整配置示例{ entity_labels: [ { key: engagement, description: Student engagement level during the session, type: value, optional: true, values: [ { value: active, description: Student is actively participating }, { value: passive, description: Student is listening but not participating } ] }, { key: pedagogy, description: Teaching strategies used, type: multi-values, values: [ { value: scaffolding, description: Breaking complex tasks into smaller steps }, { value: direct_instruction, description: Explicit explanation by the teacher }, { value: socratic_questioning, description: Guiding through questions rather than answers } ] }, { key: topic, description: Specific subject being discussed. Examples: algebra, quadratic equations, geometry., type: text, optional: true } ] }对枚举类型value、multi-valuesvalues列表之外的取值会被静默丢弃——词表保持稳定图谱链接保持紧密。对text类型LLM 可以写任意字符串因此要用description提供示例和引导。配置通过 bank config API 设置控制平面 UI 也已更新以清晰展示多值和自由文本标签。源码层面的约束机制在 entity_labels.py 中配置被解析为EntityLabelsConfig内含一组LabelGroup并通过build_labels_model()动态构造一个 Pydantic 模型用于结构化提取枚举类型会生成Literal[active, passive]这样的字面量约束字段optionalTrue的字段类型为Literal[...] | None而multi-values生成list[Literal[...]]——超出词表的取值正是被 Pydantic 的 Literal 校验静默拒绝的见 entity_labels.py#L176-L241。build_labels_lookup()会预构建一份小写的key:value集合用于 O(1) 快速判定某个实体是否属于标签实体entity_labels.py#L276-L305。值得补充的是源码实际支持五种类型——除文档中的三种外还有multi-text开放词表的多值自由文本和map递归的键值结构如person:address:city:...三级路径旧的free_values/multi_value字段也通过_migrate_label_group()自动迁移到新type字段保持向后兼容。此外LabelGroup还支持tag: true标志被标记的分组值会从事实的实体镜像投影到其 tags 数组相关逻辑见label_tag_keys()与split_label_tags()entity_labels.py#L308-L342。完整行为由 test_entity_labels.py 和 test_strict_schema_entity_labels.py 验证。Timestamp Unset保留无时间戳的永恒内容在记忆参考类内容文档、书籍等没有实际事件日期的材料时现在可以传timestampunset告诉 Hindsight 该内容没有真实的关联日期# 无时间戳的参考内容 client.retain( bank_idmy-bank, contentThe quick sort algorithm has O(n log n) average-case time complexity., timestampunset ) # 单个批次里混用有时间戳和无时间戳的内容 client.retain_batch( bank_idmy-bank, items[ {content: Meeting notes..., timestamp: 2026-03-01T14:00:00Z}, {content: Company handbook..., timestamp: unset}, ] )传unset时事实提取 prompt 中会显示Event Date: Unknown模型对每个提取事实的when字段正确地返回N/A而不会把事实锚定到某个任意日期上。这一点在源码中有直接印证事实提取的 schema 中when字段被描述为When it happened. N/A if unknown.fact_extraction.py#L264且 prompt 明确要求Write N/A ONLY if absolutely no temporal context existsfact_extraction.py#L382。同时 prompt 会以Event Date作为相对日期yesterday、last week的解析参考点fact_extraction.py#L1267-L1268因此当 Event Date 未知时模型不会拿今天当锚点去猜测日期。性能面向大规模记忆库的数据库级优化0.4.15 在数据库层做了大量面向大规模记忆库的工作更好的索引、改进的查询规划、降低锁竞争、死锁修复以及连接预热connection warmup改进。官方在最多10 万条记忆、1 亿实体链接的银行规模上进行了基准测试Retain大规模下最高快 10 倍Recall超大规模下最高提升约20 倍其中图检索graph与时间检索temporalretriever 的收益最大。这些优化无需任何额外配置升级即生效。它们与前述observation_scopes的按 scope 加锁调度consolidator.py#L1878-L1882共同构成了本版本大规模场景下的可靠性基础。其他更新功能与修复速览新功能OpenClaw auto-retainOpenClaw 现在每 N 轮默认 N10保留最近N*2 4条消息而不是每轮都保留。滑动窗口保证会话边界处的上下文不丢失同时显著减少每个会话的 LLM 调用次数。可在插件配置中用retainEveryNTurns调整。Gemini/Vertex AI 安全设置Gemini 与 Vertex AI 的 LLM 调用安全设置现在可配置便于需要放宽或收紧内容过滤的部署。文档标签过滤list documents API 现在支持按标签过滤便于查询某个标签下保留了哪些文档。扩展钩子Extension hooks新增用于定制根路由行为、添加自定义错误头的钩子服务于需要在传输层拦截请求或装饰响应的部署。Bug 修复修复大规模记忆库上 reflect 因context_length_exceeded失败的问题现在会正确截断上下文窗口修复僵尸处理任务重试导致的归并死锁修复控制平面中观察计数始终显示 0 的问题修复claude_codeLLM provider 的 JSON 序列化与日志相关异常传播问题修复 ZeroEntropy rerank 端点 URL修复 MCPasync_processing参数处理增加按银行bank隔离的请求校验防止跨银行操作修复 TypeScript SDK 在includeEntities为false时发送undefined而非null的问题。升级兼容性Hindsight 0.4.15 是 0.4.x 的无缝替换版本drop-in replacement无破坏性变更。升级后可立即使用上述新能力PydanticAI 集成hindsight-integrations/pydantic-ai/、observation_scopes参数、bank 配置中的entity_labels、timestampunset以及全部性能改进。详细的逐项变更清单可查阅仓库的 changelog 文档。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进