跳至正文
来两杯美式
返回

RAG 答非所问?从索引到生成,打通最后一公里

By 来两杯美式
发布于

上篇我们覆盖了 RAG 链路的前三个阶段——查询转换、路由和查询构建,核心目标是在检索发生之前把查询优化到位。本篇进入后半程:索引、检索和生成。这三个阶段是 RAG 的核心链路,也是优化策略最密集的地方。

先回顾一下全景图:

RAG 6阶段优化全景图:查询转换、路由、查询构建、索引、检索、生成六个阶段对应的优化策略

阶段四:索引(Indexing)

目标:构建高质量的索引,确保检索时能找到最相关的片段。

索引阶段是 RAG 的基石。如果索引建得不好,后面的检索和生成再努力也是”垃圾进、垃圾出”。

1. 分块策略

分块(Chunking)是 RAG 优化中最基础也最容易踩坑的一环。关于四种主流分块策略的详细对比,可以参考 RAG 实战:核心组件、调优与问题排查。这里补充两个容易被忽略的要点:

块大小不是越小越好。 太小可能丢失上下文,太大又可能引入噪声。500-1000 字符可以作为部分文本知识库的实验起点,但不是通用最佳值;代码、表格、FAQ 和长篇规章应分别设计切分策略,并用检索评测选择大小。

重叠不是“多就好”。 可以先测试 10%-20% 等较小重叠率,再比较召回率、重复结果和索引成本。是否需要超过 30% 取决于边界语义和文档结构,不能脱离数据集断言“没有收益”。

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
    separators=["\n\n", "\n", "", ".", " "]  # 优先在自然边界切
)

2. RAPTOR(递归文档树检索)

处理长文档的利器。核心思路:给文档建立层次化的摘要树

                    文档总摘要(第 3 层)
                   /                    \
            段落组摘要 A              段落组摘要 B(第 2 层)
           /     |     \            /     |     \
        Chunk1 Chunk2 Chunk3   Chunk4 Chunk5 Chunk6(第 1 层:原始块)

构建方法:先将文档切成小块,用 LLM 对相邻块做摘要并聚类,逐层向上构建。检索时可以从任意层级切入:

适用场景:知识库包含大量长篇文档(论文、技术手册、产品说明书)。短文档(如 FAQ)用 RAPTOR 性价比不高。

3. 多向量 / 表征检索

为同一文档块生成多个向量表示。比如为一篇长文档生成一个概括性向量(用于粗筛),再为其中每个小段落生成详细向量(用于精排)。检索时先用概括性向量快速定位候选文档,再用详细向量做精确匹配。

这种方法在处理”一篇文档涵盖多个子主题”的情况时特别有效——概括性向量负责”找到对的文档”,详细向量负责”找到对的段落”。

4. Embedding 选型

Embedding 选型可能显著影响召回质量,但收益取决于语言、领域、查询分布和基准数据,应该与分块、混合检索等方案在同一评测集上比较。

考量维度建议
维度维度影响存储和计算,但跨模型不能用“1024 > 768”推断质量;应比较实际检索指标
领域适配医疗、法律等垂直领域优先选领域微调过的模型
多语言中英混合场景选 BGE-M3 等多语言模型
部署方式API 调用省运维但按量付费;本地部署前期投入但边际成本低

领域微调只有在数据量、标注质量和评测结果支持时才值得投入。先建立基线,再比较通用模型、领域模型和微调方案的质量与成本。

阶段五:检索(Retrieval)

目标:从索引中高效、准确地召回最相关的文档片段。

1. 多路召回 + 混合检索

单一检索方式总有盲区。向量检索擅长语义匹配但容易漏掉精确关键词,关键词检索(BM25)擅长匹配专有名词但对同义词不敏感。

关于混合检索的详细讨论可以参考 企业级 RAG 怎么落地?,这里给出一个完整的集成检索器实现:

# LangChain v1 需要额外安装 langchain-classic
from langchain_classic.retrievers import EnsembleRetriever, BM25Retriever

# 向量检索器
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": 10})

# 关键词检索器
bm25_retriever = BM25Retriever.from_documents(docs)
bm25_retriever.k = 10

# 组合检索器(可调权重)
ensemble_retriever = EnsembleRetriever(
    retrievers=[vector_retriever, bm25_retriever],
    weights=[0.6, 0.4]  # 向量检索权重略高
)

三种检索方式的分工:

方式擅长盲区
向量检索语义匹配、同义词、模糊表达精确关键词、专有名词
BM25 关键词专有名词、编号、精确匹配同义词、语义相近但用词不同
元数据过滤按日期/作者/类别/权限过滤无法做内容级别的检索

