面灵AI→

虾皮研发工程师一二面:五路召回、加权 RRF 与消息队列压测

轮次
一面+二面+HR面
时间
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. 你有什么问题想问面试官?

二面

  1. 请做一下自我介绍。
  2. 四个月实习中,投入最大、技术成长最多的项目是什么?
  3. 简历中的开源消息队列是否由你独立完成?
  4. Broker、Topic、ACK、持久化和通信等核心模块是否都是你做的?
  5. 消息队列实际测过的单机吞吐、消费延迟、消费者数量和重启耗时分别是多少?
  6. RAG 项目是否也是你个人完整实现的?
  7. 选择加权 RRF 时,主要考虑了哪些指标和融合因素?
  8. 40 条评测集的 Recall@K 和引用正确率是多少,有没有大致数据?
  9. HNSW 索引是 Agent 帮你实现的,还是使用了开源库?
  10. 你还了解哪些向量索引方案,什么时候选择 HNSW,为什么不用其他方案?
  11. 与 AI 联合开发 RAG 时,是否使用过 SDD、Spec 或其他开发范式?
  12. 面对包含入库、检索和测评的大项目,你怎样向 Agent 描述并拆解任务?
  13. AI 生成数百甚至上千行代码时,除了单元测试,你怎样确认它符合预期且交付正确?
  14. 请使用 std::nth_element 返回数组中的第 N 大元素。
  15. 这段实现的时间复杂度和空间复杂度是什么?
  16. 对按 . 分段的字符串,如何处理普通字段、* 匹配一段和 # 匹配零段或多段?请先说明算法、复杂度和边界用例,再完成编码与测试。
  17. 团队负责什么业务,新人入职后通常会做什么?
  18. AI 除了写代码,还能怎样提升广告研发效率?AI 时代工程师应保留什么能力?
  19. 搜广推研发当前最大的技术挑战是什么?

《参考解析》

RAG 检索链路:为什么五路召回、加权 RRF 与 reranker 降级

这场虾皮研发岗的节奏是 9.10 一面、9.21 二面、10.9 HR 面,一面不走常规问答,而是让 AI 按简历生成整套卷子、自己在卷面上作答——题量四十多道,几乎全围着简历里的两个项目(RAG 与自研消息队列)转,泛泛而谈会当场露馅。

为什么不是只做向量召回或「向量 + 全文」,关键在于两类召回的失效方式不同:向量召回吃语义改写,却会漏掉编号、专有名词和精确字段;全文(BM25 一类)正好相反,字面命中强但不理解同义替换。补到五路,通常是在这两路之外再加标题与字段加权召回、结构化过滤(时间、类目、文档配额)和更细粒度的段落级召回。收益是召回率上限变高,代价是候选集变大、融合与 rerank 的延迟和成本上升——路数不是越多越好,要按评测集上的边际增益决定。

RRF 解决的是各通道分数量纲不可比的问题(cosine 相似度和 BM25 分根本不在一个尺度上),所以它只用排名:score(d) = Σ wᵢ / (k + rankᵢ(d)),k 一般取 60 左右做平滑,wᵢ 是通道权重。权重别凭感觉给,做法是在验证集上做消融,看每个通道单独拿掉后 Recall@K 掉多少,再按贡献分配。同一 chunk 被多路命中时用稳定 id(文档 id + chunk 序号)合并累加分;同一文档多个 chunk 命中要先按文档聚合成一个候选再排序,否则一篇长文档会霸榜。

排序确定性是最容易被忽略的追问:RRF 分数撞车很常见,尤其候选集小时,如果依赖 sort 的稳定性或哈希遍历顺序,同一个 query 两次请求可能给出不同结果,评测就无法复现。工程做法是补一个全序的二级键,比如文档 id 或入库时间。reranker 超时则要提前设计降级:超时预算用尽就返回融合阶段的结果,并在响应里带上降级标记(降级阶段、超时阈值、是否 degraded),让上游和评测能把它与正常结果区分开,同时保证超时能在调用链上传播、不把整条查询链路拖死。

评测与数据口径:Recall@K、评测集分层与 AI 协作验收

40 条评测集要讲清分层:按查询类型分(事实型、多跳、长尾、对抗/无答案),每一层的指标意义不同;31 项测试一般覆盖检索命中、引用正确、拒答、边界与失败用例。指标别只报一个 Recall@K——召回率看上限,MRR/NDCG 看排序质量,引用正确率(答案是否有据、能否溯到原文)看生成侧,再补拒答率和 P95 延迟。40 条这个量级方差很大,单项差几分不一定是真改进,所以固定随机性(温度 0、固定索引与排序二级键)并分层看,比盯总分可靠。

