面灵AI→

美团全栈开发日常实习一面:ReAct、RAG 三路召回与 Agent 自进化 49 问

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

《面试题目》

  1. 自我介绍并介绍一下你的项目
  2. 为什么主体选 ReAct?它和思维链、思维树、Plan and Execute 有什么区别?
  3. 为什么不用 LangChain 等流行框架,要自己写?
  4. 用户输入后,从路由到 Skill 调用的完整流程是什么?
  5. 精确场景为什么不走 RAG?什么场景走 RAG?
  6. RAG 三路召回的完整流程是什么?(粗过滤、Top20、打分、ReRank 取 Top8)
  7. RAG 检索可能遇到什么问题?数据坍缩、噪声、召回不足怎么解决?
  8. 多 Agent 在什么情况下触发?怎么拆分子 Agent?
  9. 子 Agent 的工具和消息权限怎么做隔离?
  10. 子 Agent 之间怎么通信和传递结果?
  11. 会话记忆怎么压缩和存储?(滑动窗口、摘要、SQLite、倒排索引)
  12. 历史对话内容存在哪里?怎么按需调取?
  13. Agent 的提示词怎么设计?分哪几层?
  14. 怎么防提示词注入?
  15. 工具调用的 Schema 和权限怎么设计?
  16. 工具调用失败怎么办?(重试、降级、报错)
  17. 是否支持文件上传?文件怎么存储?
  18. MCP 是什么?协议里 host、client、server 各自的角色?
  19. 为什么要用 MCP?解决了什么问题?
  20. Skill 和 MCP 有什么区别?
  21. Agent 自进化怎么设计的?轨迹层和知识层分别存什么?
  22. 因子 / 策略生成的状态怎么流转?
  23. 自进化的触发机制是什么?产出有哪些?
  24. 项目怎么做测试和迭代?(测试集、端到端、线上反馈)
  25. 检索效果用什么指标评估?(精确率、召回率、MRR)
  26. 微服务项目整体架构是什么?拆成了哪几个模块?
  27. 服务之间怎么调用?(OpenFeign)
  28. 登录认证怎么做的?为什么用双 Token(RefreshToken + AccessToken)?
  29. Gateway 负责什么?(路由分发、鉴权)
  30. 数据分层存储怎么设计的?各类数据分别存在哪里?
  31. 为什么行情 / 资金曲线选 ClickHouse、关系数据选 Neo4j?
  32. MQ 在项目里的作用是什么?
  33. 回测这类长任务为什么要异步处理?完整流程是什么?
  34. 幂等怎么实现?常见方案有哪些?
  35. 分布式事务了解吗?
  36. 前后端实时通信怎么做的?为什么用 WebSocket?
  37. WebSocket 的协议头和握手流程是什么?
  38. Redis 在项目里做什么用?
  39. 多实例部署下重复获取数据怎么办?(分布式锁)
  40. Redis 和数据库的一致性怎么保证?三种方案分别是什么?
  41. 缓存和数据库操作的先后顺序怎么选?binlog 方案怎么做?
  42. 之前有没有 Java 项目经历?
  43. 熟悉哪些 Java 技术栈和中间件?(Spring Boot、Spring Cloud、Redis、RabbitMQ)
  44. 什么是 IOC?什么是 AOP?
  45. 你是哪里人?
  46. 为什么研一就想出来实习?时间怎么安排?
  47. 拿过哪些竞赛奖项?
  48. 你怎么看待数学?

《参考解析》

为什么选 ReAct、以及它和 CoT / ToT / Plan-and-Execute 的区别,是 Agent 岗的第一道分水岭。 CoT 是「一次想完再答」,中间没有外部信息介入,适合纯推理题;ToT 在 CoT 基础上做多分支搜索与回溯,成本高,适合解空间小、可评估的规划类问题;Plan-and-Execute 是「先出一份完整计划再逐步执行」,好处是全局视角、便于人工审阅,坏处是计划一旦与现实不符就得整体重来。ReAct 的核心是推理与行动交替——每一步 Thought 之后可以调工具拿 Observation,再据此调整下一步,所以它天然适合「信息不全、需要边查边定」的任务。选它的理由要说清场景:任务的不确定性高、外部工具是主要信息来源、而且允许中途失败重试。反过来说,流程固定、步骤可枚举的场景就不该用 ReAct,直接写 workflow 更可控也更便宜。

「为什么不用 LangChain」要答成工程权衡,不是贬低框架。 常见理由有三条:一是链路定制深,框架的抽象层会在调试时遮蔽真实请求(提示词被拼成什么样、检索命中哪些片段看不清);二是框架迭代快、依赖重,生产上不好锁版本;三是自研只需要一个很薄的编排层(路由、工具注册、状态机、重试),代码量并不大。回答时可以补一句诚实的话:框架适合验证想法,自研适合背责任——一旦线上出问题,得有人能定位到具体那一行。

