面试面经 · 图森未来
【图森未来】【Agent 开发】【暑期实习HR面】面经(八股+大模型项目+手撕)
海外一年制硕士,投递图森未来 Agent 开发暑期实习,HR 面后隔天收到一面邀约。整体流程是 HR 先电话沟通约 30 分钟,确认基本信息、项目经历和技术栈匹配度,随后安排技术一面。以下按考点维度复盘。
题目摘要
- Go 语言基础:goroutine 与 channel 的底层实现,
select多路复用的随机性,sync.Map与普通 map 加锁的取舍场景。 - MySQL / Redis 八股:InnoDB 聚簇索引与回表,MVCC 版本链 + Read View 如何实现可重复读;Redis 缓存穿透/击穿/雪崩的区分与各自解法,以及 Redis 分布式锁的续期问题。
- Agent 项目深挖:RAG 检索链路的分块策略、召回评估,Function Calling 的 schema 设计与失败重试,多轮对话的上下文窗口管理。
- 推理成本优化:如何在不显著掉点的前提下降低 token 消耗与延迟,prompt 缓存、模型分级路由、结果缓存的实际效果。
- 手撕算法:LRU 缓存(LeetCode 146),要求 O(1) 的 get 和 put。
- 行为面:为什么选 Agent 方向、实习时长能否保证、对自动驾驶 + 大模型结合的理解。
技术考点展开
Go 语言。面试官没有停留在语法层,而是问「channel 底层是什么数据结构」。参考方向:channel 本质是 hchan 结构体,内部维护环形缓冲区 buf、发送/接收等待队列 sendq/recvq(sudog 链表)和一把互斥锁。无缓冲 channel 的发送会直接阻塞直到有接收方,本质是 goroutine 的 park/unpark。select 在多个 case 就绪时通过 fastrand 随机选一个,避免饥饿。sync.Map 适合读多写少、key 相对稳定的场景,内部用 read + dirty 双 map 做读写分离,写多时退化为普通 map 加锁,反而更慢。
MySQL / Redis。MVCC 是高频题:每行有隐藏的 DB_TRX_ID 和 DB_ROLL_PTR,回滚指针串成版本链;Read View 记录当前活跃事务集合,通过可见性判断决定读哪个版本,RC 每次查询生成新 Read View,RR 只在首次查询生成,这就是两者隔离级别差异的根源。Redis 三兄弟要能一句话区分:穿透是查不存在的数据(布隆过滤器 / 空值缓存),击穿是热点 key 过期瞬间(互斥锁重建 / 逻辑过期),雪崩是大量 key 同时失效(过期时间加随机)。分布式锁要提到 setnx + 过期时间 + 唯一 value 释放,以及 Redisson 看门狗续期的原理。
Agent 项目深挖。这部分占比最重,面试官会顺着简历一路追问到底,见下一节。
项目深挖
追问一:你的 RAG 检索为什么用这个分块大小?怎么评估召回质量?
参考回答方向:不要只说「按 512 token 切」。要讲清楚分块策略与文档类型的关系——结构化文档按标题层级切,长文本用滑动窗口加重叠避免语义截断。评估上,构造一批「问题-标准答案」对,看召回文档是否包含答案片段,算 Recall@k 和 MRR;再人工抽样看 bad case 是分块问题还是 embedding 问题。如果提到 rerank 模型,要能说清它和向量召回的召回率/精度权衡。
追问二:Function Calling 如果模型返回的参数格式不对,你怎么处理?
参考回答方向:分三层。第一层在 schema 上用 JSON Schema 严格约束字段类型和枚举,减少模型自由发挥;第二层做解析兜底,JSON 解析失败时用正则或修复 prompt 让模型重出;第三层设置最大重试次数,超过就降级到规则匹配或直接返回错误给用户。要强调「工具调用的幂等性」——重试时不能让有副作用的工具重复执行,需要引入 request_id 去重。
追问三:多轮对话上下文越来越长,你怎么控制成本?
参考回答方向:一是分层记忆,最近 N 轮保留原文,更早的做摘要压缩;二是把稳定的 system prompt 和工具定义放到支持 prompt caching 的位置,命中缓存的部分成本大幅下降;三是模型分级路由,简单意图用小模型,复杂推理才上大模型。可以补充一个量化视角:统计线上 P50/P99 的 token 数和延迟,找到成本大头再针对性优化,而不是盲目砍上下文。
手撕算法
LRU 缓存:设计一个数据结构,容量为 capacity,支持 get(key) 和 put(key, value),两者都要求 O(1)。超出容量时淘汰最久未使用的 key。
关键思路:哈希表 + 双向链表。哈希表存 key 到链表节点的映射实现 O(1) 查找,双向链表维护访问顺序,头部是最近使用、尾部是最久未使用。get 命中后把节点移到头部;put 时若 key 存在则更新并移到头部,不存在则新建插入头部,若超容量删除尾部节点并同步删哈希表。用 Go 实现时可以用 container/list 快速搭,但要能说清为什么不用单向链表(删除尾节点需要前驱指针)。面试官可能追问并发场景怎么办,答加锁或分片即可。
准备建议
- 把简历上的 Agent 项目拆成「决策点」:每个技术选型都准备一个「为什么这么选、替代方案是什么、效果差多少」的回答。面试官不关心你用了 LangChain,关心你为什么在某个环节不用它。
- 八股按「一句话结论 + 底层原因 + 适用场景」三段式背:比如 MVCC 不要只背定义,要能画出版本链和 Read View 的判断流程,这样追问时才不会卡壳。
- 手撕题限时练:LRU、LFU、TopK、限流器这类「数据结构设计题」是 Agent/后端岗高频,用白板或纯文本编辑器练,不要依赖 IDE 补全,控制在 15 分钟内写完并自测边界。
HR 面当天沟通顺畅,第二天收到技术一面邀约,间隔约 3 天。
想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。