百度后端开发一面凉经 全程 AI 八股
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 为什么使用 Spring AI Alibaba 或者 Spring 的框架来做 AI 智能体?
- ReAct 模式的核心原理是什么?如何避免一直循环?
- ReAct 和 Plan、Execute、RePlan 模式有什么区别?各自适用于什么场景?
- 要查询数据库状态你会选择哪种模式?
- Function Calling 的原理了解吗?JSON Schema 起到什么作用?
- 假如 SSE 流式传输只返回了一半的 JSON,要不要执行这个工具?或者说你会采取什么策略来应对这种未知情况?
- 你使用到了多 Agent,为什么?单个 Agent 加多个工具不行吗?有什么优势?
- 上下文超了如何解决?
- 任务很复杂,需要拆分为多个子任务,子任务中有难有易,如何派发给子 Agent 执行?如何进行多个 Agent 之间的协调?
- 子 Agent 工作应该需要给哪些信息?
- 工具很多导致上下文被挤占,如何解决?
- 用的什么模型?有做过模型间的横向对比吗?
- RAG 是为了解决什么问题?web search、web fetch 等工具也可以获取新知识,为什么一定要 RAG?
- RAG 为什么要用向量数据库?MySQL 这种不行吗?
- 语义查询的底层原理讲一下。
- 抽奖算法如何实现的?
- 为什么要使用 Lua 脚本?起什么作用?
- HashMap 底层实现原理是什么?数据结构是怎么样的?是否线程安全?不使用 ConcurrentHashMap、HashTable 这种已有实现,你会如何改进现有的 HashMap 实现线程安全?
- Java 的垃圾回收机制。
- 缓存三兄弟。
- RabbitMQ 和 Kafka 的区别,两边介绍一下。
- 手撕:矩阵螺旋输出(Leetcode 54 变体,需反转方向)。
《参考解析》
ReAct 与 Plan-Execute-RePlan 的取舍:ReAct 是「推理—行动」交替的循环:模型先输出一段思考,再选择工具并给出参数,执行结果作为观察回填上下文,然后继续,直到它认为可以给最终答案。关键点是这个循环由你的代码控制,终止条件不能只靠模型自觉:要设最大步数上限、检测重复动作(同一工具加同一参数连续出现就打断并提示)、检测无进展(连续 N 步没有新信息)、限制总 token 与总耗时,另外只读工具可以放宽、有副作用的工具要限制调用次数。Plan-Execute-RePlan 是先一次性产出完整计划再逐步执行,执行中偏差过大才重新规划,适合步骤多、依赖关系明确、需要给用户展示进度的任务;ReAct 更适合下一步取决于上一步结果的探索型任务。至于「查数据库状态」,这是一次确定性的事实查询,最优解是直接一次工具调用(甚至是参数化的固定 SQL),用 ReAct 会多烧几轮 token 还可能查错;只有当状态需要多条件组合、或查询结果决定后续动作时,才值得上 Plan 先排好顺序。
Function Calling 与「半截 JSON」:模型自己不执行任何东西。Function Calling 是把可用函数的名称、参数结构与用途说明随请求一起发给模型,模型返回一个结构化的调用意图(函数名 + 参数 JSON),由你的代码解析、校验、真正执行,再把结果回填成一条消息。JSON Schema 干三件事:约束模型的生成空间(字段名、类型、枚举、必填项,减少它编造字段)、作为服务端入参校验的依据、同时也是给模型的文档——description 写得准不准,直接决定它选工具和填参数的准确率。流式 SSE 下工具参数的 JSON 是分片到达的,流中断在半截 JSON 时绝对不能执行:可能缺必填字段、也可能某个字符串被截断,执行等于拿幻觉参数去改数据。正确策略是按工具调用 id 把分片缓冲起来,用增量 JSON 解析器判断是否已完整闭合,只有解析成功且通过 Schema 校验才执行;不完整就按可重试错误处理(重新发起该轮,或降级为让模型重新输出参数),并且对有副作用的工具带幂等键,防止重试造成重复写入。
上下文超限与工具过多:四条路可以组合用。第一,压缩历史:把早期对话结构化摘要(目标、结论、未决事项),丢掉原文。第二,裁剪输入:工具返回只保留需要的字段、大文件分页读、长文本先摘要再进上下文,别把整份日志塞进去。第三,外置记忆:事实与知识写进向量库或文件,按需检索注入,而不是常驻上下文。第四,从工具侧治理:把工具按场景分组、按意图动态注册(先判断用户想干什么,只把候选工具给模型),或者把一批同质工具收敛成一个带 action 参数的统一入口,压缩工具定义占用的系统提示空间。更彻底的做法是用子 Agent 做隔离——把「工具多」这件事关进子上下文,主 Agent 只看到子 Agent 的结论,这样主链路的上下文增长与工具数量解耦。
多 Agent 的收益与派发:单 Agent 加多工具在工具数量上去之后有两个硬伤:工具定义把上下文吃掉,导致选错工具;长任务里中间结果污染上下文,主目标被冲淡。多 Agent 用「上下文隔离 + 职责拆分」换这两个问题,主 Agent 负责规划与汇总,子 Agent 各带一小撮工具和专属提示词。派发时不要平均分配:简单子任务交给便宜快的小模型或干脆用固定脚本,难题交给强模型并允许多轮尝试,路由依据是任务类型加预估复杂度。给子 Agent 的信息必须自包含:目标与验收标准、必要的背景事实、可用工具的边界、输出格式,以及步数与时间预算,同时明确它不能做什么(权限范围)。协调靠共享产物(文件、结构化黑板)而不是让 Agent 之间自由聊天——自由聊天会把隔离又破坏掉;主 Agent 负责校验每个子结果、决定重派还是采纳。
HashMap 的线程安全改造:HashMap 是数组 + 链表 + 红黑树:按 hash 定位桶,冲突挂链;链表长度到 8 且数组容量 ≥ 64 时转红黑树,元素降到 6 退回链表;扩容翻倍,JDK 8 用高低位拆分避免重算 hash。它线程不安全:并发 put 会丢更新(两个线程读到同一个桶头再各自挂链),JDK 7 的头插在并发扩容时还可能成环导致 CPU 打满,JDK 8 改尾插解决了环但依然会丢数据。如果不用现成并发容器而要自己改造,思路是拆锁粒度 + 保证可见性:要么分段锁(每段一把锁,等价于自己实现一遍 JDK 7 的 ConcurrentHashMap),要么 CAS 加只锁单个桶头(JDK 8 的做法),桶头与节点 next 用 volatile 保证可见性,扩容时用状态位做协作式迁移(多线程一起搬)。面试想听的是你理解「锁粒度」和「可见性」这两个要害,答的时候要顺带说清自研的代价——内存开销、复杂度、扩容协作难写难测,所以生产上直接用 ConcurrentHashMap 更划算(读基本无锁,写只锁桶)。