VoltAgent 集成 Pinecone 向量数据库:构建双模式 RAG 知识检索 Agent 实战指南
2026/9/24 15:36:04 网站建设 项目流程
  • 人工智能
  • AI Agent
  • Agent 框架
  • 后端
  • 多智能体
  • RAG
  • 工具调用
  • Agent 记忆

【免费下载链接】voltagent

AI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework

项目地址:https://gitcode.com/gh_mirrors/vo/voltagent
点击查看免费下载

导读

本文基于 VoltAgent 官方示例 examples/with-pinecone,完整讲解如何在 VoltAgent 中接入 Pinecone 向量数据库,为 Agent 赋予基于语义相似度的知识检索(RAG,Retrieval-Augmented Generation)能力。示例同时提供了两种检索模式:自动检索(每次交互自动执行语义搜索)与工具化检索(由 LLM 自行决定何时查询知识库),并自动完成索引创建、文档嵌入与向量检索的完整链路。读完本文,你将掌握如何在 VoltAgent 中编写自定义 Retriever、配置 Pinecone 索引、注入环境变量,以及理解BaseRetrieverretriever.tool两种接入方式背后的源码原理。

示例概述:Pinecone + VoltAgent 能做什么

本示例演示 VoltAgent 与 Pinecone 向量数据库的集成,面向需要"高级知识管理与检索"的场景。示例内置了一个预加载的知识库——包含 VoltAgent、Pinecone、RAG、向量数据库、TypeScript 等主题的样例文档——并在运行时自动完成以下工作:

  • 自动创建索引:检测 Pinecone 中是否已存在目标索引,不存在则自动创建;
  • 自动填充知识库:使用 OpenAItext-embedding-3-small模型为样例文档生成向量并写入索引;
  • 语义向量检索:对用户查询做同样嵌入后,在 Pinecone 中执行高相似度向量搜索;
  • 来源追踪:将命中文档的 ID 与相似度分数写入上下文(context.get('references')),便于 Agent 与用户追溯答案出处。

整个示例的核心文件只有两个:

  • 入口文件:组装 Memory、两个 Agent 与 Hono 服务器;
  • 检索器实现:Pinecone 客户端初始化、索引管理、嵌入生成与PineconeRetriever类。

前置条件

在开始之前,需要准备以下资源:

  • Pinecone 账号:注册并登录 Pinecone 控制台;
  • Pinecone API Key:从控制台获取,用于初始化@pinecone-database/pinecone客户端;
  • OpenAI API Key:示例使用 OpenAI 同时承担两类职责——生成文档/查询的嵌入向量(text-embedding-3-small),以及作为 Agent 的语言模型(openai/gpt-4o-mini)。

示例依赖清单可参见 package.json,其中与 VoltAgent 相关的核心依赖为@voltagent/core(Agent 与 Retriever 框架)、@voltagent/libsql(持久化记忆)、@voltagent/logger(日志)、@voltagent/server-hono(HTTP 服务),以及@pinecone-database/pineconeopenai两个第三方客户端。

快速开始

第 1 步:创建项目。使用 VoltAgent 官方脚手架,指定with-pinecone示例模板:

npm create voltagent-app@latest -- --example with-pinecone cd with-pinecone

第 2 步:配置环境变量。复制环境变量模板并填入密钥:

cp .env.example .env

编辑.env,添加 API Key:

PINECONE_API_KEY=your_pinecone_api_key_here OPENAI_API_KEY=your_openai_api_key_here

说明:入口依赖.env文件读取密钥。项目的dev脚本为tsx watch --env-file=.env ./src,即运行时会显式加载.env中的变量;若没有正确配置上述两个 Key,Pinecone 客户端与 OpenAI 客户端将拿到空字符串,索引初始化和检索都会失败。

第 3 步:安装依赖并运行:

npm install npm run dev

启动成功后,控制台会输出提示,说明两个 Agent 已就绪,并建议尝试类似这样的提问:

  • "What is VoltAgent?"
  • "Tell me about vector databases"
  • "How does Pinecone work?"
  • "What is RAG?"

