错误答案 vs 正确答案:RAG 系统设计

一句话总结

RAG系统的核心设计不是"把文档塞进向量数据库然后问LLM",而是"在正确的时间,用正确的成本,把正确的上下文,以正确的形态,喂给正确的模型"——这四个"正确"里任何一个出错,整个系统就会从"智能助手"降级为"自信胡说"。大多数团队在检索精度和生成质量上反复打转,却对召回策略、上下文压缩、延迟预算、失败模式这些真正决定系统上限的维度视而不见。真正区分一个能上线的RAG和一个能扛住生产的RAG的,不是用了哪家向量数据库,而是对"什么情况下系统应该承认自己不知道"这件事的工程设计。

适合谁看

这篇文章写给三类人:第一类是正在面试RAG相关岗位的系统设计候选人,你的面试官不是想听你背Retrieval-Augmented Generation的定义,而是想看你如何在15分钟内从"用户上传了一份PDF"推导到"我们需要一个混合检索策略加重排序层加上下文截断加置信度阈值加fallback机制"的完整决策链;第二类是已经拿到offer准备入职、即将面对真实业务场景的工程师,你们会发现面试里那个"理想情况下的RAG"和上线后那个"用户上传了扫描版合同、表格跨了三页、问了一个需要对比三个条款才能回答的问题"的RAG,几乎是两个物种;第三类是技术负责人和架构师,你们需要判断团队现有的RAG设计是否值得继续投入,还是在某个节点应该彻底重构。

不适合的人也有:想找现成代码copy的开发者,这篇文章不会给你任何可以直接git clone的repo;想把RAG当万能药的业务方,你会失望地发现大多数"AI搜索"问题的瓶颈根本不在AI而在数据治理;以及坚信"只要embedding够好就能解决一切"的算法工程师,你会在后面的章节里反复遇到反例。

薪资参考(硅谷2024-2025年,Senior Machine Learning Engineer / Staff级别,RAG/LLM Infra方向):Base $160,000-$220,000,RSU四年总计$200,000-$600,000(年均$50,000-$150,000),Bonus 15%-20% of base,总包区间$240,000-$450,000。Staff级别总包可突破$600,000。

面试流程长什么样:不是考你知不知道RAG,而是考你在约束条件下做取舍

典型的RAG系统设计面试是45-60分钟,不是让你画一张"文档->Embedding->向量数据库->检索->Prompt->LLM"的架构图就完事。真实流程通常这样展开:

第1-5分钟:Clarification。面试官给出一个模糊场景,比如"设计一个帮助法律团队检索内部判例的系统"。错误打开方式是直接开始画架构图;正确打开方式是先问三个问题:用户是谁(律师助理还是合伙人)、查询模式是什么(关键词搜索还是自然语言问答)、成功标准是什么(速度优先还是准确性优先)。我见过一个候选人在这一轮直接问"这些判例是结构化的还是非结构化的,OCR质量如何,更新频率怎样",面试官事后在debrief里说"这人做过生产环境"。

第6-20分钟:High-level Design。需要覆盖数据流、检索策略、生成策略三个层面。不是A是B:不是只谈"用向量检索",而是必须对比Dense Retrieval(向量)、Sparse Retrieval(BM25/关键词)、Hybrid(两者结合)的优劣和切换条件。

第21-35分钟:Deep Dive。面试官会挑刺,"如果用户问了一个需要综合五份文档的问题怎么办""如果向量数据库返回的结果都不相关怎么办""如果上下文窗口不够长怎么办"。这是压力最大的环节,需要你展示对失败模式的认知。

第36-50分钟:Trade-off Discussion。延迟vs准确性、成本vs覆盖率、实时性vs新鲜度。面试官想看你在资源约束下的决策逻辑。

第51-60分钟:Wrap-up。通常会问"如果你有一周时间优化,最先做什么",考察优先级判断。

核心架构:不是"向量数据库+LLM",而是"多层检索漏斗+动态上下文管理+置信度控制"

错误答案的典型架构是这样的:用户Query -> Embedding -> 向量数据库Top-K -> 拼接进Prompt -> LLM生成回答。这个流程在demo里能跑通,在生产环境里会死得很惨。

正确答案的架构需要四层漏斗:

第一层:Query理解层。不是直接把用户问题扔给embedding模型,而是先做意图识别、实体抽取、查询扩展。一个具体场景:用户问"去年和A公司签的NDA里保密期限是多久",原始query的embedding可能和"保密期限""NDA"相关的文档都相似,但经过实体解析识别出"A公司""去年"后,可以先在元数据层面过滤掉其他公司的合同和其他年份的版本。这一层的错误设计是"让向量检索自己解决一切";正确设计是"能用元数据过滤的绝不交给向量相似度"。

