面灵AI→

小红书社区工程 Product Engineer 一面:RAG 深挖与 AI Coding

轮次
一面
时间
2026-09
来源
牛客网

《面试题目》

自我介绍与实习

  1. 自我介绍。
  2. 简单介绍一下实习经历。
  3. 为什么研究生期间没有新的实习?

AI 项目深挖

  1. 这个项目用了哪些 AI 相关功能?
  2. 讲一下完整的 RAG 流程。
  3. 检索部分具体做了哪些功能?
  4. 为什么不用向量检索?
  5. 为什么这个场景更适合关键词检索?
  6. 保留了向量检索 / 混合检索接口,具体怎么实现?
  7. 有没有验证过检索准确率?
  8. 如果召回不准,可能是什么原因?怎么优化?
  9. Chunk 切得太细和太粗分别有什么问题?
  10. 切块除了按段落 / 标题,还有做其他优化吗?
  11. 了解 overlap 吗?作用是什么?
  12. 这个项目最大的难点是什么?
  13. 怎么提升 AI 本身的准确率?
  14. 这个项目你自己平时用得多吗?
  15. 模型用的是哪个?

Agent 与 Workflow

  1. 再介绍一下另一个 AI 项目。
  2. 这个项目里 AI 具体做了什么?
  3. 有没有自己搭过 Agent?
  4. 现在更像是把 LLM 当一个功能点使用,还是 Agent?
  5. Workflow 和 Agent 有什么区别?
  6. 了解 ReAct 吗?

AI Coding

  1. 日常开发怎么使用 AI?
  2. 现在写代码频率高吗?
  3. 是不是全部用 AI Coding?
  4. 有没有写 Skill 给 AI 补充上下文?
  5. 了解 Skill 的加载模式 / 渐进式加载吗?

算法

  1. 手撕:和为 K 的子数组。

工程与高并发

  1. 你的项目有没有考虑过高并发?
  2. 如果这个 AI 应用出现高并发,你会怎么处理?
  3. 哪些结果适合加 Redis 缓存?
  4. 如果不同用户需求不同,缓存怎么设计?
  5. 知道哪些限流策略?
  6. 用过异步任务 / 异步队列吗?

其他

  1. 你之前主要做后端还是前端?

《参考解析》

RAG 的完整链路与切块的取舍

一条完整的 RAG 链路分离线与在线两段。离线:解析文档(保留标题层级与结构)→ 清洗 → 切块 → 向量化 → 建索引(向量库加关键词倒排)。在线:查询理解与改写 → 多路召回(向量、关键词、元数据过滤)→ 融合与重排 → 组装上下文 → 生成并标注引用。切块的粗细是典型取舍:切得太细,单个块缺少上下文,指代与限定条件被切掉(“它的延迟是 20ms”里的”它”是谁),召回准但不足以回答;切得太粗,一个块里混了多个主题,向量被平均掉、匹配精度下降,还会浪费上下文窗口并引入噪声。实践做法是结构优先、长度兜底:按标题与段落切,超长的递归细分,过短的与相邻块合并,重叠一小段(overlap)防止关键信息正好落在边界。更进阶的是父子块(小块建索引、命中后把父章节回填给模型)与语义切分(按主题变化切断)。面试里讲清”为什么这么切”比罗列策略名更得分。

关键词、向量与混合检索:什么时候不用向量

向量检索擅长语义近似,换一种说法也能召回;弱点是专有名词、型号、代码标识符、精确数字这类必须字面命中的内容——嵌入模型对这些 token 不敏感,甚至可能因语义漂移召回无关段落。关键词检索(BM25)恰好相反,字面精确、可解释,但不懂同义与改写。所以垂域知识库里”关键词为主、向量为辅”(或反之)很常见,判断依据是查询形态:用户问条款、报错码、API 名称这类精确内容,关键词更稳;用户用自然语言描述需求,向量更稳。工程上更推荐混合检索加 RRF 融合,并把”检索器”做成可替换组件(关键词 / 向量 / 混合),换策略不用动上层。被问”为什么不用向量”时,正确的答法是给场景依据、说明接口保留了可切换性、再给评估数据,而不是笼统地说向量不好。

检索效果的评估与优化

