hindsight-all Python 编程式 API 指南:在本地进程内一键启动 Hindsight 记忆服务
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
本指南围绕 Hindsight 仓库中的 hindsight-all 编程式 API(Python) 文档展开,系统讲解如何通过hindsight-all包在本地 Python 代码中直接拉起一个完整的 Hindsight 记忆服务——无需部署任何服务器基础设施。读完本文,你将掌握HindsightServer(显式生命周期)与HindsightEmbedded(自动托管)两种使用方式、Profile 数据隔离机制、四大 API 命名空间(banks / mental_models / directives / memories)的完整用法,以及 daemon 崩溃自动恢复等底层原理,可直接在测试、脚本和长期运行的应用中落地。
为什么需要 hindsight-all:一套安装包,零基础设施启动
Hindsight 是一个“会学习的 Agent 记忆系统”(Agent Memory That Learns)。要把它接入自己的应用,通常需要部署 API 服务、准备数据库、再引入客户端——这在实际开发中是一笔不小的开销。hindsight-all的目的就是把这套流程压缩成一个安装包和几行 Python 代码。
从仓库中的 hindsight-all/pyproject.toml 可以看到它的依赖构成(当前版本 0.9.2):
hindsight-api-slim[all]==0.9.2—— Hindsight API 服务端(精简版,含全部可选依赖)hindsight-client>=0.0.7—— 官方 Python HTTP 客户端hindsight-embed==0.9.2—— 嵌入式 daemon 管理模块
因此pip install hindsight-all一次安装,就能同时获得 API 服务、嵌入式 PostgreSQL 存储和类型化 Python 客户端三件套。
需要注意的是,这里的“嵌入式”并不意味着服务跑在你的 Python 进程内存里。相反,hindsight-all/hindsight/init.py 导出的两个核心入口HindsightServer与HindsightEmbedded,其底层 daemon 都以独立的 OS 进程运行在127.0.0.1上,你的代码通过 HTTP 与该进程通信。也就是说:Python 进程崩溃不影响记忆数据,记忆服务随时可以被其他进程、CLI 工具复用。
安装与依赖
pip install hindsight-all如果你的运行环境没有 LLM API 密钥,也可以选择本地推理方案:
pip install "hindsight-all[local-llm]"该可选依赖通过hindsight-api-slim[local-llm]引入本地模型支持。仓库的测试套件还声明了test可选依赖(pytest、pytest-asyncio),用于运行 hindsight-all/tests 下的集成测试。
环境要求为python >= 3.11。如果你已经有运行中的 Hindsight 服务器、只需要一个客户端,那么应当直接使用 Python Client(hindsight-client),无需引入整套嵌入式依赖。
两种 API 形态:HindsightServer 与 HindsightEmbedded
hindsight-all暴露两类主要 API,二者最终都通过同一个HindsightClientHTTP 接口与同一个底层 daemon 通信,区别只在于服务器进程由谁管理:
| API | 生命周期管理 | 适用场景 |
|---|---|---|
HindsightServer | 显式:进入上下文即启动,退出即关闭 | 测试、短生命周期脚本,要求确定性的启停 |
HindsightEmbedded | 自动:首次调用启动,跨调用复用,空闲自动退出 | 长期运行的应用,不想关心生命周期 |
下面分别深入讲解。
HindsightServer:显式生命周期(上下文管理器)
HindsightServer作为上下文管理器使用,进入with块时立即启动服务,退出时干净关闭,非常适合测试和短脚本:
import os from hindsight import HindsightServer, HindsightClient with HindsightServer( llm_provider="openai", llm_model="gpt-4o-mini", llm_api_key=os.environ["OPENAI_API_KEY"], ) as server: client = HindsightClient(base_url=server.url) client.retain(bank_id="my-bank", content="Alice works at Google") results = client.recall(bank_id="my-bank", query="What does Alice do?") for r in results: print(r.text) answer = client.reflect(bank_id="my-bank", query="Tell me about Alice") print(answer.text) # Server is stopped here从源码看,hindsight-all/hindsight/server.py 中的Server类提供了完整的生命周期实现:
- 启动:
start(timeout=30.0)在一个后台守护线程(threading.Thread(daemon=True))中创建MemoryEngine、构建 FastAPI 应用(create_app)、并启动 uvicorn 服务器。启动后通过socket.create_connection轮询确认端口已就绪才返回,超时则抛出RuntimeError。 - 端口:默认通过
_find_free_port()自动选择一个空闲端口,无需手动指定;也可以通过port参数固定端口。 - 停止:
stop()将uvicorn.Server.should_exit置为 True,等待线程退出(默认最多 10 秒),并完成MemoryEngine.close()清理。 - URL:
server.url属性返回http://{host}:{port},默认绑定127.0.0.1。
Server的完整构造参数(也是start_server便捷函数接受的参数)如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
db_url | "pg0" | 数据库 URL;"pg0"表示使用嵌入式 PostgreSQL |
llm_provider | "groq" | LLM 提供商:groq、openai、ollama、gemini、anthropic、lmstudio等 |
llm_api_key | "" | LLM 提供商 API 密钥 |
llm_model | "openai/gpt-oss-120b" | 使用的模型名 |
llm_base_url | None | 可选的 LLM API 自定义 base URL |
host | "127.0.0.1" | 服务绑定地址 |
port | None | 绑定端口,默认自动选择空闲端口 |
mcp_enabled | False | 是否启用 MCP 服务器 |
log_level | "info"(Server)/"warning"(start_server) | uvicorn 日志级别 |
除了上下文管理器,你还可以手动管理生命周期:先用start_server(...)或Server(...).start()启动,用完调用server.stop()(hindsight-all/README.md 的 Quick Start 展示了这种写法)。
HindsightEmbedded:自动托管,开箱即用
HindsightEmbedded是 Hindsight 在 Python 中使用的最简方式。它自动管理后台 daemon:首次调用时启动,之后跨调用复用同一个 daemon,空闲后自动退出;你也可以调用close(stop_daemon=True)显式停止。
from hindsight import HindsightEmbedded import os # Server starts automatically on first call client = HindsightEmbedded( profile="myapp", # Profile for data isolation llm_provider="openai", llm_model="gpt-4o-mini", llm_api_key=os.environ["OPENAI_API_KEY"], ) # Use immediately - no manual server management needed client.retain(bank_id="my-bank", content="Alice works at Google") results = client.recall(bank_id="my-bank", query="What does Alice do?") # Server continues running (auto-stops after idle timeout) # Or explicitly stop it: client.close(stop_daemon=True)HindsightEmbedded的构造参数非常灵活(见 hindsight-all/hindsight/embedded.py)。关键设计是:你显式传入的设置才会被转发给 daemon,未指定的参数全部交给 daemon 按序解析——先查 Profile 的.env文件,再查父进程环境变量,最后使用 daemon 自身默认值。这意味着你可以构造一个不带凭据的客户端,让它直接复用某个已配置好凭据的 Profile 或 shell 环境,而不会被占位符覆盖(源码注释中引用了 issue #3253 的设计约束)。
重要参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
profile | "default" | Profile 名称,用于数据隔离 |
llm_provider | None(继承) | LLM 提供商,省略则继承;服务器默认"openai" |
llm_api_key | None(继承) | API 密钥,省略则继承;显式传""表示明确运行在无密钥环境(如本地免鉴权服务) |
llm_model | None(继承) | 模型名,省略则继承,服务器按已解析的提供商选默认模型 |
llm_base_url | None | 自定义 LLM API base URL |
database_url | None | 数据库 URL 覆盖项,默认使用 Profile 专属 pg0 |
idle_timeout | 已弃用并被忽略 | daemon 不再因空闲自动退出,保留参数仅为兼容旧调用方 |
log_level | None(继承) | daemon 日志级别,daemon 默认"info" |
ui | False | 是否随 daemon 一同启动控制平面 Web UI |
ui_port | None | UI 端口,默认daemon_port + 10000 |
ui_hostname | "0.0.0.0" | UI 绑定主机名 |
内部实现上,HindsightEmbedded通过get_embed_manager()(来自hindsight-embed包)获得DaemonEmbedManager,其配置以HINDSIGHT_API_LLM_PROVIDER、HINDSIGHT_API_LLM_API_KEY、HINDSIGHT_API_LLM_MODEL等环境变量键的形式传给 daemon。
什么是 Profile?
Profile 是一个隔离的 Hindsight 环境。每个 Profile 拥有:
- 自己的嵌入式 PostgreSQL 数据库(存储在
~/.pg0/instances/hindsight-embed-{profile}/); - 自己的 API 服务器进程。
因此可以用不同 Profile 来隔离开发/生产环境、不同应用,甚至不同用户的数据。仓库中的集成测试 hindsight-all/tests/test_embedded.py 中的test_embedded_profile_isolation验证了这一点:两个不同 Profile 使用相同的bank_id各自写入内容,互相看不到对方的数据。
HindsightEmbedded与hindsight-embedCLI 共享同一套 daemon 管理接口和 Profile 存储,因此可以放心地与 CLI 工具混用同一份 Profile 数据。
何时选择哪种?
| 使用场景 | 选择 |
|---|---|
| 测试、短生命周期脚本、需要确定性启停 | HindsightServer(上下文管理器) |
| 长期运行的应用、首次使用自动启动、不想管理生命周期 | HindsightEmbedded |
| 已有运行中的 Hindsight 服务器 | 直接使用 hindsight-client |
API 命名空间:组织化的银行、心智模型、指令与记忆操作
HindsightEmbedded和HindsightClient都暴露了组织化的 API 命名空间,用于银行(Bank)管理、心智模型(Mental Models)、指令(Directives)和记忆(Memories):
from hindsight import HindsightEmbedded import os embedded = HindsightEmbedded( profile="myapp", llm_provider="openai", llm_api_key=os.environ["OPENAI_API_KEY"], ) # Core operations embedded.retain(bank_id="test", content="Hello") results = embedded.recall(bank_id="test", query="Hello") # Bank management embedded.banks.create(bank_id="test", name="Test Bank", mission="Help users") embedded.banks.set_mission(bank_id="test", mission="Updated mission") embedded.banks.delete(bank_id="test") # Mental models embedded.mental_models.create( bank_id="test", name="User Preferences", content="User prefers dark mode" ) models = embedded.mental_models.list(bank_id="test") # Directives embedded.directives.create( bank_id="test", name="Response Style", content="Be concise and friendly" ) directives = embedded.directives.list(bank_id="test") # List memories memories = embedded.memories.list(bank_id="test", type="world", limit=50)这些命名空间由 hindsight-all/hindsight/api_namespaces.py 中的四个类实现(BanksAPI、MentalModelsAPI、DirectivesAPI、MemoriesAPI),在 hindsight-all/hindsight/client_wrapper.py 中还有一套绑定在HindsightClient上的同名实现。每个命名空间的方法签名与底层客户端方法一一对应:
banks:create(bank_id, name=None, mission=None, disposition=None)、delete(bank_id)、set_mission(bank_id, mission)、set_disposition(bank_id, disposition)(HindsightClient版本另有list())。mental_models:create(bank_id, name, content, tags=None)、list(bank_id, tags=None, detail=None)、get(bank_id, mental_model_id)、refresh(bank_id, mental_model_id)、update(...)、delete(...)。其中list()默认只返回元数据,需要正文时传detail="content"。directives:create(bank_id, name, content, tags=None)、list(bank_id, tags=None)、get(bank_id, directive_id)、update(...)、delete(...)。memories:list(bank_id, type=None, search_query=None, limit=100, offset=0),支持按记忆类型过滤、文本搜索与分页。
为什么推荐走命名空间而不是直接访问 client?
关键原因在于daemon 崩溃的优雅处理。命名空间的每个方法调用都会先执行_ensure_started()(见 hindsight-all/hindsight/embedded.py):它会检查 daemon 是否仍在运行,若已崩溃则自动清理过期客户端并重启 daemon,然后才发起真实 API 调用:
# ✅ GOOD - Uses API namespace (daemon restarts handled) embedded.banks.create(bank_id="test", name="Test") # ❌ BAD - Direct client access (daemon crashes NOT handled) client = embedded.client client.create_bank(bank_id="test", name="Test") # Fails if daemon crashed这一点有测试直接背书:hindsight-all/tests/test_embedded_namespaces.py 中的test_daemon_restart_handling模拟了“daemon 崩溃→清除客户端→再次调用”的场景,验证命名空间方法能透明地重启 daemon 并继续工作;test_multiple_calls_ensure_daemon_each_time则确认每次命名空间调用都会执行_ensure_started()。此外 hindsight-all/tests/test_embedded.py 的test_embedded_daemon_crash_recovery通过client._manager.stop(profile)模拟真实崩溃,随后下一次retain调用自动重启 daemon 并成功写入数据。
需要注意的是,HindsightEmbedded的普通方法代理(__getattr__)同样会在调用前执行_ensure_started(),所以直接调用client.retain(...)也具有崩溃恢复能力;真正危险的是先通过embedded.client拿到底层Hindsight客户端引用再保存下来使用——该引用在 daemon 崩溃后不会自动刷新。
完整工作流示例:从建库到反思
结合仓库测试 hindsight-all/tests/test_embedded.py 中的test_embedded_complete_workflow,一个典型的完整工作流如下:
client = HindsightEmbedded(profile="myapp", llm_provider="openai", llm_api_key=os.environ["OPENAI_API_KEY"]) # 1. 创建记忆银行 client.create_bank(bank_id="assistant", name="Test Assistant", mission="Help with programming tasks") # 2. 存储单条记忆 client.retain(bank_id="assistant", content="User prefers Python for data analysis.", context="Programming preferences") # 3. 批量存储记忆 client.retain_batch(bank_id="assistant", items=[ {"content": "User works with pandas and numpy."}, {"content": "User likes matplotlib for visualization."}, {"content": "User is interested in machine learning with scikit-learn."}, ]) # 4. 检索记忆 results = client.recall(bank_id="assistant", query="What tools does the user prefer?", max_tokens=2000) # 5. 反思(基于记忆生成上下文回答) answer = client.reflect(bank_id="assistant", query="What programming tools should I recommend?", budget="low") # 6. 列出记忆 client.list_memories(bank_id="assistant", limit=10) client.close()retain/recall/reflect的完整参数参考(无论客户端以何种方式获得,行为一致)见 Python Client 页面:例如retain支持context、timestamp、document_id、metadata、retain_async;recall支持types、max_tokens、budget(low/mid/high)、include_chunks;reflect支持budget与context;所有方法都有以a前缀开头的异步版本(aretain、arecall、areflect等)。
进阶:上下文管理器与 UI 控制平面
HindsightEmbedded同样支持上下文管理器,退出时自动调用close():
from hindsight import HindsightEmbedded with HindsightEmbedded(profile="myapp") as client: client.retain(bank_id="alice", content="Alice loves AI") # Daemon managed automatically如果你希望记忆服务同时附带可视化控制平面,可以设置ui=True(并可选ui_port、ui_hostname)。测试 hindsight-all/tests/test_embedded.py 中的test_embedded_ui_flag验证了:启用 UI 后,首次调用会同时拉起 daemon 和 UI,且 UI 的健康检查端点({ui_url}/api/health)返回status: "ok"且dataplane.status: "connected",说明数据平面已成功连接。
最佳实践小结
- 测试与短脚本用
HindsightServer上下文管理器:确定性的启停让测试互不干扰,server.url可直接注入HindsightClient。 - 应用代码用
HindsightEmbedded:懒启动 + 跨调用复用 + 空闲自动退出,配合命名空间获得 daemon 崩溃自愈能力。 - 用 Profile 做环境隔离:dev/prod、不同应用或不同用户各用一个 Profile,数据库与服务器进程完全隔离(存储于
~/.pg0/instances/hindsight-embed-{profile}/)。 - 优先走 API 命名空间(
embedded.banks、embedded.mental_models等),避免长期保存embedded.client裸引用。 - 无密钥本地服务:将
llm_api_key显式传"",可清除继承的 API 密钥,配合本地 LLM 服务(如ollama、lmstudio)使用。 - 省略参数即继承:构造
HindsightEmbedded时未显式给出的配置会按“Profile.env→ 父进程环境变量 → daemon 默认值”的顺序解析,适合复用已配置好的环境。
从安装到生产级接入,hindsight-all用一套依赖覆盖了 API 服务、嵌入式 PostgreSQL 与类型化客户端,让“Agent 记忆”真正成为应用里随手可用的本地基础设施。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考