构建生产级RAG:摄取、嵌入、检索、重排序与评估
高级12 分钟阅读企业AI

构建生产级RAG:摄取、嵌入、检索、重排序与评估

生产级RAG流水线包含六个阶段,每个阶段都有决定质量的特定模式。本文介绍整体架构、各阶段的选择,以及让有效RAG与令人失望的RAG拉开差距的迭代评估规范。

您应该能够做到的事情

生产级RAG不是“分块 + 嵌入 + 检索”。它是一条六阶段流水线(摄取、分块、嵌入、检索、重排序、生成),每个阶段都需要仔细评估。关键模式包括干净的摄取、智能分块、混合检索、重排序和持续评估。跳过其中任何一项,质量都会停滞在远低于可实现水平的位置。

AI Expert Team发布日期: 2026年5月15日
仅在此浏览器中保存。
本文内容

如果你已经发布过简单的RAG系统,就会熟悉这种模式:将文档分块、生成嵌入、存入向量数据库,根据查询检索top-k,再把结果塞进提示词。演示时效果不错,到了生产环境却往往令人失望。

演示级RAG与生产级RAG之间差距很大。现实文档杂乱无章,现实查询含义模糊,不同查询类型的质量差异巨大,成本和延迟是真实约束,更新和版本管理也很重要。

本文介绍生产级RAG流水线是什么样的——六个阶段、每个阶段的模式,以及让有效系统与令人失望的系统拉开差距的评估规范。

流水线

生产级RAG系统包含六个逻辑阶段:

[文档]
    ↓
1. 摄取(解析、清理、提取元数据)
    ↓
2. 分块(拆分为检索单元)
    ↓
3. 嵌入(向量 + 存储)
    ↓
[查询]
    ↓
4. 检索(语义 + 词法 + 筛选)
    ↓
5. 重排序(top-k → top-N)
    ↓
6. 生成(LLM + 上下文)
    ↓
[响应]

每个阶段都有自己的质量关注点。改进任何一个阶段都会改善整体效果。

下面逐一介绍。

阶段1:摄取

输入的是垃圾,输出的也是垃圾。摄取质量决定了所有下游环节的质量上限。

你会遇到的来源类型:

  • PDF(大多是最难处理的)。
  • Word文档。
  • HTML页面。
  • Markdown。
  • 电子表格。
  • 幻灯片(PowerPoint、Google Slides)。
  • 电子邮件。
  • 代码。
  • 结构化数据(CSV、JSON)。

每种类型都有自己的解析难题。

PDF解析。 PDF是演示格式,而不是数据格式,解析起来极其困难。可采用以下策略:

  • 文本型PDF: pdfplumberpymupdfunstructured。适用于整洁的文本。
  • 扫描型PDF: 使用Tesseract、Google Cloud Vision或AWS Textract进行OCR。
  • 布局感知型: 对复杂布局(表格、多栏)使用 LayoutLM、Mathpix或基于LLM的解析(GPT-4 vision)。

处理困难PDF的现代方法是:使用具备视觉能力的LLM进行OCR并构造内容结构。成本更高,但质量远胜传统OCR。

处理表格。 非结构化文本中的表格很难处理。可以:

  • 转换为Markdown表格(保留结构)。
  • 线性化为散文(“第1行:客户A有50个订单……”)。
  • 作为具有结构化Schema的独立可检索单元。

正确选择取决于预期查询。

提取元数据。 每份文档都有重要的元数据:

  • 标题、作者、日期、版本。
  • 主题、类别、标签。
  • 来源URL或位置。
  • 权限/可见性。

在摄取时采集这些信息,之后可以在检索时用作筛选参数。

清理。 去除样板内容:

  • 每页重复的页眉/页脚。
  • 导航、广告、Cookie横幅。
  • “目录”页。
  • 空白或重复段落。

干净的语料库能产生更好的检索结果。样板内容会造成错误匹配。

质量检查。

  • 解析器是否确实提取了文本?(有些PDF会返回空字符串。)
  • 是否存在编码问题?
  • 表格是否得到保留?
  • 图像是添加了说明,还是被跳过?

