news 2026/9/13 19:03:40

为 Google ADK 智能体接入持久记忆:hindsight-google-adk 集成实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为 Google ADK 智能体接入持久记忆:hindsight-google-adk 集成实战指南

为 Google ADK 智能体接入持久记忆:hindsight-google-adk 集成实战指南

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

本指南围绕 Hindsight 项目中的 Google ADK 官方集成(hindsight-google-adk包)展开,讲解如何为 Google ADK(Agent Development Kit)智能体添加跨会话的长期记忆能力。读完本文,你将掌握两种互补的接入模式——基于BaseMemoryService的自动记忆与基于FunctionTool的显式记忆工具,并能熟练配置 Bank 划分、标签过滤、全局默认参数与生产部署方式。

集成概览:两种互补的记忆模式

Google ADK 智能体默认只具备单次会话内的上下文能力,会话结束后对话内容即被丢弃。Hindsight 提供的hindsight-google-adk包,通过 集成文档 中定义的两种模式,把 Hindsight 的长期记忆能力嵌入 ADK 的运行时:

  • HindsightMemoryService—— 实现 ADK 的BaseMemoryService抽象。将它传给Runner(memory_service=...)后,会话结束时由 ADK 生命周期自动触发 retain 将整个会话写入 Hindsight;当智能体调用search_memory时,集成层在同一个 Hindsight Bank 上执行 recall 并把结果转换为 ADK 的MemoryEntry对象返回。
  • create_hindsight_tools(...)—— 返回一组 ADKFunctionToolhindsight_retainhindsight_recallhindsight_reflect),让模型在单轮对话内部主动决定何时写入或检索记忆。

两种模式互补:前者"零干预"地自动沉淀对话,后者赋予模型按需操作记忆的自主性,二者可同时启用并共享同一个 Bank(只要 Bank ID 对齐)。

推荐使用 Hindsight Cloud:集成默认指向生产环境 API,无需自行维护本地服务,注册即可获得 API Key。

安装

包已发布到 PyPI,使用pip直接安装:

pip install hindsight-google-adk

根据 pyproject.toml 中的声明,包依赖google-adk>=2.0hindsight-client>=0.4.0,要求 Python 3.10+,当前版本为0.1.0,采用 MIT 许可。

模式一:自动记忆(HindsightMemoryService)

这是将记忆接入 ADK 最省事的方式,仅需三步:构造服务、创建 Agent、把服务挂到 Runner 上。

import asyncio from google.adk.agents import LlmAgent from google.adk.runners import Runner from google.adk.sessions import InMemorySessionService from hindsight_google_adk import HindsightMemoryService memory = HindsightMemoryService.from_url( hindsight_api_url="https://api.hindsight.vectorize.io", api_key="hsk_...", ) agent = LlmAgent(name="assistant", model="gemini-2.0-flash") runner = Runner( app_name="my-app", agent=agent, session_service=InMemorySessionService(), memory_service=memory, ) # ... use runner.run_async(...) as normal. Memory is automatic.

HindsightMemoryService实现了 ADK 的BaseMemoryService(见 memory.py),这意味着它对 ADK 运行时是透明的:Runner在会话结束时调用add_session_to_memory,把会话的全部事件(按作者: 内容逐行拼接)retain 到由(app_name, user_id)推导出的 Hindsight Bank;智能体调用search_memory时,服务在相同 Bank 上执行 recall,并把结果包装成带author="hindsight"、保留原始时间戳的MemoryEntry列表返回。

写入细节:事件如何变成记忆文档

从 memory.py 的实现可以看到会话文本的组装逻辑:遍历会话事件,抽取每个事件文本 part,跳过无文本内容的事件,最终生成多行文本;如果会话为空或全部事件无文本,则直接跳过 retain(对应测试 test_memory.py 中test_empty_session_does_not_retain等用例)。