1800 行重构到 500 行怎么证明行为等价:拿同一批输入跑新旧两版,逐条比对返回的文档集合、排序和融合分,差异都要能解释;纯函数部分留黄金用例快照,线上可以用影子流量对照。困难样例、对抗样例和失败样例不是随机凑的——困难样例从线上低分或无答案的 query 里挖,对抗样例改写成同义、缩写、错别字、跨语言,失败样例是已知会把链路带偏的输入,三者都要进回归集。

简历上的数字会被逐个对账,这部分值得单独准备:“日均 2.7 万入团用户”要说清时间窗口、去重方式(同一个人重复入团算几次)和用户口径;“每位新人 0.5 个关注”“75% 回关”要说明是实验观测还是估算,估算就得给区间和算法。被问「如果还没测过,你会先建哪些基线」时,答出可执行的顺序(先定义指标与口径 → 再做离线评测 → 最后线上小流量),比临时补一个数字更得分。二面反复追问「HNSW 是 Agent 写的还是开源库」「AI 生成上千行代码除了单测怎么确认正确」,本质是在查同一件事:你对交付物有没有真实的掌控力——AI 可以写,但选型、验收标准和证据必须由你负责。

消息队列项目:压测基线、故障注入与恢复耗时

自研消息队列这类项目,面试官问的都是可测量的量:单机吞吐、P50/P99 延迟、并发连接数、topic/queue 数、消费者数、消息大小,以及 Broker 重启后的恢复耗时。这几项凑不齐,基本会被判定为没真压过——顺带要能说清压测的硬件配置、消息大小梯度和客户端实现。吞吐和延迟必须成对报,只给吞吐不给延迟等于没给结论。

恢复耗时取决于持久化设计:顺序追加的 commitlog 重放、索引重建、刷盘策略(同步刷还是页缓存异步刷)各占多少时间,并且要和数据量对应起来报,比如 10 GB 数据恢复到可服务是几十秒还是几分钟。故障注入验证重复与丢失的标准做法,是注入 broker 被 kill、网络分区、磁盘写满、消费者长时间不 ack 触发 rebalance,再在生产端和消费端按消息序号对账,统计重复率与丢失率。多数 MQ 的语义是 at-least-once,所以重复只能靠消费端幂等(唯一消息 id 加去重表)压到业务无感,而丢失必须为零——这两句答出来,比报一个漂亮的吞吐数字更能说明你懂自己的系统。

手撕与开放题:中序遍历、nth_element、通配符匹配

不用递归的中序遍历就是显式栈模板:从根一路向左压栈,弹出即访问,然后转向右子树;时间 O(n)、空间 O(h)。可以顺口补一句 Morris 遍历能用 O(1) 空间做到,但过程中会临时改写树结构,不适合并发读的场景。

std::nth_element 的要点是它只保证第 N 位就位、两侧不保证有序,平均 O(n)(libstdc++ 是 introselect,递归深度超限回退堆选择,标准不保证最坏复杂度),所以它适合找第 k 大或 top-k,而不是完整排序;参数是 (first, nth, last),返回后 [first, nth) 的元素都不大于 *nth,求第 N 大要么传 greater 比较,要么对下标做对称换算。复杂度追问直接答平均 O(n)、额外空间 O(log n)(递归栈)即可。

通配符分段匹配(. 分段、* 匹配一段、# 匹配零段或多段)是 glob 类问题,朴素回溯在多个 # 的情况下会指数爆炸,稳妥写法是 DP:dp[i][j] 表示前 i 个模式段能否匹配前 j 个字符串段,* 只允许从 dp[i-1][j-1] 转移,# 则可以从 dp[i-1][j-1]、dp[i][j-1](吞一段)和 dp[i-1][j](吞零段)转移;边界要专门处理空串、连续 #、模式以 # 结尾。面试官要求先说算法、复杂度和边界用例再动手,是在看工程习惯,别跳过。

开放题按真实理解回答即可:AI 提升广告研发效率不止写代码,还包括日志与指标排查、实验配置生成、取数与日报、代码 review 辅助和 case 归因,工程师要守住的是问题定义、判断与验收能力。被问到「搜广推当前最大的技术挑战」时,如果不在这个方向,坦白说明并给出自己的理解(冷启动与样本稀疏、多目标与长期价值、实时性与特征一致性、算力与延迟预算等)比硬编一个答案安全。原帖写到 10.9 HR 面结束、面试官说十月底发带薪意向,没有交代最终结果。