最近陪好几个朋友模拟 RAG 岗位的面试,发现一个很普遍的现象:候选人基本都能背出“检索增强生成”的定义,但一被追问“索引怎么建”“top_k 为什么取这个数”“怎么评估生成内容有没有忠实于知识库”,就明显卡壳。RAG 面试现在几乎成了大模型应用岗的必考题,但从原理到优化能讲透的人确实不多。这篇我把面试里最常出现的 RAG 六连问完整拆一遍,从检索原理、文本切分、效果评估到优化手段都覆盖到,适合准备面试的工程师,也适合做业务落地时遇到瓶颈想系统查漏补缺的团队。
1. 第一问:什么是 RAG,为什么它比“裸微调”更适合问答类场景?
1.1 RAG 的核心思想
RAG 的全称是 Retrieval-Augmented Generation,中文叫检索增强生成。一句话概括:先从一个外部知识库里检索出和当前问题最相关的若干片段,再把这些片段连同用户问题一起交给大模型,让模型基于这些材料来生成答案。这个过程很像开卷考试——允许你翻资料,但答案必须从资料里找依据。
面试官为什么第一个问这个?因为很多人会把 RAG 和“给大模型加知识”这件事混为一谈。实际上 RAG 解决的是三个具体问题:
- 大模型的知识截止日期问题。模型训练完毕之后,世界还在变化,新版本的产品文档、新出的政策、新发生的新闻,模型都不知道,RAG 可以把这些内容放进知识库动态检索;
- 私有数据和长尾知识问题。企业内部文档、客服工单、个人笔记这类数据永远不会出现在公开训练集里,靠训练让模型学会不现实;
- 幻觉问题。模型在不确定时会一本正经地编造,RAG 通过给模型限定“只能根据提供的材料回答”,把答错的概率压到可控范围。
跟面试官解释的时候,最好用一个具体业务例子,比如“一个银行客服助手,需要回答理财产品的最新收益率,这些数据每天变,模型训练的时候根本不可能学到”。这样比干讲定义有说服力得多。
1.2 RAG 与模型微调的取舍关系
RAG 经常被拿来和微调(Fine-tuning)对比。它们不是二选一的对立面,而是两种不同思路的“知识注入”方式。
| 对比维度 | RAG | 微调 |
|---|---|---|
| 是否改变模型权重 | 不改变,模型本身不变 | 改变权重,模型参数被更新 |
| 知识更新成本 | 低,替换/增量更新知识库即可 | 高,需要重新准备数据、重新训练 |
| 回答可控性 | 高,通过检索结果约束回答范围 | 低,模型可能自由发挥 |
| 幻觉抑制能力 | 较强,只要检索到正确内容并约束提示词 | 一般,微调仍可能存在幻觉 |
| 训练资源需求 | 不需要训练,只做推理时检索 | 需要 GPU 资源和训练流程 |
| 适用场景 | 知识频繁更新、需要引用来源、私有数据问答 | 调整输出格式、模仿特定风格、提升特定任务能力 |
实际项目里通常是 RAG 打底,微调做补充。比如一个智能助手,主体问答用 RAG 管实时知识,但“必须用简短口语回复”“不能暴露内部流程”这类风格和纪律要求,光靠提示词不稳定,可以单独做一次小规模微调。
面试追问到这里,有一个高频问题:“RAG 和微调能结合吗?”不能只说“能”,要说清楚分工。我的建议是:知识类问题全部走 RAG,表达风格类问题靠微调,两者共用同一个基座模型,互不干扰。这个回答体现了系统设计思维,比单纯背定义更容易拿高分。
2. 第二问:一次完整 RAG 链路里,哪个环节最容易翻车?
一次完整的 RAG 链路通常由五个模块组成:查询理解、检索、重排、上下文组装、生成。面试官会问“你觉得哪一步最容易出问题”,很多人下意识答“生成”,但我经手过的项目里,最大的坑在检索之前和检索本身。
2.1 查询理解与改写
用户输入的问题往往不是理想的检索语句。真实场景里充满口语、指代词、省略成分。比如用户在多轮对话里说“那它的有效期是多久”,如果直接把“它”拿去检索知识库,基本什么都召回不到。所以第一步要做查询改写。
常见的查询理解手段有三种:
- 规则改写:维护同义词表、实体别名表,把“价格”映射成“费率”,把“你们家”映射成产品名;
- 大模型改写:用一个轻量模型把口语问题改写成适合检索的书面描述,例如“它的有效期”改写成“根据知识库,该产品的有效期是多长”;
- 假设性文档嵌入(HyDE):先让大模型根据问题生成一个假设答案,再用这个假设答案去检索,因为假设答案和文档片段在语义空间里往往比原始问题更接近。
面试里能够主动提到“多轮对话的指代消解是 RAG 容易忽略的前置环节”,会让面试官觉得你有实战经验。我见过太多团队在单轮问答上测试效果不错,一扔到线上多轮对话就崩溃,问题就出在查询理解。
2.2 索引与检索模块
索引阶段要处理的问题很杂:把 PDF、Word、网页、表格清洗成纯文本,去掉页眉页脚和乱码,再按结构切成文本块,然后对每个块做向量化,写入向量索引。这个过程里最容易被低估的是“文档清洗”。如果原始文档是扫描件,OCR 错字多,后面的向量化再强也救不回来。
检索阶段存在两种经典方法:
- 稀疏检索:以 BM25 为代表,基于关键词匹配和词频统计。优点是快、无需训练、对专业术语和编号精确匹配效果好;缺点是无法理解语义近义表达。
- 稠密检索:用向量模型把 query 和文档都编码成向量,计算余弦相似度或内积。优点是能召回语义相关但字面不同的内容;缺点是需要好的向量模型,且对精确 ID 号、型号的匹配不一定比关键词好。
真正能打的方案基本是两者结合:先并行跑稀疏检索和稠密检索,再合并结果,称为混合检索。面试官问“为什么混合检索比单路好”,答案是:精确匹配交给 BM25,语义扩展交给向量,互补。
2.3 融合与重排
混合检索会得到多路候选结果,直接拼在一起会有问题——同一内容可能被不同路召回、排序位置重复,且向量召回的结果不一定按真实相关性排在最前。此时需要两步处理:
- 结果融合:RRF(Reciprocal Rank Fusion)是主流思路,把每个结果在各自列表中的排名取倒数再加权合并,排名靠前的结果天然获得更高分,简单有效;
- 重排:融合之后的候选集合通常还需要一个更精确的排序模型,把“最可能回答问题”的片段排在最前面。重排模型往往比召回向量模型更重,所以只在候选集上执行,兼顾效率和精度。
很多人以为向量检索完直接塞给大模型就行,这是典型错误。检索是“找可能相关的”,重排是“找确定相关的”,中间隔着一步精度提升。面试时把这个链路讲清楚,能甩开大部分候选人。
2.4 生成模块与引用溯源
最后一步是把重排后的片段组装成提示词,交给大模型生成答案。这里的核心提示词设计要求是:明确告诉模型只依据给定上下文回答、禁止编造、无法回答时明确说不知道,并要求在答案后面标注引用了哪个片段编号。这一条“引用溯源”在面试里很加分,因为它涉及工程可信度——企业里做 RAG,用户需要能点开答案看原文出处,否则答错了没人敢用。
生成阶段还有一个小技巧:可以对答案做一次“自校验”,让模型自己判断回答里的每个关键信息点是否都能在给定上下文中找到依据。虽然会增加一次模型调用,但能显著降低幻觉泄漏到终端的概率。
3. 第三问:文本切分到底怎么切,chunk_size 怎么定?
文本切分几乎是 RAG 工程里最“玄学”但又最影响效果的一环。面试官会问“chunk 大小怎么选”,很多候选人答“512 token”,说不出为什么。这个问题的本质是:检索的最小单位是文本块,块的大小直接决定了召回结果的信息完整性。
3.1 为什么切分是 RAG 质量的基石
假设你有一份 50 页的产品手册,如果整篇作为一条记录去向量化,检索时会把整本手册返回给模型,里面只有一两句和问题相关,其余全是噪音,模型很难提取正确答案。反过来,如果切得太碎,比如按一句话切,一句孤立的话往往缺少上下文,比如“它的价格为 299 元”中的“它”在单独的块里无法理解。
所以切分追求的是:每个文本块尽量语义自洽、长度适中、能够独立回答一个子问题。这就是为什么面试官特别爱问 chunk 选择逻辑。回答的关键不是说“我用 512”,而是说“我先定了块的目标语义单元,再根据评估效果调参”。
3.2 常见的切分策略对比
几种主流切分方式各有适用场景:
- 固定长度切分:按字符数或 token 数硬切。实现简单,但容易切断句子和段落,导致语义破碎;
- 递归字符切分:按优先级依次切分,先按段落分隔符,再按句子分隔符,最后按单词或字符兜底。比固定切分温和,是很多框架的默认方式;
- 文档结构切分:根据 Markdown 标题、PDF 章节、表格、列表等文档原生结构切分。能保留层级信息,但依赖文档格式规整;
- 语义切分:利用嵌入模型计算相邻句子之间的语义相似度,在语义转折处切分。效果更好,但计算成本高,需要额外处理。
实际项目里我惯用的组合是:结构切分打底,遇到长段落再用递归字符切分兜底,最后在相邻块之间加一段重叠区域。重叠的意义是防止切断语义——本段结尾和下段开头重复 10%~15% 内容,让关键信息不会因为边界断开而丢失。
3.3 chunk 大小的经验值与调参流程
chunk 大小没有标准答案,但有几个经验边界:
- 中文场景下,单块控制在 300~800 字符(约 200~500 token)比较常见;
- 更准确的上限取决于向量模型的最大输入长度,不要超过模型限制;
- 块越小,召回越精确但上下文越不完整;块越大,上下文越完整但噪音越多。
调参流程比具体数值更重要,建议按这个顺序走:
- 先确定知识库里的文本类型,比如是标准文档、聊天记录还是代码库;
- 从 500 字符开始,构建一个 50~100 条问题的评估集;
- 分别以 300、500、800 字符切分,跑同一套评估,看召回率和答案正确率变化;
- 选择指标最高的参数,再叠加重叠区间测试。
举一个我实际踩过的案例:某文档库里有大量产品对比表格,按固定长度切分后表格被拆得四分五裂,检索结果里全是“型号”“价格”这类孤立字段,答案错得离谱。后来改成按文档行和表格行边界切,把表格整体作为一个块,指标立刻上来了。这个例子说明,切分策略永远跟着文档结构走,而不是机械地套模板。面试时能说出这种细节,比背一堆概念强太多。
4. 第四问:RAG 系统怎么评估,用什么指标?
RAG 的评估经常被一笔带过,但面试官问“你怎么知道你的 RAG 更好”时,能给出完整评估框架的人不多。RAG 是检索和生成串联的系统,所以评估也必须拆成两部分:检索好不好,生成好不好。
4.1 检索质量指标
检索模块的常见指标来自信息检索领域:
- Hit Rate(命中率):对于每个问题,看正确答案是否出现在召回的 top_k 片段里。只要出现就算命中,计算方式是“命中的问题数 / 总问题数”;
- Recall@k:正确答案被召回的覆盖程度,强调“该有的有没有”;
- MRR(Mean Reciprocal Rank):正确答案在排序列表中的倒数排名取平均,第一名为 1,第二名为 0.5,第三名为 0.33。这个指标同时惩罚“没召回”和“排得太靠后”;
- NDCG(归一化折损累计增益):考虑多个相关文档的排序折扣,适合标注了多级相关性的场景。
面试时可以说,我最关注的是“召回第一名是否就是正确片段”,因为 LLM 生成时对排在第一位的上下文依赖最强,第一名错了,后面再对也容易答偏。
4.2 生成质量指标
生成模块的评估核心有三个维度,行业里通常称为 RAG 评估的“三角”:
- 忠实性(Faithfulness):模型生成的每一个关键论断,是否都能在给定上下文里找到依据。这是对幻觉的直接度量;
- 答案相关性(Answer Relevance):生成的答案是否真正回应了用户的问题,跑题、答非所问都属于低分;
- 上下文相关性(Context Relevance):检索到的上下文本身是否包含回答问题所需的必要信息。如果检索结果都是无关内容,生成再好也白搭。
这三个维度里,忠实性最值得优先盯。RAG 的初衷就是反幻觉,如果忠实性低了,整个系统就没有存在价值。实操里可以人工抽样,也可以借助大模型裁判,让一个更强的模型给答案按这三个维度打分。要注意的是,LLM 裁判自身也有偏差,所以关键问题集最好保留人工复核通道。
4.3 一套可落地的评估流程
评估集怎么来,是面试里最容易暴露“没做过真系统”的地方。至少要准备 50~100 条问题,来源包括:
- 真实的用户反馈,筛选高频问题;
- 根据知识库内容人工编造边界问题,比如多轮指代、同义改写、跨章节问题;
- 用大模型批量生成候选问题,再由人筛掉重复和错误项。
不要只准备简单问题。评估集里一定要混入“问题中有明确答案但检索很难召回”“答案散布在多个文本块中”“知识库里根本没有答案”这三类负样本,否则指标再高也没说服力。
评估脚本可以很轻量,代码上大体是这样一个流程:
# 伪代码:RAG 离线评估的最小流程 questions = load_questions("eval_set.jsonl") rag_system = build_rag_system() for item in questions: retrieved_contexts = rag_system.retrieve(item.question) answer = rag_system.generate(item.question, retrieved_contexts) item.golden_id_found = check_hit(item, retrieved_contexts) item.context_relevance = score_context(retrieved_contexts, item.reference) item.faithfulness = score_faithfulness(answer, retrieved_contexts) item.answer_relevance = score_answer_relevance(answer, item.question) summary = aggregate(item) print(summary)这里的重点不是代码本身,而是你要能说出“指标高不代表系统可用”。我见过不少项目离线打分很漂亮,上线后用户就是不满意,原因就是评估集和真实分布不一致。所以评估流程里必须加一步:人工查看 20~30 条失败样本,归结出共性原因,再针对性优化。面试官问怎么评估时,把这个闭环讲清楚,分数会明显不一样。
5. 第五问:检索效果差,怎么一步步排查?
检索是 RAG 里最值得反复打磨的模块。面试官经常会抛一个具体场景:“检索结果乱七八糟,正确答案根本没被召回,你打算怎么排查?”这题考察的是系统的问题定位能力,而不是单个技术点的记忆。
5.1 先判断问题出在“召回”还是“排序”
第一步是缩小范围。把一次检索的中间结果全部打印出来,看 top_k 里到底有什么:
- 如果正确答案根本没有出现在候选集里,说明是召回阶段的问题,可能是查询改写不对、文档切分不合适、嵌入模型效果弱;
- 如果正确答案出现在了候选集里,但排得很靠后,说明是排序阶段的问题,比如重排模型不够强、融合策略不合理、top_k 截断了正确答案。
这个区分非常关键,因为两种问题的优化手段完全不同。召回问题需要动查询和索引,排序问题需要动重排和融合。很多人上来就换向量模型,结果问题出在重排上,白折腾一圈。
5.2 召回不足时的排查顺序
按我使用的排查顺序,通常是这样:
- 检查查询改写结果:打印改写后的查询语句,确认语义是否准确,指代有没有还原;
- 检查切分情况:定位正确答案在原始文档中的位置,看看它所在文本块是否语义完整,有没有被切断;
- 检查向量模型和知识库的域匹配度:通用向量模型在垂直领域的效果往往不理想,需要用领域数据做适配或替换专用模型;
- 加入混合检索:用 BM25 和向量召回并行,观察关键词精确匹配是否能补回语义召回的缺口;
- 调整召回数量:把 top_k 从 3 调到 10,看正确答案是否进入候选,再靠重排把它顶到高位。
这些步骤每一层都有明确的验证动作,面试时按这个顺序讲,逻辑会很清晰。
5.3 排序偏差与噪声干扰问题
如果候选集里已经有正确答案,但生成效果还是差,问题大概率出在排序。常见做法是引入重排模型,把“可能相关”变成“确定相关”。我在一个中文法律问答项目里就发现,向量召回的 top3 里经常混入表面语义相似但结论相反的历史条文,必须靠重排模型把精确匹配的当前有效条文抬上去,才能解决问题。
噪声干扰还有另一个来源:知识库里存在重复或互相矛盾的文档。比如同一个产品在不同版本文档里写了不同的价格表,检索时全部召回,生成模型就不知道该信哪条。此时要在索引侧加元数据过滤和版本标签,允许时用时间字段筛选,让过期的版本不参与召回。
另外,一个常被忽略的排查手段是“看失败问题的归类”。把所有检索失败问题聚一下类,通常会发现知识库本身缺内容、文档结构混乱、专业术语表达不一致这几类。这时候与其反复调模型,不如补充知识库、统一文档写法。这个经验在面试里讲出来,能体现出你有没有真正做过线上系统的迭代。
6. 第六问:有哪些真正有效的进阶优化方案?
最后一问通常会开放一些,面试官想听的是你对 RAG 优化方向的理解密度。只背一个方向肯定不够,最好按“查询侧、索引侧、生成侧、系统侧”四个维度组织答案,每个维度给一个具体技术点。
6.1 查询侧优化:多路查询与假设答案
查询侧的核心思想是“一个查询不够,就生成多个查询变体,提高召回覆盖”。
- Multi-Query:让大模型把原始问题改写成多个不同表达、不同角度的子问题,分别检索后再合并结果;
- HyDE:先生成一个假设答案,再用假设答案检索。因为答案的语义描述通常比问题更贴近文档原文,有时能明显提高召回;
- 查询分解:面对复合问题,拆成多个更小的独立查询,每个子查询分别检索,再汇总生成。
这几种方式会显著增加检索调用次数和 GPU 开销,所以要用在“值得”的问题上,比如用户重复咨询的高频问题、知识库较大的场景。面试官问“有没有副作用”,主动说出成本增加,比一味鼓吹效果更可信。
6.2 索引侧优化:父子分块与层级索引
索引侧最有效的一个优化是“父子分块”:
- 检索时用小的子块(比如 200 字符),提高语义精确度;
- 检索命中子块后,回溯到它所属的父块(比如对应一个完整的章节),把父块作为上下文送回生成模块。
这个方案的逻辑是:小块用于精准定位,小块所在的上下文用于完整理解。检索时定位到某个表格片段,生成时把该表格所在的整节文档内容一并给模型,模型就更有把握答对。另一个索引侧方向是给文档增加结构化元数据,比如来源、时间、用途、权限标签,检索时用过滤条件缩小范围。这在企业场景里几乎必备,因为知识库往往按部门隔离,不控制可见范围的 RAG 根本无法上线。
再往深走,可以把文档实体之间的关系建模成图,先检索出关键实体,再沿着关系边扩展出相关段落,这就是知识图谱增强 RAG 的初步形态。做起来复杂,但对多跳推理类问题效果提升明显。面试时提到这个方向,能证明你对 RAG 前沿进展有了解。
6.3 生成侧优化:上下文压缩与输出约束
生成侧不只是写提示词,还包括:
- 上下文压缩:重排后如果 top_k 里有大段冗余文本,先用一个轻量模型把每一段压缩成和问题相关的几句话,再把压缩文本送入生成,能显著降低噪声干扰,减少幻觉;
- 输出约束:在提示词里声明“只能依据给定资料回答”,并配合少量示例(few-shot)说明期望的答案格式;
- 可信引用:要求模型在答案中注明引用编号,前端展示为可点击的引用来源。
生成侧还有一个容易被忽略的细节:答案自校验。在正式回答前,让模型逐句判断“这句话有没有超出给定上下文的范围”,把不忠实的句子标记出来。代价是多一次模型调用,但能大幅提高忠实性。线上对准确率要求高的场景,值得加上。
6.4 系统侧优化:缓存、反馈与持续迭代
RAG 上线后还有一个持续优化问题。两个方向比较实用:
- 语义缓存:把相同或相似 query 的回答缓存起来,命中后直接返回,不重复走检索和生成。对高频重复提问的客服场景,可以省大量成本和延迟;
- 反馈闭环:把用户的点赞、点踩、追问行为回传,把负面样本定期加入评估集,驱动下一轮检索和提示词优化。
我在实际系统里试过最有效的一步,就是把“用户点踩但答复看似完整”的样本收集起来,逐条标注失败原因,发现很多是知识库不存在最新答案,后来加了知识库更新提醒机制,问题比例立刻下降。面试时如果能讲出“优化不只在模型层,也在数据和流程层”,就达到了资深工程师的思考水平。
我自己的体会是,RAG 面试最怕背概念清单。面试官真正想看到的,是你面对一个检索失败案例时,能不能准确说出“先排查召回还是排序”“chunk 大小是怎么调出来的”“评估集怎么构造”。把这六个问题吃透,再用真实业务案例去印证,整个面试的逻辑线就通了。