环境变量一览

变量是否必填说明
PINECONE_API_KEY你的 Pinecone API Key
OPENAI_API_KEY你的 OpenAI API Key(用于生成嵌入向量与 LLM 调用)

从源码看,两个 Key 的使用位置分别为 retriever/index.ts(Pinecone 客户端,并额外设置了sourceTag: "voltagent")和同一文件中的 OpenAI 客户端初始化(apiKey: process.env.OPENAI_API_KEY || "")。

入口代码剖析:如何组装一个带检索能力的 Agent

src/index.ts 展示了 VoltAgent 的核心装配流程,依次包含四步:日志、记忆、Agent、服务器。

1. 日志:使用createPinoLogger创建名为with-pinecone的 Pino 日志实例,级别为info

2. 持久化记忆:示例使用 LibSQL 作为记忆存储,且两个 Agent 共享同一份记忆:

import { Agent, Memory, VoltAgent } from "@voltagent/core"; import { LibSQLMemoryAdapter } from "@voltagent/libsql"; const memory = new Memory({ storage: new LibSQLMemoryAdapter({ url: "file:./.voltagent/memory.db", }), });

记忆数据被持久化到本地 SQLite 文件.voltagent/memory.db,这保证了 Agent 重启后仍能保留跨会话的上下文。

3. 两个 Agent:分别演示"直接挂载 Retriever"与"把 Retriever 包装成 Tool"两种模式:

// Agent 1: 自动检索 —— 每次交互自动搜索知识库 const agentWithRetriever = new Agent({ name: "Assistant with Retriever", instructions: "A helpful assistant that can retrieve information from the Pinecone knowledge base using semantic search to provide better answers. I automatically search for relevant information when needed.", model: "openai/gpt-4o-mini", retriever: retriever, memory, }); // Agent 2: 工具化检索 —— LLM 自行决定何时搜索 const agentWithTools = new Agent({ name: "Assistant with Tools", instructions: "A helpful assistant that can search the Pinecone knowledge base using tools. The agent will decide when to search for information based on user questions.", model: "openai/gpt-4o-mini", tools: [retriever.tool], memory, });

关键差异在于:

  • agentWithRetriever通过retriever字段挂载,对应 README 中说的"Automatic retrieval":Agent 在生成回答前会自动把检索结果注入系统消息;
  • agentWithTools通过tools: [retriever.tool]挂载,对应"tool-based retrieval":检索行为变成 LLM 可自主调用的工具函数。

4. HTTP 服务:通过honoServer暴露 Agent 能力,监听3141端口:

new VoltAgent({ agents: { agentWithRetriever, agentWithTools }, logger, server: honoServer({ port: 3141 }), });

两种检索模式背后的源码原理

理解两种模式的差异,需要看 VoltAgent 核心包中BaseRetriever的实现。

BaseRetriever:一个实例,两种用法

抽象基类 BaseRetriever 定义在packages/core/src/retriever/retriever.ts。它要求子类实现retrieve(input, options): Promise<string>,并在构造函数中自动完成两件事:

  1. 自动创建工具:调用createRetrieverTool生成this.tool,工具名称默认search_knowledge,描述默认为 "Searches for relevant information in the knowledge base based on the query."。因此retriever.tool无需任何额外配置即可直接塞进tools数组;
  2. 绑定方法上下文:将retrieve显式bind到实例上,保证从对象解构或作为回调传入时this不丢失。

RetrieverOptions(见 types.ts)支持自定义toolNametoolDescriptionlogger,同时允许子类扩展任意自有配置项。

createRetrieverTool:Retriever 到 AgentTool 的桥接

createRetrieverTool 位于packages/core/src/retriever/tools/index.ts,是"工具化检索"的核心。它用zod定义工具参数query(字符串,描述为 "The search query to find relevant information"),并在execute内调用retriever.retrieve(query, options),同时:

  • 把调用方的options(含loggeruserIdconversationId等)完整透传给retriever
  • 记录RETRIEVER_SEARCH_STARTED / COMPLETED / FAILED日志事件;
  • 支持通过getObservabilityAttributes()为 OpenTelemetry span 附加检索器属性。