第二层:多路召回层。Dense Retrieval(语义相似)和Sparse Retrieval(词频匹配)并行,不是二选一。一个insider场景:某头部云厂商的RAG团队曾经全量迁移到纯向量检索,结果用户搜索"AWS S3 pricing"时,向量检索返回的是一篇讲"AWS S3 architecture"的文档,因为语义相近;而BM25能精准命中包含"pricing"字样的页面。他们的修复不是调embedding模型,而是加了Hybrid Search,向量+关键词各召回100条,由重排序层统一打分。具体实现:Dense用cosine similarity,Sparse用BM25 score,归一化后加权融合,权重根据查询类型动态调整——事实型查询调高Sparse权重,概念型查询调高Dense权重。

第三层:重排序与上下文压缩层。召回500条,不可能全塞进prompt。不是A是B:不是按相似度截断Top-K,而是用Cross-encoder重新打分,再用句子级别相关性做动态截断。一个具体数字:某团队的原始实现直接把Top-10文档全文塞进32k context window,平均token数8000,latency 4.2秒;优化后用句子级切分+重排序,只保留高相关性段落,平均token数降到1200,latency 1.1秒,答案准确率反而提升——因为减少了无关信息的干扰。

第四层:生成控制与失败处理层。这是区分玩具和生产系统的关键。不是A是B:不是"LLM一定会给出答案",而是"系统需要在置信度不足时拒绝回答或触发人工介入"。具体机制:检索结果的最大相似度低于阈值(如0.72)时,返回"基于现有资料无法确认";多个来源矛盾时,显式列出冲突点而非强行综合;长文档需要多跳推理时,先拆解子问题而非直接问LLM。

检索策略对比:不是"向量比关键词好",而是"查询类型决定武器选择"

错误答案的一个典型表述:"我们用向量检索替代了Elasticsearch,因为语义理解能力更强。"这个判断在RAG发展早期(2022-2023)还算合理,在2024年的生产环境里属于严重的选型失误。

正确答案需要这张决策表:

查询类型 示例 首选策略 为什么
精确匹配 "合同编号2024-NDA-0031的签署日期" Sparse/BM25 需要精确匹配编号
概念理解 "解释我们公司的竞业限制条款" Dense/向量 需要语义关联
多条件组合 "去年和科技公司签的、金额超过100万的合同" 元数据过滤+Sparse 结构化条件优先
模糊/口语化 "那个关于远程工作的政策" Dense+查询扩展 表述不规范
对比/综合 "对比A合约和B合约的付款条款" 多轮检索+结构化输出 需要分解子问题

一个具体的BAD vs GOOD对比:

BAD(某候选人在面试中的回答):"我会用OpenAI的text-embedding-3-large做embedding,存在Pinecone里,用户查询时也做embedding,然后cosine similarity找最相似的。"

GOOD(同一问题的优秀回答):"我会先分析查询类型。如果是合同编号、日期、金额这类结构化查询,直接走 inverted index 和精确匹配,延迟低且不会出错。如果是'解释我们的保密政策'这种概念型查询,用dense retrieval。关键是怎么自动区分:我可以在入口处放一个轻量分类器,或者先并行两路、看重排序后的结果分布。另外,对于'去年签的合同'这种有时间范围的,向量检索完全无能为力,必须配合元数据过滤。"

面试官在hiring committee上的反馈通常是:BAD回答的人"对生产环境缺乏认知,把POC当成架构";GOOD回答的人"展示了对检索问题的分层理解,知道没有银弹"。

上下文管理:不是"把相关文档塞进去",而是"在有限窗口内最大化信息密度"

LLM的context window不是无限资源,即使是200k的模型,塞满无关信息的代价是注意力稀释和latency飙升。错误答案的典型表现:检索到10篇文档,每篇取前500字,直接拼接。

正确答案需要解决三个问题:切分策略、选择策略、压缩策略。

切分策略不是A是B:不是"按固定长度切chunk",而是"按语义边界切分,保留上下文完整性"。一个具体场景:法律合同里一个条款可能跨三个段落,中间插入了定义条款。固定长度256 token的切分会把这个条款拦腰斩断。正确做法是识别文档结构(标题、段落、列表、表格),按逻辑单元切分,必要时在chunk metadata中保留"前一个chunk""后一个chunk"的指针。

选择策略不是A是B:不是"按相似度排名取Top-K",而是"用信息增益指导选择"。一个具体算法:先选最相关的chunk,然后计算后续chunk与已选集合的增量相关性,避免选入重复信息的chunk。某团队的实现中,这一步让等效信息量的token数减少了40%。

