Hindsight AI SDK 集成指南:基于 Changelog 解读 @vectorize-io/hindsight-ai-sdk 的持久化记忆接入与版本演进
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
本篇文章以仓库中 Vercel AI SDK Changelog 为核心骨架,结合 AI SDK 集成完整文档、集成包源码 与 测试用例,系统讲解@vectorize-io/hindsight-ai-sdk如何为 Vercel AI SDK 应用注入长期记忆能力,以及 0.4.20 → 0.5.1 三个版本的关键演进与背后实现原理。读完本文,你将掌握五个记忆工具的完整用法、构造函数选项语义、四种典型接入场景,以及类型兼容性修复的来龙去脉。
一、Changelog 总览:一条记忆集成能力的演进主线
官方 Changelog 页面以 "Vercel AI SDK Changelog" 为标题,副标题明确其定位:@vectorize-io/hindsight-ai-sdk — memory integration for Vercel AI SDK。目前共收录 3 个版本,演进脉络清晰:
| 版本 | 类型 | 核心变更 |
|---|---|---|
| 0.4.20 | 里程碑 | 首次引入 AI SDK 集成;为 TypeScript 客户端增加 Deno 兼容性;改进 AI SDK 工具支持;修复影响集成的依赖安全漏洞 |
| 0.5.0 | 兼容性 | 改进与 Hindsight Client v0.5.2 的兼容性,避免使用 AI SDK 时出现集成不匹配 |
| 0.5.1 | 类型修复 | 修复 AI-SDK reflection 工具类型定义,使其与 OpenAPI 规范一致,集成行为更可靠 |
从版本节奏可以看出,该集成包在功能落地(0.4.20)之后,将工作重心转向生态兼容(与客户端版本对齐)与规范对齐(与 OpenAPI 类型一致)——这正是生产级集成库的典型演化路径。下文将依次深入每一个版本,并联动源码解释其实际影响。
二、v0.4.20:AI SDK 集成诞生与 Deno 兼容
0.4.20 是该集成包的起点,包含四项变更,分别对应四个 Commit:
1. 新增 AI SDK 集成(7e339e16)
集成包位于仓库hindsight-integrations/ai-sdk目录,package.json声明其名称为@vectorize-io/hindsight-ai-sdk(版本 0.5.1),描述为 "Hindsight memory integration for Vercel AI SDK - Give your AI agents persistent, human-like memory",许可证为 MIT。关键工程约束:
- peerDependencies:
ai ^6.0.0、zod ^3.0.0 || ^4.0.0,即面向 AI SDK 6.x 及现代 Zod 版本; - engines:
node >= 22; - 模块格式:ESM(
"type": "module"),通过tsup构建出dist/index.js与类型声明dist/index.d.ts; - 源码结构极简:
src/index.ts仅做导出聚合,全部实现集中在 src/tools/index.ts。
2. Deno 兼容性(72c25c97)
为 TypeScript 客户端增加 Deno 兼容。集成包在package.json中提供了专门的测试脚本test:deno:deno test --no-check --allow-all --unstable-sloppy-imports src/tools/index.test.ts,并附带 deno.json 与deno.lock,同时提供 vitest-compat.ts 辅助测试环境适配——说明该集成不仅服务于 Node.js,也面向 Deno 运行时。
3. 工具支持改进(d06a0259)
"Improve AI SDK tool support to make integrations more capable and reliable"——对应到源码,即createHindsightTools返回的五个标准 AI SDKtool对象,每个都带有完整的description、inputSchema(Zod)与execute实现。默认的工具描述在 src/tools/index.ts 中定义:
retain:"Store information in long-term memory. Use this when information should be remembered for future interactions, such as user preferences, facts, experiences, or important context."recall:"Search memory for relevant information. Use this to find previously stored information that can help personalize responses or provide context."reflect:"Analyze memories to form insights and generate contextual answers..."getMentalModel:检索由记忆综合出的心智模型(mental model),比检索原始记忆更快更高效;getDocument:按 ID 精确检索文档(应用状态、用户画像等需要精确取回的结构化数据)。
4. 依赖安全修复(b6a4f17c)
"Security fixes by resolving dependency vulnerabilities affecting the integration." 对应到 package.json 中的overrides字段,可以看到对rollup、picomatch、vite、postcss等构建链依赖的版本锁定与升级(如vite >= 8.0.5、postcss >= 8.5.23 < 9.0.0),这正是该 Commit 在工程层面的落地痕迹。
三、v0.5.0:与 Hindsight Client v0.5.2 的兼容性对齐
0.5.0 只做一件事:改进与 Hindsight Client v0.5.2 的兼容性,防止使用 AI SDK 时出现集成不匹配(Commitbca87412)。
其根源可以从 src/tools/index.ts 中定义的HindsightClient接口看出端倪:集成包并不直接依赖具体的客户端实现,而是声明了一个结构性接口(structural interface),要求客户端提供retain、recall、reflect、getMentalModel、getDocument五个方法。只要官方 TypeScript 客户端(@vectorize-io/hindsight-client)的方法签名随版本演进发生任何参数或返回类型变动,集成就需要同步适配——0.5.0 正是完成这一同步。
从测试角度看,index.test.ts 使用mockClient(对五个方法全部vi.fn()打桩)来验证调用关系,这意味着任何满足该接口的对象都能驱动这些工具,包括自定义 HTTP 客户端。这一点为"灵活客户端"设计提供了测试级证据。
四、v0.5.1:reflection 工具类型定义对齐 OpenAPI 规范
最新版本 0.5.1 修复了AI-SDK reflection 工具的类型定义与 OpenAPI 规范不一致的问题(Commit3d6b3805),目的是让集成行为更可靠。
"reflection 工具"在实现上对应reflect工具及其依赖的类型体系。对照源码可以定位到具体的类型定义:
ReflectResponse(src/tools/index.ts):text+ 可选的based_on;ReflectBasedOn(L77-L81):嵌套的memories(ReflectFact[])、mental_models(含id/text/context)、directives(含id/name/content);ReflectFact(L65-L72):text、type、context、occurred_start/end等字段。
这些结构直接对应后端 OpenAPI 中/reflect端点的响应 schema。该版本修复意味着:此前 AI SDK 侧的类型声明与后端 OpenAPI 返回结构存在字段命名(如based_on与basedOn)或可空性差异,可能导致类型断言出错;修复后,前端 TypeScript 类型与后端规范严格对齐。
配套的测试也覆盖了这些字段的透传行为,例如 index.test.ts 中 "should pass through based_on with mental_models and directives" 验证memories、mental_models、directives三个嵌套结构被完整返回,以及 "should handle null based_on"(L324-L335)验证空响应场景。类型修复与行为测试相互印证,正是"更可靠集成行为"的保证。
五、安装与快速开始
集成文档(docs-integrations/ai-sdk.mdx)给出的安装命令:
npm install @vectorize-io/hindsight-ai-sdk @vectorize-io/hindsight-client ai集成包 README 补充了zod依赖。最简接入示例(来自 README):
import { HindsightClient } from "@vectorize-io/hindsight-client"; import { createHindsightTools } from "@vectorize-io/hindsight-ai-sdk"; import { generateText } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; // 1. 初始化 Hindsight 客户端 const hindsightClient = new HindsightClient({ apiUrl: "http://localhost:8000", }); // 2. 创建记忆工具 const tools = createHindsightTools({ client: hindsightClient }); // 3. 配合 AI SDK 使用 const result = await generateText({ model: anthropic("claude-sonnet-4-20250514"), tools, system: `You have long-term memory. Use: - 'recall' to search past conversations - 'retain' to remember important information - 'reflect' to synthesize insights from memories`, prompt: "Remember that Alice loves hiking and prefers spicy food", }); console.log(result.text);在未启动 Hindsight 服务时,可先用嵌入式模式在本地拉起 API(见 hindsight-embed 与集成包 README):
uvx hindsight-embed@latest -p myapp daemon start # API 默认地址 http://localhost:8000六、五个记忆工具:职责划分与参数语义
集成包注册五个工具。设计上有一个核心原则:bankId在创建时固定,Agent 无法更改;语义输入(记什么、查什么)交给 Agent,基础设施关切(预算、标签、异步模式)由应用在构造时决定。
工具职责总览
| 工具 | Agent 提供 | 构造函数控制 |
|---|---|---|
retain | content、documentId、timestamp、context | async、tags、metadata |
recall | query、queryTimestamp | budget、types、maxTokens、includeEntities、includeChunks |
reflect | query、context | budget |
getMentalModel | mentalModelId | — |
getDocument | documentId | — |
这一"分工"在源码中体现得十分明确。以retain为例(L275-L286),Agent 可见的 Zod schema 只含content(必填)、documentId、timestamp、context四个语义字段;而tags、metadata、async通过闭包从构造选项注入,完全不出现在inputSchema中(L343-L350)。recall同理,Agent 只能传query与queryTimestamp(L289-L295),检索预算、事实类型过滤等由应用锁定。
测试用例 index.test.ts 中 "should always use the bankId from constructor options" 专门验证了bankId的强制固定行为,从测试层面确认了该设计约束。
返回结构要点
recall返回{ results, entities? }:RecallResult含id/text/type/entities/context/occurred_start/occurred_end/mentioned_at/document_id/metadata/chunk_id;开启includeEntities后返回EntityState(实体 ID、规范化名称、观察列表);reflect返回{ text, basedOn? }:text为空时兜底为"No insights available yet."(L388);getMentalModel返回{ content, name, updatedAt },content为空时兜底"No content available yet.";getDocument找不到文档时返回null(测试见 L413-L420)。
七、四种典型接入场景
1. 与generateText搭配(单轮文本生成)
来自 示例代码 的generate-text片段:
import { generateText } from 'ai'; import { openai } from '@ai-sdk/openai'; const { text } = await generateText({ model: openai('gpt-4o'), tools, maxSteps: 5, // 允许多轮工具调用循环 system: 'You are a helpful assistant with long-term memory.', prompt: 'Remember that I prefer dark mode and large fonts.', });maxSteps: 5让模型可以在一次generateText内自主完成"检索 → 回答 → 记忆"的多次工具调用。
2. 与streamText搭配(流式输出)
import { streamText } from 'ai'; const result = streamText({ model: openai('gpt-4o'), tools, maxSteps: 5, system: 'You are a helpful assistant with long-term memory.', prompt: 'What are my display preferences?', }); for await (const chunk of result.textStream) { process.stdout.write(chunk); }3. 与ToolLoopAgent搭配(自主 Agent 循环)
ToolLoopAgent是 AI SDK 6 提供的显式工具循环抽象,配合stepCountIs限定最大步数:
import { generateText, ToolLoopAgent, stepCountIs } from 'ai'; import { openai } from '@ai-sdk/openai'; import { HindsightClient } from '@vectorize-io/hindsight-client'; import { createHindsightTools } from '@vectorize-io/hindsight-ai-sdk'; const client = new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL! }); const agent = new ToolLoopAgent({ model: openai('gpt-4o'), tools: createHindsightTools({ client, bankId: 'user-123' }), stopWhen: stepCountIs(10), system: 'You are a helpful assistant with long-term memory.', }); const result = await agent.generate({ prompt: 'Remember that my favorite editor is Neovim', });4. 在 Next.js Route Handler 中按请求隔离用户(多用户场景)
多用户应用的关键技巧:在每个请求处理函数内部创建tools,让每次请求闭包捕获正确的bankId(通常是userId),避免跨用户串号:
// app/api/chat/route.ts import { streamText } from 'ai'; import { openai } from '@ai-sdk/openai'; import { HindsightClient } from '@vectorize-io/hindsight-client'; import { createHindsightTools } from '@vectorize-io/hindsight-ai-sdk'; const hindsightClient = new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL!, }); export async function POST(req: Request) { const { messages, userId } = await req.json(); // 每次请求都创建 tools,闭包捕获当前用户的 bankId const tools = createHindsightTools({ client: hindsightClient, bankId: userId, }); return streamText({ model: openai('gpt-4o'), tools, maxSteps: 5, system: 'You are a helpful assistant with long-term memory.', messages, }).toDataStreamResponse(); }八、构造函数选项详解
createHindsightTools的完整选项如下(除client与bankId外全部可选,源码定义见 HindsightToolsOptions):
const tools = createHindsightTools({ client, bankId: userId, retain: { async: true, // fire-and-forget,不等待写入完成(默认 false) tags: ['env:prod', 'app:support'], // 附加到每条记忆的标签 metadata: { version: '2.0' }, // 附加到每条记忆的元数据 }, recall: { budget: 'high', // 检索深度:low | mid | high(默认 'mid') types: ['experience', 'world'], // 事实类型过滤(默认全部) maxTokens: 2048, // 返回 token 上限(默认 API 默认值) includeEntities: true, // 包含实体观察(默认 false) includeChunks: true, // 包含原始源块(默认 false) }, reflect: { budget: 'mid', // 综合深度(默认 'mid') maxTokens: 2048, // 响应 token 上限 }, });各工具选项语义汇总(完整表格见 集成文档):
retain:
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
async | boolean | false | fire-and-forget,不等待摄取完成 |
tags | string[] | — | 附加到每条记忆的标签 |
metadata | Record<string, string> | — | 附加到每条记忆的元数据 |
description | string | 内置 | 覆盖展示给模型的工具描述 |
recall:
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
budget | 'low' \| 'mid' \| 'high' | 'mid' | 控制检索深度与延迟 |
types | ('world' \| 'experience' \| 'observation')[] | 全部 | 限制返回的事实类型 |
maxTokens | number | API 默认 | 限制返回总 token |
includeEntities | boolean | false | 结果中包含实体观察 |
includeChunks | boolean | false | 结果中包含原始源块 |
description | string | 内置 | 覆盖工具描述 |
reflect:
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
budget | 'low' \| 'mid' \| 'high' | 'mid' | 控制综合深度与延迟 |
maxTokens | number | API 默认 | 响应最大 token |
description | string | 内置 | 覆盖工具描述 |
源码中的BudgetSchema即z.enum(["low", "mid", "high"])(L7),FactTypeSchema为z.enum(["world", "experience", "observation"])(L13)。测试 "should accept low/mid/high budget values"(L486-L502)验证了三个预算档位全部被接受,而 "should default recall budget to mid" 与 "should default reflect budget to mid"(L459-L484)从测试侧固化了'mid'默认值。
九、源码级实现原理
1. 参数分区设计
createHindsightTools的核心思想是"构造期锁定基础设施参数、执行期只暴露语义参数":
- 构造选项(
retainOpts、recallOpts、reflectOpts等)通过闭包捕获; - 每个工具用 Zod 定义 Agent 可见的
inputSchema; execute内将 Agent 输入与构造选项合并后调用client对应方法(L337-L352 等)。
这样设计的好处是:多租户场景下,应用可以在不同请求/用户间以不同预算、标签策略创建工具实例,而模型始终只操心"该记什么、该查什么"。
2. 错误传播
工具不吞异常:客户端抛出的错误会原样向上传播,由 AI SDK 的工具调用机制处理。测试 index.test.ts 的 "error handling" 段 分别验证了retain、recall、reflect的异常传播行为。
3. 默认值与兜底
recall、reflect的budget默认'mid',在execute中通过?? "mid"显式兜底(L364、L384);recall的includeEntities/includeChunks默认false;reflect空文本与getMentalModel空内容均有友好兜底文案,避免把空串交给模型。
十、从 Changelog 到落地:工程启示
回看三版 Changelog,可以提炼出集成库进入稳定期的三条工程准则:
- 功能先行,兼容跟进(0.4.20 → 0.5.0):先保证核心能力可用,再随下游客户端(
hindsight-client)版本演进同步适配; - 规范对齐即可靠性(0.5.1):类型定义与后端 OpenAPI 规范对齐,从编译期消灭行为偏差——这也是为什么
ReflectBasedOn、ReflectFact等结构会在源码与测试中同时被严格约束; - 可移植性与供应链安全(0.4.20):支持 Node.js 与 Deno 双运行时,通过
overrides锁定构建链依赖版本。
对于希望为 Vercel AI SDK 应用接入持久化记忆的开发者,推荐的落地路径是:先在本地用hindsight-embed启动 API,参照 集成文档 与 完整示例 跑通generateText场景,再按多用户需求将createHindsightTools移入请求处理函数、以userId作为bankId,最后依据响应延迟与 token 成本调整recall/reflect的budget与maxTokens。若需深入验证各工具的参数透传与边界行为,可直接阅读 工具实现源码 与 Vitest 测试套件,并以npm test(或npm run test:deno)在本地复现。
【免费下载链接】hindsightHindsight: Agent Memory That Learns项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考