1 如何做 RAG 的日志、观测和故障排查
P1 · rag
🏷 标签:rag, observability, logging, troubleshooting
1️⃣ 考察意图
面试官想考察你能否将 RAG 从“Demo 玩具”推向“生产系统”。这不是背概念题,而是工程取舍 + Debug 实战题。刁钻点在于:多数人只懂“加日志”,但不懂如何通过观测数据反推根因(如检索召回差 vs 生成幻觉的区分)。答好了能展示:你具备生产环境可观测性(Observability)的完整思维——从结构化日志、分布式追踪到告警完整流程,并能用数据驱动故障排查,这是 P6+ 级别的硬实力。
2️⃣ 标准答
RAG 的可观测性分三层:日志(Logging)、指标(Metrics)、追踪(Tracing),即“三大支柱”。核心目标是:当用户反馈“回答不对”时,能在 5 分钟内定位到是检索、生成还是基础设施问题。
1. 结构化日志设计
- 链路 ID:每个请求生成唯一 trace_id,贯穿检索、rerank、生成整条链路。
- 关键字段:query(脱敏后)、检索到的 chunk_id 列表(top-5)、rerank 分数、LLM 输入 prompt(含上下文)、输出 response、各阶段耗时(ms)、token 消耗、错误码。
- 工具:使用 JSON 格式输出到 ELK(Elasticsearch + Logstash + Kibana)或 Loki。坑:日志量爆炸。解法:采样策略——对成功请求按 1% 采样,失败请求 100% 采样;同时设置日志级别(INFO 记录正常流程,ERROR 记录异常)。
2. 指标监控(Prometheus + Grafana)
- 检索延迟:p50/p95/p99 延迟,区分向量检索(如 FAISS)和关键词检索(BM25)。trade-off:向量检索延迟高但召回好,BM25 快但精确度低;监控能帮你决定何时切换或混合。
- 召回质量:计算“检索命中率”(用户反馈的正确答案是否在 top-5 内),通过离线评估集定期计算。实际落地的坑:线上无 ground truth。解法:用用户点击/点赞行为作为弱监督信号,或定期抽样人工标注。
- 生成质量:监控“无回答率”(LLM 输出“我不知道”的比例)和“幻觉率”(通过 NLI 模型或 LLM-as-judge 打分)。注意:幻觉率不能实时计算,建议离线 batch 分析。
- 基础设施:CPU/GPU 利用率、内存、API 调用错误率(如 OpenAI 429 限流)。
3. 分布式追踪(OpenTelemetry + Jaeger)
- 每个请求生成 trace,包含 span:
query_rewrite→retrieve→rerank→generate。 - 关键:在 retrieve span 中记录检索到的文档 ID 和相似度分数;在 generate span 中记录 prompt 和 response。这样当用户说“回答错了”,你可以直接看 trace 中检索到的文档是否相关。
- 故障排查流程:用户反馈 → 查 trace_id → 看 retrieve span 的文档列表 → 如果文档不相关,问题在检索(索引更新延迟?embedding 模型版本回退?);如果文档相关但回答错误,问题在生成(prompt 注入?LLM 幻觉?)。
4. 告警规则
- 错误率:检索或生成 API 错误率 > 5% 触发告警。
- 延迟:p99 延迟 > 3s 触发告警(根据业务容忍度调整)。
- 召回率:离线计算的召回率下降 > 10% 触发告警(可能索引损坏或数据漂移)。
- 无回答率:连续 10 分钟 > 20% 触发告警(可能 prompt 被误改)。
5. 常见故障根因
- 索引更新延迟:新数据未及时索引,导致检索不到。解法:监控索引 lag(如 Elasticsearch 的 refresh 间隔)。
- 模型版本回退:LLM 或 embedding 模型被回退,导致效果下降。解法:在日志中记录模型版本号,并设置版本变更告警。
- prompt 注入:用户输入恶意 prompt 导致 LLM 输出异常。解法:在日志中记录 prompt 内容,并设置敏感词告警。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从日志、指标、追踪三个层面回答。日志层面,用结构化 JSON 记录链路 ID、检索结果和生成内容,并做采样控制;指标层面,用 Prometheus 监控检索延迟、召回率和生成质量,并设置告警规则;追踪层面,用 OpenTelemetry 实现分布式追踪,快速定位故障是检索还是生成环节。总结一句:RAG 可观测性的核心是让故障排查从‘猜’变成‘看数据’。”
4️⃣ 高频追问 & 应对
追问 1:如何区分“检索召回差”和“生成幻觉”导致的回答错误?
看 trace 中的 retrieve span。如果检索到的 top-5 文档与用户问题不相关(比如用户问“苹果公司”,检索到“水果苹果”),那问题在检索——检查索引是否更新、embedding 模型是否回退、检索参数(如 top_k)是否合理。如果检索到的文档相关,但 LLM 输出错误,那问题在生成——检查 prompt 是否被截断、是否出现幻觉(可通过 NLI 模型验证)。关键:在日志中同时记录检索文档和生成输出,才能做这个判断。
追问 2:线上没有 ground truth,如何监控召回率?
用弱监督信号。方法一:用户点击/点赞行为——如果用户对某个回答点赞,说明检索到的文档大概率正确;如果用户反复追问,说明检索可能有问题。方法二:LLM-as-judge——用 GPT-4 或开源模型(如 Qwen2.5-72B)对检索结果和回答做相关性打分,虽然成本高但准确。方法三:定期抽样人工标注——每天随机抽 100 个请求,标注检索结果是否相关,计算近似召回率。trade-off:弱监督信号有噪声,但成本低;人工标注准确但不可持续。
追问 3:日志量太大,如何平衡可观测性和成本?
分层采样策略。第一层:按请求类型——失败请求 100% 采样,成功请求按 1% 采样(可动态调整)。第二层:按用户——VIP 用户 100% 采样,普通用户按比例。第三层:按指标——当某个指标(如延迟)超过阈值时,自动提升采样率。工具:OpenTelemetry 支持基于规则的采样(如 tail-based sampling)。坑:采样后可能丢失偶发故障。解法:对告警触发的请求,自动提升采样率到 100%。
5️⃣ 避坑 · 常见错误答法
- ❌ 只提“加日志”,不提结构化设计和采样策略 → ✅ 必须说明用 JSON 格式记录关键字段,并给出采样率(如 1% vs 100%),展示成本意识。
- ❌ 只提“用 Prometheus 监控”,不提具体指标和告警阈值 → ✅ 必须给出具体指标(如 p99 延迟 < 3s)和告警规则(如错误率 > 5%),展示工程落地细节。
- ❌ 把故障排查说成“看日志就行”,不提分布式追踪 → ✅ 必须强调 trace_id 和 span 设计,展示整条链路追踪能力。
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“我在项目中用 OpenTelemetry 实现了整条链路追踪,成功定位了 3 次索引更新延迟导致的召回问题”切入,展示实战经验。
- 如果你只做过传统 NLP:用“传统 NLP 的日志只记录模型输出,但 RAG 需要追踪检索和生成两个环节,我通过类比电商系统的整条链路追踪来理解”切入,展示迁移能力。
- 如果你是校招无项目:聚焦“我复现了 LangSmith 的 RAG 可观测性 Demo,用 Jaeger 和 Prometheus 搭建了监控系统,并模拟了索引损坏故障的排查流程”切入,展示动手能力。
- 《Observability for RAG Systems: A Practical Guide》(博客)
- 《OpenTelemetry in Production: Best Practices》(论文)
- 《Evaluating RAG: Metrics, Benchmarks, and Pitfalls》(论文)
- 《LangSmith: Debugging and Monitoring LLM Applications》(工具文档)
- 《Grafana + Prometheus: Monitoring LLM APIs at Scale》(博客)