压缩策略不是A是B:不是"去掉不相关的句子",而是"用更紧凑的表达替代冗长原文"。具体技术:先用小型模型(如T5-small)对检索到的段落做摘要,只保留与查询直接相关的句子;或者使用"Lost in the Middle"研究的发现,将最关键的信息放在prompt的开头和结尾而非中间。

延迟与成本:不是"越快越好",而是"在用户体验和预算约束下做帕累托最优"

一个真实的debrief场景:面试官问"你的RAG系统p99延迟要求是多少",候选人答"200ms以内"。面试官追问"检索还是生成",候选人愣住。后续讨论发现,该候选人把向量检索的延迟和LLM生成的 latency混为一谈,而这两个数量级完全不同——向量检索在几百ms内可以完成,LLM生成即使是GPT-4o-mini处理中等长度输出也要1-3秒。

正确答案需要拆解延迟构成:

阶段 典型延迟 优化手段
查询理解 50-100ms 轻量模型,缓存常见意图
检索(向量/关键词) 100-500ms 索引优化,预过滤,并行查询
重排序 200-800ms 模型蒸馏,批量处理,缓存
上下文组装 10-50ms 预编译模板,流式处理
LLM首Token 500ms-3s 模型选择(小模型优先),prompt优化
LLM生成(流式) 1-10s 输出长度限制,提前终止条件

成本方面,不是A是B:不是"用大模型保证质量",而是"用小模型做初步筛选,大模型做最终生成"。一个具体数字:某团队将重排序从GPT-4替换为蒸馏后的Cross-encoder(参数量差100倍),检索阶段成本从每次$0.12降到$0.003,满意度下降不到2%。

失败模式与监控:不是"上线后看用户反馈",而是"预设失败模式并埋点"

生产环境RAG的监控不是可选的。一个hiring manager的真实抱怨:"我们招过人来做RAG,三个月后问'系统现在准确率怎么样',回答'用户没投诉'。这不是工程,这是祈祷。"

正确答案需要覆盖这些失败模式:

模式一:检索失败。检索返回的结果与查询无关,或虽然相关但不足以回答问题。监控指标:检索结果的平均相似度、Top-1与Top-5的相关性差距、无结果查询比例。不是A是B:不是"看相似度分数高低",而是"看相似度分数与用户反馈的校准曲线"——分数0.8但实际不相关,说明embedding空间有问题。

模式二:生成失败。LLM幻觉、与检索内容矛盾、或无法综合多源信息。监控:事实一致性(用NLI模型判断生成与来源的一致性)、覆盖率(生成中的事实有多少能在来源中找到支撑)。

模式三:系统失败。超时、模型不可用、下游服务降级。需要设计fallback:检索失败时降级到关键词搜索,LLM失败时返回预定义的"请稍后重试"而非500错误。

一个具体的insider场景:某团队在debrief中发现,他们的RAG在回答"公司病假政策"时,有时会引用已废止的旧版本。根因是向量数据库没有版本控制,新旧文档的embedding相似且都返回。修复不是改embedding模型,而是在metadata中加入"effectivedate"和"supersededby"字段,检索时过滤掉已废止版本。

准备清单

  1. 用真实文档跑通一个最小RAG,不是Jupyter notebook demo,而是带API、能并发、有日志的服务。文档选复杂的:带表格、跨页段落、扫描版PDF。
  1. 刻意制造失败案例:用模糊查询、用文档中没有答案的问题、用需要多跳推理的问题,观察系统在哪个环节崩溃。
  1. 系统性拆解面试结构,PM面试手册里有完整的系统设计实战复盘可以参考,特别是关于如何在15分钟内建立信任、如何引导面试官进入你的节奏。
  1. 准备三个具体的Trade-off故事:延迟vs准确性的一次真实取舍;成本vs覆盖率的一次决策;以及一次"我们以为问题是A,实际上是B"的认知翻转。
  1. 熟悉至少两个向量数据库(如Pinecone和Milvus)和一个传统搜索引擎(Elasticsearch/OpenSearch)的API差异,能说出"这个场景为什么选A不选B"。
  1. 读一遍"Lost in the Middle"和"RAG-Fusion"的原始论文,不是背结论,而是能复述实验设计和局限性。
  1. 设计一个监控dashboard的草图,包含至少5个核心指标和对应的告警阈值。

常见错误

错误一:All-in on向量检索

BAD(面试原话):"向量检索比关键词检索更先进,所以我们全部迁移到向量数据库了。BM25那种老技术不需要了。"