在摄取流水线中内置合理性检查。在损坏的解析结果污染索引之前将其拦截。

阶段2:分块

现在你有了干净的文档,接下来要将其拆分为检索单元(文本块)。

基本权衡:

  • 小文本块:检索精确(聚焦于问题),但缺少上下文。
  • 大文本块:上下文更多,但精度较低(相关内容埋在其中)。

两个极端都会损害质量。最佳区间因内容类型而异。

常见策略:

固定大小并重叠。 拆分为N个token的文本块(300–800个token),相邻块重叠50–100个token。简单,适合作为基线。

句子感知分块。 在句子边界处拆分(使用nltk、spaCy或类似工具),避免从句子中间切断。

按段落分块。 每段作为一个文本块。适用于段落结构清晰的文档。

分层(小块 + 大块)。 使用两个索引:

  • 小文本块(300个token)用于精确检索。
  • 大文本块(1,500个token)或完整章节用于提供上下文。

检索时查找小块,向LLM提供对应的大型父块。

感知文档结构。 使用文档结构(标题、章节)指导分块。每个章节作为一个文本块,并保留层级关系。

语义分块。 使用嵌入寻找自然分界点(主题变化的位置)。成本更高,但对某些内容可以产生更好的文本块。

基于LLM摘要的分块。 将长文档摘要为多个层级的文本块(段落摘要、章节摘要、文档摘要)。LLM在摄取时一次性生成这些内容。

正确策略取决于内容。文章和Wiki:按段落或分层。代码:按函数。对话:按轮次。技术文档:感知结构。

文本块元数据。 每个文本块都应携带:

  • 来源文档ID和URL。
  • 章节路径(章 > 节 > 小节)。
  • 页码(用于引用)。
  • 此文本块上方的标题(用于提供上下文)。
  • 文档级元数据(日期、作者、类型)。

这些元数据可以在最终响应中实现筛选和引用。

阶段3:嵌入

将文本块转换为向量。

嵌入模型选择。

在2026年:

  • OpenAI text-embedding-3-large: 综合能力强,价格昂贵。
  • Voyage Voyage-3: 竞争力强,处理技术内容时通常更好。
  • Cohere embed-v4: 多语言能力强。
  • BAAI bge-large: 强大的开源模型。
  • Nomic embed-text: 优秀的开源模型,可免费自行托管。
  • 领域专用模型: 面向代码(Voyage Code,OpenAI text-embedding-3-large对代码也有效)、法律、医疗等领域。

选择模型时,应针对你的领域进行测试。不要假设排行榜第一名就最适合你的数据。

嵌入维度。 模型提供256–3,072个维度。维度越高,质量越好,成本和存储需求也越高。对大多数用例而言,768–1,536是最佳区间。

版本管理。 嵌入模型会更新,你也可能希望切换模型。应提前规划:

  • 跟踪每个向量由哪个嵌入模型版本生成。
  • 迁移时重新嵌入所有内容(或采用双索引过渡)。
  • 不要在同一次搜索中混用不同模型生成的向量。

成本。 嵌入数百万个文本块需要付费。每百万token的成本为€0.10–€0.50(因提供商而异)。对于大型语料库,应提前计算。

存储。 向量体积很大。1M个文本块 × 1,536个维度 × 4字节 = 6GB。应据此规划存储。

阶段4:检索

查询到达后,你需要找到相关文本块。

向量搜索(密集检索)。 对查询生成嵌入,然后寻找最近邻。它可以捕捉语义相似性,是标准做法。

关键词搜索(BM25/词法检索)。 传统文本搜索。可以捕捉精确匹配、罕见词和特定名称,通常能补充向量搜索。

混合搜索。 同时运行两者,然后融合结果。倒数排名融合(Reciprocal Rank Fusion,RRF)是标准融合方法。

def reciprocal_rank_fusion(rankings, k=60):
    scores = {}
    for ranking in rankings:
        for rank, doc_id in enumerate(ranking):
            scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
    return sorted(scores.items(), key=lambda x: -x[1])

实践中,在大多数基准上,混合搜索都优于只使用向量或只使用关键词的搜索。默认使用混合搜索。

