面灵AI→

美团Kmart全栈一面面经:Agent项目深挖与后端基础

轮次
一面
结果
凉经
时间
2026-09
来源
牛客网

《面试题目》

实习项目:Agent 平台接入

  1. 意图理解的准确率从 70% 提升到 88%,这个指标具体是怎么测出来的?
  2. 为了防止高风险操作误触发做了哪些设计?准确率提到 88% 之后仍可能误触发,还有哪些办法避免?
  3. Workflow 编排引擎里用 ReentrantReadWriteLock 解决并发问题,为什么需要引入这把锁?具体解决什么问题?
  4. 这把锁是加在节点上,还是加在它调用的底层接口里?
  5. 为什么不用分布式锁?
  6. 读操作也要加锁吗?
  7. 能不能通过接口区分读写,读接口不加锁?
  8. 业务系统 Agent 化接入是通过 API 在代码里改造,而不是在平台上配置 MCP 这类方式?
  9. 「业务操作步骤减少约 60%」这个数字是怎么得出来的?
  10. 你们用 Workflow 做编排,有没有了解过 Skill?有没有想过用 Skill?
  11. Skill 和 Workflow 的优劣分别在哪?
  12. 什么场景下用哪一个更好?

个人项目追问 13. 视频智能理解平台和智能商家点评推荐平台都是你自己做的个人项目吗? 14. 有上线部署,还是只在本地执行? 15. 视频智能理解平台用了 RocketMQ,为什么选它? 16. 用了异步之后,用户怎么知道什么时候处理完?结果怎么推送给用户? 17. 幂等键是怎么设计的? 18. 分片上传和断点续传的机制详细说一下? 19. Redis 里的上传记录会设过期时间吗? 20. Checkpoint 异常重跑靠什么原理支持? 21. 整个流程有哪些节点? 22. 秒杀逻辑里,Lua 脚本还需要再判断一次库存吗? 23. 「一人一单」是通过什么校验的? 24. Redis 在这个场景里主要用来做什么? 25. 同步逻辑和异步逻辑分别做了什么?发异步之前主要做哪些事? 26. Redis 扣减成功但 MQ 执行失败怎么处理? 27. 如果同步成功、异步落库时发现 MySQL 没库存导致消费失败,而用户以为下单成功了,怎么办? 28. 滑动窗口记忆为什么用滑动窗口? 29. 长期记忆和短期记忆,什么时候该记长期、什么时候记短期? 30. 如果用户说了无意义的话被当成长期记忆,有没有纠错机制?

后端基础 31. ConcurrentHashMap 了解吗?说一下原理。 32. 链表转红黑树的阈值是多少? 33. 一个接口耗时比较长,怎么做慢查询优化? 34. 缓存的几大问题知道吗? 35. 分别解释它们的特点和解决方案。

AI 相关 36. Harness 的主要作用是什么? 37. 为什么需要 Harness?为什么最近兴起? 38. ReAct 循环里 Observation 太长怎么办?Action 连续多次失败怎么处理? 39. 循环中断了就相当于本次执行失败吗? 40. 描述一下 RAG 的完整流程。 41. 设计一个 Agent 自动修复线上 bug 的流程;测试完就结束了吗,是不是还需要代码审核?

算法与开放题 42. 算法题:写二叉树层序遍历。追问:每层都新建一个 list,能不能复用一个? 43. 结合 AI 时代,你觉得软件工程流程还有改进空间吗? 44. AI 时代开发者的职责有哪些变化? 45. 你喜欢做程序开发吗?怎么看待写代码这件事?

《参考解析》

离线指标怎么测

建一个固定评测集,每条包含用户提问、标准意图、标准工具;跑一遍线上链路,比对实际调用的工具与标准工具是否一致,一致算对。准确率就是正确条数除以总条数。优化前后各跑一次同一份评测集才有可比性。提准确率的常见手段是关键词粗召回加大模型精排、把工具描述写清楚、把意图分类层拆细。

高风险操作的兜底

