1. 完整 RAG 流水线
两阶段。
数据准备:① 数据采集加载(PDF/MD/网页/DB)② 文档解析预处理(二进制转纯文本+清洗)③ 智能分块 ④ 向量化(Embedding) ⑤ 存储与索引构建。
查询阶段:① 查询理解(预处理/改写)② 检索(向量库相似度搜索)③ 重排序(Rerank)④ 上下文构建与提示词工程 ⑤ 生成与输出。
💡 深入理解 · 工业级消费端链路:历史上下文关键词提取 → 多路召回(BM25 + 向量)→ Cross-Encoder 重排 → 提示词拼接注入大模型。生产端:多模态文档加载 → 滑动窗口切片 → Embedding → 向量库持久化。
2. RAG 优化方向
- Pre-retrieval(前):查询重写 Query Rewriting(结合历史消解指代)、多查询扩展 Multi-query、HyDE 假设性文档嵌入。
- Retrieval(中):混合检索 Hybrid Search(语义向量 + BM25,调 alpha 平衡)、多路召回。
- Post-retrieval(后):Rerank 重排、上下文压缩、置信度阈值兜底拒答。
- 数据侧:分块策略优化、更优 Embedding(M3E/BGE)、PDF 解析乱码/表格结构化。
💡 深入理解 · 排查"答非所问"四步法:① Chunking 审查(是否切断内聚知识,调 Overlap 或父子分块)② Pre-retrieval 诊断(Query 改写是否提炼出高浓度检索词)③ Retrieval 微调(混检权重配比)④ Post-retrieval 校验(Reranker 二次打分,低于阈值剔除/拒答)。
3. 分块策略 Chunking
- 固定长度切分:按字符/token,简单快但破坏语义。
- 语义切分:按段落/章节边界,保语义完整。
- 递归切分:先大单位再小单位。
- 滑动窗口切分:固定窗口+重叠(如 500/100),避免信息被切断。
- 混合/层次化切分:语义+长度限制、按 Markdown/HTML 标签层级。
💡 深入理解 · 为什么 500/100?:① Embedding 模型在 300~500 tokens 语义表达最稠密,过长稀释、过短破碎;② 业务自然段落 200~400 字,500 能包裹完整语义单元;③ 500 配 Top-3 上下文约 1.5k~2k,兼顾理解与成本;未来可用 Grid Search 测 Hit Rate 微调。特例:单场活动整体性强,直接大模型提炼成一个摘要 Chunk(语义分块)。
4. 表格与图片解析
- 文字:PyPDFLoader;可读 PDF 直接提取,扫描版每页转图交多模态。
- 表格:pdfplumber 提取 → 清理缺失值 → LLM 生成文本描述 → 合并。
- 图片:PyMuPDF 提取 + pytesseract/PaddleOCR,或转 base64 调 Vision-LLM 做 VQA。
- 复杂排版:MinerU / 布局分析模型分离文本区/表格区/图片区。
5. 混合检索与融合排序
向量召回 + 全文匹配分别算相似度,两种融合:
- RRF 融合:按排名算分 1/(k + rank + 1) 累加。
- 权重融合:vector 0.7 / keyword 0.3,原始分乘权重。
- 重排序:查询词出现加高分(2.0)否则基础分(0.1),长文档做长度惩罚防虚高。
手写混合检索公式(项目实战:Weaviate 自带混合索引效果不佳、无法按关键词检索,所以手写):
最终分数 = alpha × BM25分数 + (1-alpha) × 向量相似度 − 长度惩罚
- BM25 分和向量分各自归一化:
(分数−最小)/(最大−最小),量纲统一才能加权。 - 长度惩罚:题干+选项超 100 字符时减分(防长文本虚高,自定义 trick)。
- 这是"库自带混合检索不好用就自己实现"的典型工程判断,比背 RRF 公式更能体现实战。
6. Rerank 重排序
主流:Cohere Rerank、BGE-Reranker(智源)、BCE-Reranker(有道)。为什么用:向量检索是 Bi-Encoder(双编码器)精度有限,Rerank 用 Cross-Encoder 对 Query 与 Top-K 候选深度交互打分,从"语义相近"精筛"真正相关",大幅提升 Top-1 准确率。
7. 查询改写与召回不准
语义表达不清/召回不符:① 上下文感知检索(结合对话历史)② 多查询扩展(生成多个语义相近 query)③ 双向改写 Query2Doc/Doc2Query ④ 重排序 ⑤ 人工参与+微调。
反向召回:初步召回后反向筛选——过滤低质(长度<50 或 Cross-Encoder<0.3)、实体识别补知识图谱关联、MMR 保多样性。
8. RAG 评估
检索段:命中率 Hit Rate、召回率 Recall、精准率 Precision、MRR(平均倒数排名,看最相关结果排位是否靠前)、Context Relevance。生成段:忠实度 Faithfulness(答案是否忠于检索内容不编造)、答案相关性 Answer Relevance、正确性。工具:RAGAS 框架自动评估。离线按业务分桶抽检,线上收集 bad case 回流。
准确率 vs 召回率:召回率=检索到的相关内容/总相关内容(找得全不全,低则漏检易幻觉);精准率=检索到的相关内容/总检索内容(找得准不准,低则引噪浪费 token)。F1=两者调和平均。目标:召回率 >90%、精准率 >85%。提召回→混合检索/分块优化/同义词扩展;提精准→重排序/阈值过滤/语义去重。
8b. 进阶 RAG 范式
传统 RAG 是"先检索后生成"一次性的,进阶范式在检索/生成上做增强:
- 自适应 RAG(Adaptive/Self-RAG):模型自己判断"要不要检索、检索够不够",简单问题直接答、复杂问题多轮检索,避免无脑检索。
- CRAG(Corrective RAG):对检索结果打分,质量差就触发纠正(重写 query / 转外部搜索),过滤误导性上下文。
- 多跳检索(Multi-hop):一个问题拆成多步,前一步检索结果驱动下一步检索(回答需跨多文档串联的问题)。
- Query 路由:先判断问题该走哪个知识库/走 SQL 还是走向量库。
❓ 常见追问 · 怎么加速 RAG 检索?→ ① 向量库建 HNSW/IVF 索引(近似最近邻,牺牲极小精度换大幅提速)② 减少候选集:先粗筛元数据过滤(按分类/时间)再向量检索 ③ 缓存高频 query 结果 ④ 两阶段:向量粗召回大候选集 + Rerank 精排小集合 ⑤ Embedding 降维/量化。
8c. GraphRAG
传统 RAG 把知识当孤立文本块,GraphRAG 把知识建成实体关系网络(节点=实体,边=关系)。检索方式从"语义相似匹配"变成"沿关系边多跳遍历子图"。
| 维度 | 传统 RAG | GraphRAG |
|---|---|---|
| 知识表示 | 文本块 + 向量 | 知识图谱(实体+关系) |
| 检索机制 | 语义相似匹配 | 关系遍历多跳 |
| 擅长 | 事实查找/主题归纳 | 多跳推理/关系分析 |
| 可解释性 | 证据链弱 | 完整推理路径可追溯 |
| 成本 | 低(分块→向量) | 高(要抽实体建关系) |
什么时候用 GraphRAG? 问题需跨多文档多步推理("A 收购 B 对 C 有什么影响")、关系分析(金融风控资金链、供应链追溯)、对幻觉零容忍要每步可追溯(医疗/法律/合规)。简单 FAQ/快速起步仍用传统 RAG。
8d. 领域词典 / 术语映射
领域词典 = 把行业黑话/同义词/缩写映射到标准术语和字段。作用:① 查询改写时把用户口语("上个月的量")映射到规范词提升召回 ② 约束生成(尤其 NL2SQL 把业务术语映射到表字段)③ 补充 BM25 关键词同义扩展。是解决"专业术语召回失败"的关键手段之一。详见 → NL2SQL 业务术语映射。
8e. 排查:RAG 返回 0 结果 / 召回不准
0 结果排查五步:① Embedding 是否正常(query 向量化有没有报错/全 0)② 相似度阈值是不是设太高(先降阈值看有没有结果)③ 分块/入库是否成功(库里到底有没有数据)④ query 和文档不在一个语义空间(是否用了同一个 Embedding 模型)⑤ 元数据过滤条件是否过严(租户/时间过滤把结果全滤掉了)。
❓ 常见追问 · 混合检索已经分组排序去重了,为什么还要精排 Rerank?→ 粗召回用的是 Bi-Encoder(query 和文档分开编码算相似度),快但精度有限,只看"语义大致相近";Rerank 用 Cross-Encoder 把 query 和每个候选拼一起深度交互打分,能捕捉细粒度相关性,把"真正回答了问题的"排到最前。粗召回保"全",精排保"准",两者目标不同不可替代。
8f. Self-RAG / RAG-Fusion / 多模态 RAG
Self-RAG(自反思 RAG):让模型自己决定"要不要检索、检索的相不相关、输出有没有被支持"。核心创新是反思字符(Reflection Tokens)4 类:① Retrieve(要不要检索:yes/no/continue)② IsRel(检索片段相不相关)③ IsSup(输出是否被片段支持:全支持/部分/无)④ IsUse(回答有没有用:1-5 分)。比无脑检索更省、更准、可溯源。
RAG-Fusion:接到 query 让大模型生成 5-10 个相似 query → 每个各召回一批 → 所有结果用 RRF 倒排融合排序(可再加精排)→ 取 Top-K 拼 prompt。优点:提召回率、自动纠错/拆长句;缺点:不能从根本解决意图理解。
模块化 RAG(Modular RAG):打破"索引→检索→生成"死板结构,加入可插拔模块——搜索模块(走 SQL/Cypher/搜索引擎)、记忆模块、额外生成模块(LLM 生成上下文替代检索)、对齐模块(可训练 Adapter 解决 query-doc 对齐)、验证模块(评估检索相关性防噪声)。
多模态 RAG(文本+表格+图片)三条路线:① 多模态 Embedding 直接把图/文/表都向量化存一起 ② 用多模态大模型先给图生成 summary,只对文本 summary 向量化 ③ 检索原始图 + 构造完整 prompt 喂多模态 LLM。半结构化(文本+表格)用多向量检索器:把 raw data 和它的 summary 分离,用 summary 做检索、raw data 做生成。
查询-文档对齐技巧(提召回巧招):不用段落本身的向量做索引,而是用"这段话能回答的问题"的向量做索引——因为用户输入是问题,问题匹问题的相似度远高于问题匹段落。
💡 深入理解 · RAG 12 大痛点框架(Barnett 论文 7 点 + 工程 5 点,答"RAG 部署挑战"的结构化答法):内容缺失(提示"不知道就说不知道")、排名靠前文档被漏(Rerank + 调 top_k)、脱离上下文整合受限、未能提取答案(清数据 + 提示压缩 LongLLMLingua + LongContextReorder 缓解 Lost in Middle)、格式错误(输出解析/Pydantic/JSON mode)、特异性错误(父子/句子窗口检索)、回答不全面(查询拆分/路由)、数据处理能力(并行 ingestion)、结构化数据查询(Chain-of-table/NL2SQL)、复杂 PDF 表格提取、备用模型(路由降级)、安全(Llama Guard 输入输出双向内容审查)。
8g. 工程深水区:PDF解析 / 高级分块 / 负样本 / FLARE
PDF 版面分析两条路:基于规则(算样式,排版穷举不通用)vs 基于 AI(目标检测 + OCR pipeline,准确率高通用但耗时,建议 GPU 多进程)。版面检测工具:Layout-parser(精度高但慢)、PaddleOCR-ppstructure(小而尚可)、unstructured。标题级别用区块高度(字号)判定;单双栏取区块中心横坐标极差判断,中线分左右栏、栏内按纵坐标排序。
表格识别 = 表格检测(定位,YOLO/Faster-RCNN)+ 结构识别(单元格划分+行列关系重建)。pdfplumber 两模式:lattice(有线框,检测水平/竖直线定行列)vs stream(无线框,靠文本对齐)。深度方法:TableNet/CascadeTabNet/SPLERGE。
高级分块:① LangChain RecursiveCharacterTextSplitter(默认递归 \n\n→\n→空格→字符逐级下钻)② 结构感知 MarkdownHeaderTextSplitter(标题写入 metadata)③ 语义分块用 BERT NSP 判断相邻段落是否衔接、设阈值合并 ④ 代码分块 overlap 必须设 0(重叠代码可能改变原义,与普通文本相反)。
二级索引架构:一级用[摘要/关键信息]做 embedding 参与检索,二级[原始文本]一一映射,命中后把原文喂 LLM——兼顾细粒度检索与完整上下文。
FLARE 主动召回:解决长文本生成时一次召回不够——按 token 生成概率触发,某句置信度低就用它当假设查询主动再检索。HyDE:先让 LLM 生成"假答案",用假答案向量去检索(答案匹答案比问题匹答案更准),对未微调向量模型增益大。
负样本挖掘(训 Embedding/Reranker 时):随机负例太简单梯度趋 0、Top-K 硬负例易混入假负例致训练不稳;SimANS/困惑负采样取与正例语义相似度接近的"模糊负例",兼顾大梯度均值 + 小梯度方差。批内负采样(SimCSE 式)用同 batch 其他正例当负例。
8h. RAG 评测指标体系
RAGAS 四指标:① 答案相关性(生成假问题算与原问题相似度)② 忠实度 Faithfulness(答案拆陈述查与上下文一致比例)③ 上下文精确度(相关内容是否排前,用 Hit Rate/MRR/NDCG)④ 答案正确性(对比 ground truth)。
评估分层:独立评估(分别评检索模块 + 生成模块)vs 端到端评估(评最终响应,有标签用 Accuracy/EM 精确匹配)。测试集可让 LLM 从语料自动合成 QA 对。其他框架:RGB(抗噪声/拒答/信息综合/反事实稳健四能力)、ARES(LLM 生成合成样本 + 轻量裁判 + 统计置信区间)。
9. 高频追问速答
❓ 常见追问 · RAG 和 Function Calling 区别? → RAG 是"回答前翻私有字典"(检索增强),FC 是模型"手和脚"(调工具执行动作)。
❓ 常见追问 · RAG 和微调怎么选? → RAG 适合知识频繁更新、可溯源、低成本;微调适合固定风格/领域能力内化。可以结合。
❓ 常见追问 · 纯 LLM 还是 RAG? → 本地库命中优先 + LLM 补全;需更贴题时从向量库召回素材注入降低幻觉。
深度拆解:容易踩坑的点
维度一:数据策略
⚠️ 分块大小是 RAG 效果的隐形天花板,固定分块 vs 语义分块 vs 父子分块各自的失效场景是什么?你默认怎么选?
固定分块(如 500/100)失效在:跨块的因果/枚举关系被硬切断(比如"原因如下:1、2、3"恰好切在 2 和 3 之间),且对长短差异大的文档一刀切会导致短文档信息过稀释、长文档语义过混杂。语义分块(按段落/章节边界或 BERT NSP 判断衔接)失效在:依赖文档本身格式规整,遇到扫描件/口语转写/无明显分段的长文本,边界检测本身就不可靠,且计算成本高(要过一遍模型判断每处边界)。父子分块(小块检索、大块喂生成)失效在:父块粒度选不好一样白搭——父块太大会把不相关内容一起带进上下文稀释注意力,太小又失去"扩展上下文"的意义;另外父子结构让索引和存储复杂度上升,增量更新时子块和父块的一致性维护是隐藏成本。默认选择:先用固定滑窗(500/100)跑通兜底基线,再用父子分块做检索粒度和生成粒度的解耦(子块检索保准,父块生成保全),语义分块只在文档结构非常规整(如政策文件、合同)且离线可以预处理时才上,因为它是三者里工程成本最高、收益最不稳定的。承认边界:分块策略没有全局最优解,最终都要靠离线 Hit Rate/NDCG 网格搜索在具体数据集上调,理论推导只能给方向。
脏数据/过期文档入了库检索照样召回,怎么做数据治理和时效性淘汰?
分两层:入库前治理和入库后淘汰。入库前:源头加校验(去重、去噪、格式清洗、低质过滤,比如内容过短/乱码率过高的文档拒绝入库),关键信息加结构化元数据(生效日期、版本号、来源可信度、业务域标签)。入库后淘汰核心是让元数据参与检索而不只是文本参与检索:① 硬过滤——检索时按 valid_until >= now 或版本号过滤掉已作废文档,这是最简单也最容易被忽略的一步,很多团队只做了向量召回没做元数据前置/后置过滤;② 软降权——对老文档在最终排序分上乘一个随时间衰减的因子(类似搜索引擎的时间衰减),而不是硬删除,避免误删还有参考价值的历史文档;③ 定期批量任务扫描重复/过期文档做归档或删除,而不是让库无限增长;④ 建立文档生命周期状态机(草稿/生效/过期/作废),业务方更新文档要走替换流程而非追加新版本导致新老并存。承认边界:自动判断"内容是否过期"本身很难做到语义级别(文档没写过期日期但内容已经不适用了),这类只能靠人工标注+定期回流的 bad case 反哺。
维度二:性能优化
检索延迟随库规模增长,百万级向量怎么加速(HNSW 参数/量化/分片)?代价是什么?
三个方向叠加用:① HNSW 索引调参——ef_construction(建索引时的搜索宽度)和 ef_search(查询时的搜索宽度)越大召回越准但越慢,M(每个节点的最大连接数)越大内存占用和构建时间越高但查询路径更短;生产上一般先固定 M 在 16~32,再用 ef_search 去做延迟和召回的滑动调节,这是最容易调、最先做的一步。② 向量量化——标量量化(float32→int8)或乘积量化 PQ,把向量压缩存储,代价是相似度计算精度下降,量化越狠召回率损失越大,需要在量化后额外接一次基于原始向量的精排小候选集来找补精度。③ 分片/分区——按租户、时间、业务域做预分区,查询先路由到相关分片再检索,减小单次搜索的候选空间,代价是跨分片查询(如"搜索所有租户")变复杂,以及分片不均衡时某些分片成为热点。核心权衡:这三者都是用精度换速度,没有免费午餐,所以生产上通常是"粗召回牺牲精度换速度 + Rerank 找回精度"的两阶段设计,而不是指望检索一步到位。
多路召回 + Rerank 每步都加延迟,生产上怎么在准确率和 P99 延迟间取舍?
先明确延迟预算分配:如果总预算是几百毫秒,通常向量召回(含 HNSW 近似搜索)占大头但可控在几十毫秒,BM25 召回可以和向量召回并行发起而不是串行,Rerank(Cross-Encoder)是延迟大户因为要对每个候选做一次模型前向,所以关键杠杆在 Rerank 候选数量上——粗召回给 Top-50~100,但只对 Top-20~30 做 Rerank,而不是把所有召回结果都送进去。其次是模型选型上的取舍:用更小的 Reranker(如蒸馏版 BGE-Reranker-base 而非 large)或者用更快的 ColBERT 式后期交互模型替代重的 Cross-Encoder,牺牲一点精度换吞吐。还可以做分级策略:高优先级/高价值查询(如付费用户)走完整链路,长尾低优先级查询可以跳过 Rerank 直接用粗召回结果。最后 P99 尾延迟的治理往往不是靠单次请求优化,而是靠超时熔断+降级(Rerank 超时就直接返回粗召回结果,保证可用性优先于精度)。承认边界:没有一个通用最优的候选数量,要结合实际 QPS、Rerank 模型吞吐、业务对准确率的容忍度用压测数据说话。
维度三:模型选型与迭代
⚠️ RAG 上线后你怎么离线评估好坏?没有评估集怎么建?
分检索和生成两段评估,不能只看端到端效果,否则出问题不知道是哪个环节的锅。检索段:命中率 Hit Rate(Top-K 里有没有相关文档)、MRR(第一个相关结果排第几)、NDCG(考虑排序位置和相关性分级的综合指标,比 MRR 更精细,能反映"多个相关文档时排序质量")。生成段:忠实度 Faithfulness(把答案拆成多条陈述,逐条检查是否被检索到的上下文支持,防编造)、答案相关性(生成假设问题反查与原始 query 的相似度)。工具用 RAGAS 或 ARES 自动化跑。没有评估集怎么建:① 从业务真实历史查询日志采样,人工标注"应该召回哪些文档""标准答案是什么",这是金标准但成本高,优先做核心高频场景;② 用 LLM 从现有语料反向合成 QA 对(给一段文档,让模型生成"这段话能回答什么问题",再把该文档标为该问题的 ground truth),规模化但质量需要人工抽检把关,防止 LLM 生成的问题过于简单或和原文重合度过高失真;③ 上线后从用户反馈(点赞/踩、人工客服介入记录)持续回流 bad case,把评估集当成活的、持续增长的资产而不是一次性交付物。承认边界:自动合成的评估集天然会偏向"和检索片段高度重合"的简单问题,很难覆盖真实用户的模糊表达和多跳提问,所以合成集只能做冒烟测试,核心指标决策还是要靠人工标注的小而精的评估集。
幻觉发生时怎么归因是检索没召回到、还是模型没用好上下文?
先看检索命中——把最终送入 prompt 的 Top-K 上下文拿出来人工核对,是否包含能支撑正确答案的片段。如果压根没召回到相关内容,那是检索侧问题(分块切断了信息/召回权重配比不对/query 和文档不在同一语义空间),该去查 Embedding 模型是否匹配、混合检索权重是否合理。如果上下文里明明有正确信息但模型还是编造或忽略,那是生成侧问题,常见原因是:①上下文太长出现 Lost in the Middle(关键信息在中间位置被模型"看漏"),这时候要检查相关片段有没有排到靠前位置,可以用 LongContextReorder 把最相关内容挪到开头结尾;②提示词没有明确约束"只依据上下文回答、不知道就说不知道",模型默认行为是"编",要靠提示词工程收敛;③检索到的片段虽然语义相关但和问题不是同一个粒度(比如问题问具体数字,片段只有笼统描述),这时候即使模型"用好了"上下文也答不对,本质还是检索片段质量问题,只是不那么容易一眼看出。工程上做这个归因最好靠 RAGAS 的 Faithfulness 指标自动化跑一遍,先筛出"上下文里有答案但生成没对"的 case,再人工细看是排序问题还是提示词问题。承认边界:边界案例很多(比如上下文有一半支持答案),纯自动化指标判不了因果,最后还是要人工抽检。
维度四:架构设计
BM25 和向量分数量纲不同,怎么融合(RRF vs 加权归一)?各自适合什么场景?
两种分数天生不可比:BM25 是无上界的词频统计分,不同 query 之间的分数范围都不一样;向量相似度(余弦/内积)有界(如 -1~1),但同样受 query 长度和 embedding 模型影响分布不稳定。直接相加是错的,必须先解决量纲问题。RRF(Reciprocal Rank Fusion)不看分数只看排名,1/(k+rank+1) 累加,优点是完全绕开了分数量纲问题,鲁棒、不需要调权重、不需要归一化,缺点是丢失了"分数差距"信息——排第1和排第2可能分数差一点点也可能差很多,RRF 一视同仁,无法体现"这条结果明显更好"。加权归一化(先各自 min-max 或分位数归一化到 0~1 再按 alpha 加权)优点是保留了原始分数的相对强弱,可以按业务场景调 alpha 偏向语义还是偏向关键词(比如 NL2SQL 场景关键词精确匹配更重要就调高 BM25 权重),缺点是权重是超参需要靠离线评估调,且归一化方式(min-max 对异常值敏感,分位数归一化更稳健但计算更重)本身也是一个选择,调不好比 RRF 效果还差。场景选择:快速搭建、没有标注数据调参、想要稳定不出幺蛾子——用 RRF;有离线评估集、想针对具体业务场景精细调控两路召回比重(比如术语检索场景需要偏重关键词)——用加权归一化,并且这时候通常还要在两路各自归一化之后叠加一个长度惩罚项防止长文档虚高分数。工程实践里也常见两者结合:先 RRF 粗融合选出候选集,再用 Cross-Encoder Rerank 做真正的精排,把分数量纲问题彻底交给学习到的模型而不是手工公式。
评论