为 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(...)—— 返回一组 ADKFunctionTool(hindsight_retain、hindsight_recall、hindsight_reflect),让模型在单轮对话内部主动决定何时写入或检索记忆。
两种模式互补:前者"零干预"地自动沉淀对话,后者赋予模型按需操作记忆的自主性,二者可同时启用并共享同一个 Bank(只要 Bank ID 对齐)。
推荐使用 Hindsight Cloud:集成默认指向生产环境 API,无需自行维护本地服务,注册即可获得 API Key。
安装
包已发布到 PyPI,使用pip直接安装:
pip install hindsight-google-adk根据 pyproject.toml 中的声明,包依赖google-adk>=2.0与hindsight-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.author与custom_metadata并入元数据),覆盖了 ADK 记忆接口的完整调用面。
搜索细节:recall 到 MemoryEntry 的映射
search_memory调用hindsight_client的arecall,并固定追加user:{user_id}过滤标签,确保用户之间互不可见。每个召回结果被映射为 ADK 的MemoryEntry:
content为包含结果文本的genai.types.Content;author固定为"hindsight";id与timestamp(取自结果的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::alice、ns::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_retain | hindsight_retain(content) | 将信息存入长期记忆,返回"Memory stored successfully." |
hindsight_recall | hindsight_recall(query) | 检索记忆,返回带编号的匹配列表(如1. first、2. second);无结果时返回友好提示"No relevant memories found." |
hindsight_reflect | hindsight_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_context与reflect_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_url | https://api.hindsight.vectorize.io | Hindsight API 地址,默认指向云服务 |
api_key | HINDSIGHT_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_tokens | 4096 | 召回结果的最大 token 数 |
tags | None | 附加到每条 retain 文档上的标签;app:<name>与user:<id>总是会被自动添加 |
recall_tags | None | 追加到每次召回查询上的标签;user:<id>总是会被自动添加 |
recall_tags_match | "any" | 标签匹配模式:any/all/any_strict/all_strict |
mission | None | 若设置,首次使用时以该事实抽取使命(幂等地)创建 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_name、user_id、source: "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_KEY与HINDSIGHT_API_KEY环境变量(HINDSIGHT_API_URL默认指向开发云),并通过输出中是否命中 "rust"/"pixel"/"tesla"/"latte" 等关键词判定各阶段 PASS/FAIL。
运行要求
- Python 3.10+
google-adk>=2.0hindsight-client>=0.4.0
本文所有结论均可对照 集成文档、集成包源码 及其 单元测试 逐项验证。接入完成后,你的 ADK 智能体便拥有了跨会话、跨应用、按用户隔离的长期记忆能力。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考