
用 Hindsight 记忆构建个性化搜索 Agentretain / recall / reflect 实战配方【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight本文是 Hindsight Cookbook 系列中personalized_search配方的完整实战指南。它将带你用 Hindsight 的记忆能力retain/recall/reflect构建一个认识你的搜索助手——它会记住你的位置、饮食限制、生活方式与过往搜索在每次搜索前自动检索相关偏好、改写查询并生成个性化摘要。读完本文你将掌握 Hindsight 三大核心 API 的实际用法、本地 Docker 部署方式以及一个可直接复制运行、还能自由扩展的搜索记忆系统。一、配方概览搜索为什么需要记忆通用搜索引擎对所有用户返回相同结果而本配方要解决的核心问题是同一个查询如何为不同用户返回不同答案。答案在于给搜索过程加一层记忆记忆写入retain把用户偏好、历史搜索交互写入 Hindsight 的 memory bank记忆读取recall在搜索前按查询语义召回相关偏好与历史作为上下文注入 LLM记忆综合reflect让 Hindsight 基于整库记忆生成用户画像摘要用于审视系统学到了什么。本配方实现的个性化搜索功能特性如下学习位置location、饮食限制dietary restrictions与生活方式lifestyle基于上下文个性化搜索查询enhanced query记住过往搜索与偏好可选集成 Tavily 进行真实网页搜索未配置时自动降级为模拟结果。整个配方以 Jupyter Notebook 形式组织本仓库 cookbook 目录下同系列配方还包括 per-user-memory.md、personal_assistant.md、quickstart.md 等可互相参照你也可以直接把它整理为一个 Python 脚本运行。二、前置条件在动手之前你需要准备OpenAI API key同时用于 Hindsight 服务端的 retain/recall/reflect 语义处理与演示代码的查询增强/摘要生成Hindsight 本地实例通过 Docker 启动见下一节Tavily API key可选仅当你希望执行真实网页搜索时使用不配置则演示使用模拟搜索结果。依赖库方面配方只用到hindsight-clientHindsight 官方 Python 客户端、openai、可选的tavily-python以及nest-asyncio让 Jupyter/脚本中能安全运行异步代码。三、本地启动 HindsightDocker在运行 Notebook 之前先在终端启动 Hindsight 服务export OPENAI_API_KEYyour-openai-api-key docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \ -e HINDSIGHT_API_LLM_API_KEY$OPENAI_API_KEY \ -e HINDSIGHT_API_LLM_MODELgpt-4o-mini \ -v $HOME/.hindsight-docker:/home/hindsight/.pg0 \ ghcr.io/vectorize-io/hindsight:latest几个关键点需要说明端口约定容器暴露了两个端口8888是 Hindsight HTTP API客户端连接入口9999是控制平面Control PlaneWeb UI。这一端口约定在整个仓库中保持一致——例如 docker/docker-compose/local-llm/docker-compose.yaml 与 docker/docker-compose/custom-models/docker-compose.yaml 都映射了8888:8888与9999:9999docker/standalone/Dockerfile 中同样通过EXPOSE 8888与ENV HINDSIGHT_API_PORT8888固定 API 端口。启动完成后客户端应连接http://localhost:8888。环境变量HINDSIGHT_API_LLM_API_KEY与HINDSIGHT_API_LLM_MODEL告诉服务端用哪个模型处理记忆的写入、检索与综合此处示例为gpt-4o-mini。数据持久化-v $HOME/.hindsight-docker:/home/hindsight/.pg0把 Hindsight 内置的 PostgreSQL 数据目录pg0挂载到宿主机容器重启后记忆不丢失。如果不想用 Docker 单容器镜像仓库还提供了完整的 docker/docker-compose 多服务编排与 docker/standalone 独立部署脚本适用于接入外部 PostgreSQL、向量扩展、自托管 LLM 等不同场景本配方直接用官方镜像即可。四、安装依赖与配置 API Key4.1 安装依赖# Tavily is optional - demo works with simulated results if not installed !pip install -q hindsight-client openai tavily-python nest-asyncio其中hindsight-client即仓库 hindsight-clients/python 目录维护的官方 Python 客户端上层是手写维护、易用的Hindsight包装类hindsight_client.py底层是基于 OpenAPI 自动生成的完整 API 客户端hindsight_client_api。4.2 配置 API Keyimport getpass import os # Set OpenAI API key (used by both Hindsight and the demo) if not os.getenv(OPENAI_API_KEY): os.environ[OPENAI_API_KEY] getpass.getpass(Enter your OpenAI API key: ) # Tavily is optional - for real web search if not os.getenv(TAVILY_API_KEY): tavily_key getpass.getpass(Enter your Tavily API key (or press Enter to skip): ) if tavily_key: os.environ[TAVILY_API_KEY] tavily_key print(API keys configured!)注意OpenAI API key 是必需的它同时服务于两端——Hindsight 服务端负责记忆的语义化处理演示代码负责查询改写与摘要生成。Tavily 则完全是可选项跳过即可用模拟结果跑通全流程。五、初始化客户端连接本地 Hindsightimport nest_asyncio nest_asyncio.apply() from openai import OpenAI from hindsight_client import Hindsight # Initialize Hindsight client (connects to local Docker instance) hindsight Hindsight( base_urlos.getenv(HINDSIGHT_BASE_URL, http://localhost:8888), ) openai_client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) # Optional: Tavily for real web search try: from tavily import TavilyClient tavily TavilyClient(api_keyos.getenv(TAVILY_API_KEY)) HAS_TAVILY True print(Tavily configured - using real web search!) except (ImportError, Exception) as e: HAS_TAVILY False print(Note: Using simulated search results (Tavily not configured)) USER_ID search-user-demo print(Clients initialized!)从源码看Hindsight构造函数接受base_url、可选的api_key作为 Bearer token 注入 Authorization 头、请求超时timeout默认 300 秒与user_agent等参数见 hindsight_client.py。本配方中所有记忆都写入同一个bank_idsearch-user-demo这就是按用户隔离记忆的体现——每个用户/租户对应一个 memory bank天然支持多用户场景。六、三个核心 APIretain / recall / reflect在进入业务函数之前先理解本配方依赖的三大记忆操作。它们对应 HTTP API 的 memory 端点并在 Python 客户端中都有同步retain/recall/reflect与异步aretain/arecall/areflect两种形式同步版本适合脚本与 REPL。6.1 retain —— 写入记忆retain(bank_id, content, metadata, ...)把一条记忆写入指定 bank服务端会自动完成分块、嵌入与事实抽取。常用参数见 hindsight_client.py参数含义bank_id目标 memory bank 的唯一标识content记忆内容纯字符串或有序的 content block 列表多模态附件需要服务端 vision 能力timestamp可选事件时间戳context可选的上下文描述document_id可选用于对记忆分组metadata用户自定义元数据dict[str, str]本配方用它标注categoryentities/resolve_entities显式实体标注以及是否与 bank 已有实体解析对齐tags可选标签recall/reflect 时可按标签过滤retain_async/operation_id异步处理与幂等重试支持6.2 recall —— 语义召回记忆recall(bank_id, query, budget, ...)用语义相似度检索相关记忆返回RecallResponse其results是RecallResult列表每项至少包含id与text字段见 recall_response.py 与 recall_result.py所以代码中可以直接取m.text拼上下文。常用参数见 hindsight_client.py参数含义query检索查询语义匹配budget召回预算low/mid/high默认mid控制召回多少内容对应枚举定义见 budget.pytypes事实类型过滤world/experience/observationmax_tokens结果最大 token 数默认 4096tags/tags_match标签过滤与匹配模式any/all/any_strict/all_strict/exactmin_scores各阶段分数下限如{semantic: 0.2, final: 0.5}include_entities/include_chunks/include_source_facts是否附带实体观察、原始分块、来源事实temporal_window时间窗口用于时间感知检索6.3 reflect —— 基于记忆生成回答reflect(bank_id, query, budget, ...)基于 bank 的身份与全部记忆生成上下文相关的回答返回ReflectResponse其text字段是格式良好的 Markdown 文本见 reflect_response.py。除budget默认low外还可传response_schema做结构化输出、include_facts返回based_on依据、tags过滤等见 hindsight_client.py。一句话总结三者分工retain让系统记住recall让系统想起reflect让系统总结与作答。本配方正是用这三个原语拼出完整记忆闭环。七、定义辅助函数记忆驱动的搜索流水线本配方把整条流水线封装为 5 个辅助函数逐一看它们的职责与实现。7.1 存储偏好与交互记录def store_preference(preference: str) - str: Store a user preference. hindsight.retain( bank_idUSER_ID, contentfUser preference: {preference}, metadata{category: preference}, ) return fLearned: {preference} def store_interaction(query: str, response: str) - None: Store a search interaction. hindsight.retain( bank_idUSER_ID, contentfSearch query: {query}\nResult highlights: {response[:200]}, metadata{category: search_history}, )两个写入函数都依赖retain并通过metadata[category]区分记忆类型——preference用户偏好与search_history搜索历史。由于metadata支持任意键值对后续可以按类别筛选、审计或做标签化管理。store_interaction只截取回答前 200 字符写入避免把冗长回答整段塞进记忆这是控制记忆体积的实用技巧。7.2 召回用户上下文def get_user_context(query: str) - str: Retrieve relevant user context. memories hindsight.recall( bank_idUSER_ID, queryfpreferences location dietary lifestyle {query}, budgetmid, ) if memories and memories.results: return \n.join(f- {m.text} for m in memories.results[:6]) return 这里有两个值得学习的细节查询增强在用户原始查询前拼接preferences location dietary lifestyle等提示词引导语义检索偏向偏好类记忆——这是基于向量检索特性的工程技巧预算与截断budgetmid控制召回量级再取results[:6]收紧到最多 6 条作为上下文防止 prompt 过长。7.3 个性化搜索主流程def personalized_search(query: str) - str: Perform a personalized search. user_context get_user_context(query) enhancement_prompt fGiven this users preferences and the search query, suggest how to enhance the search. User preferences: {user_context if user_context else No preferences recorded yet.} Search query: {query} Return a JSON object with: - enhanced_query: The improved search query incorporating relevant preferences - filters: Any specific filters to apply (e.g., vegetarian, within 5 miles) - reasoning: Brief explanation of personalizations applied enhancement openai_client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: enhancement_prompt}], temperature0.3, max_tokens300, ) enhanced_info enhancement.choices[0].message.content # Perform the search if HAS_TAVILY: search_results tavily.search( queryquery, search_depthadvanced, max_results5, ) results_text \n.join( f- {r[title]}: {r[content][:150]}... for r in search_results.get(results, []) ) else: results_text f[Simulated search results for: {query}] response_prompt fBased on the search results and user preferences, provide a personalized summary. User preferences: {user_context if user_context else No preferences recorded yet.} Query: {query} Search enhancement applied: {enhanced_info} Search results: {results_text} Provide a helpful, personalized response that takes into account their preferences. response openai_client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: response_prompt}], temperature0.7, max_tokens500, ) answer response.choices[0].message.content store_interaction(query, answer) return answer该函数完整呈现了记忆 → 查询改写 → 检索 → 个性化摘要 → 记忆回写的闭环取上下文get_user_context(query)召回相关偏好查询增强让 LLM 基于偏好输出结构化的enhanced_query/filters/reasoning温度 0.3 保证稳定输出执行搜索配置了 Tavily 时调用tavily.search(search_depthadvanced, max_results5)取真实结果否则用模拟文本占位——这保证了配方在无 Tavily key 时也能端到端跑通个性化摘要把偏好、增强信息、检索结果一起交给 LLM 生成贴合用户需求的回答温度 0.7 让表达更自然记忆回写store_interaction(query, answer)把本次交互写回记忆形成越用越懂你的正反馈。注意这里的enhanced_info与results_text都是文本摘要未强制 JSON 解析——enhanced_query等内容主要通过 prompt 约束生成演示更侧重流程完整性。生产环境可要求response_format{type: json_object}并做严格解析。7.4 生成用户偏好画像def get_preference_profile() - str: Get a summary of the users preference profile. profile hindsight.reflect( bank_idUSER_ID, querySummarize what we know about this user: - Location and neighborhood - Dietary preferences and restrictions - Work style and schedule - Hobbies and interests - Family situation - Shopping preferences, budgethigh, ) return profile.text if hasattr(profile, text) else str(profile)这一步用reflect让 Hindsight 基于整库记忆综合出结构化的用户画像。budgethigh意味着给综合过程更大的召回与生成预算适合汇总全貌这类需要全面视角的任务。hasattr(profile, text)是防御性写法——ReflectResponse的text字段是 Markdown 格式的回答见 reflect_response.py直接打印即可得到可读画像。八、构建用户画像写入首批偏好一切就绪后先向 Hindsight 写入一批模拟用户偏好作为系统学习的第一手素材print(Learning user preferences...) preferences [ Lives in San Francisco, Mission District, Works remotely as a software engineer, Vegetarian, prefers organic food when possible, Has a 5-year-old daughter named Emma, Enjoys hiking and outdoor activities on weekends, Prefers quiet coffee shops for remote work, Lactose intolerant, uses oat milk, Interested in sustainable and eco-friendly products, Usually free on Tuesday and Thursday afternoons, Husband is allergic to nuts, ] for pref in preferences: result store_preference(pref) print(f {result})这 10 条偏好覆盖了位置、职业、饮食、家庭、爱好、购物倾向等多维信息每条都会以metadata{category: preference}写入search-user-demo这个 bank。它们是后续个性化搜索的知识底座。九、验证效果个性化搜索结果记忆就绪后运行三个典型的个性化搜索import time print( * 60) print( Personalized Search Results) print( * 60) searches [ Find a good coffee shop for working remotely, Restaurant recommendations for a family dinner, Birthday gift ideas for a 5-year-old, ] for query in searches: print(f\nSearch: {query}) print(- * 40) result personalized_search(query) print(result) time.sleep(1)观察三个查询理解个性化如何发生作用Find a good coffee shop for working remotely应命中Prefers quiet coffee shops for remote work与Works remotely从而倾向于推荐安静的、适合办公的咖啡店Restaurant recommendations for a family dinner应命中素食、乳糖不耐、丈夫坚果过敏、5 岁女儿等信息从而过滤掉含坚果、乳制品的餐厅并考虑家庭友好Birthday gift ideas for a 5-year-old应命中女儿 Emma 的年龄与爱好如户外活动给出适龄且贴合兴趣的礼物建议。time.sleep(1)是为了避免连续请求过密。若配置了 Tavily这里会返回真实网页搜索结果的个性化摘要否则返回基于模拟结果的演示文本——两种模式都能展示偏好注入的效果。十、查看偏好画像检验系统学到了什么print( * 60) print( User Preference Profile) print( * 60) print(get_preference_profile())这一步通过reflect(budgethigh)让 Hindsight 把散落的记忆综合成一份连贯的用户画像。它既是效果检验——确认系统确实学到了正确信息也是能力演示——体现 reflect 与简单拼接式检索的本质区别reflect 不是列出一堆记忆原文而是基于记忆生成有结构的归纳性回答。配合reflect的include_factsTrue参数还能进一步拿到based_on字段追溯画像中每个结论依据了哪些具体记忆。十一、输入你自己的搜索词配方最后留了一个自由发挥入口把任意查询换成你自己的问题your_search Best hiking trails near me # Change this! print(fSearch: {your_search}) print(- * 40) print(personalized_search(your_search))例如把查询改为 Best hiking trails near me系统应结合Enjoys hiking and outdoor activities on weekendsLives in San Francisco, Mission District等偏好给出旧金山 Mission District 附近、周末可去的徒步路线建议——这正是个性化搜索与普通搜索的体验差异所在。此外由于每次搜索都会通过store_interaction回写记忆多跑几次后系统对用户的了解会持续加深。十二、清理与收尾hindsight.close() print(Client connection closed.)close()关闭底层 HTTP 连接。在异步环境如 FastAPI、LangGraph中客户端还提供aclose()与全套a*异步方法aretain/arecall/areflect应优先使用异步版本以避免阻塞事件循环详见 hindsight_client.py 的文档说明。由于记忆持久化在~/.hindsight-docker挂载卷中即使关闭客户端甚至重启容器search-user-demo这个 bank 的数据依然保留——再次运行 Notebook 时系统仍记得上次学到的偏好。十三、进阶扩展方向本配方是一个最小可用闭环基于它你可以自然延伸多用户隔离每个用户使用独立bank_id即可零改动扩展为多用户搜索助手参考同系列 per-user-memory.md 配方中的多用户模式标签化记忆治理retain支持tagsrecall/reflect支持tags_matchany/all/any_strict/all_strict/exact可以为不同类别记忆打标签并精准过滤结构化输出reflect的response_schema参数支持 JSON Schema 结构化输出把画像生成从文本摘要升级为字段规整的用户档案异步化改造把脚本改造为异步版本aretain/arecall/areflect可嵌入 FastAPI 服务、LangGraph 或 CrewAI 等 Agent 框架真实搜索增强接入 Tavily 之外还可以把enhanced_query真正用于改写后的搜索词、把filters转化为搜索 API 的结构化过滤参数记忆质量优化通过create_bank的enable_observations、enable_reranking、enable_temporal_retrieval等 bank 级开关见 hindsight_client.py按业务需求调节记忆的观察综合、重排与时间感知能力。总结本配方完整演示了 Hindsight Agent Memory That Learns 的核心循环用retain沉淀偏好与交互、用recall在搜索前唤起相关记忆、用reflect综合生成画像与个性化回答并以 Tavily可选作为真实搜索源。对照本仓库源码可以确认budget的low/mid/high取值、RecallResponse.results[].text、ReflectResponse.text等接口细节均与 Python 客户端实现一致。将这套模式扩展到垂直搜索、推荐、客服等场景即可构建出越用越懂用户的下一代搜索体验。【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考