没有评估就没有优化。第一步造评估集:从真实用户问题里采样,标注每条问题应命中的文档或段落,形成”问题→应召片段”的集合;指标分两层看——Recall@k、MRR/NDCG 衡量召回,端到端答案正确率衡量最终效果,两者必须分开,否则召回没命中却去调生成,纯属白费。第二步定位原因:查询与文档用词不一致就加查询改写或同义扩展;块切得不好就重建索引;top-k 太小就先扩大候选再重排;领域术语多就换更适配的嵌入模型或补关键词路;有条件过滤(时间、业务线、权限)就先过滤再检索。第三步控制迭代节奏:一次只改一个变量、记录指标变化,避免凭感觉调了半天反而更差。

Agent 与 Workflow:ReAct 与”把 LLM 当功能点”的边界

Workflow 是预先编排好的固定流程,LLM 只在若干节点里做判断或生成,路径由代码决定;Agent 把”下一步做什么”交给模型,由模型决定调哪个工具、是否继续循环、何时给出最终答案,控制流是动态的。ReAct 是最经典的 Agent 范式:Reasoning 与 Acting 交替进行,把工具返回的观察结果再喂回模型形成下一轮思考,直到模型认为可以作答。区分标准可以落到三个问题上:步骤是否可枚举、路径是否依赖中间结果、失败后是否需要换策略——步骤固定就用 Workflow(可控、可观测、便宜、好测试),需要动态决策才上 Agent,因为 Agent 的延迟与 token 成本更高、行为不稳定、调试困难。把 LLM 封装成一个提取或分类函数,那只是”把 LLM 当功能点”,不算 Agent;能诚实说明项目处在哪一层,比硬说”我们做了 Agent”更可信。

AI Coding 与 Skill 的渐进式加载

日常用 AI 写代码大致分三层:补全(行内续写)→ 对话式生成(给上下文产出函数或模块)→ 带工具自主改多文件。用得越深,上下文质量越是决定性的:把项目约定、目录职责、命令入口写进上下文,模型才不至于写出与现有风格冲突的代码。Skill 的渐进式加载正是为此设计的:启动时只把每个 Skill 的名称与简短描述放进上下文(几百 token 量级,代价极低),当任务明确匹配某个 Skill 时才加载它完整的说明,需要时再读它引用的脚本与模板。这样上下文里既有一份”能力目录”,又不会因为塞满长文档挤掉当前任务的细节。这类问题的加分点是能说清取舍:常驻的是索引、按需的是正文,因此描述写得准(“什么时候该用我”)比正文写得多更重要。

高并发下的缓存与限流设计

AI 应用的高并发瓶颈通常在模型调用(贵、慢、有速率上限),所以缓存与排队是核心。适合缓存的是幂等、与用户无关或弱相关、对时效不敏感的结果:文档解析与切块结果、嵌入向量、不依赖私有数据的通用问答、检索结果;不适合的是强依赖个人上下文、要求实时数据、每次都变化的生成。不同用户需求不同时按层设计缓存:底层缓存”素材”(文档、向量、检索结果,key 用文档或查询特征),上层缓存”成品”(回答,key 必须包含用户特征与检索结果指纹);通用查询走全局缓存,个性化查询命中率低就缩短 TTL,或用语义缓存(把问题向量化后近似匹配相似问法)。限流策略常见的有固定窗口、滑动窗口(精度更好)、漏桶(恒定速率、不允许突发)、令牌桶(允许突发),以及按用户或租户的配额与并发信号量;模型场景还要叠加按 token 预算的限额和异步队列(把同步请求转成异步任务加状态轮询或推送)来削峰。无论怎么做都要有降级路径:缓存不可用或队列过长时返回旧值、简化回答,或明确告诉用户在排队,而不是把错误直接抛出去。

算法题:和为 K 的子数组

直接枚举所有子数组是 O(n²) 起步,数据一大就超时。正解是前缀和加哈希表:设 pre[i] 为前 i 项之和,以 i 结尾、和为 k 的子数组满足 pre[i] - k 曾出现在某个前缀和里。于是遍历一次数组,边累加当前前缀和 sum,边在哈希表里查 sum - k 的出现次数并累加进答案,再把当前 sum 的计数加一;哈希表初始要有 {0: 1} 表示空前缀,否则从头开始的子数组会漏掉。时间 O(n)、空间 O(n)。要主动提的边界:数组含负数时不能用滑动窗口(窗口和没有单调性),这正是本题区别于”和为正数的子数组”的关键;计数可能超出 int,用 64 位;注意空数组与 k=0。顺口说出”如果全为正数可以用双指针把空间降到 O(1)“,能说明思路不是背来的。