RAG 的三路召回,重点讲清「为什么需要三路」。 通常是向量召回(语义泛化)、关键词/BM25 召回(精确术语、编号、错误码)、以及基于元数据或规则的召回(时间、版本、类别过滤)。三路各自粗召回 20 条左右,融合(RRF 或加权)后交给 cross-encoder 重排,取 Top8 进上下文。要主动说出常见故障:数据坍缩(切分与嵌入导致不同文档向量高度相似,召回结果同质化,需要多样性控制如 MMR)、噪声(相关但不支撑答案,要靠重排和「证据是否足够」的判断过滤)、召回不足(查询与文档用词差异大,需要查询改写/HyDE)。衡量指标不能只看召回的 precision/recall,还要看最终答案的忠实度和拒答准确率。

多 Agent 的拆分与隔离,回答要落到「权限」和「上下文」两条线上。 触发条件通常是任务可明显分成异构子任务(检索、编码、校验)、单个 Agent 的工具集过大导致选路不准、或者需要并行。拆分原则是按能力边界而不是按步骤数量。隔离有两个层面:工具权限上每个子 Agent 只挂自己需要的工具,且敏感工具(写文件、发请求、付款)走白名单和参数校验;消息权限上子 Agent 只看得到自己那部分上下文,避免污染和越权。通信方式有主 Agent 汇总(层级式)和共享黑板/消息队列(对等式)两类,前者可控、后者灵活,代价都要说清。

记忆压缩的分层策略。 短期用滑动窗口保原文,中期做摘要但仍保留实体与数字,长期落库(SQLite/向量库/倒排索引)按需检索回灌。关键设计点是按需调取:历史对话不能每次全量塞进 prompt,而要先用查询去记忆库里召回相关片段。这里容易忽略的是写入侧——什么该记、以什么粒度记、冲突时谁优先,都需要明确规则,否则记忆库会变成噪音源。

提示词分层与工具 Schema 设计。 提示词一般分四层:身份与目标、能力与工具说明、行为约束(什么不能做、不确定怎么办)、以及输出格式。分层的目的不是好看,而是让改动可定位——改约束不该动到身份层。工具 Schema 要窄:参数少而明确、枚举优于自由文本、必填项显式标注,并且每个工具都要定义失败语义(可重试 / 不可重试 / 需要人工)。工具失败的处理顺序是先分类(网络抖动可重试、参数错误不该重试、权限不足要上报),再决定重试(退避 + 幂等)、降级(换工具或返回部分结果)还是抛给用户。

MCP 与 Skill 的区别,答法是「协议 vs 内容」。 MCP 是模型与外部工具/数据源之间的通信协议,host 是承载对话的应用、client 是 host 内的连接器、server 是暴露工具与资源的一方;它解决的是「工具怎么被发现和调用」的标准化问题,让同一套 server 能被不同 host 复用。Skill 更偏过程性知识——把某类任务的流程、判断标准、注意事项写给人/模型看,通常不涉及运行时协议。一句话概括:MCP 让模型能调用,Skill 让模型知道该怎么用。两者经常组合:Skill 里说明流程,具体动作通过 MCP 工具落地。

Agent 自进化与状态流转。 自进化的可行形态是「轨迹层 + 知识层」:轨迹层存每一次任务的输入、动作序列、结果与人工反馈,用来做失败归因和样本挖掘;知识层是沉淀后的规则、提示词片段、工具用法、评测集。触发机制一般有三类——定时批量挖掘、失败率阈值触发、以及人工标注回流。这里必须说清产出的验证闭环:新知识上线前要在回归集上验证,否则「进化」很容易变成把噪音写进提示词。

微服务与中间件部分的老几样,需要能自圆其说。 双 Token 的目的是让 AccessToken 短命(泄露窗口小)、RefreshToken 长命(避免频繁登录),刷新时旧 RefreshToken 要作废以防重放。网关负责路由、鉴权、限流、灰度,鉴权结果往下游透传用户身份。ClickHouse 适合列式聚合与时间序列(资金曲线、行情这类写入量大、按维度聚合的查询),Neo4j 适合多跳关系(资金链路、股权、担保关系)——选型理由要落在查询模式上。长任务(回测)异步化是为了不占请求线程、便于重试和断点续跑,链路是「提交任务 → 落库排队 → worker 消费 → 状态回写 → 前端轮询/推送」。幂等的常见方案是唯一业务键 + 去重表、状态机条件更新、以及消费侧去重。

Redis 与数据库的一致性,三种方案要能比较。 先更新数据库再删缓存(Cache Aside,最常用,仍可能有短暂不一致)、先删缓存再更新数据库(并发下更容易脏读,一般配延迟双删)、以及订阅 binlog 异步失效(Canal 之类,解耦但引入延迟)。核心结论是没有强一致,只有最终一致,所以关键业务不能把缓存当权威数据源。顺序问题的判据是「谁更容易脏、脏多久能自愈」。

WebSocket 的握手与协议头。 客户端发一个带 Upgrade: websocket、Connection: Upgrade、Sec-WebSocket-Key 的 HTTP 请求,服务端回 101 Switching Protocols 并带 Sec-WebSocket-Accept(由 Key 加固定 GUID 做 SHA-1 再 base64),之后同一个 TCP 连接上跑的是 WebSocket 帧协议,帧头包含 FIN、opcode、掩码位和长度字段。选它而不选轮询,是因为服务端要主动推送且需要低延迟、低开销——但要主动补充它的软肋:连接状态、断线重连、心跳保活、以及多实例下的会话路由(需要共享订阅或网关粘性)。