Skip to main content

AI 应用开发面试题

前置:调用过大模型 API。不需要做过 RAG 或 Agent 项目。

每题分三层:先用两三句话说清问题本身(这是面试时真正要先讲的),再给完整流程,最后是容易被追问的地方。

01 RAG 的原理和解决了什么问题

1.1 两句话的答法

大模型只知道训练时见过的东西。你问它公司内部的报销标准、上周签的合同、昨天上线的接口,它要么说不知道,要么编一个 —— 而且编得很像真的。

RAG 的做法是:别指望模型记住,每次提问前先去外部资料里找出相关的几段,连着问题一起发给它,让它照着这几段回答。

1.2 为什么不用微调解决

面试官经常会追问这一句。三个角度:

角度微调RAG
知识更新改一份文档要重新训一次,周期以天计传一份新文档就生效,周期以秒计
成本算力加标注,一次训练动辄几千到几万只多一次检索,成本在毫秒和几分钱量级
出处模型说不出这句话是从哪学的每句话都能指回具体是哪份文档的哪一段

最后一条在企业场景里往往是决定性的:业务要的不只是答案,还要能点开看依据。

微调解决的是另一类问题 —— 教模型一种它本来不会的说话方式或做事方式(固定的输出格式、特定领域的语气、某种推理套路)。「知识」用 RAG,「行为」用微调,这是一条好用的分界。

1.3 完整流程

四层,每层各自在防一类问题① 预处理让问题变得可检索用户查询指代补全 · 拆意图长查询先切块查询重写省掉这一层,检索到的东西跟用户真想问的对不上② 检索两路互补,各自有盲区向量检索关键词检索结果校验熔断降级融合重排序相关度都低最糟的做法是把不相关的几段照样塞给模型它会编一个看起来有依据的假答案,比说不知道更危险③ 生成超长要裁,答完还要再验一次Token 校验异步截断Prompt 构造vLLM 推理生成校验结果输出不通过就退回重构审计日志落地答错时,这份日志是判断「检索没找对」还是「找对了但答歪了」的唯一依据 —— 两种问题的修法完全不同。
这张原来是竖排的 Mermaid 图,619×2102 —— 要滚两屏才看得完,而四层本来是并列的层级关系。摊成泳道之后 980×386,每层右上角一句话点出这层在防什么,两条回边(校验不通过退回重构、相关度低走熔断)也能一眼看到落点。

逐段说明这张图里每一步在防什么:

预处理。用户问的话经常不适合直接拿去检索 —— 「那个呢?」这种指代要先补全,「帮我看看去年的和今年的报销标准有什么不一样」这种一句话里包含两个检索意图,要先拆开。查询太长还要先切块。省掉这一步的后果:检索出来的东西跟用户真正想问的对不上,后面做得再好也没用。

双路检索。向量检索找「意思相近」的,关键词检索找「字面相同」的。两路都要,因为它们各有各的盲区 —— 向量检索找不准产品型号、错误码这类没有语义的字符串,关键词检索则找不到换了说法的同一件事。

结果校验与降级。检索出来的几段如果相关度都很低,说明知识库里根本没有这个内容。这时候有两种选择:直接告诉用户「资料里没有」,或者退回一个更便宜的兜底检索。最糟的做法是把不相关的几段照样塞给模型 —— 它会基于这几段编一个看起来有依据的答案,比直接说不知道更危险。

重排序。第一轮检索为了快,用的是粗糙但便宜的方法,通常会取回几十段。重排序用一个更准但更慢的模型(Cross-Encoder 这类)在这几十段里挑出最相关的几段。为什么不一开始就用准的:它要把「问题 + 每一段」成对送进模型算一次,几万段算不过来,几十段可以。

Token 校验与截断。挑出来的内容加上问题,可能超过模型的输入上限。超了要裁,裁的时候优先保留相关度高的。

审计日志。记下这次用了哪几段、相似度各是多少、生成了多少 token。答错的时候,这份日志是唯一能判断「是检索没找对」还是「找对了但模型答歪了」的依据 —— 这两种问题的修法完全不同。

1.4 容易被追问的地方

  • 「检索不到怎么办」 —— 见上面的结果校验。能明确说出「宁可回答不知道,也不要拿不相关的内容去生成」,这一分就拿到了。
  • 「怎么知道 RAG 做得好不好」 —— 要分开评:检索指标(该找到的有没有找到)和生成指标(找到之后答得对不对)。只看最终答案的对错,定位不到问题出在哪一环。
  • 「切块该切多大」 —— 没有标准答案,但要说清权衡:切太小,一段话被切断,检索到的片段看不出完整意思;切太大,一段里混进无关内容,稀释了相关度。