retain 时以session.id作为document_id,这保证了同一会话的重复写入会覆盖而不是累积,避免同一对话内容被反复沉淀造成冗余。除BaseMemoryService的会话级入口外,服务还实现了add_events_to_memory(按事件增量写入,document_id形如{session_id}-{随机8位}并附带session:{session_id}标签)与add_memory(逐条写入显式MemoryEntry,把memory.authorcustom_metadata并入元数据),覆盖了 ADK 记忆接口的完整调用面。

搜索细节:recall 到 MemoryEntry 的映射

search_memory调用hindsight_clientarecall,并固定追加user:{user_id}过滤标签,确保用户之间互不可见。每个召回结果被映射为 ADK 的MemoryEntry

  • content为包含结果文本的genai.types.Content
  • author固定为"hindsight"
  • idtimestamp(取自结果的occurred_start)原样透传。

这一映射逻辑与测试 test_memory.py 中test_results_mapped_to_memory_entries的断言完全一致。

Bank ID 派生规则

默认情况下,每个(app_name, user_id)组合对应一个独立 Bank,模板为"{app_name}::{user_id}"。Bank ID 由_bank_id方法对模板做str.format(app_name=..., user_id=...)得到(见 memory.py),因此可用bank_id_template灵活定制隔离粒度:

# 按用户隔离、跨应用共享:同一用户在所有 app 中看到同一份记忆 HindsightMemoryService.from_url( hindsight_api_url="https://api.hindsight.vectorize.io", api_key="hsk_...", bank_id_template="user::{user_id}", ) # 静态 Bank:所有用户共享一份记忆(适合全局知识库场景) HindsightMemoryService.from_url( hindsight_api_url="https://api.hindsight.vectorize.io", api_key="hsk_...", bank_id_template="my-shared-bank", )

测试 test_memory.py 验证了默认模板与自定义模板的派生行为(如apple::alicens::bob)。选择模板时务必考虑数据隔离需求:默认的app::user模板已实现用户级隔离,切勿在生产环境中把多租户数据放进同一个静态 Bank。

模式二:显式工具(FunctionTool)

当你希望模型在对话中途自主决定记忆的写入与读取时机时,使用create_hindsight_tools

from google.adk.agents import LlmAgent from hindsight_google_adk import create_hindsight_tools tools = create_hindsight_tools( bank_id="user-123", hindsight_api_url="https://api.hindsight.vectorize.io", api_key="hsk_...", ) agent = LlmAgent( name="assistant", model="gemini-2.0-flash", tools=tools, )

工厂函数(见 tools.py)返回三个FunctionTool,可用include_retain/include_recall/include_reflect开关按需裁剪(对应测试 test_tools.py):

工具签名职责
hindsight_retainhindsight_retain(content)将信息存入长期记忆,返回"Memory stored successfully."
hindsight_recallhindsight_recall(query)检索记忆,返回带编号的匹配列表(如1. first2. second);无结果时返回友好提示"No relevant memories found."
hindsight_reflecthindsight_reflect(query)基于记忆综合生成连贯回答(而非原始事实列表),返回综合文本

工具级高级参数

除了文档中的基础参数,工厂还透传了一批工具级配置(见 tools.py 的参数签名):

  • retain_metadata/retain_document_id:为 retain 操作指定默认元数据与文档 ID,可用于把多条记忆归并到同一文档实现覆盖式更新;
  • recall_types:按事实类型(world/experience/observation)过滤召回结果;
  • recall_include_entities:在召回结果中包含实体信息;
  • reflect_context/reflect_max_tokens/reflect_response_schema:为 reflect 提供额外上下文、独立的 token 上限(默认回退到max_tokens),以及用 JSON Schema 约束输出结构;
  • reflect_tags/reflect_tags_match:为 reflect 指定独立的记忆过滤标签(默认回退到recall_tags/recall_tags_match)。

这些参数均可由测试用例印证,例如 test_tools.py 验证了reflect_contextreflect_response_schema会被透传到areflect

全局配置(configure)

当应用内多处需要连接 Hindsight 时,可在启动时调用一次configure(...)设置全局默认值,之后的HindsightMemoryService.from_url()create_hindsight_tools()调用会自动以此为兜底:

