深色模式
RAG 生产排障清单
摘要:本文是 RAG 系统的"急诊手册"。把召回为空、幻觉、延迟高、成本失控、跨租户泄露等高频故障按"现象 → 根因 → 处置"整理成清单,配合可复制的排查命令。各专题的深度配置见 llm-rag / chunking / hybrid-search / rerank / evaluation。
先定位层,再修
RAG 故障分索引层 / 检索层 / 生成层 / 基础设施层。先用评测拆出是 context_recall 低(检索)还是 faithfulness 低(生成),再对症下手,避免无脑调 prompt。
故障分层与定位
1. 召回为空 / 全部不相关
| 现象 | 根因 | 处置 |
|---|---|---|
| 检索返回空 | query 与 doc 用的不是同一嵌入模型 | 统一编码模型,核对模型名与维度 |
| 一直不相关 | 未 normalize_embeddings | 编码时 normalize_embeddings=True(余弦评测必需) |
| 专名查不到 | 纯向量检索盲区 | 加 BM25/混合检索(hybrid-search.md) |
| 长文档漏召 | 超过序列长度被截断 | 切分或换长上下文模型(bge-m3 8192) |
bash
# 探针:相关句相似度应明显高于无关句
python -c "import numpy as np; cos=lambda a,b:np.dot(a,b)/(np.linalg.norm(a)*np.linalg.norm(b)); print('related',cos(q,d1),'unrelated',cos(q,d2))"1
2
2
2. 召回到了但排名靠后
| 现象 | 根因 | 处置 |
|---|---|---|
| 相关文档排 40 | 未重排 | 加重排(rerank.md),召回 50→精排到 5 |
| top-k 含大量噪声 | 候选太多未压缩 | 降 top-k、加 RRF/加权融合 |
| 权重失衡 | 混合检索加权错 | 先用 RRF,再评测调 WeightedRanker |
3. 延迟高
| 现象 | 根因 | 处置 |
|---|---|---|
| 检索 >200ms | 向量库未建索引/未 load | 建 AUTOINDEX/HNSW、确认 load |
| 整体慢 | top-k 过大 + 重排候选多 | 召回 50、重排 5;重排换 fast 档 |
| 偶发尖刺 | 无批量/无缓存 | query 缓存(相似 query 复用)、批处理 |
4. 幻觉 / 不忠实
| 现象 | 根因 | 处置 |
|---|---|---|
| 编造知识库没有的内容 | 证据不足仍硬答 | 加"无相关信息则拒绝"(generation.md) |
| 复述了敏感 chunk | 上下文含 PII | 检索期脱敏 + tenant_id 过滤 |
| 引用错乱 | 未强制引用格式 | 系统提示要求 [n] 标注来源 |
5. 答非所问但检索正确
| 现象 | 根因 | 处置 |
|---|---|---|
| 上下文被截断 | 超过生成模型上下文上限 | 压缩上下文、减小 top-k |
| query 不完整 | 多轮对话指代缺失 | 检索前 query 改写(generation.md) |
6. 全库答案集体变差(索引层)
| 现象 | 根因 | 处置 |
|---|---|---|
| 换模型后全差 | 向量空间变,旧索引未重建 | 全量重建索引并蓝绿切换 |
| 改 chunk 后变差 | chunk 策略变,需重建 | 重建 + 评测对比 |
| 增量后重复 | 主键非确定性 | 用 hash(source:chunk_index) 做 upsert 主键 |
7. 成本失控
成本失控是生产头号事故
开放 query 无限流,嵌入/重排/生成 API 易被刷爆。必须:限流(per-user/IP)、相似 query 缓存、预算告警、模型分级(简单问题用小模型)。详见各篇"成本与性能"。
| 现象 | 根因 | 处置 |
|---|---|---|
| 嵌入账单暴涨 | 大批量重复编码 | 文档级去重、增量 upsert |
| 重排费用高 | 候选数过大 | 召回 50→重排 5;换本地 BGE-Reranker |
| 生成贵 | 上下文塞满 top-50 | 重排后只取 top-3/5 |
8. 跨租户数据泄露
| 现象 | 根因 | 处置 |
|---|---|---|
| A 看到 B 的文档 | 检索无 tenant_id 过滤 | 每路检索加租户/权限 filter,dense 与 sparse 两路都要加 |
| 图谱泄露关系 | GraphRAG 图未隔离 | 图谱按租户分库/分集合 |
权限是检索的一部分,不是附加项
混合检索的 dense 路与 sparse 路必须施加同一租户过滤表达式,漏一路即泄露。RAG 不应绕过既有鉴权体系。
9. 提示注入
| 现象 | 根因 | 处置 |
|---|---|---|
| 文档中指令被执行 | 检索内容被当可信指令 | 系统指令与不可信 context 用 XML 标签隔离,显式声明外部内容不可改指令 |
| 社区报告被污染 | GraphRAG 抽取受注入 | 生成侧护栏 + 输入清洗 |
通用排查命令
bash
# 探活
curl -s -X POST http://rag-svc:8080/query -H 'Content-Type: application/json' \
-d '{"query":"如何重置密码","top_k":5}'
# 向量库集合统计(Milvus 示例伪命令,按客户端核对)
# MilvusClient.get_collection_stats("rag_documents") -> row_count
# 评测回归(见 evaluation.md)
python eval.py --baseline v1.2 --current v1.31
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
安全与合规(排障时的红线)
排障不能随意降级安全
排查"召回差"时,不要为提召回而去掉租户过滤或关闭注入护栏;排查"成本高"时,不要为降本而关掉引用/拒答。安全与成本控制是底线,应通过架构(缓存、模型分级、混合检索)解决,而非撤防。