做 RAG 时,为什么应该优先保证“可用、可控、可评测”,再追求“高级”
1️⃣ 考察意图
面试官想看你是否具备工程落地思维,而非只会堆砌炫技模块。这道题表面是问优先级,实则考察你对 RAG 系统全生命周期管理的理解:从零到一搭建时,如何避免“Demo 跑得欢,上线就崩盘”的陷阱。刁钻点在于:很多人会空谈“先做对再做好”,但说不出具体什么是“可用”、怎么“可控”、用什么“评测”。答好了能展示你系统设计能力、迭代优化经验和对生产环境问题的认知,这是大厂 P6+ 的核心素质。
2️⃣ 标准答
这个问题从三个层面拆解:基线系统、评测完整流程、迭代节奏。
1. 可用:先让系统“能跑”且“跑得稳”
- 基础流程:文档切分(chunking,如固定 512 token + 50 overlap)→ 向量化(embedding,如 text-embedding-3-small)→ 检索(top-k=5,用 FAISS 或 HNSW 索引)→ 生成(LLM,如 GPT-4o-mini)。不要一开始就上 query rewriting、multi-hop 检索,这些会引入额外延迟和失败点。
- 工程取舍:固定 chunk size 比动态切分更可控,因为你能预测检索结果的结构。动态切分(如 semantic chunking)虽好,但边界不稳定,上线后可能突然切出无意义片段,导致 LLM 胡编。
- 实际坑:embedding 模型和 LLM 的 tokenizer 不匹配,导致切分后检索出的片段在生成时被截断。解法:统一用 LLM 的 tokenizer 做切分,或用 tiktoken 预估 token 数,确保 chunk 长度不超过 LLM 上下文窗口的 70%。
2. 可控:让系统行为“可预期”
- 检索可控:设置召回阈值(如 cosine similarity > 0.7),低于阈值直接返回“无相关信息”,避免 LLM 硬编。为什么:LLM 在低质量上下文下会 hallucinate,不如直接拒绝。
- 生成可控:用 prompt 模板强制 LLM 输出格式(如 JSON),并加入“如果检索结果不相关,请回答‘无法回答’”。坑:LLM 可能忽略指令,需配合 logit bias 或 structured output(如 OpenAI 的 JSON mode)强制约束。
- 监控可控:记录每次检索的 top-1 分数、生成延迟、是否触发 fallback。原因:没有监控,你无法区分是检索烂还是生成烂。
3. 可评测:用数据驱动迭代
- 建立评测集:至少 200 条 QA 对,覆盖常见问题、边缘问题(如拼写错误、多义词)、无答案问题。方法:用 GPT-4 自动生成,再人工校验 20%。
- 核心指标:
- 检索指标:Recall@k(检索结果是否包含正确答案)、MRR(第一个正确答案的排名)。取舍:Recall@5 比 Recall@1 更实用,因为 LLM 能处理多片段融合。
- 生成指标:Answer Correctness(用 LLM-as-judge 打分)、Faithfulness(是否忠实于检索结果,用 NLI 模型或 GPT-4 评估)。
- 系统指标:P95 延迟(< 2s)、吞吐量(QPS)。
- 实际落地:先跑基线(基础 RAG),记录所有指标。然后每次加一个高级特性(如 rerank),对比指标变化。常见错误:直接上高级特性,结果指标变差,但不知道是检索、生成还是 rerank 的锅。
4. 迭代节奏:先有基线,再优化
- 阶段一(1-2 周):基础 RAG + 评测管道。目标是 Recall@5 > 0.8,Answer Correctness > 0.7。
- 阶段二(1-2 周):加 rerank(如 Cohere rerank-v3)或 query rewriting(如 HyDE)。目标是 Recall@5 提升 5-10%,但延迟增加 < 30%。
- 阶段三(持续):根据评测结果,针对性优化(如调整 chunk size、换 embedding 模型)。原则:每次只改一个变量,否则无法归因。
总结:先做对(可用、可控、可评测),再做好(高级特性)。没有基线,所有优化都是盲人摸象。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从三个层面回答:第一,可用是基础,先让系统能跑且稳定,用固定 chunk size 和简单检索,避免过早引入复杂模块;第二,可控是关键,通过阈值、prompt 模板和监控,让系统行为可预期;第三,可评测是迭代的基石,建立评测集和指标,用数据驱动优化。总结一句:没有基线,所有高级特性都是空中楼阁。”
4️⃣ 高频追问 & 应对
追问 1:你提到“可用”优先,但如果业务要求立即支持多模态(如图文检索),你怎么平衡?
我会分两步走:第一步,用文本替代方案快速上线,比如把图片的 OCR 文本和 caption 作为检索内容,保证“可用”;第二步,在评测管道中增加多模态指标(如图文匹配准确率),然后逐步替换为多模态 embedding(如 CLIP)。取舍:先牺牲精度换取上线速度,再用数据驱动迭代。如果业务硬要一步到位,我会要求 2 周时间做 A/B 测试,对比两种方案的 Recall 和延迟,用数据说服。
追问 2:你的评测集只有 200 条,够吗?怎么保证覆盖度?
200 条是最小可行评测集,用于快速发现明显问题。要保证覆盖度,我会用分层采样:从用户日志中随机抽取 100 条,从业务专家提供的典型场景中抽取 50 条,从边缘情况(如拼写错误、否定句)中构造 50 条。后续每两周用 GPT-4 自动生成 50 条新 QA,人工校验后加入评测集。坑:评测集不能一成不变,否则模型会过拟合到评测集上。
追问 3:你说“每次只改一个变量”,但实际开发中多个团队并行改,怎么归因?
我会用实验管理平台(如 MLflow 或 Weights & Biases)记录每次部署的配置(chunk size、embedding 模型、rerank 开关等),并自动跑评测管道。如果多个变量同时改,用A/B 测试:将流量随机分为两组,每组只改一个变量,对比指标。取舍:这需要额外流量和基础设施,但能避免“改了一堆,不知道哪个有效”的窘境。如果资源不足,至少保证核心变量(如 embedding 模型)单独测试,次要变量(如 chunk overlap)可以批量验证。
5️⃣ 避坑 · 常见错误答法
- ❌ 答:“先做基础 RAG,再慢慢加高级功能,比如多模态、Agent 等。” → ✅ 正确切入:必须具体说明“基础”是什么(固定 chunk size、top-k 检索、简单 prompt),“高级”是什么(rerank、query rewriting、multi-hop),并给出评测指标和迭代节奏。空谈“先基础再高级”等于没答。
- ❌ 答:“可用就是系统不崩溃,可控就是能调参数,可评测就是有准确率。” → ✅ 正确切入:可用要具体到“chunk 长度与 LLM 上下文匹配”、“检索阈值设置”;可控要具体到“prompt 模板强制输出格式”、“监控日志记录”;可评测要具体到“Recall@k、Answer Correctness、P95 延迟”等可量化指标。
- ❌ 答:“直接上 LangChain 或 LlamaIndex 的默认配置就行。” → ✅ 正确切入:框架默认配置(如 LangChain 的 recursive chunking)不一定适合你的数据,必须自己调参并验证。默认配置只能作为起点,不能作为终点。
6️⃣ 简历呼应
- 如果你有 RAG 项目:从“实际踩过的坑”切入,比如“我在项目中先用了 advanced chunking,结果上线后召回率暴跌,后来退回固定 chunk size 并建立评测管道,才稳定下来”。强调你如何用评测数据驱动迭代。
- 如果你只做过传统 NLP:用“分类模型迭代”类比,比如“就像做文本分类,先跑一个逻辑回归基线,再上 BERT,而不是直接上 GPT-4。RAG 也一样,先有基础检索+生成,再上 rerank 和 query rewriting”。
- 如果你是校招无项目:聚焦“论文复现 demo”,比如“我复现了 RAPTOR 论文的树状检索,但发现没有基线对比,无法评估效果。后来我按这个原则,先跑基础 RAG 作为 baseline,再用 RAPTOR 对比,才得出有意义的结论”。
- 《RAG 系统设计:从基线到生产》—— 博客,详细讲解评测管道搭建
- 《Evaluating RAG: A Practical Guide》—— 论文,介绍 Recall@k、MRR、Faithfulness 等指标
- 《LangChain vs LlamaIndex: A Production Perspective》—— 博客,对比框架的默认配置和坑
- 《HyDE: Precise Zero-Shot Dense Retrieval》—— 论文,query rewriting 的经典方法
- 《The RAG Stack: From Demo to Production》—— 博客,讲迭代节奏和实验管理