置信度低于阈值时不要猜,主动追问让用户澄清;写入、删除、扣款这类操作强制二次确认;再叠加角色权限校验和工具白名单,把高风险工具只开放给特定角色;全程记录操作审计,关键动作走人工审批或先在沙箱里预演。

读写锁加在哪、为什么不用分布式锁

加在底层业务接口上,按接口的读写性质取读锁或写锁,锁粒度细、能复用。读锁的意义不是防止读读冲突,而是读锁与写锁互斥,保证读的时候不会读到写操作的中间状态。分布式互斥锁连读读都互斥,会白白牺牲并发;真要多节点共享读写语义,应该用支持分布式读写锁的实现(如 Redisson 的 RReadWriteLock),而不是拿一把普通分布式锁硬套。

Skill 与 Workflow 怎么选

Workflow 是把固定流程写死的编排,路径确定、可控性高、便于审计,适合流程稳定且含高风险写操作的场景。Skill 更像可复用的能力包,带角色定位、工作流程说明和注意事项,适合需要反复复用、灵活组合的低风险场景。复杂业务通常是 Workflow 编排若干 Skill,兼顾可控与复用。

异步任务怎么让用户看到进度

上传接口立即返回任务号,前端用 SSE 建长连接接收进度与最终结果,也可以用 WebSocket。关键是任务状态要落库,断线重连后能拿到当前进度,而不是只靠内存里的推送。

幂等键的分层设计

上传阶段以视频 MD5 为键,保证同一文件只上传一次。内容解析阶段(ASR 转写、关键帧 OCR)产物只与视频本身有关,键仍是 MD5,可复用已有结果。面向目标的分析阶段键要取「视频 MD5 + 用户目标」,因为同一视频不同目标的结论不同。处理时用 Redis 分布式锁保证同一键同一时刻只有一个线程在跑,其余请求等结果而不是重复计算。

分片上传与断点续传

前端按固定大小切片,算出每个分片的 MD5 和整个文件的 MD5,先向后端询问该文件是否已有上传记录。没有就在 Redis 里初始化一个 Hash 记录文件名、大小、分片总数,再用一个 Set 记录已上传分片序号。每个分片携带文件 MD5、分片 MD5 和序号,后端重算分片 MD5 校验一致后落到临时目录并记序号。全部分片到齐后前端发起合并,后端先核对分片总数,再合并、重算整体 MD5 与前端给的值比对,一致才转入正式存储并标记完成。上传记录要设过期时间(比如 24 小时),否则用户中途放弃的任务会长期占着 Redis 内存。

秒杀链路里 Lua 与 MQ 的分工

Redis 里用 Lua 脚本把「判断库存是否充足、校验一人一单、扣减库存、记录购买」合成一次原子执行,这样中间不会被其他请求插入造成超卖。一人一单用 Set 或 Hash 记 userId 加 itemId 是否已存在。同步阶段只做 Redis 预扣和生成订单号、组装消息;异步阶段发 MQ,由消费者扣 MySQL 库存、创建订单。Redis 扣减成功而 MQ 投递失败,靠生产端重试加本地消息表兜底,再由定时任务补偿。反过来如果异步落库时发现 MySQL 没库存,就要靠定时对账以 MySQL 为准回写 Redis,同时把订单做成「待确认 → 已确认」的状态机,未确认的给用户退款或补偿,并对不一致告警。

记忆的短期与长期

短期记忆用滑动窗口保留最近若干轮对话,实现简单、能有效控制上下文长度,代价是丢失早期信息,可以每 N 轮生成一次摘要补回来。长期记忆存的是用户身份、偏好、稳定事实这类长期有效的信息,抽取成实体或摘要后放向量库。判断标准就是这条信息是否长期有效、是否与用户身份相关、是否反复出现。无意义内容要在入库前过滤掉,给记忆加置信度打分,长期不用的做衰减或过期,并定期清理。

ConcurrentHashMap 与树化阈值

它是线程安全的 HashMap。JDK 1.7 用分段锁,把表分成若干段,每段一把锁,不同段可以并发,但并发度受段数限制。JDK 1.8 去掉分段锁,改成 CAS 加 synchronized:建表和空桶插入用 CAS,桶里已有节点时用 synchronized 锁住头节点,再操作链表或红黑树,锁粒度更细。链表长度达到 8 且数组长度达到 64 才树化;数组不足 64 时优先扩容而不是转红黑树。

