NiceOffer

面试面经 · 黑芝麻智能

【黑芝麻智能】【大模型开发】【暑期实习二面】面经(八股+大模型项目+手撕)

黑芝麻智能面经大模型开发实习

背景

海外一年制硕士在读,投递黑芝麻智能大模型开发暑期实习,二面为技术面,时长约 50 分钟,面试官为部门技术负责人,全程无闲聊,节奏紧凑。

题目摘要

  1. Go 语言基础:goroutine 与 channel 的底层实现,select 的随机选择机制,以及 map 并发读写 panic 的原因与解决方案。
  2. MySQL/Redis 八股:MySQL 事务隔离级别与 MVCC 实现原理;Redis 持久化机制(RDB/AOF)对比及混合持久化。
  3. 大模型项目深挖:围绕 RAG 项目的 chunk 切分策略、检索召回优化、Function Calling 的容错处理、上下文窗口管理及推理成本优化。
  4. 手撕算法:实现一个带过期时间的 LRU 缓存(LRU with TTL),要求 get/put 均为 O(1) 复杂度,过期 key 在访问时惰性删除。

项目深挖

追问一:你的 RAG 项目在 chunk 切分时如何避免语义断裂?如果检索效果不好,你会怎么排查?

参考回答方向
先说明切分策略的演进——从固定长度切分到按段落/标题结构切分,再到引入重叠窗口(overlap)保留上下文。若效果不好,我会按以下顺序排查:

  1. 检查 embedding 模型是否与领域文本匹配(比如代码文档用通用 embedding 效果差);
  2. 检查检索召回率,用 hit rate 指标评估,若召回不足则调整 top-k 或改用混合检索(BM25 + 向量);
  3. 检查 rerank 环节,是否因相关性排序不准导致噪声进入上下文;
  4. 最后检查 prompt 构造,是否因上下文过长导致模型注意力分散。

追问二:你的 Agent 项目里 Function Calling 的容错是怎么设计的?如果模型返回了不存在的函数名怎么办?

参考回答方向
先说明整体流程:系统 prompt 中注入函数 schema,模型输出结构化 JSON,解析后做参数校验再执行。容错设计分三层:

  1. Schema 校验:用 JSON Schema 校验函数名和参数类型,不合法则直接拒绝执行并返回错误信息给模型,让模型重新生成;
  2. 重试机制:同一轮对话最多重试 2 次,若仍失败则降级为普通文本回复,避免死循环;
  3. 兜底策略:维护一个「模型幻觉函数名」映射表,将常见错误名映射到正确函数,减少无效调用。

额外补充:每次函数调用的输入输出都会记录到日志中,用于后续微调或规则优化。

追问三:你的项目里如何控制推理成本?如果用户量放大 10 倍,你的方案有什么瓶颈?

参考回答方向
先说当前方案:

  1. 上下文压缩:对历史对话做摘要,只保留最近 N 轮完整对话 + 之前轮次的摘要;
  2. 缓存复用:对用户 query 做 embedding 相似度匹配,命中缓存直接用历史回答;
  3. 模型分级:简单问题用轻量模型,复杂任务才调用大模型。

然后说瓶颈:缓存命中率会随用户 query 多样化下降;摘要压缩会丢失细节导致回答质量下降;模型分级需要维护路由规则,本身有误判风险。放大 10 倍后,embedding 检索的 QPS 会成为瓶颈,需要引入向量数据库集群或做本地缓存。

手撕算法:LRU with TTL

题目:实现一个 LRUCache,支持 get(key)put(key, value, ttl) 操作,ttl 为过期时间(秒)。get 时若 key 已过期视为未命中,put 时若 key 已存在则更新值并重置过期时间。要求 getput 均为 O(1) 时间复杂度。

关键思路

  1. 使用哈希表 + 双向链表实现 LRU 基础结构,哈希表存 key 到链表节点的映射;
  2. 链表节点除了 key/value 外,额外存 expireTime(绝对时间戳);
  3. get 时先检查 expireTime 是否小于当前时间,若过期则删除节点并返回 -1;
  4. put 时若 key 存在,更新 value 和 expireTime,并移动到链表头部;若不存在,判断容量是否已满,满则淘汰链表尾部节点(同时从哈希表删除);
  5. 过期 key 采用惰性删除策略,仅在访问时清理,避免额外后台线程增加复杂度。

面试官追问:如果要求过期 key 也能被主动清理(比如内存敏感场景),你怎么改?
回答:可以增加一个最小堆(按 expireTime 排序),每次 put 时检查堆顶是否过期并批量删除,删除时同步移除哈希表和链表中的节点。代价是 put 操作从 O(1) 变为 O(logN),但内存释放更及时。

准备建议

  1. Go 语言重点复习并发模型:goroutine 调度(GMP 模型)、channel 底层结构(hchan)、sync.Map 适用场景。黑芝麻智能的后端大量使用 Go,面试官会从源码层面追问,建议看 runtime 包关键实现源码片段。
  2. RAG/Agent 项目准备「量化指标」:不要只说「用了 RAG 提升效果」,要准备具体数字——比如检索命中率从 70% 提到 85%,端到端回答准确率提升多少,推理延迟从多少降到多少。面试官会顺着数字追问方法论。
  3. 手撕题训练「带约束的变种题」:LRU 本身是高频题,但加了 TTL 后很多人会漏掉过期检查的时机。建议刷题时主动给经典题加约束条件(比如并发安全、过期时间、容量动态调整),并思考时间复杂度的变化。

结果反馈

整体面试偏工程实践,无八股背诵感,项目追问深度较大,手撕题在提示下完成。面试结束 2 天后收到 HR 通知,二面通过,约 3 天后进行三面(HR+主管面)。

想系统备战大厂大模型/Agent 开发?NiceOffer 提供 SDE+LLM 双轨 1v1 陪跑,合同保底 40w 年薪,文末扫码咨询。