这也解释了为什么tools: [retriever.tool]能直接工作——createRetrieverTool返回的就是标准的AgentTool

Agent 侧的自动检索流程

当通过retriever字段挂载时,Agent 在生成系统消息阶段调用getRetrieverContext(见 agent.ts):

  1. 将用户输入(字符串、UIMessage[]BaseMessage[])统一归一化为检索器可处理的输入;
  2. 创建名为retriever.search的 OpenTelemetry 子 span;
  3. 调用retriever.retrieve(...),并把结果拼装进系统提示词,格式为Relevant Context:\n<检索内容>(见 enrichInstructions)。

因此"自动检索"本质上是在每次生成前,把语义检索结果作为上下文固定注入;而"工具化检索"则由 LLM 根据问题相关性决定是否触发搜索。前者答案更稳定地基于知识库,后者更省 Token、更灵活。

Pinecone 检索器实现详解

retriever/index.ts 是本示例的核心,包含索引管理、文档填充与检索器实现三个部分。

1. 自动索引管理

initializeIndex()函数实现"不存在即创建"的幂等逻辑:

const pc = new Pinecone({ apiKey: process.env.PINECONE_API_KEY || "", sourceTag: "voltagent", }); const indexName = "voltagent-knowledge-base"; // 先探测索引是否存在 try { await pc.describeIndex(indexName); indexExists = true; } catch (_error) { // 不存在则创建 } if (!indexExists) { await pc.createIndex({ name: indexName, dimension: 1536, // OpenAI text-embedding-3-small dimension metric: "cosine", spec: { serverless: { cloud: "aws", region: "us-east-1", }, }, waitUntilReady: true, }); }

随后通过describeIndexStats()检查totalRecordCount:若索引为空,则为样例文档生成嵌入并upsert;若已有数据则直接跳过填充,避免重复写入。

2. 嵌入与写入

文档向量化使用 OpenAI 官方 SDK:

const embeddingResponse = await openai.embeddings.create({ model: "text-embedding-3-small", input: record.metadata.text, });

每个文档的metadata包含text(原始内容)、category(分类)、topic(主题)三个字段,这些元数据后续可用于过滤与展示。写入使用index.upsert(recordsWithEmbeddings)批量提交。

3. 语义检索

retrieveDocuments(query, topK = 3)完成查询向量化与相似度搜索:

const searchResults = await index.query({ vector: queryVector, topK, includeMetadata: true, includeValues: false, }); return ( searchResults.matches?.map((match) => ({ content: match.metadata?.text || "", metadata: match.metadata || {}, score: match.score || 0, id: match.id, })) || [] );

检索结果被格式化为{ content, metadata, score, id }结构,供后续注入上下文。

4. PineconeRetriever:自定义 Retriever 的标准范式

PineconeRetriever继承自BaseRetriever,其retrieve方法展示了自定义检索器的标准写法:

  • 输入归一化:兼容stringBaseMessage[]两种输入——对消息数组取最后一条,提取其中type === "text"的内容片段拼接为搜索文本;
  • 执行检索:调用retrieveDocuments(searchText, 3)取 Top-3 结果;
  • 写入引用:若调用方传入options.context(一个Map),则将结果映射为{ id, title, source, score, category }context.set("references", references)——这正是 README 中"Source Tracking"的来源,运行时可通过context.get('references')查看使用了哪些文档及对应分数;
  • 格式化输出:将每条结果拼接为带Document N (ID: ..., Score: ..., Category: ...)前缀的文本块,交给 LLM 作为Relevant Context;无结果时返回 "No relevant documents found in the knowledge base."。

文件末尾export const retriever = new PineconeRetriever();导出单例,供入口文件直接引用。

自定义:接入你自己的知识库

添加自有文档

修改 retriever/index.ts 中的sampleRecords数组即可替换/扩充知识库:

const sampleRecords = [ { id: "your_doc_1", metadata: { text: "Your document content here...", category: "your_category", topic: "your_topic", }, }, // Add more documents... ];

values字段无需手填(源码中置空),示例会在初始化阶段用 OpenAI 嵌入模型自动生成。注意:由于索引在totalRecordCount === 0时才填充,若要强制重新灌入新文档,需要先清空或更换索引。

调整索引配置

索引创建参数同样在 retriever/index.ts 中配置:

await pc.createIndex({ name: indexName, dimension: 1536, // OpenAI text-embedding-3-small dimension metric: "cosine", // or 'euclidean', 'dotproduct' spec: { serverless: { cloud: "aws", // or 'gcp', 'azure' region: "us-east-1", // choose your preferred region }, }, waitUntilReady: true, });

关键参数说明:

  • dimension:向量维度,必须与嵌入模型输出维度一致。示例使用 OpenAItext-embedding-3-small(1536 维),更换嵌入模型时必须同步修改;
  • metric:相似度度量方式,cosine(余弦相似度,对向量模长不敏感,语义检索最常用)、euclidean(欧氏距离)、dotproduct(点积)三选一;
  • spec.serverless:Serverless 部署配置,cloud可选aws/gcp/azureregion选择就近区域以降低延迟;
  • waitUntilReady:设为true时阻塞等待索引就绪后再继续写入。

检索行为调优

retrieveDocumentstopK参数(默认3)控制每次注入上下文的文档条数,可根据知识库规模与 Token 预算调整;index.query还可补充filter条件利用metadata做元数据过滤(如按category限定检索范围),README 中提到的"Metadata filtering capabilities"即指此能力。

运行验证与排查建议

启动npm run dev后:

  1. 首次运行时控制台应依次出现索引探测、索引创建/填充日志(Creating new index...Populating index with sample documents...Successfully upserted N documents);
  2. 向两个 Agent 提问 "What is RAG?" 这类与知识库强相关的问题,对比自动检索与工具化检索的行为差异;
  3. 通过context.get('references')查看命中文档的idscore,验证来源追踪是否生效。

常见问题排查方向:

  • 索引初始化失败:检查PINECONE_API_KEYOPENAI_API_KEY是否正确写入.env,并确认 Pinecone 控制台已开通对应云与区域;
  • 检索结果为空:确认索引中totalRecordCount大于 0;若使用新索引,可删除索引后重启示例触发重新填充;
  • 维度不匹配:更换嵌入模型后需同步修改createIndexdimension,否则upsert会报错。

延伸阅读

  • 核心抽象 BaseRetriever 与 Retriever 类型定义;
  • 工具化桥接 createRetrieverTool;
  • Agent 侧自动注入检索上下文 getRetrieverContext;
  • 核心框架测试 retriever.spec.ts(验证默认工具名search_knowledge、自定义toolName/toolDescriptiontool属性暴露);
  • 同仓库内还有更多检索相关示例可供对照,例如 examples/with-retrieval、examples/with-voltops-retrieval,以及独立封装的 packages/rag。

总结

本示例用最小的代码量呈现了 VoltAgent × Pinecone 的完整 RAG 落地路径:一条PineconeRetriever(继承BaseRetriever)同时支撑"自动检索"与"工具化检索"两种模式,配合自动索引管理、OpenAI 嵌入、引用追踪与持久化记忆,构成了一个可直接扩展为生产级知识问答 Agent 的骨架。理解BaseRetriever/createRetrieverTool/ Agent 系统消息注入这三层机制后,你可以轻松将其替换为任意向量数据库或检索后端。

  • 人工智能
  • AI Agent
  • Agent 框架
  • 后端
  • 多智能体
  • RAG
  • 工具调用
  • Agent 记忆

【免费下载链接】voltagent

AI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework

项目地址:https://gitcode.com/gh_mirrors/vo/voltagent
点击查看免费下载
上一篇:装好就能玩的开源桌宠 VPet:摸头、喂食、还能嵌进你自己的软件
下一篇:mobiledevice安装教程:在Linux系统上编译与配置的详细指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询