02 对话的 history 怎么处理

2.1 两句话的答法

多轮对话里,模型本身不记得上一轮说过什么 —— 每次请求你都得把之前的对话原样再发一遍。

聊得越久,这份历史越长。三个问题会依次出现:装不下(超过模型输入上限,直接报错)、变贵(每轮都为同一段历史付一次钱)、变笨(历史里绝大部分和当前这句话无关,把模型的注意力稀释掉了)。

所以要处理,处理的方式无非四种:扔掉一部分、把旧的压成摘要、挪到外部存储、以及下次再取回来。

2.2 完整流程

原图有七个参与者、二十条消息,其中隐私脱敏和审计日志各只出现一次 —— 把它们收进注释和自调用,剩下五条生命线,重试路径也收进 alt 块,读起来才有主次。

四个环节,各自在解决上面说的哪个问题:

环节治的是哪个问题代价
按相关度过滤掉无关的几轮变笨阈值定高了会丢掉真正有用的上文
把早期对话压成一段摘要装不下、变贵要多花一次模型调用;压缩是有损的,细节找不回来
存进缓存,按用户 ID 取装不下多一个要运维的组件;过期时间定短了用户会觉得「它忘了」
生成失败后二次压缩重试装不下用户多等一轮

阈值、压缩用什么模型、缓存存多久,这些都要按自己的业务实测定,没有可以照抄的数值 —— 面试时说「我们当时定的是 X,因为压测发现 Y」比报一个来路不明的数字有说服力得多。

2.3 两个容易被忽略的点

脱敏必须在写入之前做,不是读出来之后做。 用户在对话里说了手机号,如果原样存进缓存和日志,那这份数据从此就是敏感数据了 —— 权限、保留期、审计全都得跟着升级。在进存储那一刻就把它抹掉,成本低得多。

改动历史会打掉前缀缓存。 模型服务通常会缓存请求的公共前缀,命中的话这部分几乎不要钱。而你一旦把前面某一轮删掉或改成摘要,从改动点往后的缓存全部作废,下一轮要重新算一遍。所以「删掉几百个 token」这件事,有时候省下的还不如多付的缓存费用贵 —— 要算过账再删。

03 微调的使用场景

3.1 两句话的答法

上一题的分界在这里再说一遍:知识用 RAG,行为用微调。

「模型不知道我们公司的报销标准」是知识问题,喂给它就行;「模型知道,但每次输出的格式都不一样、语气不对、不肯按我们的流程走」是行为问题,喂多少遍也没用,得改权重。

3.2 什么时候该考虑微调

场景为什么 RAG 解决不了
输出必须严格符合某种格式格式要求可以写进提示词,但模型偶尔还是会跑偏;微调过的模型跑偏率低一个量级
特定领域的表达习惯医疗、法律、金融的行文规范是「怎么说」,不是「说什么」,检索不到这种东西
想用小模型省钱用大模型的输出去训一个小模型,在单一任务上逼近大模型效果,推理成本降一大截
有一套自己的推理套路比如内部特有的排障流程,需要模型默认就按这个顺序想问题

3.3 什么时候不该微调

  • 知识会变。 微调把知识焊死在权重里,改一次要重训一次。这类需求一律走 RAG。
  • 数据不够。 微调要的是成百上千条高质量样本,凑不出来的时候,效果通常不如把提示词写好。
  • 还没试过把提示词写好。 这是最常见的情况 —— 很多被归因为「模型能力不行」的问题,换一版提示词、加几个示例就解决了。先试便宜的。

3.4 容易被追问的地方

「全量微调和 LoRA 怎么选」:全量微调改所有权重,效果上限高,但显存吃得多、每个任务要存一整份模型。LoRA 只训练一小部分新增参数,显存要求低得多,一个底座可以挂多个任务的适配器随时切换。绝大多数业务场景从 LoRA 起步。

「微调之后模型变笨了怎么办」:这叫灾难性遗忘 —— 在新任务上练得太久,原来会的能力退化了。常见做法是训练数据里掺一部分通用样本,以及少训几轮、早点停。

「怎么证明微调有效」:微调前后必须用同一套评测集跑对照,而且要分开记录「答错了」和「跑挂了」—— 把基础设施故障算成答错,会让你得出完全相反的结论。