跳转至

第6章 RAG与检索

学习目标

  • 理解检索增强生成(RAG)的概念与价值
  • 掌握文档分块(Chunking)策略及其影响
  • 理解检索器与重排序器(Reranker)的作用
  • 区分 RAG 与微调的适用场景
  • 使用 Python 实现一个简单的 RAG 流程

问题导入

LLM 的知识停留在训练截止日,且无法访问企业内部文档。当用户问"我们公司 2025 年 Q3 的营收是多少"时,模型要么坦白"不知道",要么凭空编造。RAG(Retrieval-Augmented Generation,检索增强生成)正是为解决这一问题而生:在生成前先从外部知识库检索相关片段,再将其作为上下文喂给模型。RAG 让 LLM "睁眼看世界",既保证了事实准确性,又支持知识实时更新,是企业 Agent 落地最核心的能力之一。据 Gartner 预测,到 2026 年超过 80% 的企业 AI 应用将采用 RAG 架构。本章将系统讲解 RAG 的原理、关键组件与工程实现。

核心概念

1. RAG 概念

RAG = 检索(Retrieval)+ 增强(Augmented)+ 生成(Generation)。流程为:用户提问 → 从知识库检索相关文档片段 → 将片段拼入 Prompt → LLM 基于片段生成答案。RAG 把 LLM 从"闭卷考试"变成"开卷考试",显著降低幻觉并支持知识动态更新。

2. 文档分块(Chunking)策略

文档不能整篇塞入上下文,需先切分成小块: - 固定长度分块:按 token 数(如 512)切分,简单但可能切断语义。 - 语义分块(Semantic Chunking):按句子/段落边界切,保留语义完整性。 - 重叠分块:相邻块重叠 50-100 token,避免边界信息丢失。 - 递归分块:先按章节,再按段落,再按句子,层级切分。 - 选择原则:块大小需平衡检索精度(小块更精准)与上下文完整性(大块更完整)。常见取值 256-1024 token。

3. 检索器(Retriever)

  • 稀疏检索:BM25 / TF-IDF,基于关键词匹配,无需模型,速度快。
  • 稠密检索:基于 Embedding 的向量检索,捕捉语义相似性。
  • 混合检索(Hybrid):稀疏 + 稠密结合,兼顾关键词与语义,是生产环境主流方案。

4. 重排序器(Reranker)

初检阶段为追求效率通常只做向量近似检索(如 HNSW),召回 Top-20;再用 Cross-Encoder 重排序模型对 query 与每个候选做精细打分,精选 Top-3-5。Reranker 显著提升相关性,常见模型有 bge-reranker、Cohere Rerank。

5. RAG vs 微调(Fine-tuning)

维度 RAG 微调
知识更新 实时,更新知识库即可 需重新训练
适用场景 事实型问答、动态知识 风格/格式固化、领域术语
成本 检索 + 推理 训练 + 推理
可解释性 高(可引用来源) 低
幻觉控制 强 弱

两者可结合:微调让模型学会"如何利用检索结果",RAG 提供"事实"。

6. 高级 RAG 技术

  • 查询改写(Query Rewriting):将用户口语化问题改写为更适合检索的表述。
  • 多查询融合(HyDE / RAG-Fusion):生成多个子查询并行检索后融合。
  • 父子块(Parent-Child Chunking):检索用小块,生成时替换为大块上下文。
  • 自纠错(Self-RAG / CRAG):模型评估检索质量,必要时重新检索。

原理图

flowchart LR
    subgraph 离线索引
        Docs[原始文档] --> Chunk[分块]
        Chunk --> Embed1[Embedding]
        Embed1 --> VectorDB[(向量数据库)]
    end

    subgraph 在线检索生成
        Query[用户提问] --> Embed2[Query Embedding]
        Embed2 --> Ret{向量检索}
        VectorDB --> Ret
        Ret --> Candidates[Top-K 候选块]
        Candidates --> Rerank[重排序 Reranker]
        Rerank --> TopN[Top-N 精选块]
        TopN --> Prompt[拼装 Prompt]
        Prompt --> LLM[LLM 生成]
        LLM --> Answer[带引用的答案]
    end
图:RAG 离线索引与在线检索生成流程

示例代码

使用 OpenAI Embedding + numpy 实现一个最小可运行的 RAG demo。

import os
import math
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])


def embed(text: str) -> list[float]:
    """获取文本向量。"""
    return client.embeddings.create(
        model="text-embedding-3-small", input=text
    ).data[0].embedding


def cosine(a: list[float], b: list[float]) -> float:
    """余弦相似度。"""
    dot = sum(x * y for x, y in zip(a, b))
    return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))


