朴素RAG的局限性

标准RAG流程很简单:文档分块→向量化→检索top-k→拼接到prompt→生成回答。但在实际场景中,朴素RAG面临几个核心问题:

  1. 检索不准:用户查询与文档语义空间不匹配
  2. 排序不佳:向量相似度高≠回答有用
  3. 上下文冗余:top-k中可能包含大量无关内容
  4. 无法自纠错:检索不到就硬编答案

检索层优化

混合检索

纯向量检索擅长语义匹配但弱于精确关键词。BM25等稀疏检索正好互补。混合检索的实践方案:

  • 向量检索(Dense):召回语义相关段落
  • 关键词检索(Sparse/BM25):召回精确匹配段落
  • 融合排序:RRF(Reciprocal Rank Fusion)算法合并两路结果
def rrf_fusion(dense_results, sparse_results, k=60):
    scores = {}
    for rank, doc in enumerate(dense_results):
        scores[doc.id] = scores.get(doc.id, 0) + 1/(k + rank)
    for rank, doc in enumerate(sparse_results):
        scores[doc.id] = scores.get(doc.id, 0) + 1/(k + rank)
    return sorted(scores.items(), key=lambda x: -x[1])

查询改写

用户的原始query往往不是最佳检索query。通过LLM对查询进行改写:

  • 查询扩展:生成多个语义变体query,分别检索后合并
  • HyDE:先让LLM生成一个假设性回答,用该回答的embedding去检索(对长尾问题效果显著)
  • 子问题分解:复杂问题拆成多个子问题分别检索

重排序(Reranking)

向量检索的召回质量参差不齐。在召回后加一个cross-encoder重排层:

  1. 向量检索召回top-50(宽召回)
  2. Cross-encoder(如bge-reranker-v2)对每对(query, doc)打分
  3. 按分数取top-5(精排序)

Cross-encoder比bi-encoder准确率高20-30%,但速度慢,所以做两阶段检索。

生成层优化

上下文压缩

检索回来的文档可能很长,需要压缩到LLM能高效处理的篇幅:

  • 提取式:用小模型抽取关键句子
  • 摘要式:LLM对每个文档生成精简摘要
  • LLMLingua:基于困惑度删除低信息token,可压缩到原长的1/10

引用标注

高质量RAG需要可溯源。实现方式:

  • 在prompt中要求模型标注引用段落编号
  • 后处理时验证引用的段落确实支持该陈述
  • 不支持的引用标记为"未验证"

自适应RAG:让模型决定怎么检索

Self-RAG

Self-RAG让模型学会自主决定:

  • 是否需要检索(通过特殊token [Retrieve]/[No Retrieve]
  • 检索到的段落是否相关([Relevant]/[Irrelevant]
  • 回答是否被段落支持([Supported]/[Partially Supported]

这种方式将检索决策内化为模型能力,需要通过强化学习训练。

CRAG(Corrective RAG)

CRAG在检索后增加一个"检索评估器":

  1. 评估检索结果质量:Correct / Ambiguous / Incorrect
  2. 如果Incorrect,触发web搜索补充
  3. 如果Ambiguous,将检索结果与web结果合并
  4. 对最终结果重排序后生成

Adaptive-RAG

根据查询复杂度自适应选择策略:

  • 简单查询→单次检索
  • 复杂查询→多跳检索+推理
  • 分类器判断查询类型,路由到对应处理流水线

工程实践要点

评估体系

RAG系统必须有量化评估。推荐使用RAGAS框架,四个核心指标:

  • Faithfulness:回答是否忠于检索内容(无幻觉)
  • Answer Relevancy:回答是否切题
  • Context Precision:检索内容中有用的比例
  • Context Recall:回答所需信息是否被检索到

分块策略

分块大小直接影响检索粒度。经验值:

  • 通用场景:256-512 tokens,10-20%重叠
  • 代码文档:按函数/类分块
  • 长文:按章节分块,父子分块结合(父块提供上下文,子块用于精确匹配)

总结

RAG系统正在从"拼接管道"进化为"自适应智能体"。从混合检索到重排序、从查询改写到自反思纠错,每个环节都有大量优化空间。核心原则是:不要把RAG当成固定流水线,而要设计成能根据查询难度自适应调整的动态系统。