新闻详情

新闻详情

首页 / 资讯中心 / 详情

AI Agent 知识获取管道实战:TypeScript 构建 RAG 检索增强生成系统

发布时间:2026/9/29 20:45:23来源:尧图网络
AI Agent 知识获取管道实战:TypeScript 构建 RAG 检索增强生成系统
1. 为什么知识获取管道是 AI Agent 的分水岭做 AI Agent 开发的人绕不开一个尴尬的现实模型本身很聪明但它不知道你公司内部的业务规则、不知道你上周刚更新的产品文档、更不知道你私有的那套运维手册里写了什么。你问它一个通用问题它答得头头是道你问它一个只有你们团队才知道的细节它要么一本正经地胡说八道要么直接告诉你“我无法回答这个问题”。这就是知识获取管道要解决的核心矛盾。所谓知识获取管道说白了就是给 Agent 装上一套“查资料”的能力——在它开口回答之前先去指定的知识库里把相关材料找出来然后基于这些材料组织答案。这套机制在行业里有个更正式的名字RAGRetrieval-Augmented Generation检索增强生成。我接触 RAG 是从一个很具体的需求开始的。当时团队内部有一个积累了三年多的技术文档库大概两千多篇 Markdown 文件涵盖接口说明、部署流程、故障处理记录。新同事入职后最常问的问题就是“这个报错怎么处理”“那个配置在哪里改”老同事被问烦了新同事也不好意思一直问。我们想做一个内部问答机器人让 Agent 自己去文档库里找答案。最开始想的是把文档全部塞进模型上下文但算了一下 token 量两千多篇文档即使每篇压缩到五百字总量也远超模型窗口上限而且每次提问都全量塞进去成本和延迟都不可接受。RAG 的思路就自然浮现出来了不把所有知识一次性喂给模型而是先建一个可检索的索引用户提问时只把最相关的几段内容取出来连同问题一起交给模型生成答案。这个思路听起来简单但真正落地时会发现从文档切分、向量化、存储、检索到最终生成每一步都有大量细节需要打磨。检索不准模型再强也白搭切分不合理关键信息被截断检索出来的片段读都读不通向量模型选错了语义相似度计算完全偏离预期。这篇文章面向的是正在从零搭建 AI Agent 的开发者尤其是那些已经跑通了基础对话流程、准备接入私有知识库的人。我会用 TypeScript 作为主要实现语言因为它在 Agent 开发中的生态越来越成熟类型系统对复杂数据流的约束也让调试成本大幅降低。全文会围绕 RAG 的完整链路展开从整体设计思路到每个环节的实操细节再到我踩过的坑和排查技巧尽量把“为什么这么做”讲清楚而不是只给一堆代码让你抄。2. RAG 知识获取管道的整体设计与选型思路2.1 核心链路拆解从文档到答案的五个阶段RAG 的完整流程可以拆成五个阶段每个阶段都有明确的输入和输出理解这个链路是后续所有优化的基础。第一阶段是文档加载与预处理。你的知识可能散落在各种地方Markdown 文件、PDF、数据库表、网页、甚至聊天记录。这一步要做的是把这些异构数据统一成纯文本格式同时保留必要的元信息比如来源文件、章节标题、更新时间。元信息在后面检索和排序时非常关键但很多人一开始会忽略它。第二阶段是文本切分。整篇文档太长直接向量化会丢失细节检索时也很难精确定位。所以需要把文档切成合适大小的片段chunk每个片段独立向量化。切分策略直接决定了检索质量的上限——切得太碎语义不完整切得太粗噪声太多。第三阶段是向量化与索引构建。用嵌入模型embedding model把每个文本片段转成一个高维向量然后存入向量数据库。这一步的核心是选对嵌入模型和距离度量方式。不同模型对中文、英文、代码的语义捕捉能力差异很大选错了后面怎么调都别扭。第四阶段是检索。用户提问时把问题也向量化然后在向量库中找最相似的 top-k 个片段。但纯向量检索有个问题它对关键词匹配不敏感有时候用户问的是一个具体的错误码向量检索反而找不到精确匹配的文档。所以实际生产中通常会做混合检索——向量检索加关键词检索再融合排序。第五阶段是生成。把检索到的片段和用户问题组装成提示词交给大语言模型生成最终答案。这一步的关键是提示词设计怎么让模型基于给定材料回答、怎么处理材料中没有答案的情况、怎么引用来源。这五个阶段环环相扣任何一个环节出问题都会导致最终答案质量下降。我见过太多人把精力全花在换更强的生成模型上结果检索出来的片段根本不对换什么模型都没用。2.2 技术选型为什么用 TypeScript 而不是 PythonRAG 领域的教程和开源项目大多用 Python这很容易理解——Python 在数据处理和机器学习生态上积累深厚。但如果你正在开发的是一个面向生产的 AI Agent 应用TypeScript 其实有它独特的优势。首先是类型安全。RAG 链路中数据在多个阶段之间流转从文档对象到切分片段到向量记录到检索结果每个阶段的数据结构都不一样。用 TypeScript 把这些类型定义清楚编译器会在你传错字段的时候直接报错而不是等到运行时才发现某个属性是 undefined。我在用 Python 写原型时经常遇到检索结果里某个字段名写错了跑半天才发现问题出在一个拼写上。其次是前后端统一。Agent 应用通常需要一个交互界面如果后端用 Python、前端用 TypeScript两边的数据契约要靠文档和约定来维护。全栈 TypeScript 的话同一套类型定义可以前后端共享接口变更时编译器会帮你找出所有需要修改的地方。第三是异步流式处理。Agent 的响应通常是流式的TypeScript 的 async/await 和 AsyncGenerator 在处理流式数据时非常自然。Node.js 的事件循环模型也很适合这种 I/O 密集型的场景——检索、调用模型 API、读写向量库这些都是 I/O 操作Node 的非阻塞特性正好发挥优势。当然如果你需要做模型微调或者复杂的本地推理Python 仍然是更好的选择。但对于大多数 RAG 应用来说你用的是云端嵌入模型和生成模型核心工作是编排和数据处理TypeScript 完全够用而且在工程化方面更省心。2.3 向量数据库选型从原型到生产的取舍向量数据库的选择是另一个关键决策。我的建议是分阶段来原型阶段用最简单的方案验证跑通后再根据数据量和性能要求升级。原型阶段我推荐用内存向量存储比如自己用数组实现一个简单的余弦相似度计算或者用hnswlib-node这样的轻量库。数据量在几千条以内时暴力计算完全够用而且没有额外的部署成本。这个阶段的目标是验证切分策略和嵌入模型是否合适不要过早引入基础设施复杂度。当数据量上万、需要持久化、或者要多进程共享时就该考虑专门的向量数据库了。常见的选择有几类SQLite 加向量扩展适合单机小规模场景部署简单Qdrant和Weaviate是专门为向量检索设计的支持过滤、混合检索等高级功能PostgreSQL 加 pgvector适合已经有 Postgres 基础设施的团队不用额外维护一套数据库。我个人的经验是如果团队已经在用 Postgres优先考虑 pgvector运维成本最低。如果对检索性能有极致要求或者需要复杂的元数据过滤再上专门的向量数据库。选型时重点看三个指标检索延迟、过滤能力、以及是否支持你需要的距离度量方式。3. 核心细节解析与实操要点3.1 文本切分RAG 质量的第一道关卡文本切分看起来简单实际上是最容易出问题的地方。我最初的做法是按固定字符数切分每五百字一段结果检索出来的片段经常从句子中间断开读起来莫名其妙。后来改成按段落切分又遇到有些段落特别长、有些特别短的问题。比较稳妥的策略是递归切分先按文档的自然结构标题、段落切如果某个段落还是太长再按句子切最后才按字符数硬切。这样能最大程度保留语义完整性。具体实现时我会设置一个目标片段大小比如 500 个 token和一个重叠区域比如 50 个 token。重叠的作用是防止关键信息刚好落在切分边界上被割裂。interface ChunkOptions { targetSize: number; // 目标 token 数 overlap: number; // 重叠 token 数 separators: string[]; // 切分优先级 } function splitText(text: string, options: ChunkOptions): string[] { const { targetSize, overlap, separators } options; // 按分隔符优先级递归切分 // 合并过短的片段拆分过长的片段 // 在相邻片段间添加重叠内容 // ... }这里有个容易被忽略的细节不同来源的文档要用不同的切分策略。Markdown 文档有明确的标题层级可以按标题切分每个小节作为一个片段同时把标题路径作为元信息保留。代码文件要按函数或类切分不能从函数中间断开。PDF 提取出来的文本往往没有清晰的段落结构需要先做一轮清洗和重排。还有一个实操心得在片段前面加上来源信息。比如每个片段开头加上“来自《部署手册》第三章第二节”这样即使片段本身语义不完整嵌入模型也能捕捉到上下文。检索出来的片段交给生成模型时模型也能知道这段内容的出处回答时引用来源会更准确。3.2 嵌入模型选择中文场景下的实测对比嵌入模型的选择直接决定了语义检索的质量。市面上常见的模型有 OpenAI 的 text-embedding 系列、Cohere 的 embed 系列、以及各种开源模型。中文场景下我实测过几个方案差异比想象中大。OpenAI text-embedding-3-small在通用语义相似度上表现稳定对中英文混合内容处理得不错但它是云端调用有网络延迟和成本问题而且数据要发到外部对隐私敏感的场景不合适。BGE 系列如 bge-large-zh是中文开源嵌入模型里口碑较好的本地部署没有数据外泄风险中文语义捕捉能力比通用多语言模型强。缺点是模型体积大推理需要 GPU 或者性能较好的 CPU首次加载慢。M3E 系列在中文短文本匹配上表现不错模型相对轻量适合资源受限的场景。我的建议是如果数据不敏感且预算允许先用云端模型快速验证流程如果对隐私和成本有要求用 BGE 本地部署。选型时不要只看论文指标一定要用你自己的数据做一轮检索测试——拿十几个真实问题看检索出来的 top-5 片段是否包含答案这比任何 benchmark 都靠谱。还有一个细节嵌入模型的维度要和向量库的配置匹配。比如 BGE-large-zh 输出 1024 维向量建库时就要指定 1024 维。如果中途换模型维度变了整个库都要重建。所以选型时最好留一点余地别选维度太小的模型。3.3 混合检索向量加关键词的融合策略纯向量检索有个天然缺陷它对精确匹配不敏感。用户问“ERR_CONNECTION_REFUSED 怎么解决”向量检索可能会返回一堆关于“网络连接问题”的通用文档但真正包含这个错误码的文档反而排不到前面。这时候就需要关键词检索来补位。混合检索的做法是同时跑向量检索和关键词检索比如 BM25 算法各自得到一组结果然后用倒数排名融合RRF把两组结果合并。RRF 的公式很简单每个文档的得分等于它在各个结果列表中排名的倒数之和。这样既考虑了语义相似度又保留了关键词精确匹配的优势。function reciprocalRankFusion( vectorResults: SearchResult[], keywordResults: SearchResult[], k: number 60 ): SearchResult[] { const scores new Mapstring, number(); vectorResults.forEach((result, index) { const score 1 / (k index 1); scores.set(result.id, (scores.get(result.id) || 0) score); }); keywordResults.forEach((result, index) { const score 1 / (k index 1); scores.set(result.id, (scores.get(result.id) || 0) score); }); return Array.from(scores.entries()) .sort((a, b) b[1] - a[1]) .map(([id]) findResultById(id, vectorResults, keywordResults)); }关键词检索的实现可以用minisearch或flexsearch这样的轻量库它们支持中文分词和 BM25 排序。中文分词建议用nodejieba或segmentit分词的粒度会影响关键词匹配的召回率。实测下来混合检索在技术文档场景下的命中率比纯向量检索高出不少尤其是涉及具体错误码、配置项名称、API 路径这类查询时优势非常明显。代价是检索延迟会增加因为要跑两套检索再融合。如果延迟敏感可以给关键词检索加缓存或者只在向量检索置信度低时才触发关键词检索。3.4 提示词组装让模型基于材料回答而不是自由发挥检索到相关片段后最后一步是把它们和用户问题组装成提示词。这一步看似简单但提示词的结构直接影响生成质量。我的提示词模板通常包含四个部分角色设定、材料区、问题区、回答要求。角色设定告诉模型它是什么身份比如“你是一个技术文档助手”。材料区把检索到的片段按相关度排序后拼接每个片段标注来源。问题区放用户原始问题。回答要求最关键要明确告诉模型只基于材料回答、材料中没有的信息不要编造、如果材料不足以回答就直说、回答时标注引用的来源。function buildPrompt(question: string, chunks: RetrievedChunk[]): string { const context chunks .map((chunk, i) [片段${i 1}] 来源${chunk.source}\n${chunk.content}) .join(\n\n); return 你是一个技术文档助手。请严格基于以下材料回答用户问题。 材料 ${context} 用户问题${question} 回答要求 1. 只使用材料中提供的信息不要添加材料之外的知识 2. 如果材料中没有足够信息回答问题直接说明根据现有资料无法回答 3. 回答时用[片段N]标注引用的来源 4. 保持回答简洁准确; }这里有个坑材料区不能塞太多片段。检索 top-10 全塞进去提示词会很长模型注意力被分散反而容易忽略关键信息。我的经验是 top-3 到 top-5 比较合适如果片段内容短可以适当增加。另外片段之间要有明确的分隔标记否则模型可能把不同片段的内容混在一起。还有一个进阶技巧在材料区前面加一句“以下材料按相关度从高到低排列”。这能引导模型优先关注前面的片段减少被低相关度内容干扰的概率。4. 实操过程与核心环节实现4.1 项目初始化与依赖安装先把项目骨架搭起来。我用的是 Node.js 加 TypeScript包管理用 pnpm构建工具用 tsx 直接跑 TypeScript 文件省去编译步骤。mkdir rag-pipeline cd rag-pipeline pnpm init pnpm add openai qdrant/js-client-rest minisearch nodejieba pnpm add -D typescript tsx types/nodeopenai用来调用嵌入模型和生成模型qdrant/js-client-rest是 Qdrant 的客户端minisearch做关键词检索nodejieba做中文分词。如果你用本地嵌入模型还需要装xenova/transformers或者onnxruntime-node。tsconfig.json的配置要注意几个点target设成ES2022module设成NodeNextmoduleResolution设成NodeNext。如果你看到“选项 baseUrl 已弃用”或者“选项 moduleResolutionnode10 已弃用”的警告说明配置需要更新用NodeNext可以避免这些问题。{ compilerOptions: { target: ES2022, module: NodeNext, moduleResolution: NodeNext, strict: true, esModuleInterop: true, skipLibCheck: true, outDir: dist }, include: [src/**/*] }4.2 文档加载与切分实现先定义文档和片段的数据结构。文档对象包含原始内容和元信息片段对象包含切分后的文本、所属文档 ID、在文档中的位置、以及来源信息。interface Document { id: string; content: string; source: string; metadata: Recordstring, string; } interface Chunk { id: string; documentId: string; content: string; source: string; position: number; metadata: Recordstring, string; }加载 Markdown 文档时我会先按二级标题切分成大块每个大块再按段落切分成片段。这样每个片段都带有明确的章节归属检索时如果命中某个片段能直接知道它来自哪一章。function loadMarkdown(filePath: string): Document { const content fs.readFileSync(filePath, utf-8); const title content.match(/^#\s(.)$/m)?.[1] || path.basename(filePath); return { id: hash(filePath), content, source: filePath, metadata: { title, type: markdown } }; } function chunkDocument(doc: Document, options: ChunkOptions): Chunk[] { const sections doc.content.split(/\n(?##\s)/); const chunks: Chunk[] []; sections.forEach((section, sectionIndex) { const sectionTitle section.match(/^##\s(.)$/m)?.[1] || ; const paragraphs section.split(/\n\n/); let buffer ; paragraphs.forEach((para) { if (buffer.length para.length options.targetSize buffer.length 0) { chunks.push(createChunk(buffer, doc, sectionTitle, chunks.length)); buffer para; } else { buffer (buffer ? \n\n : ) para; } }); if (buffer.length 0) { chunks.push(createChunk(buffer, doc, sectionTitle, chunks.length)); } }); return chunks; }createChunk函数会在片段内容前面加上来源标题比如“《部署手册》- 第三章 故障处理”这样嵌入模型能捕捉到章节上下文。4.3 向量化与索引构建向量化这一步我用 OpenAI 的嵌入接口做演示如果你用本地模型把embed函数替换掉就行。async function embed(texts: string[]): Promisenumber[][] { const response await openai.embeddings.create({ model: text-embedding-3-small, input: texts, }); return response.data.map((item) item.embedding); }批量向量化时要注意分批处理。一次发太多文本会被限流我一般每批 20 到 50 条根据接口的速率限制调整。每批之间加一点延迟避免触发限流。async function embedInBatches(texts: string[], batchSize 32): Promisenumber[][] { const results: number[][] []; for (let i 0; i texts.length; i batchSize) { const batch texts.slice(i, i batchSize); const embeddings await embed(batch); results.push(...embeddings); if (i batchSize texts.length) { await sleep(200); } } return results; }建 Qdrant 集合时向量维度要和嵌入模型输出一致。text-embedding-3-small输出 1536 维集合配置里就写 1536。距离度量用余弦相似度因为嵌入向量通常做了归一化余弦相似度比欧氏距离更合适。async function createCollection(client: QdrantClient, name: string, dimension: number) { await client.createCollection(name, { vectors: { size: dimension, distance: Cosine, }, }); }写入数据时把片段内容、来源、位置等信息放在 payload 里检索时可以按这些字段做过滤。比如只检索某个文档的片段或者只检索最近更新的内容。4.4 混合检索与结果融合检索环节我实现了两路向量检索走 Qdrant关键词检索走 MiniSearch。两路各取 top-10然后用 RRF 融合最终取 top-5 交给生成模型。async function hybridSearch( query: string, client: QdrantClient, miniSearch: MiniSearch, topK 5 ): PromiseRetrievedChunk[] { const queryVector (await embed([query]))[0]; const vectorResults await client.search(knowledge, { vector: queryVector, limit: 10, }); const keywordResults miniSearch.search(query, { prefix: true }).slice(0, 10); const fused reciprocalRankFusion( vectorResults.map((r) ({ id: r.id as string, score: r.score, payload: r.payload })), keywordResults.map((r) ({ id: r.id, score: r.score, payload: r })) ); return fused.slice(0, topK); }MiniSearch 的索引构建要在文档切分后同步进行。中文分词用 nodejieba 的cutForSearch模式它会把长词切成更细粒度的子词提高召回率。const miniSearch new MiniSearch({ fields: [content, source], storeFields: [content, source, position], tokenize: (text) nodejieba.cutForSearch(text), });4.5 生成环节与流式输出最后一步是把检索结果组装成提示词调用生成模型。我用流式输出这样用户能更快看到响应。async function generateAnswer( question: string, chunks: RetrievedChunk[] ): PromiseAsyncGeneratorstring { const prompt buildPrompt(question, chunks); const stream await openai.chat.completions.create({ model: gpt-4o-mini, messages: [{ role: user, content: prompt }], stream: true, temperature: 0.1, }); return (async function* () { for await (const chunk of stream) { const content chunk.choices[0]?.delta?.content; if (content) yield content; } })(); }temperature设成 0.1 是为了让回答更稳定、更贴近材料内容。如果设太高模型容易自由发挥编造材料里没有的信息。5. 常见问题与排查技巧实录5.1 检索结果不相关从五个维度逐层排查检索不准是最常见的问题排查时按以下顺序逐层检查。第一层嵌入模型是否适合你的数据。拿几个典型问题手动看检索出来的 top-5 片段。如果完全不相关可能是模型对领域术语不敏感。试试换一个在你的领域数据上微调过的模型或者在片段前面加上更多上下文信息。第二层切分粒度是否合理。片段太短语义不完整片段太长噪声太多。我一般会打印出片段的平均长度和长度分布如果大部分片段都在 100 token 以下说明切太碎了如果超过 1000 token说明切太粗了。第三层查询和文档是否在同一语义空间。用户提问的口语化表达和文档的书面化表达之间可能有鸿沟。解决办法是在检索前用模型把用户问题改写成更接近文档风格的查询或者生成多个查询变体分别检索再融合。第四层是否需要混合检索。如果问题包含具体错误码、配置项名称、API 路径纯向量检索大概率找不到精确匹配。加上关键词检索后这类查询的命中率会明显提升。第五层top-k 是否合适。top-k 太小可能漏掉正确答案太大噪声太多。我的经验是检索阶段取 top-10 到 top-20融合后取 top-3 到 top-5 交给生成模型。5.2 生成答案编造内容提示词与温度的双重约束模型编造材料里没有的信息通常有两个原因提示词约束不够强或者温度设太高。提示词方面除了明确说“只基于材料回答”还可以加一个自检步骤让模型在回答前先判断材料是否足够如果不够就直接说无法回答。这个自检步骤能显著降低编造概率。const prompt 请先判断以下材料是否足以回答用户问题。 如果材料不足直接回复根据现有资料无法回答。 如果材料充足再基于材料组织答案。 材料 ${context} 问题${question};温度方面生成环节建议设在 0.1 到 0.3 之间。温度越低模型越倾向于复制材料内容温度越高越容易自由发挥。RAG 场景下忠实于材料比创造性更重要所以温度要低。还有一个技巧在材料区末尾加一句“以上是全部可用材料”。这能防止模型脑补出材料之外的内容因为它知道材料已经给完了。5.3 性能瓶颈定位延迟与成本的平衡RAG 链路的延迟主要来自三个地方嵌入模型调用、向量检索、生成模型调用。嵌入模型调用通常最快几百毫秒向量检索在数据量不大时也很快几十毫秒生成模型调用最慢几秒到十几秒不等。如果延迟太高先看是不是检索阶段取了太多结果。top-20 和 top-5 的检索延迟差异不大但生成阶段的提示词长度差异很大直接影响生成速度。把交给生成模型的片段控制在 5 个以内每个片段控制在 500 token 以内能显著降低生成延迟。成本方面嵌入模型调用是按 token 计费的建库时一次性成本较高但查询时的嵌入调用很便宜。生成模型调用是大头提示词越长、输出越长成本越高。优化方向是精简提示词、控制输出长度、以及用更便宜的模型做初筛。如果预算紧张可以考虑缓存机制对常见问题缓存检索结果和生成答案下次同样的问题直接返回缓存。缓存键可以用问题的嵌入向量做近似匹配相似度超过阈值就命中缓存。5.4 常见问题速查表问题现象可能原因排查方法解决方向检索结果完全不相关嵌入模型不适合领域数据手动检查 top-5 片段换模型或加领域微调检索结果部分相关但缺关键信息切分粒度不合理检查片段长度分布调整切分策略和重叠区域具体错误码查不到纯向量检索对精确匹配不敏感对比关键词检索结果启用混合检索生成答案编造内容提示词约束不够或温度太高检查提示词和 temperature加强约束、降低温度响应延迟高检索结果太多或提示词太长统计各阶段耗时减少 top-k、精简提示词中文检索效果差分词或嵌入模型对中文支持不足用中文问题测试换中文优化模型、调整分词新增文档后检索不到索引未更新检查索引构建流程增量更新向量库和关键词索引5.5 几个我踩过的坑坑一片段重叠区域设太大。我一开始把重叠设成 200 token结果检索出来的片段大量重复浪费了宝贵的上下文窗口。后来改成 50 token效果反而更好。重叠的目的是防止关键信息被切断不是越多越好。坑二忽略元信息过滤。早期版本我没有用元信息过滤检索时全库搜索。后来发现很多问题其实有明确的文档范围比如“部署问题”只需要搜部署相关文档。加上元信息过滤后检索准确率和速度都有提升。坑三嵌入模型和生成模型用同一家但版本不匹配。有次我换了生成模型的版本但嵌入模型没换结果检索出来的片段和生成模型的语义空间有偏差答案质量下降。嵌入模型和生成模型最好来自同一家、同一代或者至少做过兼容性测试。坑四没有做检索结果去重。相邻片段内容高度重叠检索 top-5 可能有三条来自同一段内容。去重后实际有效信息只有两条。解决办法是在融合排序后做一次去重相似度超过阈值的片段只保留一个。坑五关键词索引没有持久化。MiniSearch 的索引默认在内存里重启服务就没了。生产环境要把索引序列化到磁盘启动时加载。或者直接用支持持久化的关键词检索方案。6. 从基础 RAG 到 Agentic RAG 的演进方向基础 RAG 跑通之后你会发现它有几个天然局限检索是一次性的不管问题复杂不复杂都只查一轮检索策略是固定的不会根据问题类型调整多个片段之间的关系没有被利用只是简单拼接。Agentic RAG 的思路是让 Agent 自己决定怎么检索。比如面对一个复杂问题Agent 可以先拆解成子问题分别检索再综合如果第一轮检索结果不理想Agent 可以改写查询再试一次如果发现某个片段提到了另一个相关概念Agent 可以顺着线索继续检索。这种多轮、自适应的检索策略在复杂问答场景下效果明显更好。实现 Agentic RAG 的关键是给 Agent 提供一组检索工具让它自己编排调用顺序。工具可以包括向量检索、关键词检索、按文档标题检索、按时间范围检索等。Agent 根据问题类型选择合适的工具组合而不是每次都走同一条固定链路。另一个方向是GraphRAG把知识片段之间的关系也建模进去。比如文档 A 引用了文档 B或者概念 X 和概念 Y 经常一起出现这些关系可以在检索时作为扩展线索。当用户问题涉及多个概念时GraphRAG 能沿着关系图找到更完整的上下文。不过这些进阶方案的前提是基础 RAG 已经跑稳了。切分策略、嵌入模型、混合检索、提示词组装这些基本功没做好上再复杂的架构也是空中楼阁。我的建议是先把基础链路跑通用真实数据做一轮评估找到瓶颈之后再针对性升级。评估 RAG 系统时我常用两个指标命中率和忠实度。命中率看检索结果里是否包含正确答案忠实度看生成答案是否严格基于检索材料。这两个指标一个管“找得对不对”一个管“答得准不准”结合起来能比较全面地反映系统质量。评估集不用很大二三十个真实问题就够关键是问题要覆盖不同类型的查询场景。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

0基础学会Agent Harness工程(13):用Background Tasks与daemon thread避免慢操作阻塞 2026/9/29 21:29:58

0基础学会Agent Harness工程(13):用Background Tasks与daemon thread避免慢操作阻塞

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
DeepSeek本地部署实战:Ollama+RAG知识库搭建与报错排查 2026/9/29 21:29:51

DeepSeek本地部署实战:Ollama+RAG知识库搭建与报错排查

前阵子朋友丢给我一堆技术手册,PDF、Word、Markdown混在一起,加起来快两个G。我想给这些文档做一个可以“随问随答”的本地问答机器人,第一时间想到的就是DeepSeek本地部署加Ollama加知识库的组合。折腾过程中没少踩坑,光是模型下…

阅读更多 →
课程论文不是“小论文”:用 aigcbiye 把一次作业危机拆解成七次有效决策 2026/9/29 21:29:51

课程论文不是“小论文”:用 aigcbiye 把一次作业危机拆解成七次有效决策

aigcbiye官网 微信公众号搜一搜 aigcbiye 课程论文这件事,大多数学生都误解了它的性质。 他们把它当成“缩小版的毕业论文”,于是用写毕业论文的方式对待它——打开知网,下载二十篇文献,对着空白文档发呆三天,最后在…

阅读更多 →
倒反天罡!Gemini Flash表现超越Pro,“帕累托前沿已经反转了”:用TaoToken统一Key实测配置与验证 2026/9/29 21:29:51

倒反天罡!Gemini Flash表现超越Pro,“帕累托前沿已经反转了”:用TaoToken统一Key实测配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
vSan 6.7 超融合实战:从架构原理到磁盘组配置与排错指南 2026/9/29 21:29:51

vSan 6.7 超融合实战:从架构原理到磁盘组配置与排错指南

简介:这份PDF文档是VMware vSAN 6.7官方技术白皮书,面向虚拟化架构师、数据中心运维人员及超融合方案选型者,系统讲解vSAN作为领先HCI解决方案的核心能力与部署思路。资源包内仅含1个PDF文件,大小约709KB,轻量便携&…

阅读更多 →
MCP 集群到底怎么做?从单机 MCP 到企业级 AI Agent 工具平台,一篇讲透 TaoToken 统一 Key 通道 2026/9/29 21:29:44

MCP 集群到底怎么做?从单机 MCP 到企业级 AI Agent 工具平台,一篇讲透 TaoToken 统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