
为 Haystack Agent 接入 Hindsight 持久记忆三个即插即用 Tool 与自动召回包装器实战指南【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight本篇技术指南围绕hindsight-haystack集成包展开讲解如何为 deepset Haystack 的Agent组件加上跨会话的长期记忆能力。文中会覆盖两种集成模式由 Agent 自主调用的三个 Tool以及HindsightMemoryWrapper的自动召回/自动存储并结合仓库源码深入剖析 retain / recall / reflect 三个记忆原语、全局配置、序列化与事件循环桥接等实现细节读完即可在自己的 Haystack 应用中落地一套可跨会话、可跨工具共享的持久记忆。为什么 Haystack Agent 需要持久记忆Haystack 是 deepset 开源的生产级 LLM 应用框架覆盖 pipelines、agents、RAG 等完整技术栈。其Agent组件在单次会话内表现良好它会把消息历史携带到整个 run 中聊天模型可以从上下文中读取这些历史。但它有一个本质限制——跨 run 无状态。一旦一次agent.run()结束下一次调用只会从你传入的messages开始除此之外什么都不记得。对于一次性 RAG 端点这种无状态不是问题但对于需要跨会话记住用户偏好的客服助手、需要持续积累已知问题修复方案的支持系统、或者需要数周时间逐步构建项目认知的研究型 Agent你就需要一个能活过单次 run 的存储层。这正是hindsight-haystack集成要填补的空白。该集成的完整实现位于仓库的 hindsight-integrations/haystack 目录包名为hindsight-haystack当前版本 0.1.1依赖haystack-ai2.12.0与hindsight-client0.4.0要求 Python 3.10见 pyproject.toml。两种集成模式总览hindsight-haystack提供两个入口覆盖了团队接入记忆的两种典型方式create_hindsight_tools()返回一个list[Tool]把它传给任意 HaystackAgent由 Agent实际上是模型决定何时调用HindsightMemoryWrapperToolset子类带auto_recall与auto_retain开关。使用toolset.run(agent, ...)后记忆工作会在每一轮turn前后自动执行。两种模式共享同一套记忆原语retain存储、recall搜索、reflect综合。并且都可以通过include_retain/include_recall/include_reflect参数单独裁剪工具面。从源码看二者的工具构建逻辑完全一致——HindsightMemoryWrapper.__init__内部同样调用_build_tools()来生成工具见 tools.py只是额外叠加了自动行为。模式一由 Agent 自主决策调用工具create_hindsight_tools()返回一组 HaystackTool实例你将其传给Agent(tools...)模型根据工具描述与用户请求自行决定何时调用from hindsight_client import Hindsight from hindsight_haystack import create_hindsight_tools from haystack.components.agents import Agent from haystack.components.generators.chat import OpenAIChatGenerator from haystack.dataclasses import ChatMessage client Hindsight(base_urlhttp://localhost:8888) tools create_hindsight_tools( clientclient, bank_iduser-123, missionTrack user preferences, ) agent Agent( chat_generatorOpenAIChatGenerator(modelgpt-4o-mini), toolstools, system_prompt( You are a helpful assistant with long-term memory. Use retain_memory to store important facts. Use recall_memory to search memory before answering. ), ) result agent.run(messages[ChatMessage.from_user(Remember that I prefer dark mode)]) print(result[messages][-1].text)默认你会得到三个工具retain_memory、recall_memory、reflect_on_memory。系统提示词负责告诉模型每个工具何时触发。这种模式适合需要显式控制的场景模型只在有意义的轮次调用记忆无关轮次直接跳过。代价是模型必须记得去用这些工具——在负载较重的提示词下较弱的模型有时会忘记。从源码看这三个工具的定义集中在_TOOL_DEFS字典中tools.py每个工具都带有一段面向模型的中文式描述和单参数content/query的 JSON Schema这正是模型进行工具路由的依据。模式二HindsightMemoryWrapper自动记忆HindsightMemoryWrapper是Toolset子类它接管记忆生命周期让 Agent 无需操心。auto_recallTrue时每一轮开始前会把相关记忆注入系统提示词auto_retainTrue时每一轮结束后会把用户与助手消息存储起来from hindsight_haystack import HindsightMemoryWrapper toolset HindsightMemoryWrapper( clientclient, bank_iduser-123, missionTrack user preferences, auto_recallTrue, # 每轮开始前把记忆注入系统提示词 auto_retainTrue, # 每轮结束后存储 user assistant 消息 ) agent Agent( chat_generatorOpenAIChatGenerator(modelgpt-4o-mini), toolstoolset, system_promptYou are a helpful assistant with long-term memory., ) # 使用 toolset.run() 而不是 agent.run() 才能触发自动行为 result toolset.run(agent, messages[ChatMessage.from_user(I prefer dark mode)])一个关键细节必须调用toolset.run(agent, ...)而非agent.run(...)自动召回/存储才会生效。wrapper 用前轮后轮的记忆工作包裹了 agent 的 run绕过 wrapper 就等于绕过了自动化。三个显式工具仍然挂在 agent 上所以模型在轮次中途也可以主动调用它们实现更细粒度的控制比如用reflect_on_memory回答需要综合的问题。这种模式适合希望记忆开箱即用、不依赖模型工具路由能力的场景。三大记忆工具详解无论选择哪种模式可用的都是同一套三个工具。其底层行为由_HindsightToolBackend实现tools.py每个工具调用都会走_ensure_bank()→ 构建请求参数 → 调用hindsight_client的异步方法这条链路。retain_memory把自由文本内容存入 bank。Hindsight 会在调用返回后异步做结构化事实抽取因此工具返回很快抽取发生在服务端。源码中该方法调用aretain()失败时返回以Failed to store memory:开头的错误字符串而不是抛异常保证 Agent 能继续运行。默认会为每条内容自动生成document_id格式为{session_id}-{uuid_hex_12}见 tools.py。recall_memory在 bank 中搜索与查询相关的内容返回带编号的排序记忆列表。budgetlow/mid/high控制搜索深度。源码中_format_recall会把结果格式化为1. ...\n2. ...的编号文本空结果返回No relevant memories found.tools.py。它同时支持max_tokens限制返回内容长度、tags/tags_match过滤、typesworld/experience/observation三类事实过滤以及include_entities开关。reflect_on_memory让 Hindsight 在 bank 之上用 LLM综合一段答案而不是返回原始记忆。适合关于 X 我们知道些什么这类希望得到一段连贯文字、而非五条零散片段的提问。它额外支持reflect_context补充上下文、reflect_max_tokens默认回落到max_tokens、reflect_response_schemaJSON Schema 约束结构化输出设置后返回json.dumps(structured_output)与reflect_tags/reflect_tags_match默认回落recall_tags。可在构造时按需裁剪工具面# 只要 retain recall不要 reflect tools create_hindsight_tools( clientclient, bank_iduser-123, include_reflectFalse, )同样的标志也存在于HindsightMemoryWrapper上include_retain、include_recall、include_reflect三者默认均为True。单元测试 tests/test_tools.py 覆盖了只保留单个工具、全部排除等各种组合。全局配置与参数速查对大多数应用而言连接设置是全局统一的。configure()一次性设定默认值之后每次create_hindsight_tools()或HindsightMemoryWrapper()只需传bank_idfrom hindsight_haystack import configure configure( hindsight_api_urlhttp://localhost:8888, api_keyyour-api-key, budgetmid, tags[source:haystack], contextmy-app, missionTrack user preferences, ) # 现在 bank_id 是唯一必填参数 tools create_hindsight_tools(bank_iduser-123)你也可以在需要按租户路由或自定义 HTTP 设置时显式传入已配置好的client一个Hindsight实例。配置由 config.py 中的HindsightHaystackConfigdataclass 承载全局配置通过configure()/get_config()/reset_config()管理。下面是结合源码整理出的完整参数速查表create_hindsight_tools()与HindsightMemoryWrapper构造参数一致参数类型默认值作用bank_idstr必填记忆 bank 路由键决定记忆归属clientHindsightNone已配置客户端优先使用hindsight_api_urlstrhttps://api.hindsight.vectorize.ioAPI 地址未传 client 时使用api_keystrenvHINDSIGHT_API_KEY认证密钥未传 client 时使用budgetstrmidrecall/reflect 搜索深度low/mid/highmax_tokensint4096recall 结果最大 token 数tagslist[str]Noneretain 存储时打的标签recall_tagslist[str]Nonerecall 搜索时过滤的标签recall_tags_matchstrany标签匹配模式any/all/any_strict/all_strictretain_metadatadict[str, str]Noneretain 操作的默认元数据retain_document_idstrNone显式 document_id默认自动生成retain_contextstr配置的context默认haystackretain 的来源标签recall_typeslist[str]None事实类型过滤world/experience/observationrecall_include_entitiesboolFalserecall 结果是否附带实体信息reflect_contextstrNonereflect 的额外上下文reflect_max_tokensint回落max_tokensreflect 结果最大 tokenreflect_response_schemadictNone约束 reflect 输出的 JSON Schemareflect_tags/reflect_tags_matchlist[str] / str回落recall_tagsreflect 记忆过滤missionstrNonebank 使命用于事实抽取上下文include_retain/include_recall/include_reflectboolTrue是否包含对应工具auto_recallboolFalse每轮前自动召回并注入系统提示词auto_retainboolFalse每轮后自动存储消息max_recall_resultsint10自动召回注入提示词的最大记忆条数memory_prompt_templatestrDEFAULT_MEMORY_PROMPT记忆注入模板须含{memories}占位符其中自动记忆的注入模板默认值为Below are relevant memories from previous conversations:\n{memories}\nUse these memories to provide more personalized and contextual responses.tools.py你可以通过memory_prompt_template自定义措辞。配置的解析优先级从源码看参数解析遵循显式参数 全局配置 内置默认值的 None 哨兵回退链tools.py显式传入的参数优先否则读取configure()设置的全局配置get_config()最后使用内置默认值如budgetmid、max_tokens4096、recall_tags_matchany、contexthaystack。api_key的解析链还要再深一层configure(api_key...)未指定时会读取HINDSIGHT_API_KEY环境变量config.py。resolve_client()_client.py在未传client时会依次尝试显式 URL/Key → 全局配置 → 环境变量 → 默认 Cloud URL并将timeout30.0与user_agenthindsight-haystack/version一并注入。测试 tests/test_config.py 与 tests/test_tools.py 分别验证了环境变量、全局配置、显式参数覆盖这三层优先级。安装与运行环境准备你需要一个 Hindsight 账户与 API key。官方推荐 Hindsight Cloud 作为最快路径注册账号免费额度足够端到端试跑创建 API key格式为hsk_...让客户端指向 Cloudfrom hindsight_client import Hindsight client Hindsight( base_urlhttps://api.hindsight.vectorize.io, api_keyhsk_your_key, )也可以在configure()上一次性设置 URL 与 key之后省略显式 client。自托管路径完全一致把base_url指向本地实例通常是http://localhost:8888即可。仓库中提供了多套自托管部署方案例如 docker/docker-compose 下的编排文件以及 hindsight-api 的 Python 服务实现。安装集成包本身只需pip install hindsight-haystack仓库内的 README.md 提供了与博客一致的 Quick Start 示例可作为快速上手参考。源码深潜序列化安全与事件循环桥接为了让集成在生产中真正可靠源码里有几处值得展开的工程细节。工具序列化与 API key 防泄漏Haystack pipeline 常被 dump 成 YAML 用于检查、checkpoint 或共享。_HindsightTool重写了to_dict()/from_dict()将工具配置bank_id、API URL 等序列化下来而不是序列化绑定方法tools.py。关键设计是_build_backend_kwargs()中api_key被刻意排除在序列化之外tools.py如果 key 被写入序列化字典就会泄漏到每一次 YAML dump 中。反序列化时resolve_client()从HINDSIGHT_API_KEY环境变量重新读取 key因此重新部署的 pipeline 从宿主环境而非 YAML 中取回密钥。测试 tests/test_tools.py 专门验证了序列化字典中不出现 api_key 字面量反序列化后从环境变量取回 key这一行为。持久事件循环桥接 aiohttp 会话hindsight_client的异步方法aretain/arecall/areflect必须被 await但 Haystack 的Tool要求同步可调用对象。为此 tools.py 在后台守护线程中维护了一个持久事件循环通过run_coroutine_threadsafe提交协程并阻塞等待结果。这个设计不是随意为之aiohttp 会把 session 绑定到创建它的那个事件循环而asyncio.run()每次都新建并关闭一个临时循环会导致后续调用时 aiohttp 失效。保持单循环常驻才能让多次调用复用同一个 session。_run_sync同时兼容调用方不在事件循环中与调用方正处于运行中的事件循环如 Haystack 的 agent 运行时两种上下文TestRunSync测试类tests/test_tools.py对这两种路径都做了验证。模块自建的客户端即调用方未传client时会在atexit钩子中于后台循环上关闭避免退出时出现 Unclosed client session/connector 警告调用方自有的客户端则由调用方自行负责关闭tools.py。Bank 的惰性创建与幂等处理当传入mission时工具首次实际调用会通过_ensure_bank()创建/更新 banktools.py。创建逻辑是幂等的遇到 already exists、409 Conflict 等错误时直接标记为已初始化遇到瞬时错误则不标记下次调用会重试。测试 tests/test_tools.py 验证了首次调用创建 bank 且只创建一次无 mission 时不创建 bank等行为。未传mission时则完全跳过 bank 创建。自动召回/自动存储的实现细节HindsightMemoryWrapper.run()的执行顺序为tools.pyauto-recall从消息列表中提取最后一条用户消息文本_extract_last_user_text以其为查询执行 recall结果按max_recall_results默认 10截断后用memory_prompt_template拼装成记忆块追加到基础系统提示词之后——基础提示词取显式传入的system_prompt未传则回落 Agent 自身的system_promptagent 执行用增强后的系统提示词调用agent.run()auto-retain把用户消息与 agent 的last_message若为 assistant 且有文本分别 retain 到 Hindsight并在 metadata 中合并role与source: haystack标记便于后续区分回忆来源。run_async()是对应的异步版本复用同一套持久事件循环桥行为与同步版一致tools.py。max_recall_results的存在是为了防止提示词无限膨胀——测试 tests/test_tools.py 验证了 20 条记忆只会注入前 3 条。端到端测试 tests/test_e2e.py 则展示了如何对接真实 Hindsight 服务并轮询等待异步事实抽取完成_recall_until_nonempty。权衡与最佳实践模式选择是有意义的。纯工具模式让 Agent 保持控制权在记忆无关的轮次省下一次 Hindsight 调用自动模式更可靠每轮都召回与存储但每次轮询会多出 Hindsight 调用且首 token 延迟略增。对于高价值的生产级助手自动模式通常是更稳妥的默认选择对于低成本的 RAG 式流程纯工具模式已经足够。bank 路由应属于你的应用。bank_id是谁拥有这段记忆的路由键。多数生产应用倾向于每个用户或每个项目、每个租户使用一个一致的 bank。把不同用户的记忆混进同一个 bank 技术上可行但会消解持久记忆的大部分意义。HindsightMemoryWrapper会自动在 retain 的 metadata 中写入role与source: haystack可以配合recall_tags做粗粒度的来源过滤。retain 是异步的。一次retain_memory调用在内容落入 bank 时即返回而抽取器尚未完成。事实通常在几秒内变得可召回。对聊天流程这不是问题——下一轮开始时抽取早已完成但对同一脚本内先 retain 再 recall的自动化场景建议加一个短暂延迟或改用 Reflect它不依赖抽取完成。这一点在 tests/test_e2e.py 的轮询式_recall_until_nonempty中也有体现。回顾对比HaystackAgent默认接入hindsight-haystack后跨 run 记忆无持久化按 bank 隔离记忆接入方式手动传上下文三个工具或自动 wrapper跨工具共享不适用同一 bank 可被 Claude Code、Cline、Flowise、API 等读取轮前自动召回不适用auto_recallTrue轮后自动存储不适用auto_retainTrue工具面裁剪不适用include_retain/recall/reflect标志综合答案不适用reflect_on_memory返回 LLM 综合文本下一步建议阅读集成包的完整源码hindsight-integrations/haystack核心实现集中在 hindsight_haystack/tools.py、hindsight_haystack/config.py 与 hindsight_haystack/_client.py参考单元测试理解各参数的预期行为tests/test_tools.py 与 tests/test_config.py如需端到端验证参考 tests/test_e2e.py 的用法需本地运行 Hindsight 服务通过HINDSIGHT_API_URL指定地址了解 Hindsight 客户端 API 可阅读 hindsight-clients/python 下的客户端源码自托管服务端见 hindsight-api。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考