面灵AI→

虾皮 AI 应用开发一面面经

轮次
一面
结果
挂
时间
2026-10
来源
牛客网

《面试题目》

  1. 先做个自我介绍。
  2. 做 RAG 功能时,给 AI 提供了什么目标、代码和上下文?
  3. 如何把 RAG 开发拆成多个任务,并判断每一步已经完成?
  4. AI 第一次产出了哪些错误或不合理设计,怎么发现并修正?
  5. 最终用了哪些测试、评测和数据证明 RAG 项目有效?
  6. 「日均 2.7 万入团用户」的统计时间窗口、去重方式和用户口径是什么?
  7. 「每位新人 0.5 个关注」「75% 回关」来自实验观测还是估算?
  8. 实验上线后除了曝光、点击和关注转化率,还应观察哪些体验和稳定性护栏?
  9. 消息队列实际测过的单机吞吐、延迟、并发连接数、队列数、消费者数和消息大小是多少?
  10. Broker 重启后的恢复耗时是多少?
  11. 如何通过故障注入验证消息重复投递率和丢失率?
  12. 如果数据还没测量,优先建立哪些基线、压测方法和验收标准?
  13. 完整说明 RAG 从用户输入到答案输出的在线查询链路。
  14. 为什么需要五路召回,不只做向量或向量加全文?
  15. 同一 chunk 被多路召回命中时如何合并和去重?
  16. RRF 的公式是什么,各通道权重如何设置?
  17. 融合分数相同时,如何保证排序稳定和结果确定?
  18. Reranker 超时时返回哪个阶段的结果,怎样标记降级?
  19. RAG 中哪段核心代码是你独立实现的?举一个删除、修复或调整权重的真实例子。
  20. 40 条评测问题怎样分层,31 项测试分别覆盖什么?
  21. 如何验证检索服务从约 1800 行重构到约 500 行后行为等价?
  22. 如何构造困难样例、对抗样例和失败样例?
  23. 在两个 AI Agent 实操方向中选择一个,并先写清问题定义、技术设计、接口、约束和测试范围。
  24. 如何让 AI 实现五路混合检索融合模块,并验证 RRF、去重、标题加分、文档配额和 reranker 超时降级?
  25. 解释 AI 生成的方案和代码,找出确定性、性能、超时传播或数据结构方面的问题并修正。
  26. 不使用递归,手写二叉树的中序遍历。
  27. 反问。

《参考解析》

RAG 在线链路与为什么做五路召回。一条完整的在线链路是:query 进来先做改写与扩展(同义扩展、指代消解、必要的分词处理)→ 多路召回并行 → 融合排序 → 去重与业务加权 → Rerank 精排 → 上下文构建 → LLM 生成 → 事实核查后输出。多路召回的必要性来自每种检索的失效模式互补:向量召回语义泛化好但专有名词、型号、数字弱;BM25 精确匹配强但换个说法就召不回;标题召回对「某产品的官方说明」这类指向性查询有效;实体召回补人名地名机构名;时间召回处理「最近」「最新」这类时效诉求。工程上要注意三件事:几路召回要并行发,总延迟取决于最慢的一路而不是累加;各路口径要统一(Top-K 相同、用排名融合保证可比);成本要算清——向量检索和 BM25 是主要开销,标题/实体/时间这类走轻量索引,成本很低。

RRF、去重与排序稳定性。RRF 的公式是 score = Σ w_i /(k + rank_i),其中 rank_i 是该文档在第 i 路召回中的名次,k 通常取 60:k 越小头部名次权重越大、长尾好结果容易被淹没,k 越大排名影响越平滑。权重 w_i 要靠实验调,比如向量 0.4、BM25 0.3、标题 0.1、实体 0.1、时间 0.1,每次只调一路看 NDCG 变化,最后再回落做平衡。去重必须用稳定的文档标识(chunk_id)而不是内容 hash——同一段内容不同切块方式 hash 不同,会出现重复。实现上是「chunk_id → 融合分数」的映射,同一 chunk 被多路命中就把分数累加;标题命中可额外加分,再叠一层文档配额限制单一文档占位过多。排序稳定性容易被忽略:融合分数相同时必须加次级排序键(chunk_id 字典序或时间戳降序),否则每次返回顺序不同,测试不稳定、AB 实验也不可比——用 HashMap 做中间容器还会引入遍历顺序的不确定性,应该用 TreeMap 或显式排序。