元数据筛选。 在评分之前按元数据筛选检索结果。“只搜索2025年及之后的文档。”“只搜索用户有权访问的文档集合。”“只搜索policy类型的文档。”

这对多租户系统至关重要:每次查询都必须限定在该租户可访问的文档范围内。

查询理解。 对查询进行预处理:

  • 拼写纠正。 “engineerin” → “engineering”。
  • 缩写扩展。 “MFA” → “Multi-Factor Authentication MFA”。
  • 同义词/查询扩展。 生成替代表述,并分别搜索。
  • 分解。 将多部分问题拆分为子查询,分别检索。

这些预处理步骤能显著改善现实查询的检索效果。

HyDE(假设文档嵌入,Hypothetical Document Embeddings)。 使用LLM生成虚构的“理想答案”,为其生成嵌入,再用该结果作为检索查询。通常比直接嵌入问题效果更好,因为虚构答案与真实答案文档更加相似。

def hyde_retrieve(query, k=20):
    hypothetical = llm("写一段文字回答:" + query)
    embedding = embed(hypothetical)
    return vector_search(embedding, k=k)

权衡是每次查询多一次LLM调用(增加延迟和成本)。对困难查询值得,对简单查询则过度。

多向量检索。 每个文本块不只生成一个向量,而是生成多个(例如文本块本身、摘要、假设问题各一个)。会增加存储和复杂度,但对某些内容可以改善检索效果。

阶段5:重排序

完成初步检索(top-k,k=20–50)后,使用重排序器更仔细地为候选项评分。

为什么要重排序?

初步检索速度快,但不够精确。向量相似度只是相关性的粗略代理。重排序器(通常是交叉编码器模型)会同时读取查询和每个候选项,从而生成更准确的分数。

重排序器选项:

  • Cohere Rerank。 行业标准。质量好,托管服务。
  • Voyage Rerank。 强劲的竞争者。
  • BGE Rerank-large。 开源,可免费自行托管。
  • MiniLM交叉编码器。 更小、更快,但质量较低。
  • 基于LLM的重排序。 使用小型LLM为查询—候选项对评分。质量最高,成本也最高。

影响。

在大多数RAG系统中,加入重排序通常可以改善最终任务质量;经常被引用的10–20%区间应视为用于规划的估算值,仍需使用自己的评估加以验证。它带来的质量提升几乎总能抵消延迟和成本。

典型设置:

  • 使用混合搜索检索30–50个候选项。
  • 重排序后选取前5–10个。
  • 将排名靠前的结果传给LLM。

自适应重排序。

如果查询的首个初步结果具有很高的向量相似度(明确匹配),可以跳过重排序。如果多个候选项分数相近,则进行更积极的重排序。

阶段6:生成

LLM使用检索到的上下文生成答案。

提示词结构:

你是一名根据所提供上下文回答问题的助手。

上下文:
[文档1 - 标题、URL]
[文本块1的内容]
[文档2 - 标题、URL]
[文本块2的内容]
...

用户问题:{query}

指令:
- 仅根据所提供的上下文回答。
- 如果上下文不包含答案,请明确说明。不要编造信息。
- 使用 [Source N] 标记引用来源。
- 简洁但完整。

以下提示词模式很重要:

  • 来源标记。 为每个上下文文本块标记来源,以便引用。
  • 依据指令。 明确要求模型仅使用上下文。
  • 引用要求。 强制引用,有助于捕获幻觉。
  • 回退指令。 “如果上下文没有答案,请明确说明。”防止编造。

引用处理。

一种常见模式是在响应中包含来源链接,由UI将其渲染为可点击链接。

"公司的远程办公政策允许每周最多4天在家办公 [1]。
[1]: https://wiki.company.com/policies/remote-work"

这样可以验证响应。相比没有依据的答案,用户更信任有依据的回答。

上下文大小管理。

过长的上下文会降低效果。大多数模型在上下文聚焦时表现最佳(5–10个高度相关的文本块),而不是一次性塞入所有内容。上下文膨胀会导致质量下降。

如果必须加入大量上下文,应对相关性较低的项目进行摘要,而不是全文加入。

在每个阶段进行评估

