面试面经 · 字节跳动
【字节跳动】【Agent 开发】【暑期实习三面】面经(八股+大模型项目+手撕)
背景
海外一年制硕士,投递字节跳动 Agent 开发暑期实习,三面为技术终面,面试官为部门技术负责人,全程约 70 分钟,整体风格偏工程落地与系统设计,八股占比低于一面,项目深挖与场景设计占比极高。
题目摘要
- Go 语言基础:Goroutine 与 Channel 的底层实现区别,什么时候用 Mutex 而不是 Channel。
- MySQL 与 Redis 八股:MySQL 的隔离级别与 MVCC 实现原理;Redis 的持久化机制对比(RDB vs AOF),以及缓存穿透/击穿/雪崩的应对方案。
- Agent 项目深挖:围绕 RAG 检索召回质量、Function Calling 的容错处理、多轮对话上下文管理与推理成本优化展开连环追问。
- 手撕算法题:实现一个带过期时间的 LRU 缓存(LRU with TTL)。要求先讲思路,再写代码,最后分析时间/空间复杂度。
项目深挖
追问 1:你的 RAG 方案里,检索召回率不高时,除了调 chunk_size 和 top_k,还做了哪些优化?
参考回答方向:不要只说“调参”。我实际做了三层优化:第一层是查询改写,对用户原始 query 做意图识别,拆解为多个子查询分别检索后合并结果;第二层是混合检索,结合 BM25 稀疏检索和向量稠密检索,用 RRF(Reciprocal Rank Fusion)做分数融合,解决了纯向量检索对专有名词不敏感的问题;第三层是重排序,用 cross-encoder 模型对召回的前 50 条结果精排,最终只取 top 5 送入 LLM。面试官会追问“重排序模型的推理延迟如何控制”,可以答用小型 distilled 模型,批量推理,且只对 top 50 做精排,整体延迟增加约 80ms,可接受。
追问 2:Function Calling 场景下,如果模型返回的 JSON 格式不合法或参数缺失,你怎么处理?
参考回答方向:核心是“防御性解析 + 多级回退”。第一层用正则或 JSON parser 做语法校验,失败则直接抛给模型要求重新生成,并附上错误信息作为 prompt 的一部分;第二层是 schema 校验,用 JSON Schema 验证必填字段和类型,缺失时尝试从对话上下文中推断补全,推断失败则返回用户澄清问题。第三层是设计了一个“函数执行沙箱”,所有外部 API 调用都加超时和熔断,避免单次 tool call 阻塞整个 Agent 循环。另外,我在 prompt 中强制要求模型输出严格的 JSON 格式,并在 few-shot 示例中加入了失败案例,显著提升了首轮解析成功率。
追问 3:多轮对话上下文管理上,怎么控制 token 成本?
参考回答方向:不能简单用“滑动窗口截断”。我做了分层上下文管理:短期记忆(最近 3 轮完整对话)用高精度 embedding 存储;中期记忆(用户意图、关键实体、已确认信息)用结构化摘要存储,每轮对话后用 LLM 异步压缩更新;长期记忆(用户偏好、历史任务结果)存入向量数据库,按需检索。同时,对每轮 tool call 的输入输出做了 token 级裁剪,只保留关键字段。这样整体 token 消耗降低了约 40%,且关键信息召回率没有明显下降。面试官可能追问“异步压缩的延迟怎么处理”,可以答用独立队列异步执行,不阻塞主对话流程,用户无感知。
手撕算法题:带过期时间的 LRU 缓存
题意:设计一个数据结构,支持 get(key) 和 put(key, value, ttl) 操作。get 时若 key 不存在或已过期返回 -1;put 时若 key 已存在则更新 value 和过期时间,若缓存满则淘汰最久未使用的 key(即使未过期也要淘汰)。
关键思路:核心是“两个维度”的管理——访问时间(LRU)和绝对过期时间(TTL)。我用了哈希表 + 双向链表(O(1) 访问和淘汰),同时每个节点额外存储 expireAt 时间戳。get 操作时先检查当前时间是否大于 expireAt,是则删除节点并返回 -1,否则移动节点到链表头部。put 操作时若 key 存在,更新 value 和 expireAt,并移到头部;若不存在,先检查容量,满了则删除链表尾部节点(同时从哈希表删除),再插入新节点到头部。为了处理过期 key 的主动清理,可以在 put 时顺带检查链表尾部是否过期,惰性删除即可,不需要额外后台线程。
复杂度:get 和 put 均为 O(1) 平均时间复杂度,空间复杂度 O(capacity)。面试官会追问“如果过期 key 很多但一直没有被访问怎么办”,可以答在 put 时如果发现尾部节点已过期,连续删除所有过期节点,直到遇到未过期节点,保证过期数据不会长期占用容量。
准备建议
- 项目深挖不要只准备“做了什么”,要准备“失败了怎么排查” 。面试官对于 Agent 项目的追问,几乎全部集中在“召回不准怎么办”“模型输出格式错乱怎么办”“token 超预算怎么办”这类异常处理上。建议把你项目里每个模块的 failure mode 列出来,逐个想好兜底策略和量化指标(如解析成功率从 70% 提升到 95%)。
- 手撕题要练“带业务约束的变种题” 。纯 LRU 太常见,字节面试喜欢加 TTL、加并发安全、加批量操作等变种。建议把 LeetCode 146 的解法吃透,然后自己扩展实现 LRU + TTL、LFU + 过期时间、以及支持并发读写的版本(用 sync.RWMutex 或分段锁)。写完后一定要自己讲一遍复杂度分析。
- 八股要按“为什么”和“对比”来准备。比如 MySQL 的 MVCC,不要只背 undo log 版本链,要能说清楚 RC 和 RR 下快照读的区别以及当前读的实现差异;Redis 持久化不要只背 RDB/AOF 的优缺点,要结合“数据丢失容忍度”和“恢复时间”来选型。面试官会顺着你的答案往下追问,所以每个知识点要准备两层深度。
结果反馈
三面通过,约 3 天后 HR 通知进入 HR 面,整体流程推进速度很快。
想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。