思维导图笔记:RAG检索增强生成
RAG检索增强生成 思维导图(定稿版)
- 总览
- 文档解析与内容提取
- 检索策略
- 增强与生成
- 系统架构与工程化
- 评估与质量保障
- 评估与质量保障
一、文档解析与内容提取
- 工具选型
- PDF
- PyMuPDF(快,适合可编辑PDF)
- pdfplumber(准但慢)
- Unstructured(一站式但重)
- OCR
- PaddleOCR(中文识别率高)
- Tesseract(英文好)
- 表格
- Camelot(规则表格首选)
- Tabula(无边框表格)
- 选型逻辑:根据文档类型、数据量、中文/英文场景做决策
- PDF
- 工程风险预判(通用工程思维)
- 格式兼容性风险 → 上线前跑兼容性测试,失败case分类处理
- 内容丢失风险 → 解析后加质量检查(空文本/长度异常自动告警)
- 处理链路稳定性 → 异步任务队列 + 失败重试 + 断点续传
- 兜底设计
- 解析失败 → 自动重试(1次) → 降级OCR → 人工兜底
- 解析质量自动检查(产出文本为空或异常短时告警)
- 失败case分类存档,持续优化解析链路
- 真实踩坑(可选,只写真做过的)
- [你的项目中的具体问题及解决方式]
二、检索策略
- 基础检索方式
- 关键词检索(BM25)
- 原理:基于词频和逆文档频率算相关性
- 优势:精确匹配强,实体/专有名词不会漏
- 劣势:同义词搞不定
- 适用场景:专业术语多、缩写多的领域(法律/医疗)
- 向量检索(稠密检索)
- 原理:把文本转成向量,算余弦相似度
- 优势:能理解语义
- 劣势:专有名词/精确匹配有时不如关键词
- Embedding模型选型:中文用BGE/M3E,英文用OpenAI ada
- 混合检索(BM25 + 向量检索)
- 为什么需要:两者互补,精确匹配+语义理解
- 融合方式:各自打分后用RRF(倒数排名融合)或加权求和
- 权重怎么定:实体查询降向量权重,模糊查询升向量权重
- 工具:Elasticsearch/Weaviate自带混合检索,LangChain有EnsembleRetriever
- 关键词检索(BM25)
- 检索优化
- 查询改写
- 用LLM将模糊问题润色后再检索
- 指代词补全:“它怎么配置” → “K8s集群怎么配置”
- 多路召回:一个问题生成多个变体同时检索,合并去重
- 检索后处理
- 重排序(Rerank):粗召回50条 → 精排取Top5
- 工具:Cohere Rerank / BGE-Reranker
- 多样性控制:MMR算法避免返回的5条内容高度重复
- 重排序(Rerank):粗召回50条 → 精排取Top5
- 元数据过滤 → 检索前先用标签缩小范围(时间/来源/文档类型)
- 查询改写
- 高级检索策略(加分项,了解原理即可)
- 知识图谱增强(GraphRAG)
- 核心思路:文档先抽实体和关系建图
- 检索时:问题→匹配实体→沿关系找到关联知识
- 优势:多跳推理能力强
- 工具:Neo4j + LLMGraphTransformer / Microsoft GraphRAG
- 自查询检索(Self-Querying) → LLM从问题中同时抽取语义和过滤条件
- 知识图谱增强(GraphRAG)
- 向量数据库选型
- 专用向量库:Milvus(大规模首选)/ Qdrant / Weaviate / Pinecone
- 传统数据库扩展:PostgreSQL+pgvector(小规模省事)/ Redis
- 选型逻辑:数据量小用pgvector少维护一个中间件,量大了换Milvus
三、增强与生成
- 上下文构建(Prompt组装)
- 模板设计
- 结构:角色设定 + 任务指令 + 参考资料 + 输出约束
- 面试点:角色设定要具体,“你是客服”不如“你是某银行信用卡客服,语气专业亲切”
- 上下文注入方式
- 直接拼接到System/User消息中
- 注意点:多轮对话时历史消息+检索结果容易超窗口,需动态截断
- 引用溯源
- 每条检索结果加编号[1][2]
- 要求LLM引用时标注来源编号
- 作用:用户能核实,也方便排查幻觉
- 模板设计
- 上下文窗口管理
- 问题:检索文档太多+历史对话太长 → 超出token上限
- 截断策略
- 方案一:优先保留最新消息,历史消息从旧开始丢弃
- 方案二:对历史对话做摘要压缩,保留关键信息
- 检索结果数量控制 → 根据问题复杂度动态调整:简单问题Top3,复杂问题Top5-10
- 幻觉抑制(生成阶段能做的)
- 指令约束
- “仅根据提供的资料回答,不知道就说不知道”
- “如果资料不足以回答,列出缺失信息”
- 输出校验
- 要求LLM先引用原文,再给结论
- 结构化输出(JSON)更容易做格式校验
- 置信度门槛 → 检索相关性分数低于阈值的直接回复“未找到相关信息”
- 指令约束
- 生成策略控制
- 解码参数调优
- temperature:事实问答设00.3,创意类设0.71.0
- top_p:一般设0.8~0.95,和temperature二选一
- 结构化输出
- 让LLM输出JSON/Markdown格式
- 工具:LangChain的StructuredOutputParser / instructor库
- 兜底:解析失败时重试一次+修复常见JSON错误(尾部逗号/引号)
- 解码参数调优
- 流式输出与体验优化
- 为什么要流式:首Token延迟高时用户会等得不耐烦
- 实现方式:SSE协议,前端逐字展示
- 注意点:流式输出时引用标注可能会被截断,需后处理补全
四、系统架构与工程化
- 整体架构设计
- 核心链路:用户提问 → 查询改写 → 检索 → 重排序 → 组装Prompt → LLM生成 → 后处理 → 返回
- 解耦设计:检索服务和生成服务分开部署,独立扩缩容
- 多级缓存体系
- 为什么需要:相同/相似问题反复检索,成本高、延迟大
- 三层缓存结构
- L1:内存缓存(最快,存热点问题结果,有过期时间)
- L2:Redis(存语义相似问题的缓存,用问题Embedding做Key)
- L3:向量数据库本体(无缓存命中时走完整检索)
- 缓存更新策略
- 定时失效:简单,但知识更新不及时
- 事件驱动:知识库更新时主动失效相关缓存,更实时但复杂
- 相似问题匹配 → 新问题先算Embedding,去Redis里找相似度>0.95的缓存问题,命中直接返回
- 高并发与性能优化
- 异步处理
- 检索和LLM调用都用async,避免阻塞
- 多路并行:查询改写生成的多个变体同时检索
- 连接池管理
- 向量库和Redis都配连接池,别每次请求新建连接
- 监控连接池状态,满了说明需要扩容或限流
- 批处理 → 离线索引构建用批量Embedding,比逐条调API快10倍以上
- LLM调用优化
- 流式输出减少用户等待体感
- 设置合理max_tokens,不让模型“废话”浪费延迟
- 异步处理
- 稳定性保障
- 超时控制
- 检索超时设500ms,LLM调用设15-30s
- 超时不重试直接降级:返回兜底答案或提示用户稍后重试
- 限流
- 用户级:每人每分钟最多20次请求
- 服务级:LLM API有QPS上限,用令牌桶做流量整形
- 熔断
- LLM连续失败5次 → 熔断10秒 → 半开探测 → 恢复或继续熔断
- 工具:semaphore或circuitbreaker库
- 降级链路
- 检索挂了 → 返回“系统繁忙,请稍后”
- LLM挂了 → 直接返回检索到的原文片段
- 全部挂了 → 返回兜底话术+告警
- 幂等性 → 同一请求重试多次不会重复扣费/重复写入
- 超时控制
- 可观测性
- 日志
- 每次请求一个trace_id,串联全链路
- 关键节点打日志:原始问题→改写后→检索结果数→LLM耗时→最终回复长度
- 监控指标
- 接口层:QPS、成功率、P99延迟
- 检索层:召回率、检索耗时、缓存命中率
- LLM层:首Token延迟、Token生成速度、幻觉率
- 告警
- 错误率>5%或P99延迟翻倍 → 飞书/钉钉/企微告警
- LLM余额不足提前预警
- 排查工具 → 至少能用trace_id在日志系统里查到一条请求的完整链路
- 日志
- 向量数据库运维
- 索引更新策略
- 增量更新:新增/修改文档只更新对应向量
- 全量重建:碎片多、性能下降时定期做
- 索引类型选择
- HNSW:查询快,内存占用高
- IVF:内存省,查询稍慢但有损精度
- 备份与恢复:定期快照
- 索引更新策略
五、评估与质量保障
- 检索质量评估
- 核心指标
- 召回率(Recall):相关文档被找回的比例
- 精确率(Precision):找回的文档中有多少是相关的
- MRR(平均倒数排名):第一个相关文档排第几
- NDCG:考虑排序质量,排名越靠前权重越高
- 评估方法
- 准备标注数据集:50-100条问题 + 人工标注相关文档ID
- 跑检索后用上述指标算分
- 没有标注数据怎么评? → 用LLM当裁判,判断检索结果和问题是否相关
- 核心指标
- 生成质量评估
- 核心维度
- 忠实度:答案是否基于检索文档,有没有瞎编
- 相关性:答案是否回答了用户问题
- 完整性:有没有遗漏关键信息
- 评估方式
- 人工打分:准确但慢,适合小规模评测
- LLM-as-Judge:用GPT-4等强模型打分,给评分标准+示例
- 工具:RAGAS框架,几行代码自动算faithfulness/context_relevancy
- RAGAS原理一句话:把生成答案拆成原子陈述,逐条检查能否从检索文档推断
- 核心维度
- 端到端评估
- 业务指标
- 用户点赞率/点踩率
- 人工介入率(多少问题最终转了人工客服)
- 答案采纳率(用户看了答案后有没有继续追问)
- 性能指标
- 端到端延迟(P50/P99)
- 吞吐量(QPS上限)
- 业务指标
- 评测数据集构建
- 来源:真实用户历史问题 + 产品/业务方给的FAQ
- 覆盖维度
- 简单事实查询、复杂推理、模糊/边界问题
- 对抗样本:故意问知识库没有的、问得很像但实际不相关
- 规模:初期50-100条就够跑一轮评估
- 持续更新:线上badcase定期加入评测集
- 反馈闭环
- 线上采集:用户点踩/举报的答案自动记录
- Badcase分析
- 用trace_id找到完整链路日志
- 分类归因:检索没召回 / 召回了但排序低 / 召回了但LLM没用
- 对症下药:检索问题改切片/改混合权重,LLM问题改Prompt/微调
- 定期Review:每周过一遍top badcase,迭代优化