2. ReRank 搜索重排

ReRank 位于初次召回之后、把上下文交给生成模型之前,因此属于检索阶段或“检索—生成边界”,不是生成本身。典型流程如下:

用户查询 + 召回候选文档


    Reranker 模型
    重新评估查询与文档的相关性


    按分数重排 → 截取 Top-K 交给 LLM

Reranker 不负责从全库检索,而是对候选集精排。候选数、最终 Top-K 和模型选择都应通过 Recall、MRR、nDCG、延迟与成本共同确定,不能把“召回 30-50、保留 5-10”当成固定规则。

模型类型部署方式评估重点
托管 Rerank API在线 API领域效果、数据合规、价格与延迟
BGE 等开源 Reranker本地部署语言/领域效果、硬件占用与吞吐

不存在对所有数据集都“效果最好”的 Reranker;应使用同一标注集做离线比较。

阶段六:生成(Generation)

目标:基于检索到的上下文,生成高质量、无幻觉、流畅的答案。

1. Prompt 工程

关于 Prompt 模板设计可以参考 RAG 实战:核心组件、调优与问题排查。这里补充两个容易被忽略的点:

明确限制回答范围。 在 Prompt 中写清楚“仅根据提供的上下文回答,如果信息不足请明确说明”,可以降低部分无依据生成,但不能替代检索质量、引用校验、事实核验和拒答评测。

控制输出格式。 要求 LLM 输出结构化答案(如先给结论、再给依据、最后标注来源),方便后续处理和验证。

2. Self-RAG(自我反思 RAG)

原始 Self-RAG 不是给任意 LLM 套一个“三次自问”Prompt,而是训练一个模型在生成时输出特殊的 reflection tokens,用它们决定是否检索,并评价证据相关性、回答支持度和整体质量。下面是概念化流程,不是原论文算法的逐步实现:

┌─────────────────────────────────────────────┐
│           Self-RAG 生成循环                   │
│                                              │
│  1. 要不要检索?                              │
│     ├─ 需要 → 执行检索                        │
│     └─ 不需要 → 直接用内部知识                  │
│                                              │
│  2. 检索结果有没有用?                         │
│     ├─ 有用 → 基于检索结果生成                  │
│     ├─ 部分有用 → 只取有用部分生成               │
│     └─ 没用 → 放弃检索结果,改用内部知识          │
│                                              │
│  3. 生成的答案是否事实正确?                     │
│     ├─ 是 → 输出                              │
│     └─ 否 → 重新生成或补充检索                   │
└─────────────────────────────────────────────┘

实现前应先阅读 Self-RAG 原论文,并区分“原始 Self-RAG”与泛化的自检索/自反思流程。

3. CRAG(纠正性 RAG)

CRAG 在传统 RAG 的基础上加了一个检索质量评估模块,在生成之前先判断检索结果靠不靠谱:

用户提问 → 检索 → 评估检索质量

            ┌─────────┼─────────┐
            ▼         ▼         ▼
         高质量     中等质量    低质量
            │         │         │
            ▼         ▼         ▼
        直接生成   问题重写   扩大搜索范围
                   再检索    或告知用户

这个评估模块可以用一个小型 LLM 或专门的分类模型来实现。相比 Self-RAG,CRAG 的”反思”发生在检索阶段而不是生成阶段,对延迟的影响更可控。

Self-RAGCRAG
反思位置生成过程中检索之后、生成之前
核心机制训练模型生成 reflection tokens,控制检索并评价证据与生成内容独立模块评估检索质量,触发纠正动作
延迟影响较高(多次 LLM 调用)中等(一次额外评估)
适用场景准确性优先鲁棒性优先

场景化选型:别什么都往上堆

RAG 优化不是做加法。不同的场景,性价比最高的策略组合完全不同。以下是从上篇和下篇所有策略中提取的选型建议:

场景特点推荐策略成本
简单问答问题直接,知识库清晰高质量 Chunking + 多查询重写 + ReRank + 精炼 Prompt
复杂推理多步骤、逻辑关联问题分解 + 混合检索 + Self-RAG/CRAG
知识密集型长文档、领域专业RAPTOR + 领域 Embedding + 集成检索器 + ReRank中-高
高实时要求对响应速度敏感自检索 + 动态路由 + 缓存 + 轻量模型低-中

建议路径:从简单问答的组合开始,跑通后看效果,再根据实际痛点逐步引入复杂策略。千万别一上来就上 Self-RAG + RAPTOR + 多路召回全家桶。

性能优化 6 招

除了算法层面的优化,工程层面的性能优化同样重要。以下 6 招可以显著提升响应速度和资源利用率:

1. 并行处理

多查询重写、多路召回等场景天然适合并行。多个子查询可以同时发往检索器,多个检索器可以同时执行。利用 asyncio 或线程池能显著减少总等待时间。

2. 增量更新

避免全量重建索引。对于新增或修改的文档,只更新受影响的索引部分。如果向量数据库支持 upsert,优先使用增量写入而非全量覆盖。

3. 缓存策略

对频繁查询、热门文档嵌入、ReRank 结果进行缓存。可以分层设计:

4. 批量操作

在 API 限制允许时,批量提交 embedding 输入通常能减少网络往返和调度开销,但不保证端到端一定更快。价格是否优惠取决于服务商是否提供单独的 Batch API 或计费方案;普通批量请求不会自动获得折扣。

5. 量化与剪枝

对于本地部署的模型,可以评估 INT8/INT4 量化或模型剪枝,以减少显存和计算开销。精度损失和速度收益高度依赖模型、硬件、量化方法与任务,必须在目标评测集和部署硬件上验证。

6. 硬件加速

GPU/TPU 往往更适合大规模矩阵计算,但小模型、低并发或受数据传输开销影响的任务未必比 CPU 更划算。应比较目标负载下的吞吐、p95 延迟、利用率和总成本,再决定本地 CPU、加速器或云实例。

评估:你怎么知道优化真的有效?

做了优化,怎么衡量效果?直觉感受不靠谱,需要量化的评估体系。

常用评估框架

框架特点适用场景
Ragas专注 RAG 评估,自动化指标丰富开源项目首选,与 LangChain/LlamaIndex 集成
LangChain Eval框架内置,用 LLM 评估 LLM已经在用 LangChain 的项目
Arize Phoenix可观测性平台,可视化追踪需要运行时监控的团队

核心指标

评估分两个维度:

检索维度

生成维度

企业场景还要额外评估权限安全:同一组问题应使用不同角色账号执行,检查检索候选、Prompt 上下文、引用来源和运行日志中是否出现无权访问内容。否则最终答案看起来合规,中间链路仍可能已经泄露敏感信息。

自动化指标能覆盖大部分场景,但对于复杂的主观判断(如”答案是否足够清晰”),人工评估仍然不可替代。

总结

回到开头的问题:你的 RAG 为什么总差一口气?

答案很可能是——你只优化了其中一两个阶段,而瓶颈藏在其他阶段。上下两篇覆盖了 6 个阶段、20+ 种策略,下面是一张快速定位表:

如果你的症状是…重点检查…
检索结果和问题不沾边查询转换(阶段一)、Embedding 选型(阶段四)
召回了正确文档但答案不对ReRank 与上下文组装(阶段五)、生成 Prompt(阶段六)
复杂组合问题翻车问题分解(阶段一)、路由(阶段二)
长文档检索效果差RAPTOR(阶段四)、分块策略
幻觉严重ReRank(阶段五)、证据质量、Prompt 限制、引用/事实校验
响应太慢性能优化 6 招、自检索(阶段三)
不知道优化有没有用评估体系

最后记住三条铁律:

  1. 从简单的开始:先建立 Chunking、基础检索和生成基线,再根据评测结果决定是否加入多查询重写或 ReRank。
  2. 不是越多越好:每加一层优化,成本就涨一截。根据场景选策略组合。
  3. 数据是根:任何优化都无法弥补知识库本身的质量问题。垃圾进、垃圾出。

本系列文章


分享这篇文章:
通过邮件分享这篇文章✓ 链接已复制
查看系列全部文章
  1. 01.做 AI 助手,最怕一上来就建知识库
  2. 02.RAG 入门:为什么大模型需要查资料再回答
  3. 03.RAG 核心原理:检索、向量与嵌入——计算机如何理解语义
  4. 04.RAG 实战:核心组件、调优与问题排查
  5. 05.RAG 为什么回答流程问题会漏步骤?原因和改进方案(附完整源码)
  6. 06.企业级 RAG 怎么落地?不只是向量检索和大模型(附完整源码)
  7. 07.RAG 检索不准?先别换模型,把问题问对再说
  8. 08.RAG 答非所问?从索引到生成,打通最后一公里
  9. 09.别再把聊天记录当记忆了:AI Agent 的四种记忆到底怎么分?
  10. 10.我手搓了一个 AI Agent 记忆框架,才发现“长期记忆”不是存聊天记录
  11. 11.精选数据与垂直 AI:AI 时代的护城河在哪

上一篇
把存量系统交给 Agent,先想清楚 API、Skill、MCP 各是什么
下一篇
RAG 检索不准?先别换模型,把问题问对再说