无法衡量就无法优化。每个阶段都需要自己的评估。

摄取评估。 文档是否正确解析?抽样检查文档,确认关键内容得到保留。

分块评估。 文本块大小是否合适?是否保留上下文?是否在合理边界处断开?

嵌入评估。 相似概念的嵌入是否相似?在包含已知相似对和已知不同对的测试集中,余弦相似度是否符合预期?

检索评估。 给定查询时,相关文本块是否出现在top-K?常见指标为recall@K(有多少百分比的查询在前K项中至少包含一个相关文本块)。

重排序评估。 给定检索候选项,重排序器是否将最相关的内容排在首位?指标包括NDCG(归一化折损累积增益)或MRR(平均倒数排名)。

生成评估。 给定上下文和查询,LLM是否生成正确答案?指标包括忠实度(答案是否使用上下文?)、正确性(答案是否正确?)、有用性(是否回应用户意图?)。

端到端评估。 给定真实查询,系统是否生成正确答案?这是最重要的评估,取决于所有阶段。

每个阶段都需要测试集。一种常见的启动方法是:

  • 构建50–100条具有已知正确答案的查询。
  • 对每条查询,确定哪些文档包含答案。
  • 用这些数据评估检索(能否检索到正确文档?)和生成(答案是否正确?)。

工具包括Ragas、TruLens和自定义套件。具体工具不如持续运行评估重要。

运营注意事项

以下是一些生产现实:

索引流水线。 新文档会不断到达,需要重新嵌入和更新索引,也要处理删除和更新。这条流水线会持续运行,而不是只在初次设置时执行。应将其构建为系统,而不是一次性脚本。

延迟。

典型分解如下:

  • 嵌入(查询):50–200ms。
  • 向量搜索:50–200ms。
  • 重排序:200–500ms(取决于K)。
  • 生成:1–5s(取决于上下文和模型)。
  • 总计:1.5–6s。

优化方法:

  • 缓存频繁查询的嵌入。
  • 缓存重复查询—候选项对的重排序结果。
  • 流式生成。
  • 尽可能并行执行。

要实现低于2s的延迟,通常需要快速嵌入模型、快速向量数据库,以及快速重排序器;对于已缓存或简单查询,也可以跳过重排序。

成本。

每次查询的成本:

  • 嵌入:约€0.0001。
  • 向量搜索:约€0.0001(取决于基础设施)。
  • 重排序:€0.001–0.01(取决于模型)。
  • 生成:€0.005–0.05(取决于模型和上下文)。
  • 总计:每次查询约€0.01–0.05。

规模扩大后,成本会迅速累积。一百万次查询 = €10K–50K。

成本优化方法:

  • 缓存。
  • 在质量允许时使用更便宜的模型。
  • 压缩上下文(摘要,而非完整文本块)。

更新。 文档会发生变化。可采用以下模式:

  • 版本管理: 每份文档都有版本;根据策略保留或删除旧版本。
  • 增量更新: 对新版本重新分块和嵌入;删除旧文本块。
  • 感知差异: 只重新处理发生变化的章节。

在更新频率高的场景中,这一点非常重要。

权限。 对私有数据进行RAG时,文档具有访问控制,检索必须遵守。

  • 基于元数据筛选(每个文本块包含accessible-by元数据)。
  • 使用租户隔离的索引实现硬隔离。
  • 审计谁访问了什么。

不要依赖LLM强制执行权限。必须在检索层执行。

常见失败模式

以下是失败RAG系统中的一些常见模式:

失败1:分块不佳。 文本块在语义中间断开,表格被拆到多个块中,标题与内容分离。修复:采用更好的分块策略。

失败2:检索遗漏答案。 相关文本块存在,却没有被检索到。通常是查询与文档表达不匹配。修复:HyDE、查询扩展、更好的嵌入。

失败3:文本块正确,顺序错误。 相关文本块被检索到,但排名较低。LLM使用了排名更高但不相关的文本块。修复:重排序。

失败4:文本块正确,仍有幻觉。 文本块正确,但LLM编造了额外信息。修复:使用更严格的依据提示词、引用要求和更低的温度。

