文章 / RAG 不是把文档扔进去——检索增强生成工程实战
工程实践

RAG 不是把文档扔进去——检索增强生成工程实战

2026.07.05 · 约 3000 字

据统计,超过 60% 的 RAG 生产系统在上线后遇到过检索质量退化的问题——要么搜不到相关文档,要么搜到的东西模型不会用。

很多人以为 RAG 就是"把文档扔进向量库,让 LLM 去搜"。实际上,RAG 是一条从文档到答案的完整流水线,每个环节的决策都会影响最终质量。本文不讲概念,只讲工程——你在搭建 RAG 系统时真正会遇到的问题和对应的解法。

一、RAG 的常见误区

先澄清三个最常见的认知偏差:

核心认知: RAG 的质量上限由检索决定,不是由 LLM 决定。搜不到,再聪明的模型也没用。

二、Chunking——第一道也是最容易被低估的坎

Chunking 策略直接决定了检索的精度和召回率。没有一种策略适合所有场景,你需要根据文档类型和查询模式来选择。

常见分块策略

// 伪代码:递归分块策略示意
function chunk(doc, maxTokens = 512, overlap = 64):
    if len(doc) <= maxTokens:
        return [doc]
    // 优先按语义边界切分
    splits = split_at_boundary(doc)
    chunks = []
    for split in splits:
        if len(split) > maxTokens:
            // 递归切分大块
            chunks.extend(chunk(split, maxTokens, overlap))
        else:
            chunks.append(split)
    // 添加重叠窗口
    return add_overlap(chunks, overlap)

实战建议

常见坑: Chunk 过大(>2000 Token)会导致检索精度急剧下降,因为一个 Chunk 包含太多无关信息,Embedding 会被"拉偏"。

三、Embedding 选型

Embedding 模型的选择不是"越强越好",而是"越匹配越好"。

选型维度

常用 Embedding 模型对比(2026 年中):
┌──────────────────────┬────────┬──────────┬───────────┐
│ 模型                  │ 维度    │ 语言      │ 适用场景   │
├──────────────────────┼────────┼──────────┼───────────┤
│ bge-m3               │ 1024   │ 多语言    │ 通用       │
│ multilingual-e5-large │ 1024   │ 多语言    │ 通用/高精度 │
│ text-embedding-3-small│ 512-1536│ 多语言    │ OpenAI 生态 │
│ jina-embeddings-v3   │ 1024   │ 多语言    │ 长文本     │
│ gte-Qwen2             │ 1024-4096│ 中文为主  │ 中文优化   │
└──────────────────────┴────────┴──────────┴───────────┘

四、检索优化

检索是整个 RAG 管线的瓶颈。优化检索能在不换模型的前提下显著提升质量。

多阶段检索

不要指望一次向量搜索拿到答案。生产级 RAG 应该走多阶段管道:

用户查询
    ↓
Stage 1: 粗排(高效召回 Top-K)
    ├─ 向量检索(语义相似度)
    └─ BM25 检索(关键词匹配)
    ↓
Stage 2: 融合(去除重复,按分融合)
    ├─ Reciprocal Rank Fusion (RRF)
    └─ 加权合并
    ↓
Stage 3: 精排(高精度重排序)
    └─ Cross-encoder Re-ranker
    ↓
Stage 4: 截断(保留 Top-N 送入 LLM)
    └─ 按质量阈值 + 数量上限
    ↓
LLM 生成

重排序(Re-ranking)

这是被低估最多的一步。向量检索的 Embedding 是双向的(查询和文档各自编码),而 Cross-encoder 是双向的(查询和文档一起编码),精度远高于向量检索,但速度慢(每次只能比较一对)。

正确做法:先用向量检索粗排 Top-100,再用 Cross-encoder 精排 Top-10。这样兼顾精度和速度。

查询重写

用户的原始查询往往不是最优的检索语句。一个简单的优化:让 LLM 先对用户的查询做一次重写,然后再去检索。

原始查询:"那个报错怎么解决"
  → 重写后:"Python ModuleNotFoundError 报错的常见原因和解决方案"
  → 检索质量显著提升

五、生成优化

搜到了还不够,模型得会用。这是 LLM 层要解决的问题。

Prompt 设计

上下文注入不是把检索结果原样扔进去就行了。设计原则:

RAG Prompt 模板示例:
---
你是一个基于知识库的问答助手。

请严格遵循以下规则:
1. 你的回答只能基于以下提供的文档内容
2. 如果文档中没有相关信息,请回答"我没有找到相关信息"
3. 引用来源:在回答末尾用 [来源: 文档X/第Y段] 标注

文档内容:
--- BEGIN CONTEXT ---
|{检索结果}|--- END CONTEXT ---
|
|用户问题:{用户输入}|---

幻觉控制

即使有 RAG,LLM 仍然会幻觉。工程层面的防护措施:

六、评估——没有度量就没有改进

RAG 系统需要从两个维度评估,缺一不可:

检索质量

生成质量

// 忠实度评估的自动化方法
function checkFaithfulness(answer, context):
    // 从回答中提取所有声明性句子
    claims = extractClaims(answer)
    for claim in claims:
        // 检查每个声明是否在上下文中被支持
        if not isSupportedBy(claim, context):
            return false  // 发现幻觉
    return true
关键原则: 评估数据集应该来自真实用户查询,而不是人工构造的完美问题。真实查询的噪音和模糊性才能暴露系统的短板。

七、小结

RAG 不是"把文档扔进去",而是一条完整工程流水线:

Chunking     → 分块策略决定精度上限
Embedding    → 模型选型匹配场景
检索         → 多阶段(粗排→融合→精排)
生成         → Prompt 设计 + 引用 + 幻觉控制
评估         → 检索 + 生成双维度闭环

核心原则:
1. 检索质量决定系统上限,LLM 只是执行者
2. 没有一种方案适合所有场景——测试、度量、迭代
3. 质量评估必须基于真实数据,而不是完美问题

RAG 不是什么新技术,但能在生产环境中持续稳定运行的系统少之又少。如果你正在搭建 RAG 系统,先从 Chunking 和检索质量入手——这两步做对了,后续的问题会少一大半。

💬 评论

加载中...
请友善发言