美团 Agent 一面:项目架构拷打加 Java 基础八股
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 介绍一下两段 Agent 实习的项目,整体架构是怎么设计的?
- 你对 AI 的看法是什么?
- 技术选型:多 Agent 和单 Agent 怎么选?
- 技术选型:微调和 RAG 怎么选?
- LLM 的记忆机制是怎么实现的(prefill 阶段)?
- 数据结构:数组和链表的区别。
- TCP 的三次握手与四次挥手,TCP 和 UDP 的区别。
- Python 和 Java 的底层差异是什么?
- Java 面向对象编程相关。
- JVM 相关。
- 手撕:最长公共前缀。
《参考解析》
多 Agent 与单 Agent 怎么选
这题不要背架构图,要给判断依据。单 Agent 的优势是上下文统一、状态简单、调试与归因容易,工具不多、任务链路线性时几乎总是更优。多 Agent 的价值出现在三类场景:任务能清晰拆成不同职责(检索、生成、评审)、单个上下文窗口塞不下需要隔离、或者子任务可并行来降延迟。代价同样明确——通信开销与信息在传递中的损耗、上下文不共享导致的重复劳动、某一环出错会沿链路放大,以及线上问题难以定位到具体 Agent。回答时给出评估维度(任务可分解性、子任务间上下文耦合度、token 预算、时延要求),再补一句自己项目里最终选了哪种、事后看哪里不理想,可信度立刻不同。
微调还是 RAG
判断轴是「知识要更新」还是「行为要固定」。需要模型掌握私域、时效性强的知识,且要求可溯源,就用 RAG:知识放在外部索引里,改了立即生效,还能给出处;短板是检索质量决定上限、长文档容易丢中间信息、多跳推理弱。需要稳定输出格式、固定话术风格、领域术语或特定语言能力,或者想用小模型替代大模型来降延迟降成本,就上微调;代价是标注与训练成本、知识更新要重训、容易灾难性遗忘。工程上更常见的是组合拳:微调负责「怎么答」,RAG 负责「答什么」,再加一层规则或结果校验兜底。面试官通常还会追问「怎么评估效果」,准备一套离线集 + 人工抽检 + 线上指标的评估方案会很加分。
LLM 的记忆机制
推理侧的「记忆」本质是上下文怎么组织。prefill 阶段把整段输入一次性并行算成 KV Cache,decode 阶段逐 token 复用这份缓存——所以记忆的容量上限由上下文窗口与 KV Cache 显存决定,不是模型自己会记。工程上分几层做:短期记忆是会话历史,超长就滚动截断或用模型摘要压缩;工作记忆把中间结论写进状态对象或 scratchpad,下一轮重新注入;长期记忆放向量库或结构化存储,按需检索回来的片段拼进 prefill。要能说出取舍:全量塞历史最准但贵、且会被无关内容干扰;摘要便宜但丢细节;检索灵活但召回不稳。实际系统多按重要性打分做分层保留,并给每段注入内容标注来源,方便排查。
数组与链表、TCP/UDP 与握手挥手
数组是连续内存,随机访问 O(1)、顺序遍历对 CPU 缓存友好,代价是中间插入删除要搬元素、扩容有拷贝;链表节点分散,插入删除 O(1),但随机访问 O(n)、每节点有指针开销、缓存命中率差。工程里通常「能用数组就用数组」(切片、动态数组),链表多见于需要 O(1) 摘除的场景,比如 LRU 与内核链表。TCP 面向连接、可靠有序、带流量控制与拥塞控制,代价是握手挥手与重传带来的时延;UDP 无连接、不保证顺序与到达,头部小、没有队头阻塞,适合音视频、游戏、QUIC 这类自己在应用层做可靠性的场景。三次握手是为了双方确认收发能力并同步初始序列号;四次挥手源于 TCP 的半关闭——一方发完数据仍可能继续接收,所以 FIN 与 ACK 要分开,最后还要 TIME_WAIT 等 2MSL 让旧报文消散。
Python 与 Java 的底层差异
关键在类型系统与执行方式。Python 动态类型、解释执行(CPython 编译成字节码后由虚拟机跑,热点靠 C 扩展而不是 JIT),对象模型是引用 + 引用计数 + 分代 GC;GIL 让同进程内多线程无法并行跑 CPU 密集代码,并发只能靠多进程或 asyncio。Java 静态类型,先编译成字节码再由 JIT 把热点方法编译成本地代码,跑得越久越快;内存有明确的分代堆与多种收集器,并发靠真线程与并发包。所以长跑的服务端更适合 Java,Python 在胶水、脚本与 AI 生态上难以替代。常见追问是「为什么 Python 慢」「GIL 怎么绕开」「JIT 做了什么优化」,答到执行模型这一层就够,别停留在语法糖。
JVM 要点
把链路串起来:类加载(加载-验证-准备-解析-初始化,双亲委派)→ 运行时数据区(堆、虚拟机栈、方法区/元空间、程序计数器)→ 执行引擎(解释器 + JIT 分层编译,常见优化有方法内联、逃逸分析、去虚拟化)→ 垃圾回收(可达性分析判定存活,分代回收;G1 面向大堆做可预测停顿,ZGC 走并发标记把停顿压到毫秒级)。调优思路比参数重要:先看 GC 日志与堆 dump 判断是内存泄漏还是分配过快,再决定调堆大小、换收集器还是改代码(减少大对象、给缓存设上限)。面试里说清「怎么定位问题」比背 -Xmx 更有价值。
手撕:最长公共前缀
思路是纵扫或横扫:拿第一个字符串作基准,逐位与其他字符串比较,一旦某串在该位置没有字符或字符不相等就截断返回;复杂度是 O(总字符数)。也可以用分治或二分答案的写法。面试官看的是边界处理:空数组返回空串、只有一个元素直接返回、出现空串则结果为空。有个不错的优化是排序后只比较首尾两个字符串的最长公共前缀——字符串按字典序排好后,公共前缀必然被首尾夹住,这个依据要能讲出来,只写代码不解释容易被追问。