1. 为什么知识获取管道是 AI Agent 的第一道生死关做 AI Agent 开发的人十有八九都经历过这样一个阶段模型选型纠结了半天工具调用调通了提示词也打磨得差不多了结果一上真实业务场景Agent 给出的答案就开始胡编乱造。不是它不够聪明而是它根本不知道你的业务里那些私有知识。这就是知识获取管道要解决的问题。所谓知识获取管道说白了就是让 Agent 在回答问题之前先去“查资料”。这个“查资料”的过程在业界有一个大家更熟悉的叫法——RAGRetrieval-Augmented Generation检索增强生成。它的核心逻辑不复杂用户提问 → 系统从知识库里检索相关内容 → 把检索结果和原始问题一起塞给大模型 → 模型基于这些材料生成回答。听起来简单但真正落地的时候从文档解析、分块策略、嵌入模型选型、向量库搭建到检索排序每一步都有坑。我见过太多团队在这一步翻车。有的把 PDF 直接丢进去解析表格全乱有的分块大小拍脑袋定检索出来的内容驴唇不对马嘴有的嵌入模型选了个通用款结果在垂直领域里检索命中率惨不忍睹。更常见的是检索回来的内容明明是对的但模型就是不用或者用错了——这又涉及到提示词编排和上下文窗口管理的问题。这篇文章面向的是正在搭建 AI Agent、准备接入知识库的开发者不管你是用 LangChain、Spring AI 还是自己手搓管道RAG 的基础逻辑和实操细节都是绕不过去的。我会从整体架构讲到具体参数从嵌入模型选型讲到检索策略优化尽量把每一步的“为什么”说清楚让你不只是抄配置而是真正理解这套管道怎么跑起来的。2. RAG 管道的整体架构与核心环节拆解2.1 从文档到向量一条完整的数据流水线RAG 的离线部分本质上是一条数据处理流水线。原始文档进来经过解析、清洗、分块、嵌入、存储五个阶段最终变成向量数据库里的一条条记录。每个阶段都有它的脾气。文档解析是第一道坎。PDF、Word、HTML、Markdown、Excel每种格式的解析难度完全不同。PDF 最麻烦尤其是扫描件和复杂排版纯文本提取工具经常把表格和正文混在一起。我的经验是如果文档里有大量表格优先用能保留结构信息的解析器比如把 PDF 转成 Markdown 再处理比直接提取纯文本效果好得多。清洗阶段要做的事情包括去页眉页脚、去重复段落、修正 OCR 错误、统一标点符号。这一步看起来不起眼但直接影响后续分块质量。我试过跳过清洗直接分块结果检索出来的内容里夹杂着一堆“第 3 页 共 12 页”这种噪音模型被干扰得很厉害。分块是整条管道里最需要动脑子的环节。块太大检索精度下降因为一个块里可能混了好几个主题块太小上下文不完整模型拿到手也不知道前因后果。业界常见的做法是设置一个基础块大小比如 512 个 token再叠加一定的重叠区域比如 50 到 100 个 token保证相邻块之间有上下文衔接。但这不是万能公式具体数值要根据你的文档类型来调。嵌入阶段就是把文本块转成向量。这里涉及到稠密嵌入和稀疏嵌入两条技术路线后面会详细展开。存储阶段则是把向量和原始文本、元数据一起写进向量数据库元数据包括来源文件、页码、章节标题等方便后续检索时做过滤。2.2 在线检索从用户提问到上下文组装在线部分是从用户提问开始的。用户的问题进来先经过查询理解模块——有时候需要做查询改写把口语化的提问转成更适合检索的形式有时候需要做查询扩展把同义词、相关概念加进去提高召回率。然后就是检索环节。向量检索是基础操作用嵌入模型把查询转成向量在向量库里做相似度搜索返回 Top-K 个最相似的块。但纯向量检索有个问题它对关键词匹配不敏感。比如用户搜一个产品型号“XR-2000”向量检索可能返回一堆语义相似但型号不同的内容。这时候就需要混合检索把稠密向量和稀疏向量比如 BM25的结果融合起来兼顾语义理解和关键词精确匹配。检索回来之后通常还要做重排序。因为向量相似度高不代表内容真的相关用一个交叉编码器或者专门的重排序模型对候选结果做精排能显著提升最终上下文的质量。重排序的代价是增加延迟所以一般只对 Top-20 到 Top-50 的结果做精排再取 Top-3 到 Top-5 送给模型。最后是上下文组装。把检索到的内容按一定格式拼接加上系统提示词一起塞给大模型。这里要注意上下文窗口的限制不能无限堆砌检索结果否则要么超长被截断要么模型注意力被分散。我的做法是给每个检索块加上来源标注让模型知道每段话出自哪里生成回答时也方便引用。2.3 为什么选择 RAG 而不是微调很多人会问为什么不直接微调模型把知识灌进去这个问题我踩过坑之后才想明白。微调适合教模型“怎么说话”比如调整语气、格式、推理风格RAG 适合教模型“说什么”也就是注入事实性知识。微调的成本高、周期长而且知识更新一次就要重新训练一次。RAG 的知识库可以随时增删改查今天加一份新文档明天就能被检索到。另一个现实问题是微调后的模型仍然可能胡编乱造而且你很难追溯它为什么编。RAG 的检索结果是可以审计的你能看到模型是基于哪些材料生成的回答出了问题也能定位是检索错了还是生成错了。对于企业级应用来说可追溯性有时候比准确率还重要。3. 稠密嵌入与稀疏嵌入两条技术路线的选型与配合3.1 稠密嵌入语义理解的基石稠密嵌入的核心思想是把文本映射到一个低维稠密向量空间语义相近的文本在空间中的距离也相近。比如“如何重置密码”和“忘记密码怎么办”这两句话字面重叠很少但稠密嵌入能把它们映射到相近的位置检索时就能匹配上。稠密嵌入模型的选择直接决定检索质量。目前主流的选择包括 OpenAI 的 text-embedding 系列、BGE 系列、GTE 系列、Jina 系列等。选型时要考虑几个维度向量维度、最大输入长度、多语言支持、推理速度、以及在你所在领域的实际表现。向量维度不是越高越好。高维度理论上能表达更丰富的信息但存储成本和检索延迟也会上升。768 维和 1024 维在实际检索效果上差距可能很小但存储成本差了不少。我的建议是先用一个中等维度的模型跑 baseline如果检索命中率不达标再考虑升级。最大输入长度很关键。很多嵌入模型只支持 512 个 token超过部分会被截断。如果你的文本块设得比较大就要选支持更长输入的模型比如支持 8192 个 token 的模型。但要注意支持长输入不代表长文本的嵌入质量就好有些模型在长文本上表现会下降。多语言支持对于中文场景特别重要。有些模型在英文上表现很好但中文语义理解能力一般。选型时一定要用你自己的业务数据做测试不能只看论文里的 benchmark 分数。3.2 稀疏嵌入关键词精确匹配的保障稀疏嵌入的代表是 BM25 和 SPLADE。BM25 是经典的信息检索算法基于词频和逆文档频率计算相关性。它的优势是关键词匹配精确比如用户搜“Spring AI RAG”包含这些词的文档会被优先返回。缺点是它不理解语义“密码重置”和“重置密码”在 BM25 看来可能是两个不同的查询。SPLADE 是一种学习式的稀疏表示方法它通过模型预测每个词的重要性权重既能保留关键词匹配的能力又引入了一定的语义扩展。比如它可能会给“密码”这个词很高的权重同时给“重置”“忘记”“修改”等相关词也分配一定权重提高召回率。稀疏嵌入的存储方式和稠密嵌入不同。稠密向量用浮点数组存储稀疏向量用倒排索引或者键值对存储。很多向量数据库现在同时支持两种索引比如 Milvus、Qdrant、Weaviate 都提供了混合检索能力。3.3 混合检索11 大于 2 的实践策略纯稠密检索和纯稀疏检索各有短板混合检索就是把两者的结果融合起来。融合策略主要有两种一种是加权求和给稠密和稀疏的相似度分数各分配一个权重然后相加排序另一种是倒数排名融合RRF不看具体分数只看排名把两个列表的排名做加权融合。RRF 的好处是不需要调分数权重对不同检索器的分数尺度不敏感。公式很简单对于每个文档它的融合分数等于所有检索器中该文档排名的倒数之和。比如一个文档在稠密检索里排第 3在稀疏检索里排第 5那它的 RRF 分数就是 1/3 1/5 0.533。按这个分数重新排序就能得到融合后的结果。实际使用中我通常先用混合检索召回 Top-50 左右的结果再用重排序模型精排到 Top-5。这个流程在多个项目里验证下来检索命中率比纯向量检索提升了 15% 到 30%具体提升幅度取决于文档类型和查询特点。4. 从零搭建 RAG 管道的实操步骤与参数计算4.1 环境准备与工具选型搭建 RAG 管道的第一步是选工具。如果你用 PythonLangChain 和 LlamaIndex 是两个主流框架前者生态更丰富后者在检索策略上更灵活。如果你用 JavaSpring AI 提供了完整的 RAG 支持LangChain4j 也是一个选择。如果不想依赖框架直接调嵌入模型 API 加向量数据库客户端也能跑通代码量并不大。向量数据库的选择要考虑数据规模、部署方式和检索性能。小规模数据百万级向量以内用 Chroma 或 FAISS 就够了本地文件存储零运维成本。中等规模千万级可以考虑 Qdrant 或 Milvus支持分布式部署和混合检索。大规模亿级以上通常需要专门的向量数据库集群比如 Milvus 集群版或者云服务。嵌入模型方面如果预算充足且数据可以出外网OpenAI 的 text-embedding-3-small 性价比很高。如果要求本地部署BGE-M3 是一个很稳的选择支持多语言、长文本而且有稠密和稀疏两种输出。中文场景下BGE 系列和 GTE 系列都有不错的表现。4.2 文档解析与分块策略的确定文档解析我推荐用 unstructured 库它支持多种格式而且能保留一定的结构信息。对于 PDF如果排版复杂可以先用 PyMuPDF 提取文本再用正则表达式做清洗。对于 HTMLBeautifulSoup 是标配。对于 Markdown直接按标题层级切分就很自然。分块策略我通常分两步走。第一步按文档的自然结构切分比如 Markdown 按标题切PDF 按段落切。第二步对过长的段落做二次切分用递归字符分割器按段落、句子、词的优先级依次尝试直到块大小符合要求。块大小的确定需要做实验。我的做法是准备一组典型查询然后测试不同块大小下的检索命中率。通常 256 到 512 个 token 是一个合理的起点。重叠区域设为基础块大小的 10% 到 20%比如块大小 512重叠 64 到 100 个 token。这里有一个容易被忽略的细节分块时要保留元数据。每个块都要记录它来自哪个文件、哪个章节、在原文中的位置。这些元数据在检索时可以用来做过滤比如只检索某个产品线的文档或者在生成回答时标注引用来源。4.3 嵌入计算与向量入库的完整流程嵌入计算本身不复杂调 API 或者本地跑模型都行。但有几个实操细节要注意。第一是批处理不要一条一条调把多个文本块打包成一个批次能显著提高吞吐量。第二是错误处理网络请求可能失败要有重试机制。第三是速率限制很多 API 有 QPS 限制要控制并发数。向量入库时除了向量本身还要存原始文本和元数据。原始文本用于后续组装上下文元数据用于过滤和引用。如果向量数据库支持可以同时建立稠密索引和稀疏索引为混合检索做准备。入库之后要验证数据完整性。我通常会随机抽几条记录检查向量维度是否正确、原始文本是否完整、元数据是否齐全。这一步看起来多余但实际项目中经常出现向量维度不匹配或者文本被截断的问题早发现早解决。4.4 检索参数调优Top-K、阈值与重排序检索参数直接影响最终效果。Top-K 决定了召回多少候选太小可能漏掉相关内容太大则引入噪音并增加延迟。我的经验是如果后面有重排序Top-K 可以设大一些比如 20 到 50如果没有重排序Top-K 设 3 到 5 就够了。相似度阈值是另一个重要参数。低于某个阈值的结果直接丢弃避免不相关内容干扰模型。但阈值设多少合适取决于你的嵌入模型和数据类型。我通常先用一个较低的阈值比如 0.5跑一遍观察检索结果的分数分布再确定一个合理的截断点。重排序模型的选择也很关键。BGE-reranker 系列在中文场景下表现不错Cohere 的 rerank 接口也很好用。重排序的输入是查询和候选文档对输出是相关性分数。对 Top-50 做重排序再取 Top-5这个流程在延迟和效果之间取得了比较好的平衡。5. 常见问题排查与避坑经验实录5.1 检索命中率低的排查思路检索命中率低是最常见的问题。排查时我通常按这个顺序走先看查询本身有没有问题比如是不是太短、太模糊、或者包含错别字再看分块是否合理是不是把相关内容切散了然后看嵌入模型是否适合当前领域最后看检索参数是否调优。一个容易被忽略的点是查询改写。用户的问题往往很口语化直接拿去检索效果不好。加一个查询改写步骤把“那个新出的产品怎么用”改写成“XX 产品使用指南”检索命中率能提升不少。查询改写可以用小模型来做成本很低。另一个坑是嵌入模型的领域适配。通用嵌入模型在医疗、法律、金融等垂直领域可能表现不佳。如果预算允许可以用领域数据对嵌入模型做微调或者选用在相关领域预训练过的模型。如果不想微调至少要用领域数据做测试确认检索效果达标。5.2 模型不按检索结果回答的应对方法有时候检索结果明明是对的但模型就是不用或者用自己的知识胡编。这个问题通常出在提示词上。系统提示词要明确告诉模型只基于提供的上下文回答如果上下文里没有相关信息就说不知道不要自己编。另一个技巧是在上下文里加上来源标注让模型知道每段话的出处。生成回答时要求模型引用来源这样既能提高可信度也能倒逼模型认真使用检索结果。如果模型仍然不听话可以尝试降低温度参数减少随机性。还有一种情况是检索结果太多模型注意力被分散。这时候要减少送入模型的块数量或者对块做摘要压缩。我试过把 Top-10 的检索结果用一个小模型做摘要再送给大模型效果比直接送原文好很多。5.3 性能与成本优化的实战技巧RAG 系统的延迟主要来自嵌入计算、向量检索和模型生成三个环节。嵌入计算可以缓存相同的查询不用重复计算。向量检索的延迟和索引类型、数据规模有关HNSW 索引比 IVF 索引查询更快但内存占用更高。成本方面嵌入 API 的调用费用和 token 数量成正比。优化分块策略减少冗余内容能直接降低嵌入成本。检索时控制 Top-K避免送入过多上下文也能减少生成模型的 token 消耗。还有一个容易被忽略的成本是向量数据库的存储。高维向量占用的存储空间不小如果数据量很大要考虑用降维或者量化技术来压缩向量。比如把 float32 量化成 int8存储空间能减少 75%检索速度也能提升代价是轻微的精度损失。5.4 常见问题速查表问题现象可能原因排查方向解决方案检索结果不相关嵌入模型不适配用领域数据测试嵌入质量换模型或微调检索结果不相关分块不合理检查块大小和重叠调整分块策略检索结果不相关查询太模糊分析用户查询特点加查询改写步骤模型不用检索结果提示词不明确检查系统提示词明确要求基于上下文回答模型不用检索结果上下文太长检查送入模型的块数量减少 Top-K 或做摘要回答包含过时信息知识库未更新检查文档更新时间建立定期更新机制检索延迟高索引类型不合适检查向量索引配置换 HNSW 或优化参数嵌入成本高分块冗余分析块内容重复度优化分块和去重6. 知识获取管道的进阶方向与个人实践体会RAG 的基础管道跑通之后还有很多可以优化的方向。比如 GraphRAG把知识图谱引入检索流程能处理多跳推理和实体关系查询。再比如 Agentic RAG让 Agent 自己决定什么时候检索、检索什么、要不要多轮检索而不是固定的一次性检索。这些进阶方案在复杂场景下能显著提升效果但前提是基础管道已经跑稳了。我在多个项目里落地 RAG 的经验是不要一上来就追求完美。先用最简单的方案跑通全流程用真实数据做测试找到瓶颈再针对性优化。很多时候问题不在模型上而在数据质量和分块策略上。把文档解析和清洗做好把分块调合理检索效果自然就上来了。还有一个体会是RAG 系统的评估很重要但容易被忽视。没有评估就没有优化方向。我通常会准备一组问答对覆盖常见查询类型然后定期跑评估看检索命中率和回答准确率的变化。评估集不用很大几十条到上百条就够用关键是要有代表性。最后分享一个小技巧在检索结果里加上“相邻块”。因为分块可能把一段完整的内容切断了检索到其中一个块时把它的前后块也一起取出来能提供更完整的上下文。这个操作成本很低但效果提升很明显尤其是在处理长文档的时候。