面试题 · RAG 项目面试题
按学习路线查看教程、项目和面试题。
重写用于把含指代、错别字或不完整的问题变成独立查询;扩写生成同义表达,适合覆盖不同文档措辞;HyDE 先生成假设答案再做向量检索,适合短而抽象的问题。三者都可能引入偏差,因此应按查询类型启用,保留原 Query,并对原始与改写结果做回退或并行融合。
先看三句用户问题。
“这个怎么申请?”
“理赔和索赔有什么区别?”
“等待期。”
第一句依赖上一轮对话,不知道“这个”指什么就无法检索。
第二句包含两种可能出现在文档里的表达,系统需要覆盖不同措辞。
第三句只有一个抽象概念,信息太少,向量很容易飘到一堆相近主题。
这三类问题都可能被笼统地归入“Query 优化”,但适合的处理方法并不一样。
如果不分类型,每个问题都先交给大模型改写,不仅多一次调用,还可能把原本清楚的编号、否定和限制条件改错。
Query 重写追求的是“把问题说完整”。
用户问“这个怎么申请”,系统要结合有限的对话历史,把它恢复成类似“年假怎么申请”这样可以脱离上下文独立理解的问题。
错别字、口语填充、缩写和省略也可以通过重写处理。重点是尽量保持原意,而不是把一句话写得更漂亮。
Query 扩写追求的是“让不同表达都能被找到”。
用户说“理赔”,文档可能写“索赔”;用户说口语词,知识库可能使用专业术语。扩写可以保留原问题,同时生成若干同义表达或子查询,各自检索后合并候选。
HyDE 追求的是“让检索代理更像文档”。
短 Query 往往只有一个主题词,而知识库里的答案通常是一段陈述。HyDE 先让模型生成一段可能的答案,再把这段假设文档向量化,用来检索真正资料。
它借用的是假设文本的语义形状,不是假设文本里的事实。
重写补全一条问题,扩写覆盖多种说法,HyDE 用假设文档辅助语义检索。三者都只是检索代理。
这三种方法可能同时出现,但不应该无条件叠加。
多轮指代问题先做重写,已经得到清晰独立问题后,未必还需要 HyDE。
明确术语只是文档措辞不同,可以扩写同义词,不必让模型重新编一段答案。
短而抽象的问题如果原词也很重要,可以让原 Query 与 HyDE 并行,而不是只保留假设文本。
重写听起来只是换一种表达,实际会触碰用户意图。
第一类风险是指代补错。
上一轮同时提到两个对象,用户说“它”,模型可能选择错误对象。系统如果只检索改写后的问题,后面每一步都会围绕错误实体展开。
第二类风险是否定丢失。
“哪些情况不支持”如果被改成“支持哪些情况”,关键词仍然相近,意图却完全相反。
第三类风险是约束丢失。
时间、版本、地区、对象和数量都是检索范围的一部分。重写后只剩主题词,系统可能召回旧版本或错误对象。
第四类风险是把新话题误当追问。
用户上一轮问报销,下一轮直接问另一项制度。重写模型如果过度依赖历史,可能把新问题强行接到旧主题上。
因此,重写输出最好满足几个检查。
它应该能够独立理解,保留实体、否定和限制条件,不额外添加用户没有提供的事实,并且在证据不足时允许保持原句或请求澄清。
检查最好建立在结构化结果上,而不是只接收一条改写文本。重写器可以同时返回独立问题、保留的实体、否定词、时间范围、使用了哪段历史以及是否存在歧义。服务端再把这些字段与原 Query 对照:原问题有否定而结果没有,或结果新增了无法从历史定位的实体,就拒绝这次改写并回到原路线。
下面是一个教学输出示意,只表达约束,不对应具体模型接口:
{
"standalone_query": "年假怎么申请",
"resolved_from_turn": "turn-2",
"entities": ["年假"],
"negation_preserved": true,
"ambiguous": false
}结构化并不代表结果一定正确,它只是让错误可检查。若历史中同时存在年假与病假,ambiguous 应触发澄清,而不是为了满足 Schema 强行选择一个实体。
历史也不是越多越好。
重写只需要能消解当前问题的相关对话。把整段长历史全部交给模型,旧话题会增加误判,也增加调用成本。
扩写的好处是覆盖更多文档措辞,代价是查询数量和候选数量一起增长。
一个词如果扩出很多相近表达,每个表达再各自召回一批内容,最终候选里可能出现大量近重复 Chunk。
更危险的是扩写词不等义。
日常表达中的近义词,放到专业文档里可能有不同边界。模型动态扩出的相关词,也可能只是主题相关,并不能互换。
所以扩写需要明确来源和合并规则。
可控的领域同义词适合由词典维护。复杂语义可以让模型生成候选,但要保存每个扩写版本,并限制数量。
多路结果合并时,可以按稳定 Chunk ID 去重,并记录每条候选由哪些 Query 找回。这样既能识别多路共同命中,也能排查哪条扩写引入了噪声。
扩写还可以用于多条件问题。
一个问题同时问申请条件和办理材料时,可以拆成两个子查询,各自检索,再合并互补证据。但拆分之后要检查最终证据是否覆盖完整问题,不能只回答其中一半。
向量检索比较的是 Query 与文档在语义空间中的接近程度。
问句通常很短,文档却以完整陈述出现。HyDE 生成的假设答案包含更多主题词和上下文,向量形式可能更接近真正答案文档。
但这段假设答案没有经过知识库验证。
它可能补错实体、时间和结论,也可能在资料根本没有答案时生成一段看似完整的说明。
如果系统把假设答案直接展示给用户,就已经越过了 RAG 的证据边界。
即使只用它做检索,也存在带偏风险。错误假设会把向量推向错误主题,随后召回一批“支持”假设的相似文本。
更稳妥的方式是把 HyDE 当成一条可撤销的检索路线。
原 Query 仍然保留,假设文本单独记录。两路可以并行召回,再根据稳定 ID 合并。若 HyDE 路线没有带回可核验证据,最终回答不能引用假设文本补空白。
精确编号、产品名、错误码和法规条款更依赖原词命中。先生成自然语言假设,反而可能稀释关键字符。这类问题通常应优先走关键词或精确过滤。
资料中明确没有答案时,也要谨慎使用 HyDE。它提高“找到相似内容”的机会,不等于提高“找到正确答案”的机会。
路由可以先从可解释规则开始,不必一开始就让模型决定一切。
含有“这个、它、那项”等指代,并且相关历史里有明确对象时,进入重写。
含错别字、缩写或口语表达,且不改变实体和否定的情况下,可以做轻量纠错与规范化。
用户表达与文档术语可能不同,或者问题包含多个信息点时,考虑扩写或拆分。
Query 很短、抽象、没有精确编号,并且原向量召回表现不稳定时,才把 HyDE 放进候选路线。
产品编号、错误码、明确标题和法规条款,优先保留原词并走关键词检索。
意图不清、多个对象都可能成立时,与其强行改写,不如请用户澄清。
先判断缺少的是历史、表达覆盖还是文档式语义,再选择重写、扩写或 HyDE。精确词与高歧义问题有独立出口。
规则不可能覆盖所有问题,但它有两个价值。
一是让系统知道为什么触发某种方法,二是给后续评测提供清晰分组。等积累了真实 Query 与失败标签,再考虑训练分类器或用模型路由。
路由输出应包含“为什么走这条路”和“失败后回哪里”。例如检测到指代才调用重写,重写未保留实体就退回原 Query;只有短抽象问题且没有精确标识时才增加 HyDE;多路候选没有合格证据时进入无答案,而不是继续串更多生成步骤。每个分支都有终止条件,才能避免 Query 优化变成不可控的调用链。
缓存也要按处理版本隔离。原 Query 相同,但历史不同,重写结果可能完全不同;同义词表、提示词或模型升级后,产物也会变化。缓存键至少要包含会影响结果的会话上下文摘要和处理版本,不能只用用户输入文本,否则上一段对话的实体可能被复用到另一段会话。
Query 优化的目标不是让系统无论如何都搜出内容。
有些问题缺少的信息无法从对话历史安全补全。
例如用户说“这个能不能退”,上一轮同时出现了两个对象;或者用户只问“怎么处理”,系统不知道他在问申请、报销还是故障。
此时重写模型如果自行选一个对象,后面的检索链路可能非常流畅,却从起点就错了。
澄清适合用在几类情况。
第一,存在多个同样合理的指代对象。
第二,缺少会改变答案的关键限制,例如地区、版本或用户身份。
第三,问题同时可能落到不同知识库或处理流程。
第四,原问题过短,而 HyDE 或扩写的候选方向差异很大。
澄清问题也要尽量具体。
与其问“请提供更多信息”,不如列出系统已经识别到的两个对象,让用户选择。这样既减少来回沟通,也避免模型重新自由猜测。
当然,频繁澄清会打断体验。
所以是否澄清也应进入评测。可以记录出现歧义时,直接检索、自动改写和请求澄清分别产生什么结果。高风险业务更看重意图正确,低风险资料搜索则可能接受并行宽召回。
关键原则是:无法可靠补全的信息,不要被一句看似标准的改写藏起来。
原 Query 是用户意图最直接的证据。
如果只保存改写结果,出现错误时只能看到一条看起来很标准的问题,却不知道模型删掉了哪个词、从哪段历史补了哪个实体。
每次请求至少应记录原 Query、选用的历史、路由类型、重写结果、扩写列表、HyDE 文本、每条路线的候选和最终合并结果。
保留原 Query 还有两个恢复方式。
一种是改写路线没有找到合格证据时,退回原问题重新检索。
另一种是从一开始就让原问题与处理后问题并行召回,再合并去重。后者覆盖更稳,但候选和成本更高。
是否并行要通过评测决定,不能默认多一条路线就一定更好。
还要为处理产物标记版本。
改写提示词、同义词表和模型升级后,同一 Query 可能得到不同结果。没有版本记录,坏样本无法稳定复现。
多路合并还要保留“候选是怎样来的”。
同一个 Chunk 可能同时被原 Query、扩写 Query 和 HyDE 找回。合并时可以只保留一份正文,但不能把通道信息丢掉。多路共同命中可能是一条有用信号,某一路反复引入噪声也需要从日志中看出来。
如果只留下最终综合分,就无法判断这条候选是原词精确命中,还是被错误假设带回。调试 Query 优化时,来源通道与最终排名同样重要。
指代补错、否定丢失、扩写噪声和 HyDE 错误假设需要不同检查,但共同底线都是保留原 Query 与处理记录。
指代补错要查重写结果,噪声增加要查扩写分支,假设带偏要查 HyDE,明确问题变差则先查路由为什么没有保留原 Query。
先看对话历史中是否有唯一明确对象,再看重写结果是否成为独立问题。
如果历史有多个对象,不要默认选择一个。重写置信不足时应保留原句或发起澄清。
比较原 Query 与重写 Query,检查“不、不能、除外”等意图是否保留。
再查看正确例外条款在哪一路被找回,不能只看最终回答是否通顺。
这类精确标识应保留原词,优先走关键词或结构化过滤。
如果路由仍然触发自然语言扩写,说明 Query 分类边界需要调整。
检查假设文本添加了哪些原问题不存在的实体和结论,再比较原 Query 与 HyDE 两路候选。
假设内容不能进入最终证据。没有真实文档支持时,系统应拒绝用它补答案。
先按失败类型建立问题集。
至少包含口语改写、指代、省略、错别字、同义词、否定、多条件、精确编号、短抽象 Query 和无答案问题。
每条问题保存参考意图、正确证据和不允许丢失的约束,例如否定、时间或对象。
然后在同一知识库与检索配置下比较四组:原 Query、重写、扩写、HyDE。需要时再增加原 Query 与处理结果并行的组合。
检索层看 Recall@K 和第一条正确证据名次,确认正确资料是否被带回。
意图层检查实体、否定、时间和范围是否保持。召回更多内容,却把“不支持”改成“支持”,不能算提升。
工程层记录额外调用、候选数量、近重复、处理耗时与版本。
无答案样本还要检查错误处理是否让系统更容易强行回答。
路由本身也要单独评估。
某条重写方法在指代问题上有效,不代表路由器能准确识别指代问题。如果正确方法经常没有被触发,单独评测算法会高估整体效果。
因此评测记录要区分两层:假设已经选对方法时,它能否改善证据排名;面对混合 Query 时,路由是否把问题送到了正确分支。
还可以做逐步消融。先只运行原 Query,再分别加入重写、扩写和 HyDE,最后测试路由组合。每一步都保存新增找回的正确证据、被挤出候选的证据、近重复和额外耗时。这样能回答“是哪一种处理修好了哪类问题”,也能发现三种方法全部串联后是否只是增加成本。
对于意图保持,可以设置硬性不变量:产品编号、错误码、时间、地区、对象与否定不得无依据改变;扩写可以新增同义表达,却不能覆盖原 Query;HyDE 文本永远不能成为最终引用。硬性不变量先拦截方向性错误,Recall@K 等排序指标再衡量收益,两者不能相互抵消。
评测还要保留无处理基线和成本账。每个分组记录额外模型调用、处理耗时、多路候选数与去重后数量,才能判断新增召回是否值得。某种方法若只在很少一类问题上有效,就应缩小触发范围,而不是让所有请求承担延迟。
线上发现坏样本时,先根据日志重放原 Query、历史选择、路由结果和各路候选,再修改规则。若只保留最终答案,团队无法知道是重写改错、扩写带偏、HyDE 假设错误,还是后续排序没有选中正确证据。
还要检查不需要处理的问题。
一批明确标题和编号 Query 应该作为负向样本,验证路由不会滥用改写。只测试困难问题,会让系统倾向于给所有输入增加复杂处理,却看不到清楚问题被改坏的代价。
每次改动提示词、词典或路由规则后,应同时回放需要重写与不需要重写的两组问题。这样才能判断系统是在扩大能力,还是把风险转移到原本稳定的查询上。
既要看正确证据是否上升,也要检查原意有没有被改坏、候选是否重复,以及无答案风险有没有增加。
自动生成 Query 可以帮助扩充初稿,但参考意图和证据仍需核对。否则改写模型生成的问题与评测标准来自同一种偏差,很容易得到虚假的好结果。
不要按名词逐个背定义。先说当前 Query 缺的是上下文、表达覆盖还是文档式语义,再说明对应分支的偏差来源和回退路径。
重写通常把一个问题变成更完整的一句话,重点是准确表达原意。扩写生成多个表达或子查询,重点是覆盖不同文档措辞。
因为改写可能补错实体或删掉关键字。原 Query 是用户原始意图的保底路线,不能被不可逆覆盖。
按稳定 Chunk ID 去重,保留候选来自哪些扩写 Query,再统一融合或重排。这样能控制重复,也方便排查噪声来源。
因为它借用的是完整陈述的语义表示,不要求每个事实都正确。但错误假设仍可能带偏召回,所以必须保留原 Query 并只使用真实文档作为最终证据。
明确标题、错误码、产品编号、法规条款和其他精确实体。这些问题的原词本身就是最强检索信号。
技术上可以,工程上不应默认如此。每增加一路都会增加延迟、候选与偏差来源。先判断问题缺口,再启用最小必要处理。
把三种方法放进同一条可控链路时,重点不是全部串联,而是说明何时启用、怎样保留原意,以及最终证据从哪里来:
Query 重写、扩写和 HyDE 解决的不是同一个问题。重写用于纠错和补全指代,把依赖历史的问题恢复成独立 Query;扩写生成同义表达或子查询,覆盖文档中的不同措辞;HyDE 先生成假设文档再做向量检索,适合短而抽象、问句和文档陈述差异大的问题。
三种方法都会带来偏差。重写可能补错实体或丢否定,扩写可能增加噪声与重复,HyDE 可能用错误假设把召回带偏。因此我会按 Query 类型路由,始终保留原问题。精确编号和标题优先走原词检索,高歧义问题请求澄清,处理后无结果则回退原 Query,或者让两路并行后按稳定 ID 合并。
评测时按指代、同义、否定、精确词、短 Query 和无答案分组,比较原始、重写、扩写和 HyDE 的 Recall@K 与正确证据名次,同时检查意图保持、候选重复、额外耗时和强行回答风险。最终答案只使用真实检索证据,不能把 HyDE 的假设文本当事实。
收尾要让面试官看见一次明确决策:为什么这类 Query 需要处理,处理后怎样发现原意被改坏,又怎样退回原问题。没有与简历对应的实测结果,就只说评测方法和待验证边界,不把教学示例包装成真实收益。