尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Hindsight × Strands Agents SDK 集成指南:为 Strands Agent 赋予跨会话的持久记忆

Hindsight × Strands Agents SDK 集成指南:为 Strands Agent 赋予跨会话的持久记忆 Hindsight × Strands Agents SDK 集成指南为 Strands Agent 赋予跨会话的持久记忆【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight本技术指南围绕 Hindsight 开源仓库中的hindsight-strands集成包展开讲解如何通过 Strands Agents SDK 的原生tool模式为 Agent 接入 Hindsight 的长期记忆能力retain 存储、recall 检索、reflect 综合。读完本文你将掌握该集成包的安装接入、三大记忆工具的调用机制、全局配置方式以及客户端生命周期管理的最佳实践并能在本地或云端 Hindsight 服务上直接落地一套具备长期记忆的 Strands Agent。集成概述为什么需要 hindsight-strandsStrands Agents SDK 提供了一套简洁的 Python Agent 开发范式Agent 的能力通过原生tool装饰的普通 Python 函数声明。但 Strands 本身不提供长期记忆每个会话结束后Agent 的上下文便随会话丢失。hindsight-strands的作用正是把 Hindsight 的持久化记忆能力封装成 Strands 兼容的工具函数让 Agent 在会话之间记住事实、偏好与决策。从仓库结构看该集成是 Hindsight 众多 Agent 框架集成中的一个独立可安装包位于 hindsight-integrations/strands核心代码仅由三个模块构成hindsight_strands/tools.py —— 工具工厂create_hindsight_tools()与记忆注入函数memory_instructions()hindsight_strands/config.py —— 全局配置configure()与配置数据类HindsightStrandsConfighindsight_strands/errors.py —— 统一异常类型HindsightError。根据 pyproject.toml 中的声明包版本为 0.1.3要求 Python 3.10依赖strands-agents与hindsight-client0.4.0并需要一台运行中的 Hindsight API 服务。安装与快速开始安装只需一条命令pip install hindsight-strands快速开始的最小示例完整代码见 README.mdfrom strands import Agent from hindsight_strands import create_hindsight_tools tools create_hindsight_tools( bank_iduser-123, hindsight_api_urlhttps://api.hindsight.vectorize.io, api_keyhsk_..., # 或通过 HINDSIGHT_API_KEY 环境变量提供 ) agent Agent(toolstools) agent(Remember that I prefer dark mode) agent(What are my preferences?) tools.close() # 仅当客户端由 hindsight-strands 内部创建时才需要关闭上述代码运行后Agent 会获得三个可调用工具工具名职责底层 APIhindsight_retain把信息写入长期记忆client.retain()hindsight_recall检索长期记忆中相关事实client.recall()hindsight_reflect基于记忆综合出有依据的回答client.reflect()本地自托管接入如果在本机通过./scripts/dev/start-api.sh启动 Hindsight 本地服务只需把地址指向本地端口即可tools create_hindsight_tools( bank_iduser-123, hindsight_api_urlhttp://localhost:8888, )三大记忆工具的源码级实现三个工具都在 tools.py 中由工厂函数按开关参数动态生成每个工具都是被 Strandstool装饰的普通 Python 函数bank_id与 Hindsight 客户端通过闭包在构造时捕获无需修改 Agent 上下文。hindsight_retain存储记忆hindsight_retain(content: str)接收一段文本调用client.retain(bank_id..., content...)写入记忆库若通过tags配置了标签则一并传入tags参数。调用前会执行_ensure_bank()确保记忆银行bank存在def _ensure_bank(bid: str) - None: if bid in created_banks: return try: resolved_client.create_bank(bank_idbid, namebid) created_banks.add(bid) except Exception: created_banks.add(bid)注意created_banks集合保证了同一进程内只创建一次银行而异常被吞掉则是为了兼容银行已存在的场景——这正是仓库测试 test_tools.py 中test_retain_bank_already_exists所验证的行为。成功时工具返回字符串Memory stored successfully.。hindsight_recall检索记忆hindsight_recall(query: str)调用client.recall()并透传budget预算档位与max_tokens结果 token 上限两个参数配置了recall_tags时还会附带tags与tags_match。返回结果会被格式化为编号列表lines [] for i, result in enumerate(response.results, 1): lines.append(f{i}. {result.text}) return \n.join(lines)无结果时返回固定文案No relevant memories found.测试test_recall_no_results/test_recall_none_results覆盖了空列表与 None 两种边界。hindsight_reflect综合记忆hindsight_reflect(query: str)调用client.reflect()返回response.text若综合结果为空或为 None则回退到No relevant memories found.。与 recall 不同reflect 返回的是模型基于记忆想清楚之后的连贯回答而非原始事实列表。错误处理契约三个工具共享一致的错误处理模式见源码捕获HindsightError时直接原样抛出不透传包装捕获其他Exception时记录 error 日志并包装为HindsightError(fRetain failed: {e})抛出。对应的单元测试如test_retain_hindsight_error_not_wrapped、test_retain_failure_logs_error验证了这两种行为保证 Agent 侧可以通过统一的HindsightError感知记忆操作失败。线程桥接Strands 事件循环与 Hindsight 客户端的兼容关键hindsight-strands在实现上有一个值得注意的工程细节Strands 会在自身的 asyncio 事件循环中执行工具而 Hindsight 客户端内部同样使用 asyncio包括asyncio.timeout直接调用会与已运行的事件循环冲突。因此 tools.py 定义了模块级线程池与桥接函数_executor concurrent.futures.ThreadPoolExecutor(max_workers4) def _run_in_thread(fn: Any, *args: Any, **kwargs: Any) - Any: return _executor.submit(fn, *args, **kwargs).result()所有对客户端的同步调用retain/recall/reflect/create_bank/close都经由_run_in_thread在独立线程中执行从而获得干净的事件循环。这解释了为什么工具函数对外表现为纯同步接口——你可以把它理解为 Strands 工具生态与 asyncio 客户端之间的线程桥。配置参考三个入口的参数全解析集成提供三个配置入口均以*强制关键字参数具体参数与默认值如下与 README.md 的 Configuration Reference 保持一致并结合 tools.py 与 config.py 源码核实create_hindsight_tools()参数默认值说明bank_id必填Hindsight 记忆银行 IDclientNone预配置的 Hindsight 客户端生命周期由调用方管理hindsight_api_urlNoneAPI 地址传入时由集成内部创建并持有客户端api_keyNoneAPI 密钥未传 client 时使用budgetmidrecall/reflect 的预算档位low / mid / highmax_tokens4096recall 结果的最大 token 数tagsNone写入记忆时附加的标签recall_tagsNone检索时用于过滤的标签recall_tags_matchany标签匹配模式any / all / any_strict / all_strictenable_retainTrue是否包含 retain 工具enable_recallTrue是否包含 recall 工具enable_reflectTrue是否包含 reflect 工具只挂载需要的工具可以减小工具面例如enable_reflectFalse即可省略综合工具README 中给出完整示例。测试test_creates_three_tools_by_default与三个 enable 单开测试共同验证了工具按开关组合生成的行为。memory_instructions()参数默认值说明bank_id必填Hindsight 记忆银行 IDclientNone预配置的 Hindsight 客户端hindsight_api_urlNoneAPI 地址未传 client 时使用api_keyNoneAPI 密钥queryrelevant context about the user用于记忆注入的 recall 查询词budgetlowrecall 预算档位预注入场景默认更低控制成本max_results5最多注入多少条记忆max_tokens4096recall 结果的 token 上限prefixRelevant memories:\n记忆列表前的前缀文本tagsNone过滤 recall 结果的标签tags_matchany标签匹配模式memory_instructions()返回格式化字符串可直接拼入 system prompt让 Agent 在对话前就预知相关记忆。其实现细节tools.py值得注意无结果时返回空字符串任何异常都会被静默吞掉并返回——注释明确说明instructions 失败不应阻塞 Agent若客户端是内部创建的无论成功失败都会在finally中关闭避免泄漏测试test_closes_internally_created_client_on_success/test_closes_internally_created_client_on_exception验证。configure()参数默认值说明hindsight_api_url生产 APIhttps://api.hindsight.vectorize.ioHindsight API 地址api_keyHINDSIGHT_API_KEY环境变量API 密钥budgetmid默认 recall 预算max_tokens4096默认 recall token 上限tagsNone默认 retain 标签recall_tagsNone默认 recall 过滤标签recall_tags_matchany默认标签匹配模式verboseFalse是否启用详细日志configure()的实现config.py有两条优先级规则被 test_config.py 的多个用例锁定显式参数 环境变量api_key api_key or os.environ.get(HINDSIGHT_API_KEY)因此传入api_keyexplicit-key会覆盖环境变量配置可被替换每次调用configure()都会生成新的HindsightStrandsConfig实例test_configure_replaces_previous_config可通过get_config()读取、reset_config()复位。配置完成后后续创建工具无需再传连接信息from hindsight_strands 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 ) tools create_hindsight_tools(bank_iduser-123)在 tools.py 中显式参数与全局配置的合并遵循显式优先原则例如effective_tags tags if tags is not None else (config.tags if config else None)。测试test_retain_explicit_tags_override_config与test_retain_config_tags分别验证了显式覆盖与配置兜底两条路径。客户端生命周期管理v0.1.3 修复的核心问题create_hindsight_tools()返回的不是普通 list而是 tools.py 中定义的HindsightTools容器——它继承list因此可以直接传给Agent(toolstools)同时额外携带客户端清理能力。这与 Strands 集成变更日志strands.md中v0.1.3 的 Bug Fix 直接对应该版本修复了 Strands 集成正确关闭内部持有的 Hindsight 客户端避免资源泄漏与相关稳定性问题。理解这个修复需要掌握_resolve_client()的所有权判定逻辑def _resolve_client(client, hindsight_api_url, api_key): if client is not None: return client, False # 外部客户端owns_client False ... return Hindsight(**kwargs), True # 内部创建owns_client True传入client所有权归调用方close()/aclose()是空操作测试test_close_does_not_close_externally_owned_client仅传hindsight_api_url/api_key集成内部创建客户端并持有所有权close()/aclose()会真正关闭它测试test_close_closes_internally_owned_client/test_aclose_closes_internally_owned_client。HindsightTools还实现了上下文管理器协议支持with与async with用法close()通过_run_in_thread在独立线程中同步关闭aclose()则直接await self._client.aclose()。推荐做法FastAPI 生命周期中共享客户端README 推荐在应用 lifespan 中创建一个共享Hindsight 客户端并显式管理其生命周期from contextlib import asynccontextmanager from fastapi import FastAPI from hindsight_client import Hindsight from hindsight_strands import create_hindsight_tools, memory_instructions asynccontextmanager async def lifespan(app: FastAPI): client Hindsight(base_urlhttp://localhost:8888, api_keytest-key) app.state.hindsight_client client try: yield finally: await client.aclose() app FastAPI(lifespanlifespan) app.post(/chat) async def chat(): client app.state.hindsight_client tools create_hindsight_tools(bank_iduser-123, clientclient) memories memory_instructions(bank_iduser-123, clientclient) ...这种模式下工具容器不再拥有客户端关闭动作统一由 lifespan 的await client.aclose()完成而如果直接向create_hindsight_tools()传hindsight_api_url/api_key则必须在关闭阶段调用await tools.aclose()或tools.close()——这正是 v0.1.3 修复所保障的行为。类型支持与可观测性v0.1.2 的两个改进Strands 集成变更日志记录了v0.1.2的两个 Improvements同样在源码中有迹可循PEP 561 类型标记包内携带 py.typed 标记文件并在 pyproject.toml 的 wheel 打包配置packages [hindsight_strands]中被一并发布静态类型检查器据此对create_hindsight_tools、memory_instructions、configure等 API 提供完整类型推断。一致的 User-Agent模块顶部通过importlib.metadata读取包版本并构造标识头try: _VERSION metadata.version(hindsight-strands) except metadata.PackageNotFoundError: _VERSION 0.0.0 _USER_AGENT fhindsight-strands/{_VERSION}所有内部创建的 Hindsight 客户端都会携带user_agent_USER_AGENT测试test_creates_client_from_url等断言了该参数并附带 30 秒默认超时便于服务端识别流量来源与排查问题。版本演进时间线结合 strands.md 变更日志hindsight-strands的演进脉络如下v0.1.1Features新增 Strands Agents SDK 集成使 Hindsight 记忆工具可用于 Strands Agent——即本包的核心能力首次落地v0.1.2Improvements发布 PEP 561py.typed标记以改进 Python 类型支持所有 HTTP 请求携带统一 User-Agent提升兼容性与排障体验v0.1.3Bug Fixes修复内部持有的 Hindsight 客户端关闭逻辑杜绝资源泄漏与相关稳定性问题。该集成与 Hindsight 核心采用独立版本节奏——正如总变更日志 index.md 所述每个集成按自己的节奏发布并有自己的变更日志。因此升级时应以hindsight-strands自身版本为准而不是 Hindsight API 的版本号。测试与验证仓库为集成配备了完整的单元测试可作为接入时的行为规范参考tests/test_config.py —— 覆盖默认值、环境变量读取、显式覆盖优先级、配置替换与复位等 20 余个用例tests/test_tools.py —— 覆盖客户端解析_resolve_client、工具数量与名称、三个工具的输入输出契约、银行自动创建、标签透传、错误包装、内部客户端关闭等行为。例如_resolve_client的测试断言了三条关键规则显式client优先于 url/key无 client 时回退到全局配置配置完全缺失时抛出HindsightError消息为No Hindsight API URL configured. Pass client or hindsight_api_url, or call configure() first.。这些测试事实均来自 test_tools.py 的TestResolveClient类。总结hindsight-strands以极小的 API 面三个工具 一个注入函数 一个全局配置函数为 Strands Agent 补齐了长期记忆能力。其设计要点可概括为以原生tool函数贴合 Strands 生态、以线程桥化解 asyncio 冲突、以显式所有权规则杜绝客户端资源泄漏v0.1.3 的核心修复、以py.typed与统一 User-Agent 提升工程体验v0.1.2 的两项改进。按 README 推荐在应用生命周期中共享客户端并将memory_instructions()的结果拼入 system prompt即可在几行代码内构建出真正记得住的 Strands Agent。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表