失败5:文本块正确,答案错误。 文本块中包含答案,但LLM提取了错误部分。修复:改进生成提示词,也可能需要更大的模型。

失败6:数据陈旧。 索引没有更新。修复:持续运行摄取流水线。

失败7:权限泄露。 用户看到了本不应查看的文本块。修复:在检索时强制筛选;执行审计。

失败8:成本失控。 随着语料库和流量增长,延迟和成本不断攀升。修复:缓存、模型路由,必要时改变架构。

实例:公司知识库RAG

以典型的公司知识库RAG系统为例。

语料库: 约50,000份文档(Wiki页面、策略、运行手册、会议记录、Slack话题串)。

流水线:

  1. 摄取:

    • Notion:通过API导出。
    • Slack:导出存档,并筛选相关频道。
    • Google Drive:通过API导出已批准的文件夹。
    • 清理:删除只有表情符号的消息和样板签名。
  2. 分块:

    • 分层:段落级小文本块、章节级父文本块。
    • 小文本块层级总计约250K个文本块。
    • 元数据:source、section path、last_updated、accessible_to。
  3. 嵌入:

    • Voyage-3嵌入,1,024个维度。
    • 存储在Pinecone(托管)中。
    • 每周对已更改文档重新嵌入。
  4. 检索:

    • 混合:向量搜索 + BM25(通过Pinecone的混合搜索)。
    • 对查询使用HyDE。
    • 按可访问性进行元数据筛选。
    • 检索前30项。
  5. 重排序:

    • Cohere Rerank。
    • 前30项 → 前8项。
  6. 生成:

    • Claude Sonnet 5。
    • 提供前8个父文本块(而非小文本块)作为上下文。
    • 响应中必须引用来源。

评估:

  • 100组手工编写的查询/答案对。
  • 检索recall@30:约92%。
  • 最终答案正确率:约85%。
  • 忠实度(无幻觉):约95%。

运营:

  • 每日增量摄取。
  • 每周对已更改文档进行完整的重新嵌入。
  • 按查询提供可观测性。
  • 每月重新运行评估并监控趋势。
  • 每季度审查查询日志,发现新的失败模式。

成本:

  • 嵌入:约€500/月(稳定状态)。
  • 向量数据库托管:约€800/月(Pinecone)。
  • 每次查询的检索 + 生成:约€0.02。
  • 总计:约€2,500/月 + €0.02 × 查询量。

对大多数企业而言,这些成本完全可以通过生产力收益得到合理回报。

90天RAG建设计划

如果从零开始:

第1–30天:MVP。

  • 确定语料库和主要用例。
  • 构建基础摄取(一个来源)。
  • 基础分块(固定大小并重叠)。
  • 使用标准嵌入模型。
  • 只使用向量搜索(不重排序)。
  • 使用简单的生成提示词。

第31–60天:质量。

  • 手工构建评估集(50–100条查询)。
  • 识别失败模式。
  • 添加重排序。
  • 添加混合搜索。
  • 改进分块。

第61–90天:运营。

  • 持续摄取流水线。
  • 可观测性。
  • 评估自动化。
  • 权限/身份验证。
  • 成本监控。

90天后,你得到的不只是可演示的系统,而是真正可用的系统。真实用户可以依赖它。

质量存在于每个阶段

生产级RAG是一条六阶段流水线,每个阶段都有质量关注点。让有效系统与令人失望的系统拉开差距的模式包括:

  • 摄取: 全面解析、保留结构、采集元数据。
  • 分块: 根据内容类型选择适当策略,通常采用分层方式。
  • 嵌入: 使用高质量模型、管理版本、规划迁移。
  • 检索: 默认采用混合检索、理解查询、筛选元数据。
  • 重排序: 几乎总是值得。
  • 生成: 提供依据、引用来源、在未知时回退。
  • 评估: 在每个阶段持续进行。

以上各项都不是可选项。RAG答案质量从60%提升到90%的差距,就存在于这些细节中。

投入确实不小——生产级RAG建设需要数月,而不是数周。回报则是一个用户真正可以信任的系统。这才是重要的门槛。

继续阅读

通过下一篇文章继续沿着相同的学习路径进行学习。