导语
在大语言模型(LLM)应用中,"幻觉"(生成与事实不符的内容)是常见痛点。检索增强生成(RAG)通过将外部知识库与 LLM 结合,让模型基于真实数据回答问题,有效解决了这一问题。本文将系统拆解 RAG 的核心流程、优化方向、工程实践及进阶范式,帮助你从理论到实战掌握 RAG 技术,构建高可靠的知识问答系统。
1. 完整 RAG 流水线:从数据到生成的全链路
RAG 本质是"检索(Retrieve)→ 增强(Augment)→ 生成(Generate)" 的闭环,分为数据准备和查询响应两大阶段。
1.1 数据准备:让知识"可检索"
数据准备是 RAG 的"地基",需将非结构化/半结构化数据转化为模型可理解的格式:
-
数据采集加载
支持 PDF、Markdown、网页、数据库等多种数据源。例如:用PyPDFLoader加载 PDF,SQLAlchemy连接数据库。 -
文档解析预处理
- 二进制转纯文本:OCR 处理扫描版 PDF(如pytesseract)。
- 清洗:去噪、去重、格式标准化(如统一换行符、修正乱码)。 -
智能分块(Chunking)
将长文本拆分为语义完整的"知识块",避免因文本过长导致 LLM 处理困难。 -
向量化(Embedding)
用模型(如 BGE、M3E)将文本块转化为向量,存储到向量数据库(如 Weaviate、Milvus)。 -
存储与索引构建
向量数据库通过 HNSW/IVF 等索引算法加速相似度搜索,同时维护元数据(如文档来源、时间戳)。
1.2 查询阶段:让回答"有依据"
用户提问时,需通过以下步骤从知识库中精准提取信息:
-
查询理解
- 预处理:分词、去停用词、纠错(如将"上个月的量"标准化为"2024-05 月数据量")。
- 改写:优化表述(如将口语化问题转为结构化查询)。 -
检索(向量+关键词)
- 向量检索:用 Query 向量在向量库中做相似度搜索(如余弦相似度)。
- 关键词检索:结合 BM25 算法,补充语义外的关键词匹配。 -
重排序(Rerank)
用 Cross-Encoder 模型(如 Cohere Rerank)对候选结果二次打分,过滤低相关内容。 -
上下文构建与提示词工程
将检索到的文本块拼接为提示词,明确约束 LLM:"基于以下内容回答问题:[检索内容]。问题:[用户问题]。" -
生成与输出
LLM 基于提示词生成回答,可通过 Pydantic 或 JSON 格式约束输出格式。
工业级 RAG 链路特点
- 消费端:历史上下文关键词提取 → 多路召回(BM25+向量)→ Cross-Encoder 重排 → 提示词注入大模型。
- 生产端:多模态文档加载 → 滑动窗口切片 → Embedding → 向量库持久化。
2. RAG 优化方向:从"能用"到"好用"
2.1 前检索(Pre-retrieval):让查询更精准
- 查询重写(Query Rewriting):结合历史对话消解指代(如"它"→"用户问题中的产品")。
- 多查询扩展(Multi-query):生成多个语义相似的查询(如"如何优化 RAG?"→"RAG 优化方法有哪些?")。
- HyDE 假设性文档嵌入:让 LLM 生成"假设文档",再用其向量检索,提升低召回场景的准确性。
2.2 中检索(Retrieval):让召回更全面
- 混合检索(Hybrid Search):结合向量(语义)+ BM25(关键词),通过
alpha平衡权重(如alpha=0.7侧重语义,alpha=0.3侧重关键词)。 - 多路召回:从不同数据源/算法召回结果(如 PDF 文本+表格+图片),覆盖更多信息。
2.3 后检索(Post-retrieval):让结果更可靠
- 重排序(Rerank):用 Cross-Encoder 对 Top-K 结果二次打分(如 Cohere Rerank、BGE-Reranker)。
- 上下文压缩:过滤冗余信息,保留核心内容(如用
SentenceTransformers压缩长文本)。 - 置信度阈值兜底拒答:当检索结果相关性低于阈值(如
0.3)时,返回"无法回答",避免编造。
2.4 数据侧优化:从"基础"到"精细"
- 分块策略:滑动窗口(500/100)避免信息切断,语义分块(按章节)保语义完整。
- Embedding 模型:优先选择领域适配模型(如医疗用 MedCLIP,通用用 BGE)。
- 结构化数据处理:用
pdfplumber提取表格,转文本描述后嵌入。
排查"答非所问"四步法
- Chunking 审查:检查分块是否切断内聚知识(如调大
overlap或改用父子分块)。 - Pre-retrieval 诊断:验证 Query 改写是否提炼出高浓度检索词。
- Retrieval 微调:调整混合检索权重(如
alpha=0.6)。 - Post-retrieval 校验:用 Reranker 二次打分,低于阈值剔除。
3. 分块策略 Chunking:知识块的"切分艺术"
分块是 RAG 效果的"隐形天花板",需平衡语义完整性和检索效率。
3.1 主流分块方法
| 方法 | 实现方式 | 适用场景 | 优缺点 |
|---|---|---|---|
| 固定长度切分 | 按字符/token(如 500/100) | 简单快速,适合短文本 | 破坏语义(如"原因1、2"被切断) |
| 语义切分 | 按段落/章节边界 | 长文档(如政策文件、书籍) | 需文档格式规整,成本高 |
| 滑动窗口切分 | 固定窗口+重叠(如 500/100) | 避免信息切断(如技术手册) | 平衡语义与效率 |
| 混合切分 | 语义+长度限制 | 复杂排版(如 Markdown 文档) | 需复杂逻辑,精度高 |
3.2 为什么推荐 500/100?
- Embedding 模型特性:300~500 tokens 是语义表达最稠密区间,过长稀释、过短破碎。
- 业务场景适配:单段文本通常 200~400 字,500 字符可包裹完整语义单元。
- 成本控制:Top-3 上下文约 1.5k~2k tokens,兼顾理解与 Token 消耗。
4. 表格与图片解析:让非文本数据"可检索"
传统 RAG 依赖文本,需处理表格和图片等非文本数据:
4.1 文字提取
- 纯文本 PDF:
PyPDFLoader直接提取。 - 扫描版 PDF:OCR 处理(
pytesseract+PaddleOCR)。
4.2 表格解析
- 提取与清洗:用
pdfplumber提取表格,清理缺失值(如df.fillna(""))。 - 文本化描述:LLM 将表格转为文本(如"2024Q1 营收:[数据]")。
- 合并存储:保留原始表格结构,嵌入向量库。
4.3 图片解析
- OCR 提取文字:
pytesseract或PaddleOCR识别图片中的文字。 - 多模态向量化:用
CLIP或Vision-LLM生成图片向量,与文本向量拼接。
5. 混合检索与融合排序:让召回更精准
向量检索(语义)+ BM25(关键词)是工业界主流混合方案,需解决量纲不同和权重平衡问题。
5.1 融合算法对比
| 方法 | 公式/原理 | 适用场景 | 优缺点 |
|---|---|---|---|
| RRF 融合 | 1/(k + rank + 1) 累加排名分数 |
快速且鲁棒,无需调参 | 丢失分数差距信息 |
| 加权归一化 | alpha*BM25 + (1-alpha)*向量分 |
需保留分数相对强弱,如 NL2SQL | 需归一化(min-max) |
5.2 工程实践:手写混合检索公式
# 混合检索公式(项目实战)
def hybrid_search(query, docs):
# 1. 计算 BM25 分数
bm25_scores = [bm25_score(query, doc) for doc in docs]
# 2. 计算向量相似度分数
vec_scores = [vector_similarity(query, doc.embedding) for doc in docs]
# 3. 归一化分数到 [0,1]
bm25_norm = (bm25_scores - min(bm25_scores)) / (max(bm25_scores) - min(bm25_scores))
vec_norm = (vec_scores - min(vec_scores)) / (max(vec_scores) - min(vec_scores))
# 4. 加权融合 + 长度惩罚
final_score = 0.7*bm25_norm + 0.3*vec_norm - (len(query)+len(doc))/1000 # 长度惩罚
return sorted(docs, key=lambda x: final_score[x], reverse=True)
6. Rerank 重排序:从"候选"到"最优"
向量检索是"粗召回",Rerank 是"精排序",核心是用 Cross-Encoder 模型对候选结果深度打分。
6.1 为什么需要 Rerank?
- 向量检索局限:Bi-Encoder 模型(如 BGE)仅做"语义近似",忽略细粒度相关性(如"苹果"可能指水果或公司)。
- Cross-Encoder 优势:将 Query 和候选文档拼接为"Query+Doc"对,直接预测相关性(如
0.9表示高度相关)。
6.2 主流 Rerank 模型
- Cohere Rerank:通用场景,支持多语言。
- BGE-Reranker:智源开源,中文优化。
- BCE-Reranker:有道,适合中文语义理解。
7. RAG 评估:从"效果"到"指标"
RAG 需从检索段和生成段双维度评估,避免"黑箱"优化。
7.1 检索段指标
- 命中率(Hit Rate):Top-K 结果中是否包含相关文档。
- 召回率(Recall):检索到的相关文档占总相关文档的比例。
- MRR(平均倒数排名):最相关结果的排名倒数的平均值(如 MRR=0.8 表示平均第 2 名)。
7.2 生成段指标
- 忠实度(Faithfulness):生成内容与检索文档的一致性(如用 RAGAS 框架计算)。
- 答案相关性(Answer Relevance):生成答案与用户问题的匹配度。
7.3 工具:RAGAS 框架
from ragas import evaluate
from ragas.metrics import faithfulness, answer_relevance
# 评估示例
result = evaluate(
answers=generated_answers,
contexts=retrieved_contexts,
references=ground_truths,
metrics=[faithfulness, answer_relevance]
)
print(result) # 输出各指标分数
8. 进阶 RAG 范式:从"传统"到"智能"
8.1 GraphRAG:知识图谱驱动的多跳推理
传统 RAG 是"文本块+向量",GraphRAG 是"知识图谱(实体+关系)",适合多跳推理场景。
| 维度 | 传统 RAG | GraphRAG |
|---|---|---|
| 知识表示 | 文本块+向量 | 实体+关系(如 Neo4j 存储) |
| 检索机制 | 语义相似匹配 | 关系遍历多跳 |
| 适用场景 | 事实查找 | 金融风控、医疗推理 |
8.2 Self-RAG / RAG-Fusion:模型自主决策
- Self-RAG:让模型决定"是否检索、检索多少",简单问题直接回答,复杂问题多轮检索。
- RAG-Fusion:生成 5-10 个 Query,多检索后融合结果,提升召回率。
8.3 多模态 RAG:处理图片/表格
- 多模态 Embedding:用 CLIP 同时编码文本和图片向量。
- 图片转文本:OCR 识别图片文字后,再嵌入向量库。
8b. 工程深水区:从"能用"到"稳定"
8b.1 PDF 解析与高级分块
- 版面分析:用 Layout-parser 或 PaddleOCR 识别标题、表格、图片区域。
- 高级分块:
RecursiveCharacterTextSplitter(递归切分)、MarkdownHeaderTextSplitter(按标题层级)。
8b.2 数据治理与时效性
- 数据清洗:去重、去噪、过滤低质文档(如乱码率>30%)。
- 元数据管理:记录文档来源、时间戳、版本号,检索时过滤过期内容。
8b.3 检索加速:百万级向量库优化
- HNSW 索引调参:
ef_construction=100(建索引)、ef_search=10(查询)。 - 向量量化:标量量化(
int8)压缩存储,精度损失<5%。
小结
RAG 是解决 LLM 幻觉的核心技术,其关键链路是 "数据准备→查询响应→优化迭代"。从技术选型(如分块策略、Embedding 模型)到工程落地(如混合检索、Rerank),需平衡"效果"与"成本"。未来 RAG 将向 "知识图谱+多模态+自主决策" 演进,而你需要掌握的是:
- 核心流程:数据分块→向量检索→Rerank→生成。
- 优化方向:Pre-retrieval 提准、Retrieval 提全、Post-retrieval 提质。
- 评估指标:用 RAGAS 框架量化效果,避免盲目调参。
RAG 没有"最优解",需结合业务场景(如金融风控 vs 客服问答)迭代优化,从"能用"走向"稳定可靠"。
评论