Reranker 超时降级与延迟分布。Rerank 是链路里精度提升最多、也最容易成为延迟瓶颈的一环,因为它对每个候选都要跑一次交叉编码。降级策略是:设一个超时阈值(例如 200ms,远高于 Reranker 的 P99),超时后不抛异常,而是返回融合阶段的 Top-K 结果,同时标记 degraded=true 并记录 trace_id、超时时间、返回条数;监控里对降级率设阈值告警(超过 5% 说明 Reranker 服务有问题)。降级的代价要能说清:用户无感知,但答案精度会略降。压缩整体延迟还有一个方向是用小模型做 Rerank,把精排耗时从 80ms 级降到 50ms 级。

评测集、测试覆盖与重构等价性。评测问题要分层,通常按简单(单跳事实)、中等(多跳推理)、困难(对抗性查询、长尾实体)三档,各档占比要能反映真实流量,困难集不足会让模型在简单问题上刷出虚高指标。测试要覆盖正常路径与异常路径:召回、融合、去重、加分、配额、超时降级、边界都要有,且每项都有明确输入与预期输出。重构(比如 1800 行缩到 500 行)的验收方式是黄金测试集:准备一批覆盖各场景的查询,重构前后各跑一遍、逐条 diff 输出,出现差异必须人工分析——行为变了就改回去或明确记录为有意变更,不能「跑通了就发布」。自动化 diff 要进 CI,否则下一次重构又得靠人肉。困难与对抗样例要专门构造:多跳问题、长尾实体、同义词替换、拼写错误、prompt 注入,以及知识库里确实没有答案的问题(用来检验模型会不会如实说不知道而不是编造)。

消息队列压测与故障注入。压测要给出可复现的口径:单机吞吐、P99 延迟、并发连接数、队列(分区)数、消费者数与平均消息大小,方法是逐步加压找到「吞吐不再增长而延迟急剧上升」的拐点,而不是只报一个峰值数字。消费者数一般与分区数对齐;消息体积的长尾对吞吐影响很大,大消息要压缩或走对象存储加引用。故障注入用来验证可靠性指标:注入 broker 宕机、网络分区、消费者宕机,消费端按消息 ID 统计重复与丢失;重复主要发生在消费者提交 offset 前宕机,靠幂等消费加去重表(Redis + TTL)解决;不丢靠生产者 acks=all 加副本。Broker 重启的恢复时间要拆开看:leader 选举与消费者 rebalance 各占多久,rebalance 慢就调 session.timeout.ms 与 heartbeat.interval.ms,但调太小会误判 broker 宕机导致频繁 rebalance。如果数据还没测,先建基线(空载资源占用、吞吐、延迟、错误率),再定验收标准(P99、错误率、重复率、丢失率的阈值),优化后才有对照。

AB 实验口径与护栏指标。实验结论要能站住,必须先说清口径:统计窗口(7 天滚动)、去重方式(按 user_id,同一天多次只算一次)、样本口径(排除机器人与测试账号)、分流逻辑(按 user_id 哈希取模保证同一用户始终进同一组)、以及指标定义(回关率是关注后对方也回关的比例,排除取关后重新关注)。护栏指标和转化指标要一起看:负反馈率、举报率、取关率反映内容质量与合规,页面加载时间、接口错误率、消息队列积压、缓存命中率反映稳定性,转化率涨了但举报率也涨,说明是在透支体验。阈值要提前定好并写进实验设计(比如负反馈超过基线 20% 告警、举报超过 15% 回滚),否则事后解释空间太大。

用 AI 写代码的正确姿势。给 AI 的输入要包含四样东西:明确目标、可参考的既有代码(让它复用而不是另造一套)、数据结构与接口签名、以及之前踩过的坑写成的约束(比如「同 chunk 多路命中必须去重」「权重必须配置化不能硬编码」)。任务拆成可验收的小步,每步都有判定标准,而不是「实现混合检索」这种一句话需求——需求太泛的典型后果是它生成的去重逻辑用内容 hash、权重写死在代码里。AI 的产出要重点验证异常路径:正常路径它写得不错,超时传播、并发共享状态、数据结构的有序性这三处最容易出问题(例如用 HashMap 存中间结果导致顺序不确定、超时信号没往下传)。手写二叉树中序遍历用栈:一路把左孩子压栈,弹出访问后再转向右孩子,时间 O(n)、空间 O(树高),并补一句 Morris 遍历可以做到 O(1) 空间但要临时改树结构。