def retrieve(query: str, corpus: list[str], k: int = 2) -> list[str]:
    """从语料库检索 Top-K 相关片段。"""
    q_vec = embed(query)
    scored = [(cosine(q_vec, embed(doc)), doc) for doc in corpus]
    scored.sort(reverse=True)
    return [doc for _, doc in scored[:k]]


def rag_answer(query: str, corpus: list[str]) -> str:
    """简单 RAG 流程:检索 + 生成。"""
    context = "\n---\n".join(retrieve(query, corpus))
    prompt = (
        f"请根据以下资料回答问题,若资料不足请说明。\n\n资料:\n{context}\n\n问题: {query}"
    )
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": prompt}],
        temperature=0,
    )
    return resp.choices[0].message.content


if __name__ == "__main__":
    knowledge = [
        "Qwen3 是阿里 2025 年发布的开源大模型系列,支持 0.6B 到 235B 多种规模。",
        "Llama 3.3 70B 由 Meta 发布,在多项基准上接近 GPT-4 级别能力。",
        "Claude 3.5 Sonnet 是 Anthropic 的模型,擅长长文本与代码生成。",
    ]
    print(rag_answer("阿里 2025 年发布的开源模型叫什么?", knowledge))

运行结果说明:模型会从检索到的 Qwen3 片段中准确回答"阿里 2025 年发布的开源模型是 Qwen3 系列",而非凭训练知识猜测。

企业案例

案例 1:法律知识库问答

某律所将 5 万份判决书向量化存入 Milvus,构建 RAG 问答系统。律师提问"近三年关于竞业协议的判决趋势",系统检索相关判例并生成带引用的摘要,检索准确率 88%,律师检索效率提升 5 倍。

案例 2:企业内部知识助手

某科技公司用 RAG 构建内部知识助手,接入 Confluence、GitLab Wiki、HR 制度文档。员工提问"年假怎么折算",系统检索 HR 制度文档并精确回答,HR 工单量下降 60%。采用混合检索(BM25 + 向量)后召回率提升 15%。

案例 3:客服中心 RAG 升级

某运营商客服中心从关键词 FAQ 升级为 RAG,增加 Reranker 后 Top-3 命中率从 72% 提升至 91%,且支持"我的套餐流量用完了怎么办"这类自然语言提问,客户满意度提升 18%。

常见问题

Q1:RAG 一定能消除幻觉吗? A:不能完全消除,但能大幅降低。模型仍可能误读上下文或在片段不足时编造。需要配合"资料不足时拒答"的指令与来源引用机制。

Q2:分块大小怎么选? A:从 512 token 起步,用业务评测集对比 256/512/1024 的召回与准确率。表格类内容需结构化抽取而非简单切分。

Q3:为什么我的 RAG 检索不准? A:常见原因:分块不合理、Embedding 模型与语种不匹配、未做 Reranker、查询未改写、知识库质量差。建议逐环节排查。

Q4:RAG 和微调该用哪个? A:知识频繁变化、需引用来源 → RAG;需固化输出风格、领域术语 → 微调;两者不互斥,可组合使用。

面试题

1. 简述 RAG 的完整流程。 参考答案:离线阶段分块→向量化→入库;在线阶段 query 向量化→检索 Top-K→重排序→拼装 Prompt→LLM 生成带引用的答案。

2. 为什么需要 Reranker?它和向量检索有何区别? 答题要点:向量检索用双塔模型(query 与 doc 独立编码)求近似相似度,速度快但精度有限;Reranker 用 Cross-Encoder 对 query-doc 联合编码,精度高但慢,用于精排少量候选。

3. 如何评估 RAG 系统的质量? 参考答案:从检索(Recall@K、MRR)与生成(答案准确率、幻觉率、引用命中率)两层评估,可用 RAGAS、TruLens 等框架。

4. 混合检索为什么优于单一检索? 答题要点:稀疏检索擅长精确关键词(如产品型号、人名),稠密检索擅长语义匹配,两者互补,融合后召回率与准确率均提升。

练习题

  1. 分块实验:将一篇 3000 字文章分别按 256、512、1024 token 分块,对比相同问题的检索 Top-3 差异。
  2. RAG 实现:为本章示例增加 Reranker(用 bge-reranker-base),观察 Top-2 排序变化。
  3. 思考题:当知识库规模从 1 万文档扩展到 1000 万文档时,RAG 架构需要做哪些调整?

小结

RAG 通过"检索 + 生成"让 LLM 获得实时、可引用的外部知识,是企业 Agent 落地的核心架构。分块策略、混合检索、重排序是影响效果的关键环节。相比微调,RAG 更适合知识频繁更新、需可解释性的场景。延伸阅读:论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》、Anthropic Contextual Retrieval、LlamaIndex 与 LangChain RAG 教程。