慢查询优化

先用慢查询日志定位,再用 EXPLAIN 看执行计划:type 至少要 range、最好到 ref 或 const;rows 越小越好;Extra 里出现 Using filesort 或 Using temporary 就要警惕。索引层面避免失效写法——对索引列做函数运算、隐式类型转换、or 两侧有一侧没索引、不满足最左前缀、以 % 开头的 like。SQL 层面避免 select *,大分页改成基于游标的翻页,子查询尽量改 join。再往上才是读写分离、分库分表和缓存。

缓存三大问题

穿透是查不存在的数据,缓存和数据库都没有,请求全部压到库上,用布隆过滤器加缓存空值来挡。击穿是单个热点 key 过期瞬间大量请求回源,用互斥锁只放一个线程去加载,或者让热点 key 逻辑过期、后台异步续期。雪崩是大量 key 同一时间失效或 Redis 整体不可用,给过期时间加随机值、做集群高可用,并在入口限流降级。

Harness 是什么、为什么兴起

Harness 是围绕大模型的工程约束框架,目标是让 Agent 稳定、可控、可观测地交付,内容包括工具调用的 schema 与权限约束、超时重试、上下文与记忆管理、输出格式校验、流程编排、可观测性以及评估体系。它兴起的根因是模型本身有幻觉、行为不可控、成本高,而业务落地要求可预期,于是把过去散落在各个 Agent 项目里的工程问题抽出来标准化。面试时能把「为什么需要」讲到这个层面,比只列功能清单更有说服力。

ReAct 的 Observation 过长与连续失败

Observation 太长就压缩:对历史 Observation 做摘要,只保留最近若干轮,其余按需检索,或者直接截断只留关键信息。Action 连续失败要设重试上限,比如三次;重试仍失败就触发重新规划,再不行就降级或转人工,并把失败原因记下来用于后续优化和告警。轮次和时间都要有硬上限,避免无限循环。中断确实等于本次执行失败,但如果中途落了 Checkpoint,下次可以从断点继续。

RAG 的完整链路

离线侧:文档解析、清洗与格式统一、按语义或标题分块并留 overlap、向量化后写入向量库。在线侧:把用户问题向量化,同时做向量检索与关键词检索,召回 Top-K 片段后做 rerank 二次排序,再把筛选后的片段和问题一起拼进提示词交给大模型生成,最后可以附上引用来源并做幻觉检测。

Agent 自动修线上 bug 的流程

监控告警触发后,Agent 拿日志和堆栈分析根因,并检索运维知识库找同类问题的处置方案;随后生成修复计划,按计划改代码并记录改动点;改完跑单测和集成测试;通过后必须走人工代码审核,重点看安全、隐私与代码风格;审核通过才发布,发布后继续观察线上指标,失败则自动回滚。这里的关键边界是线下测试环境不连生产库,线上真正执行是独立的最后一步。

层序遍历的写法与追问

用队列:根节点先入队,循环里记录当前队列长度作为本层节点数,按这个数量出队并收集本层结果,同时把左右孩子入队。按层长度出队这一步本身就替代了「每层新建一个 tmp 列表再整体替换」的做法,队列里同一时刻只存相邻两层,空间是 O(最宽层)。如果一定要区分层,也可以在处理每层时清空复用一个缓冲区,避免反复分配;但这属于微优化,真正的复杂度瓶颈在树本身。

AI 时代软件工程流程与开发者职责

需求分析阶段可以让 AI 参与梳理和用户故事生成,架构设计让 AI 给出多个技术选型方案再由人决策,编码阶段 CRUD、单测、文档大量交给 AI,人负责 review 与关键节点决策,测试用例可以由 AI 生成后自动执行,运维侧用 AI 辅助告警分析和根因定位。开发者的职责从执行者转向决策者、审查者、问题定义者和上下文提供者,并且始终是最终责任人——AI 出的错由人承担。