from hindsight_google_adk import configure configure( hindsight_api_url="https://api.hindsight.vectorize.io", api_key=None, # 不传则回退到 HINDSIGHT_API_KEY 环境变量 budget="mid", max_tokens=4096, bank_id_template="{app_name}::{user_id}", )

从 config.py 的实现看,configure的解析优先级为:显式参数 >HINDSIGHT_API_KEY环境变量 > 内置默认值,并返回一个HindsightAdkConfig数据类实例。客户端解析逻辑(见 _client.py)则按"显式client参数 > 显式 URL/Key > 全局配置 > 报错"的次序解析连接;若最终既无 URL 也无全局配置,会抛出HindsightError提示先调用configure()或传入连接参数。测试 test_config.py 覆盖了 Key 的优先级与环境变量回退行为。

另外HindsightAdkConfig还暴露了verbose开关(默认关闭),用于开启集成层的详细日志;reset_config()可清空全局配置,便于测试隔离。

配置参考

以下配置项同时适用于HindsightMemoryService.from_url()create_hindsight_tools()configure()(后两者共享同一份默认值,见 config.py):

参数默认值说明
hindsight_api_urlhttps://api.hindsight.vectorize.ioHindsight API 地址,默认指向云服务
api_keyHINDSIGHT_API_KEY环境变量Hindsight Cloud 的 Bearer Token
bank_id_template"{app_name}::{user_id}"从 ADK 的app_name/user_id推导 Bank ID 的格式化模板
budget"mid"召回预算级别:low/mid/high
max_tokens4096召回结果的最大 token 数
tagsNone附加到每条 retain 文档上的标签;app:<name>user:<id>总是会被自动添加
recall_tagsNone追加到每次召回查询上的标签;user:<id>总是会被自动添加
recall_tags_match"any"标签匹配模式:any/all/any_strict/all_strict
missionNone若设置,首次使用时以该事实抽取使命(幂等地)创建 Bank
context"google-adk"附加到 retain 内容的来源标签(即 Hindsight 的 provenance 字段)

其中mission的行为可在 memory.py 的_ensure_bank中看到:只有当 mission 非空且该 Bank 尚未处理过时,才调用acreate_bank并缓存 Bank ID,保证幂等;测试 test_memory.py 验证了同一 Bank 只创建一次、无 mission 时不创建。

预置标签与元数据

无论采用哪种模式,retain 时都会自动写入结构化元数据(见 memory.py):

  • 标签固定包含app:{app_name}user:{user_id},再加自定义tags
  • 元数据固定包含app_nameuser_idsource: "google-adk",可再并入custom_metadata/MemoryEntry.author

recall 时则固定追加user:{user_id}过滤标签。这套设计保证了"用户永远只能召回自己的记忆",即使多个用户共用同一个 Bank 模板也不会串数据。

生产环境实践

按环境给记忆打标签

利用自动附加的app:/user:标签之外的自定义标签,可以按环境隔离记忆并精确控制召回范围:

HindsightMemoryService.from_url( hindsight_api_url="https://api.hindsight.vectorize.io", api_key="hsk_...", tags=["env:prod"], # retain 时附加 recall_tags=["env:prod"],# 召回时仅命中该标签 )

这样生产环境的记忆不会被开发/预发环境的数据污染;app:user:标签始终在此基础上自动添加(见 test_memory.py 的断言)。

自托管 Hindsight

无需认证的本地服务可直接省略api_key

HindsightMemoryService.from_url( hindsight_api_url="http://localhost:8888", )

如需自托管部署方式,可参考仓库中的 docker/docker-compose 目录下的各类编排模板。

结合两种模式

自动记忆与显式工具并不互斥——Runner(memory_service=HindsightMemoryService(...))负责会话结束时的自动沉淀,tools=create_hindsight_tools(...)让模型在轮次内主动 recall/reflect。只要两者的 Bank ID 保持一致,它们读写的就是同一份记忆。

源码级可靠性设计

错误处理策略:自动模式吞错、工具模式抛错

这是一个值得注意的设计差异(两处实现分别为 memory.py 与 tools.py):

  • 自动记忆模式(HindsightMemoryService:所有add_*search_memory方法对 Hindsight 失败一律"记录日志、不向上抛",保证记忆服务故障不会拖垮整个 ADK Runner 主流程;search_memory失败时返回空结果而非异常。测试 test_memory.py 与test_recall_failure_returns_empty对此有专门覆盖。
  • 显式工具模式(create_hindsight_tools:底层调用失败时包装为HindsightError抛出,让模型感知到工具失败并决定下一步动作(如重试或告知用户)。

连接层细节

客户端解析(见 _client.py)为不同操作设置了差异化超时:retain 15 秒、recall 10 秒、reflect 30 秒、Bank 创建 15 秒、默认 30 秒,并为所有请求附加hindsight-google-adk/{version}的 User-Agent,便于服务端追踪集成来源。

端到端验证:smoke 脚本

仓库提供了完整的端到端冒烟脚本 smoke_runner.py,使用真实的 Gemini 模型驱动的Runner验证跨会话记忆,是理解集成完整链路的绝佳参考:

  • 阶段一(自动记忆):会话 A 中告知 Agent"我叫 Ben,喜欢 Rust,养了条叫 Pixel 的狗",会话结束后手动触发add_session_to_memory沉淀;会话 B 中询问"我的偏好与狗的名字",Agent 通过load_memory_tool触发search_memory,从 Hindsight 召回并作答。
  • 阶段二(显式工具):会话 C 中让 Agent 调用hindsight_retain存入"开 Tesla Model 3、喝燕麦拿铁";短暂等待写入提交后,会话 D 中让 Agent 调用hindsight_recall检索并回答。

脚本要求设置GOOGLE_API_KEYHINDSIGHT_API_KEY环境变量(HINDSIGHT_API_URL默认指向开发云),并通过输出中是否命中 "rust"/"pixel"/"tesla"/"latte" 等关键词判定各阶段 PASS/FAIL。

运行要求

  • Python 3.10+
  • google-adk>=2.0
  • hindsight-client>=0.4.0

本文所有结论均可对照 集成文档、集成包源码 及其 单元测试 逐项验证。接入完成后,你的 ADK 智能体便拥有了跨会话、跨应用、按用户隔离的长期记忆能力。

【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight

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

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

FunASR Python SDK 安装完全指南:从环境创建到离线推理

FunASR Python SDK 安装完全指南&#xff1a;从环境创建到离线推理 【免费下载链接】FunASR Open-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/MCP serving. 项目地…

作者头像 李华
网站建设 2026/9/13 19:02:34

示波器八大灵魂问题:从操作工具到信号思维

1. 为什么这八个问题比“怎么调旋钮”更重要示波器不是万用表&#xff0c;它不直接告诉你“电压是多少”&#xff0c;而是逼你回答一连串更根本的问题&#xff1a;这个信号到底在“想说什么”&#xff1f;它的时间尺度是否合理&#xff1f;它的能量分布是否健康&#xff1f;它的…

作者头像 李华
网站建设 2026/9/13 19:00:53

3 步用自然语言查数据库:LangChain4j SQL 交互实战指南

3 步用自然语言查数据库&#xff1a;LangChain4j SQL 交互实战指南 【免费下载链接】langchain4j LangChain4j is an idiomatic, open-source Java library for building LLM-powered applications on the JVM. It offers a unified API over popular LLM providers and vector…

作者头像 李华
网站建设 2026/9/13 18:57:35

通用MCU+硅MOS做FOC驱动的硬件瓶颈深度解析

1. 项目概述&#xff1a;为什么“通用MCU 硅MOS”在FOC驱动中总卡在体积与扭矩的矛盾点上&#xff1f;你有没有拆过市面上那些标称“300W无刷电机驱动板”&#xff0c;尺寸比名片还小&#xff0c;却能带动2kgcm以上堵转扭矩的负载&#xff1f;我去年帮一家电动工具客户做竞品逆…

作者头像 李华