GOOD:"我们保留了关键词检索作为精确匹配的fallback。实际上,我们的混合检索在70%的查询上表现更好,但剩下的30%——尤其是合同编号、人名、日期——BM25的准确率是100%,向量检索可能只有60%。"

面试官在HC上的点评:BAD回答的人"对检索问题的历史缺乏认知,不知道BM25为什么存活了30年";GOOD回答的人"展示了技术选型的成熟度,知道不同工具的不同适应症"。

错误二:忽视上下文窗口的隐性成本

BAD(某候选人的架构图):"我们把Top-20文档全都放进prompt,GPT-4的128k窗口足够用了。"

GOOD:"我们会做动态截断。首先,128k窗口的实际有效注意力远低于理论值,研究表明中间部分的信息提取率显著下降。其次,我们的成本模型显示,每增加1k token,单次查询成本上升$0.002,在日均10万次查询的规模下这是不可忽略的。我们的方案是:重排序后取Top-5段落,如果总token数超过阈值,用小型模型做压缩摘要。"

错误三:没有"我不知道"的机制

BAD(某系统的产品日志):用户问"2025年的新政策是什么",系统回答"根据2024年政策,员工每年有10天病假"——实际上2025年政策已改为15天,但新文档尚未入库。

GOOD:系统回答"我的知识截止于2024年12月,关于2025年的最新政策,建议查阅内部wiki或联系HR。"实现机制:在prompt中明确知识截止日期,对时间敏感查询提高置信度阈值,检索结果的时间戳晚于截止日期时触发fallback。

FAQ

Q1: 面试官问"如果向量检索返回的结果都不相关,你会怎么优化",从调整embedding模型开始回答对吗?

不对。这是最常见的错误起手式。正确思路是分层的:首先检查query本身是否被正确理解——是否有拼写错误、是否包含未对齐的术语、是否需要查询扩展;其次检查检索策略是否匹配查询类型——精确匹配问题用向量检索本身就是错配;然后才检查索引质量——文档切分是否合理、是否覆盖了query中的关键实体;最后才是embedding模型是否适配domain。直接说"换更好的embedding模型"暴露的是对检索问题缺乏系统性分析框架。一个具体案例:某团队花两周时间微调embedding模型,问题未解决;最后发现是OCR把"NDA"识别成了"N D A",分词后完全不匹配。修复是加了一个拼写纠错层,成本接近零。

Q2: RAG和Fine-tuning是什么关系,面试里被问到"为什么不直接fine-tune"怎么答?

这不是非此即彼的选择,而是不同约束条件下的不同工具。Fine-tuning适合需要改变模型行为模式、输出格式、或注入大量结构化知识的场景,但无法解决知识时效性问题——模型权重更新一次的成本和时间让"上周的新政策"不可能通过fine-tuning及时反映。RAG的优势正是知识新鲜度和可解释性:你能明确指出"这个答案来自哪份文档的哪个段落"。常见错误是试图用fine-tuning替代RAG来"提升准确性",这通常意味着团队没有做好数据治理,试图用模型训练的成本掩盖数据管道的问题。正确的表述:"对于稳定不变的知识,我们考虑fine-tuning来优化输出格式和语调;对于频繁更新的知识,RAG是唯一可行的架构。当前面试场景下,由于知识库持续更新,RAG是更合适的基线方案。"

Q3: 小型公司没有大厂的infra资源,RAG设计需要妥协什么,不能妥协什么?

可以妥协的是模型大小和检索精度,不能妥协的是失败处理机制。具体而言:可以用更小的embedding模型(如BGE-small代替OpenAI的text-embedding-3-large),接受一定的检索质量下降;可以用开源LLM(Llama 3.1 8B)代替GPT-4,通过prompt工程和RAG的质量来弥补生成能力的差距;甚至可以不用向量数据库,先用传统搜索加缓存起步。但不能妥协的是:系统必须能识别"我不知道"并优雅降级,必须记录足够的日志用于事后分析,必须有机制防止敏感信息泄露。一个真实案例:某startup用最小资源搭建RAG,embedding模型用开源的,LLM用API最便宜的tier,但他们在prompt层面强制加入了"如果检索结果不充分,回答'基于现有信息无法确认'"的指令,并设置了人工审核队列。这个设计让他们在两个月内避免了三次可能的客户纠纷——比任何模型优化都更有价值。不能妥协的底线是:用户更恨"自信地给错答案" than "诚实地不知道"。


想系统准备PM面试?

获取PM面试通关手册 →

想要配套练习工具?PM面试准备系统 包含框架模板、Mock 追踪表和30天备战计划。