hindsight-litellm 集成完全指南:Hindsight 记忆体系接入 LiteLLM 的架构、配置与版本演进
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
本篇技术指南围绕 Hindsight 官方 LiteLLM 集成(hindsight-litellm)展开,系统讲解它如何在任意 LiteLLM 支持的 LLM 应用之上叠加持久记忆能力,并完整梳理 0.5.0 → 0.5.4 的版本演进脉络。读完本文,你将掌握该集成的安装配置、configure/set_defaults/逐调用覆盖三层配置体系、reflect 与 recall 两种记忆模式、直接记忆 API、原生客户端包装器与流式响应支持,并能在源码层面理解每次版本修复背后的实现细节。
该集成属于 Hindsight 生态中的hindsight-integrations/litellm包(源码位于 hindsight-integrations/litellm),其完整使用文档见 LiteLLM 集成文档,版本变更记录即本文所述内容(对应 changelog)。
集成定位:为什么要在 LiteLLM 之上再建一层记忆
LiteLLM 是业界常用的统一 LLM 网关,一套 API 对接 OpenAI、Anthropic、Groq、Azure OpenAI、AWS Bedrock、Google Vertex AI 等 100+ 提供方。hindsight-litellm的价值在于:在不改变你现有 LiteLLM 调用方式的前提下,为任何 LLM 应用加上"会学习、可召回"的持久记忆——这正是 Hindsight "Agent Memory That Learns" 项目愿景在 LiteLLM 生态中的落地形态。
从包描述(pyproject.toml)可以看到它的核心卖点:Universal LLM memory integration via LiteLLM - works with 100+ providers。你只需"配置 → 设默认值 → 启用 → 调用hindsight_litellm.completion()"四步,记忆的注入与存储便自动发生。
五分钟上手:安装与 Quick Start
安装
pip install hindsight-litellm集成依赖两个核心包(见 pyproject.toml):
hindsight-client>=0.4.0:提供 Hindsight 的 API 客户端;litellm>=1.93.0(非 macOS);macOS 上无对应 wheel,放宽为litellm>=1.91.3,<1.92。文档要求的最低版本为litellm >= 1.83.0,当前仓库已为供应链安全把下限提高到 1.93.0,并额外锁定aiohttp>=3.14.3、filelock>=3.20.3、urllib3>=2.6.3、requests>=2.33.0等传递依赖的安全修复版本。
Quick Start
import hindsight_litellm # Step 1: 配置静态设置 hindsight_litellm.configure( hindsight_api_url="http://localhost:8888", verbose=True, ) # Step 2: 设置默认值(bank_id 必填) hindsight_litellm.set_defaults( bank_id="my-agent", use_reflect=True, # 使用 reflect 获取综合上下文 ) # Step 3: 启用记忆集成 hindsight_litellm.enable() # Step 4: 带记忆调用 completion response = hindsight_litellm.completion( model="gpt-4o-mini", messages=[{"role": "user", "content": "What did we discuss about AI?"}], hindsight_query="What do I know about AI discussions?", )关键点:当inject_memories=True(默认开启)时,hindsight_query用于指定从记忆中检索什么。若不提供,集成会自动回退使用最近一条用户消息作为查询——这个回退行为正是 0.5.0 版本修复项之一(详见下文版本演进)。从源码看(_inject_memories),查询解析顺序为:hindsight_query参数 →defaults.query默认值 → 反向扫描 messages 中最后一条 user 消息(同时支持纯文本与多模态结构化 content 列表)。
核心工作流:记忆注入与对话存储的完整链路
当调用completion()时,集成自动完成五步:
- 记忆检索(LLM 调用前)——向 Hindsight 查询与对话相关的记忆:
use_reflect=False时走 recall 返回原始事实,use_reflect=True时走 reflect 返回综合上下文; - 提示注入——把记忆写进 system message(默认)或拼到最后一条 user 消息前;
- LLM 调用——将增强后的 prompt 发给模型;
- 对话存储(LLM 调用后)——对话内容异步写入 Hindsight 供未来召回;
- 返回响应——你拿到的响应与普通 LiteLLM 调用完全一致。
注入的两种形态
Recall 模式(原始事实列表):
hindsight_litellm.set_defaults(bank_id="my-agent", use_reflect=False) # 注入形如: # 1. [WORLD] User prefers Python # 2. [OBSERVATION] User dislikes Java...Reflect 模式(综合上下文段落):
hindsight_litellm.set_defaults(bank_id="my-agent", use_reflect=True) # 注入形如: # "Based on previous conversations, the user is a Python developer who..."Reflect + context(塑造推理而非影响检索):
hindsight_litellm.set_defaults( bank_id="my-agent", use_reflect=True, reflect_context="I am a delivery agent looking for package recipients.", )从源码看,注入内容的组装逻辑位于_inject_memories:recall 模式下每条记忆被格式化为序号. [类型] 文本,统一加上# Relevant Memories标题;reflect 模式则生成# Relevant Context from Memory段落。注入位置由injection_mode决定——system_message会追加到已有 system message 或新建一条,prepend_user则逆序找到最后一条 user 消息,把记忆上下文拼到其内容之前(字符串或结构化 content 列表均兼容)。
对话存储的细节:全量 UPSERT 而非增量追加
回调实现(callbacks.py)中的_plan_store有一段重要设计说明:每次存储发送的是完整对话历史而非新增片段。原因在于 Hindsight 的 retain API 配合document_id执行的是 UPSERT(整体替换)语义,如果只发送增量,Hindsight 只会看到最新片段而丢失前文上下文。通过每次携带完整对话,配合session_id/document_id对会话分组,最终文档始终包含完整对话供事实抽取。此外存储前还会计算user_input|assistant_output的 MD5 哈希做去重(_compute_conversation_hash),避免重复写入同一轮对话。
存储的消息会做角色归一化处理:system 消息与注入的记忆上下文会被跳过(避免把记忆本身当对话存回记忆),tool 消息转为TOOL_RESULT:,带tool_calls的助手消息转为ASSISTANT_TOOL_CALLS:,最终以USER:/ASSISTANT:分段拼接。
配置体系:configure / set_defaults / 逐调用覆盖
集成将 API 拆成两个层级,再加上逐调用覆盖,共三层配置(对应源码 config.py 中的HindsightConfig与HindsightCallSettings两个 dataclass)。
1.configure()——静态设置
连接级配置,会话中通常不变:
hindsight_litellm.configure( # 必填 hindsight_api_url="http://localhost:8888", # Hindsight API 服务地址 # 可选 - 认证 api_key="your-api-key", # Hindsight 认证密钥 # 可选 - 记忆行为 store_conversations=True, # LLM 调用后是否存储对话 inject_memories=True, # 是否把相关记忆注入 prompt sync_storage=False, # False = 异步存储(默认,性能更好) # True = 同步存储(阻塞,立即抛出错误) # 可选 - 高级 injection_mode="system_message", # 注入方式:"system_message" 或 "prepend_user" excluded_models=["gpt-3.5*"], # 排除被拦截的模型(fnmatch 通配符) verbose=True, # 开启详细日志与调试信息 )源码细节补充:
hindsight_api_url默认指向https://api.hindsight.vectorize.io(云端默认地址,见 config.py);api_key不传时会自动读取HINDSIGHT_API_KEY环境变量(HINDSIGHT_API_KEY_ENV);- 额外支持
mission与bank_name参数——传入时会立即调用 Hindsight 创建/更新 memory bank(_create_or_update_bank); configure()还接受全部逐调用默认值参数(bank_id、budget、session_id等),一套调用即可完成全部初始化。
2.set_defaults()——逐调用默认值
hindsight_litellm.set_defaults( # 必填 bank_id="my-agent", # 记忆银行 ID # 可选 - 记忆检索 budget="mid", # 预算级别:"low"、"mid"、"high" fact_types=["world", "observation"], # 过滤要检索的事实类型 max_memories=10, # 最多注入的记忆条数(None = 不限制) max_memory_tokens=4096, # 记忆上下文的最大 token 数 include_entities=True, # 检索时是否包含实体观察 # 可选 - Reflect 模式 use_reflect=True, # 用 reflect API(综合)还是 recall(原始记忆) reflect_include_facts=False, # 是否在调试信息中包含源事实 reflect_context="I am a delivery agent finding recipients.", # reflect 推理上下文 reflect_response_schema={...}, # reflect 结构化输出的 JSON Schema # 可选 - 调试 trace=False, # 开启 trace 信息 document_id="conversation-1", # 用于对话分组的文档 ID )源码细节补充:
budget的合法值由VALID_BUDGETS = {"low", "mid", "high"}校验,传入其他值会直接抛ValueError;fact_types可取值world、experience、observation;- 关于
document_id:新版推荐改用session_id(两者都设置时session_id优先,见effective_document_id属性),设置后 Hindsight 走 UPSERT 语义实现会话分组; set_defaults()仅更新传入字段、保留其余默认值,未配置时还会自动触发一次默认configure()。
3. 逐调用覆盖(hindsight_*kwargs)
任意默认值都能在单次调用中用hindsight_前缀参数覆盖:
response = hindsight_litellm.completion( model="gpt-4o-mini", messages=[...], hindsight_query="Where is Alice located?", # 自定义记忆检索查询 hindsight_reflect_context="Currently on floor 3", # 本次调用的 reflect 上下文 # hindsight_bank_id="other-bank", # 覆盖本次调用的 bank_id )该机制的通用性来自_merge_call_settings(config.py):它读取HindsightCallSettingsdataclass 的全部字段,自动把hindsight_*kwargs 合并进默认设置——新增字段无需改动合并逻辑。
Bank 任务配置:set_bank_mission
用set_bank_mission()告诉记忆银行该学习和记住什么(用于心理模型 mental model 的生成):
hindsight_litellm.set_bank_mission( mission="""This agent routes customer support requests to the appropriate team. Remember which types of issues should go to which teams (billing, technical, sales). Track customer preferences for communication channels and past issue resolutions.""", name="Customer Support Router", # 可选显示名 )源码中该方法(config.py)会先解析bank_id(参数 → 当前默认值 → 报错),然后调用hindsight_client的create_bank创建或原地更新银行。
多 Provider 支持:一套记忆,百种模型
由于注入与存储发生在 LiteLLM 层,任何 LiteLLM 支持的提供方都直接可用,无需额外适配:
import hindsight_litellm hindsight_litellm.configure(hindsight_api_url="http://localhost:8888") hindsight_litellm.set_defaults(bank_id="my-agent") hindsight_litellm.enable() messages = [{"role": "user", "content": "Hello!"}] # OpenAI hindsight_litellm.completion(model="gpt-4o", messages=messages, hindsight_query="greeting") # Anthropic hindsight_litellm.completion(model="claude-sonnet-4-20250514", messages=messages, hindsight_query="greeting") # Groq hindsight_litellm.completion(model="groq/llama-3.1-70b-versatile", messages=messages, hindsight_query="greeting") # Azure OpenAI hindsight_litellm.completion(model="azure/gpt-4", messages=messages, hindsight_query="greeting") # AWS Bedrock hindsight_litellm.completion(model="bedrock/anthropic.claude-3", messages=messages, hindsight_query="greeting") # Google Vertex AI hindsight_litellm.completion(model="vertex_ai/gemini-pro", messages=messages, hindsight_query="greeting")如果某些模型不想被记忆逻辑拦截,可用configure(excluded_models=["gpt-3.5*"])排除——_is_model_excluded(init.py)用fnmatch通配符匹配模型名,命中则直接透传原始 LiteLLM 调用。
直接记忆 API:不调 LLM 也能读写记忆
集成提供与注入链路同源的底层 API,可手动查询、综合、存储记忆:
Recall——查询原始记忆
from hindsight_litellm import configure, set_defaults, recall configure(hindsight_api_url="http://localhost:8888") set_defaults(bank_id="my-agent") memories = recall("what projects am I working on?", budget="mid") for m in memories: print(f"- [{m.fact_type}] {m.text}")Reflect——获取综合上下文
from hindsight_litellm import configure, set_defaults, reflect configure(hindsight_api_url="http://localhost:8888") set_defaults(bank_id="my-agent") result = reflect("what do you know about the user's preferences?") print(result.text) # 用 context 塑造回答(不影响检索) result = reflect( query="what do I know about Alice?", context="I am a delivery agent looking for package recipients.", )Retain——存储记忆
from hindsight_litellm import configure, set_defaults, retain, get_pending_retain_errors configure(hindsight_api_url="http://localhost:8888") set_defaults(bank_id="my-agent") # 异步 retain(默认)- 快速、不阻塞;实际存储发生在后台 result = retain( content="User mentioned they're working on a machine learning project", context="Discussion about current projects", ) # 同步 retain - 阻塞直到完成,出错立即抛出 result = retain( content="Critical information that must be stored", context="Important data", sync=True, ) # 定期检查异步 retain 的错误 errors = get_pending_retain_errors() if errors: for e in errors: print(f"Background retain failed: {e}")异步 API
from hindsight_litellm import arecall, areflect, aretain memories = await arecall("what do you know about me?") context = await areflect("summarize user preferences") result = await aretain(content="New information to remember")异步能力(0.5.0 加入)背后是 wrappers.py 的实现:recall/reflect/retain等同步 API 通过_async.py中的ensure_loop/run_sync桥接到hindsight-client的异步接口。_async.py采用每线程一个自有事件循环的设计:显式new_event_loop+set_event_loop,既规避了 Python 3.12+ 对get_event_loop()的 DeprecationWarning(3.14 起直接移除),又保证 client 缓存的 aiohttp 会话始终绑定在存活的事件循环上,跨多次同步调用可复用(详见 _async.py)。
原生客户端包装器:wrap_openai 与 wrap_anthropic
不想经过 LiteLLM 时,可以直接包装 OpenAI / Anthropic 原生 SDK:
from openai import OpenAI from hindsight_litellm import wrap_openai client = OpenAI() wrapped = wrap_openai( client, bank_id="my-agent", hindsight_api_url="http://localhost:8888", ) response = wrapped.chat.completions.create( model="gpt-4", messages=[{"role": "user", "content": "What do you know about me?"}] )from anthropic import Anthropic from hindsight_litellm import wrap_anthropic client = Anthropic() wrapped = wrap_anthropic( client, bank_id="my-agent", hindsight_api_url="http://localhost:8888", ) response = wrapped.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, messages=[{"role": "user", "content": "Hello!"}] )流式响应支持
stream=True完全受支持。检测到流式响应时,集成会把响应自动包装起来,边消费边收集 chunk;当流被完整消费(或上下文管理器退出)后,整段对话才写入 Hindsight。
三种模式下的行为差异(对应 0.5.2 修复的流式存储问题):
- Monkeypatch 包装(
enable()/completion()/acompletion()):流式响应被透明包装。同步侧由_LiteLLMStreamWrapper、异步侧由_LiteLLMAsyncStreamWrapper(均在init.py)负责收集 chunk,在StopIteration/StopAsyncIteration或__exit__/close时把累积的助手输出与消息历史拼接后存储; - 原生客户端包装器(
wrap_openai()、wrap_anthropic()):同样的 chunk 收集行为; - 回调处理器:流式响应会被跳过(回调无法控制返回值,拿不到完整流),因此需要流式 + 存储时请使用 monkeypatch 或原生包装器模式。
调试模式与错误追踪
查看注入了什么记忆
开启verbose=True后,可用get_last_injection_debug()检查最近一次注入的细节:
from hindsight_litellm import configure, set_defaults, enable, completion, get_last_injection_debug configure(hindsight_api_url="http://localhost:8888", verbose=True) set_defaults(bank_id="my-agent", use_reflect=True) enable() response = completion( model="gpt-4o-mini", messages=[{"role": "user", "content": "What's my favorite color?"}], hindsight_query="What is the user's favorite color?", ) debug = get_last_injection_debug() if debug: print(f"Mode: {debug.mode}") # "reflect" 或 "recall" print(f"Injected: {debug.injected}") # True/False print(f"Results: {debug.results_count}") print(f"Memory context:\n{debug.memory_context}") if debug.error: print(f"Error: {debug.error}")对应的InjectionDebugInfodataclass 定义在init.py,除上述字段外还包含query、bank_id、reflect_text、reflect_facts(当reflect_include_facts=True时从 reflect 响应的based_on中抽取)、recall_results等。可用clear_injection_debug()清空。
严格错误处理
与 LiteLLM 原生回调(静默吞异常)不同,本集成采用严格错误处理(模块 docstring 明确说明):当inject_memories=True且 recall/reflect 失败,或store_conversations=True且存储失败时,会抛出HindsightError并传播到你的代码。同时提供get_pending_retain_errors()与get_pending_storage_errors()两个函数,分别收集后台 retain 与后台对话存储的异步错误。
上下文管理器与清理
hindsight_memory 上下文管理器
from hindsight_litellm import hindsight_memory import litellm with hindsight_memory(bank_id="user-123"): response = litellm.completion( model="gpt-4", messages=[{"role": "user", "content": "Hello!"}], hindsight_query="greeting context", ) # 上下文退出后记忆集成自动关闭这里正是 0.5.4 修复的重点:上下文管理器退出时必须原子地恢复全局配置快照。源码中_restore_config(config.py)专门用于此场景——直接还原保存的配置对象,绕过configure()的副作用(告警、bank 创建等),确保with块内设置的bank_id等配置不会泄漏到块外。
禁用与清理
from hindsight_litellm import disable, cleanup # 临时禁用记忆集成(恢复原始 litellm.completion / acompletion) disable() # 关闭时清理所有资源 cleanup()enable()在实现上会猴子补丁litellm.completion与litellm.acompletion(保存原函数引用后替换为_wrapped_completion/_wrapped_acompletion),disable()则恢复原函数并关闭缓存的 HTTP 客户端。cleanup()依次执行disable()、清理回调、重置配置。需要特别注意的是:enable()与HindsightCallback是互斥的注入路径——enable()检测到litellm.callbacks中已有HindsightCallback时会发出RuntimeWarning,因为两者并存会导致记忆被重复注入两次。
API 速查表
主函数
| 函数 | 说明 |
|---|---|
configure(...) | 配置静态 Hindsight 设置(API URL、认证、存储选项) |
set_defaults(...) | 设置逐调用默认值(bank_id、budget、reflect 选项) |
enable() | 启用 LiteLLM 记忆集成 |
disable() | 禁用记忆集成 |
is_enabled() | 检查记忆集成是否启用 |
cleanup() | 清理所有资源 |
配置函数
| 函数 | 说明 |
|---|---|
get_config() | 获取当前静态配置 |
get_defaults() | 获取当前逐调用默认值 |
is_configured() | 检查是否已配置 bank_id |
reset_config() | 将所有配置重置为默认 |
set_document_id(id) | 便捷更新 document_id |
set_bank_mission(...) | 设置记忆银行的任务(用于心理模型) |
记忆函数
| 函数 | 说明 |
|---|---|
recall(query, ...) | 查询原始记忆(同步) |
arecall(query, ...) | 查询原始记忆(异步) |
reflect(query, ...) | 获取综合记忆上下文(同步) |
areflect(query, ...) | 获取综合记忆上下文(异步) |
retain(content, sync=False, ...) | 存储记忆(默认异步,sync=True阻塞) |
aretain(content, ...) | 存储记忆(异步) |
错误追踪与调试
| 函数 | 说明 |
|---|---|
get_pending_retain_errors() | 获取并清除后台 retain 的错误 |
get_pending_storage_errors() | 获取并清除后台对话存储的错误 |
get_last_injection_debug() | 获取最近一次记忆注入的调试信息 |
clear_injection_debug() | 清空已存调试信息 |
客户端包装器
| 函数 | 说明 |
|---|---|
wrap_openai(client, ...) | 为 OpenAI 客户端包装记忆能力 |
wrap_anthropic(client, ...) | 为 Anthropic 客户端包装记忆能力 |
版本演进时间线:0.5.0 → 0.5.4
以下内容完整继承自 集成变更日志,并结合当前仓库源码逐条展开说明。
v0.5.4 —— 注入行为与状态恢复的可靠性修复
Bug Fixes
- 修正注入模式(injection mode)行为,确保上下文管理器状态能被正确恢复,并使校验/错误处理保持一致。对应代码层面即
MemoryInjectionMode(system_message/prepend_user)两种路径的注入实现与_restore_config原子恢复逻辑的校正; - 该版本同时体现了"校验与错误一致"的工程原则:
budget与recall_tags_match在configure()/set_defaults()双入口都做VALID_BUDGETS/VALID_TAGS_MATCH校验,保证错误在任何配置路径下行为一致。
v0.5.3 —— 内部维护
该版本仅包含内部维护与基础设施变更,无面向用户的 API 或行为改动。
v0.5.2 —— 流式对话存储修复
Bug Fixes
- 修复使用 LiteLLM 流式响应时对话存储失效的问题。这正是前文"流式响应支持"一节描述的
_LiteLLMStreamWrapper/_LiteLLMAsyncStreamWrapper引入的背景——流式响应没有.choices属性,早期实现(包括回调路径的_plan_store)无法从中提取助手输出,0.5.2 通过包装流、边消费边收集 chunk 的方式,在流完全消费后再把完整对话写入 Hindsight。
v0.5.1 —— 类型信息、依赖安全与请求标识
Improvements
- 打包内置类型信息(
py.typed文件),在类型化 Python 工程中使用集成时获得更好的类型检查支持; - 更新并约束 LiteLLM 依赖,包括排除一个被攻陷的版本——对应 pyproject.toml 中把
litellm下限提到 1.93.0(非 macOS)并注释了 GHSA-* 系列供应链安全公告的处理。
Bug Fixes
- 在所有 HTTP 请求上设置可识别的 User-Agent 头,提升与各 Provider 和代理的兼容性。对应 config.py 中的
USER_AGENT = f"hindsight-litellm/{_VERSION}",该值通过Hindsight(base_url=..., user_agent=USER_AGENT)传入客户端。
v0.5.0 —— 集成首版:流式、异步与 API 清理
Features
- 新增 LiteLLM 包装集成下的流式支持(见上文流式一节);
- 新增异步 retain 与 reflect 支持,并清理 LiteLLM 集成 API——即
aretain/areflect(以及arecall)与_async.py的同步→异步桥接层; - Hindsight LiteLLM 集成实现的首个发布版本。
Improvements
- 支持通过 LiteLLM 集成发送 tags 与 mission 元数据,改善记忆的组织与检索——对应
HindsightCallSettings.tags(存储时附加标签)与recall_tags/recall_tags_match(检索时按标签过滤,支持any/all/any_strict/all_strict四种匹配模式),以及set_bank_mission()的记忆银行任务配置。
Bug Fixes
- 未提供显式 Hindsight 查询时,改用最近一条用户消息作为查询,避免记忆检索为空——即前文所述查询解析回退链:
hindsight_query→defaults.query→ 最后一条 user 消息; - 修复 API key 处理:把配置的
api_key正确传递给 Hindsight 客户端——对应init.py 中创建客户端时显式传递config.api_key的注释说明(托管后端对无 key 的 recall/reflect 会以 401 拒绝)。
运行前提
- Python >= 3.10;
- litellm >= 1.83.0(当前仓库实际要求非 macOS 平台
>=1.93.0,macOS 为>=1.91.3,<1.92,详见 pyproject.toml); - 一个运行中的 Hindsight API 服务(本地
http://localhost:8888或云端默认地址)。
测试与验证
仓库在 hindsight-integrations/litellm/tests 下提供了覆盖完整的测试套件,包括test_integration.py(配置管理、enable/disable 生命周期、注入行为等)、test_config.py、test_async.py、test_callback_async_http.py与test_e2e.py。其中端到端测试通过 pytest markerrequires_real_llm标记,需要真实 Hindsight 服务与真实 LLM Provider 密钥,可用-m 'not requires_real_llm'在确定性 CI 中排除、用-m requires_real_llm单独运行(见 pyproject.toml 的 marker 定义)。测试覆盖了configure全参数、is_configured的三种判定路径、reset_config等关键行为,可作为集成接入时的回归验证参考。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考