你简历里写着“熟悉RAG”,面试官一听就会接着问:RAG和微调怎么选?文档怎么切?向量召回多少个?要不要加重排?Prompt怎么写?最后怎么评估?这六个问题不夸张,我面过的人里能从头答到结尾的不到三分之一。多数人停在“检索增强生成”这句话上,再往深问就露馅。
今天我把这套RAG面试6连问完整拆一遍,从原理到优化都给可落地的回答思路和关键参数。准备大模型应用岗面试的同学可以直接照着准备,已经在做RAG系统的开发者也能拿这篇文章当查漏补缺的清单。
1. 第一连问:RAG和微调到底怎么选,怎么答才算过关
1.1 面试官真正想从这道题里听到什么
这个问题看起来像是在考定义,实际上考的是技术选型能力。RAG的全称是检索增强生成,核心思路是先把外部知识库拆成片段、做向量化,用户提问时先检索出相关片段,再把这些片段作为上下文交给生成模型回答。整个过程不修改模型本身的参数,相当于开卷考试:模型不需要死记硬背,只需要会查资料、会组织答案。
微调则相反,它把特定知识通过训练写进模型权重里,模型记住了这些知识,回答时不需要外部材料。这就是闭卷考试:知识进了脑子,但想改答案得重新训练。
面试官想听的不是这两个概念的复述,而是你面对一个真实业务场景时,能不能判断出该走哪条路。如果你只会背“RAG是检索增强生成”,那这道题最多拿个及格分。
1.2 一套可以直接用的回答思路
我建议按四个维度展开回答,顺序不要乱。
第一,看知识更新频率。如果知识库每周甚至每天都在变,比如产品手册、活动规则、新政策解读,强烈建议RAG。因为新文档入库只需要做一次解析和向量化,几分钟后就能被检索到。如果用微调,每次更新都要重新准备训练集、重新训练,周期长且成本高。
第二,看可解释性要求。RAG的答案可以精准追溯到某篇文档、某个片段,出了问题能快速定位是检索的问题还是生成的问题。微调模型是黑盒,你只能看到它输出了一个答案,但很难说清楚这个答案对应哪条语料。在客服、法律、医疗这类需要追责的场景里,可解释性极其重要。
第三,看成本边界。RAG的成本主要在向量存储和检索服务上,模型本身不用反复训练,比较可控。微调的一次训练成本并不低,尤其是要反复调参、跑实验的时候。知识规模越大,微调需要的数据量也越大,成本会快速上涨。
第四,也是最容易被忽略的一点:两者不是二选一。我在几个生产项目里用的都是RAG为主、微调为辅的组合。业务规则、输出格式、语气偏好这些稳定的行为用微调固化下来,知识问答部分全部走RAG。这样既保证模型“懂规矩”,又保证知识实时更新。
提示:如果面试官追问“知识库有上百万篇文档,检索会崩吗”,不要慌。回答方向是分层检索:先粗召回、再精排,配合缓存和知识库分片。这个追问其实就是给后面的Rerank问题做铺垫,你可以在回答里自然带一句“所以工业界通常不会只靠一次向量检索”。
2. 第二连问:文档切分的三个方案,每个都有坑
2.1 从固定长度切到结构化切分的演进逻辑
文档切分是整个RAG链条里最容易被低估的环节。很多人上来就按固定长度把文本一刀切,结果检索效果一塌糊涂,还以为是模型不行。其实切分方案可以直接决定上层检索命中的质量。
我做过的项目里,切分基本可以分成三个层级。
第一个层级是固定长度切分。按字符数或者token数硬切,例如每512个token一个chunk。这种方式最简单,跑一个循环就能完成。但问题非常明显:语义完整的句子可能被拦腰截断,表格被劈成上下两半,代码块从中间断开。即使加了overlap,也只是缓解信息断裂,不能解决语义割裂的问题。
第二个层级是结构化切分。利用文档本身的标题、段落、列表、表格结构来做切分边界。比如Markdown文档按标题层级划分,每个二级标题下面的内容作为一个chunk,并保留章节目录信息。这样检索时能命中更有主题一致性的片段,效果比固定长度好很多。
这里我想重点提一个在生产里非常实用的技巧:父块和子块结合。大致思路是,切分时保留一个较大的父块用于检索,再拆出更小的子块用于生成。假设一个章节内容当作父块,它对应的摘要或子问题片段充当子块。检索时先命中父块粗筛,再让生成模型使用更聚焦的子块内容。这样既保证“检索到相关内容”,又避免把整章塞进上下文导致信息过载。
第三个层级是语义切分。通过embedding相似度来识别语义边界,甚至用模型判断段落之间的主题连续性。效果最好,但成本也最高,适合对检索精度要求极高的高质量语料库。面试时能说出这个方案的适用边界,就已经比只会固定切分的人高出一截。
2.2 切分参数怎么定,overlap到底有什么用
接下来是参数细节。chunk_size和overlap是面试里最常见的追问点。
先说chunk_size。太小,比如64个token,单个片段信息量不足,检索容易命中碎片化内容,生成模型也get不到完整上下文;太大,比如2048个token,虽然上下文信息多了,但向量包含的噪音也变多,检索精度下降,而且生成模型的输入窗口也会被消耗。我常用的起步值是512个token,之后根据文档类型和检索评估结果再调。表格密集的文档反而适合更小一点,比如128到256,因为表格的语义边界本来就比长段落清晰。
再说overlap。它的作用是给切分边界一个缓冲。假设chunk_size是512,overlap是64,实际从第二个chunk开始,新内容只有448个token,前64个token和上一个chunk结尾是重复的。这个重复不是浪费,它能防止一个完整句子或关键结论恰好落在边界上被切散。
但overlap也不是越大越好。overlap比例太高会造成大量内容冗余,检索时会反复召回几乎相同的片段,既浪费存储也浪费重排算力。我一般控制在10%到20%。如果你的文档里长句子特别多,可以适当提高。
我还想提醒一个隐蔽的坑:切分之前一定要做文本清洗。PDF转出来的文本经常全是断行、页眉页脚、重复导航;网页正文爬下来会带脚印和无关链接。这些脏数据一旦进入向量库,检索结果会被严重污染。我见过一个项目,怎么调模型都没用,最后发现是同一家公司的联系人签名页被重复切了几百次,一直在干扰embedding计算。
切分后的去重也很关键。尤其多篇文档存在内容重叠时,比如不同版本的公告,重复片段会占据向量检索的召回名额,影响最终答案的多样性。
3. 第三连问:向量检索原理和召回量的取舍
3.1 向量检索不是万能的,为什么还要混合召回
向量检索的原理要讲清楚,核心就一句话:把query和文档片段分别映射到同一个向量空间,让语义相近的文本在空间中距离更近,检索时通过计算相似度找到最近邻。
文档侧会提前离线向量化并建好索引,query侧在请求时实时向量化,然后去索引里做近邻搜索。常见的索引算法中,HNSW会在高维空间里构造多层图,检索时从高层粗筛索引,逐层下探到更精确的邻居。这就像一个先翻目录、再翻章节的过程。它的两个关键参数,一个是m控制每个节点的连接数,连接越多召回越准但内存越大,一个是search_ef控制检索时扩展的候选数量,调大更准但更慢。能说出这两个参数,面试官会觉得你真碰过索引调优,而不是只会调SDK。
但为什么不能只靠向量检索?因为向量模型擅长语义匹配,不擅长精确关键词匹配。比如用户要查“编号DM-2024-001”,Embedding之后可能因为token切分和语义建模把精确编号的信息模糊掉了,这时候传统的关键词检索反而更准。BM25这类基于词频和逆文档频率的算法,对精确词项命中的处理比向量更敏感。
工业界的标准解法是混合检索:一路走BM25关键词召回,一路走向量语义召回,两个结果集合并后做重排。合并时最省事的算法是RRF,它不直接比较两类分数,而是先把每个文档在两路召回里的排名取倒数,再求和排序。为什么不用原始分数相加?因为两路分数的分布完全不同,直接相加等于让分数高的一路主导。RRF用排名而非分数,能很好规避这个问题。这个细节如果你能在面试中讲出来,大概率是加分项。
3.2 召回数量、相似度阈值到底怎么调
接下来是工程上最关键的参数:召回多少条、阈值怎么定。
先说召回数量top_k。我刚做RAG时习惯只取前5条,觉得上下文干净、价格低,后来发现效果经常很差。原因是检索本身有误差,如果只拿5条,偶尔一条没命中,模型就无米下锅了。正确做法是把召回量放大到20到50条,先保证相关文档尽量都在候选集里,再通过后续重排把最相关的选出来。直接进生成的话,取5到10条就够,但前提是前面经过了重排。如果完全不做重排,建议先解决重排问题,而不是靠调大top_k硬撑。
相似度阈值更是个大坑。很多教程喜欢给一个阈值比如0.7,但实际不能直接用。不同的embedding模型、不同语言、不同领域文本,分数分布都不一样。有些文档切得短,语义向量天然更贴近query,0.8都不奇怪;有些领域术语密集,0.6可能已经是最高分。
那怎么定?先在测试集上跑一批真实query,把每条查询召回到的最高分记录下来,再人工标注哪些查询是“确实能找到答案”的,观察这两类查询的分数分布,找它们之间的分界线。低于这个分界线的,不用硬答,直接走兜底话术,比如“没有找到相关资料”。
我在多个项目里验证过,设置一个合理的“无答案阈值”,对幻觉率的影响非常大。很多RAG事故不是模型不行,而是找到了一堆不相关的片段,模型又不得不硬答,于是开始编造。阈值其实就是给模型一个合法地拒绝回答的出口。
提示:面试时如果被问到混合检索,完全可以直接说“BM25加向量检索加RRF融合”。这个组合回答简洁但信息密度高,面试官一听就知道你对工业实践有概念。
4. 第四连问:Rerank和召回的差异,要不要多花这一步
4.1 双塔召回和cross-encoder精排之间的差异
Rerank这道题基本是必追的。面试官网是问你“检索直接返回就好,为什么还要重排”,本质是想确认你是否理解召回和精排的区别。
召回阶段用的通常是双塔结构,或者叫Bi-Encoder。Query和文档各自过一个编码器,得到两个向量之后算相似度。因为query和文档可以离线编码、在线比对,速度非常快。缺点是query和doc在编码时没有交互,一些需要细粒度比较的问题处理不好。比如“谁获得了项目一等奖”,标题是“项目评审结果公示”的片段可能在双塔结构下分数很高,但真正包含一等奖名单的段落反而排名靠后。
Rerank阶段用的通常是Cross-Encoder结构。它将query和每个候选文档拼接成一整段文本,一起送进模型打分。因为模型能同时看到两边的完整内容,可以计算更精细的匹配关系,质量明显更高。代价是每一对都要单独前向计算,速度慢很多。
这两个阶段的组合可以类比招聘流程:向量召回是HR按关键词筛简历,快速圈出几十个候选;Rerank是业务面试官面对面聊一轮,挑出真正合适的三五个人。只靠初筛就发offer,风险显然很高。
所以工业级RAG的标准流程是:向量召回20到50条候选,进入重排,取前3到5条进入生成。这个“先粗后精”的漏斗结构,是控制延迟和质量平衡的关键。
4.2 重排分数怎么融合,模型怎么选
模型选型上,首选专门的Rerank模型,不要用底座大模型直接给候选片段打分。原因有两个:延迟太高,每个候选都要拼长文本做一次推理;二是大模型做排序时偏好感很强,经常是答案越长分越高,和真实相关性没关系。
现在社区有很多开源Rerank模型,中文场景也有不少可选。选型时我会看三个指标:排序质量、单条延迟、长文本上限。候选文档很长时,模型可能要截断,导致跨段落的因果信息被丢掉,所以要留意模型的长度支持范围。
分数融合的方式可以分两派。一派是完全信任Rerank分数,候选集按重排后的顺序取前几个。实现简单,效果也不差。另一派是把召回阶段分数和Rerank分数线性融合,给两边各加一个权重,权重靠验证集调。我倾向于先用第一派跑基线,如果发现在召回阶段某个来源总是被埋没,再切换成融合方案。盲目融合有时候反而会把Rerank好不容易拉上来的好结果又拽下去。
还有一点容易被忽略:Rerank模型也是需要迭代的。上线后要把badcase积累下来,定期分析哪些排序错误是模型能力不足,哪些是候选集本身就没召回到正确文档。前者需要换模型或继续微调,后者其实是切分和召回环节的问题,换Rerank模型解决不了。
面试的时候如果能主动提一句“重排模型也需要数据回流迭代”,会体现出你对整个算法的生命周期有完整的认识,这在面试官眼里很加分。
5. 第五连问:生成环节的深度优化,怎么让模型不乱说
5.1 Prompt约束的三个关键点
很多人觉得Prompt随便写两句让模型“根据资料回答”就行,实际效果差得远。我把Prompt的写法归纳成三个关键点:限制来源、限制行为、要求格式。
限制来源,是明确告诉模型只能使用给定资料,不要使用训练阶段学到的背景知识。比如可以这样写:
你是一个知识库问答助手。请仅根据下面提供的参考资料回答问题。如果参考资料中没有明确信息,请回答“资料中没有找到相关内容”,不要尝试编造或补充背景知识。回答时请标注信息来自哪个片段编号,例如[1][2]。
这段模板不长,但每个指令都有作用。“仅根据参考资料”是切断模型自由发挥的源头,“资料中没有就明说”是给模型一个安全出口,“标注片段编号”则是帮助追溯答案来源。
如果不让模型标注来源,你很难判断它是真查到还是编的。一旦加上引文标注,后期就可以做自动化校验。
5.2 超参数、引文校验和忠实度控制
生成阶段的超参数,最重要的是temperature。事实型问答我一般调到0到0.2,让模型开集概率几乎不发挥作用,输出尽量确定。开放式问答可以调高一点,但RAG场景我很少超过0.5。top_p通常配合temperature一起调,维持在0.8到0.95之间比较稳定。
还想说一个很多人忽略的做法:答案生成之后做忠实度校验。最轻量的方案是规则校验:检查模型输出的所有引用编号是否存在,并且引用的片段是否真的出现在输入上下文中。有的模型会张冠李戴,引用了编号但内容根本不在那个片段里,这时候要能拦截住。
更重一些的做法是用一个独立的“判官模型”来打分:把答案和检索片段重新拼好,让判官模型判断答案是否完全来自材料。这会多一次推理成本,但值得对高价值业务场景加一道保险。
我实际使用中发现,如果拦截率高,问题通常不在Prompt,而在检索阶段:要么没召回到正确内容,要么召回内容本身被切碎了。这时应该回头改切分和召回策略,而不是反复调Prompt措辞。顺着这个思路往下答,面试官会知道你是一个会做闭环排障的工程师。
多轮对话也是生成优化里常被追问的点。最简单可靠的做法是先把历史对话做一次压缩或者摘要,再和当前问题合并去检索,避免直接塞全部历史导致上下文漂移。
6. 第六连问:评估指标与上线迭代,别等项目挂了再补
6.1 检索侧和生成侧分开评估,测试集怎么建
RAG系统上线前必须有评估,否则你根本不知道一次改动到底让系统变好了还是变坏了。评估要拆成检索和生成两个独立维度。
检索侧主要看召回效果。常用指标有命中率recall@k,指的是正确答案是否出现在前k个结果里;MRR看第一个正确答案的排名有多靠前;NDCG则更关心排序靠前位置的准确性。这些指标可以自动化计算,比较适合做回归测试。
生成侧就比较难自动化了。建议关注三个点:忠实度,答案有没有严格遵守检索材料、有没有编造;相关性,答案是否真正回答了用户问题;完整性,该覆盖的点有没有漏掉。
测试集的构建是整个评估的基石。我建议至少准备200到500条真实问题,覆盖几类:事实型问题,答案藏在文档里;操作型问题,答案是多步骤流程;否定型问题,需要明确回答“没有这个功能”;跨文档问题,答案散落在两篇以上文档里;无答案问题,文档里根本找不到。其中无答案型问题很容易被忽略,但它恰恰是测试幻觉率的试金石。
用大模型当裁判打分是目前比较常见的做法,但要警惕裁判模型自身的偏好。有的模型偏爱总分结构,有的偏爱长答案,甚至对特定风格有倾向。比较稳妥的方法是先抽几十条人工打分,和模型裁判分数对一遍,发现系统性偏差再调整Prompt或者换裁判模型。
| 评估维度 | 主要指标 | 解决的问题 |
|---|---|---|
| 检索侧 | recall@k、MRR、NDCG | 正确答案是否被召回到、排序是否合理 |
| 生成侧 | 忠实度、相关性、完整性 | 答案有没有编造、是否回答了问题、有没有漏点 |
| 兜底能力 | 无答案拒绝率 | 没有资料时能否正确拒答而不是硬编 |
6.2 从badcase反推问题,迭代顺序不要乱
系统上线之后,数据闭环比算法本身更重要。要记录每条请求的query、召回结果、重排结果、最终答案、用户反馈。没有这份日志,badcase分析无从谈起。
拿到badcase后,我给团队定的排查顺序永远不变:先查检索,再查生成。先看正确文档有没有进到候选集里。如果没有,问题出在切分、向量化或者召回数量上,改Prompt解决不了。如果正确文档命中了,但最终答案仍不对,这时候才去动Prompt和超参数。如果答案明显编造且没有引用来源,回到相似度阈值和引文校验。
这个顺序非常关键。我见过太多人一遇到badcase就去改Prompt,结果折腾一周,最后发现是切分时把关键段落的表格拆成了乱码,检索根本没召回到正确信息。先检索后生成,能省掉大量无用功。
迭代上线的节奏也要稳。新模型或新切分方案上线前,先开一个小的流量灰度,比如切5%,对比badcase率、无答案率、答案长度分布。同时把这批流量里的badcase手工看一遍,确认没有系统性恶化再逐步放量。每次改动都要跑一遍固定回归测试集,防止这个问题的修复导致另一个问题回归。
7. 实操心得:面试里最容易被追问的三个细节
7.1 参数为什么这么设,一句话回答好过背八股
面试面到最后,面试官经常会挑一个最基础的参数问“为什么”。最容易中招的是chunk_size。
准备一个标准答法:chunk_size本质上受文档类型、语言和后续检索效果共同影响。英文长文档可以偏大,中文表格多的页面更适合偏小。判断依据不是经验值,而是拿真实query在验证集上测响应recall。我在项目里常用的做法是先跑256、512、1024三组基线,观察命中率变化,然后选更稳的那组,再微调overlap。这样答,面试官能明显感觉到你不是在背教程。
第二个高频追问是大模型能不能做重排。直接答能,但不好用。大模型排序的延迟是分钟级,对在线RAG不可承受;而且生成式模型的打分偏好会干扰排序准确性。专业的Rerank模型用排序目标训练,效率和效果都更匹配。如果你面试的是偏实时性的业务,这个回答基本是加分项。
第三个容易混淆的点是相似度分数和排序分数。向量召回给出的相似度衡量语义距离,Rerank模型给出的分数衡量候选和query的相关性,两者用途不同、分布不同,不能直接比大小。做混合检索时用RRF融合排名而不是融合原始分数,也是这个原因。
7.2 亲手跑一个RAG Demo,比看十篇面经都有效
最后给你一条最实在的建议:在准备面试前,拿一批自己的文档亲手搭一个最小RAG demo。不用追求复杂,二十篇文档就够。
跑起来之后,把chunk_size分别设成128、512、2048,看检索结果差异;把top_k从5改到50,看引入噪音的变化;加一个Rerank模型,对比前后答案质量。每改一个参数,记录一组结果,形成自己的“实验笔记”。
这样做有两个好处:一是你自己踩过坑,面试时能讲出只有亲自动手才知道的细节;二是你会真正建立“检索结果长什么样”的直觉,而不是停留在纸上谈兵。面试官只要问一句“你怎么调优过”,你实打实说出对比实验和badcase观察,比背出十篇面经里的概念都管用。