蚂蚁集团大模型算法岗面经 01:多模态与 Agent 合集
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
面经 01 · 多模态算法(2026-08-20)
- 介绍项目
- 为什么多模态模型在票据场景中容易出现「看起来正确但实际错误」的结果?
- 多模态训练中,为什么需要区分图像级、区域级和 token 级监督?
- SFT 和偏好优化阶段的 batch size 过大或过小,会造成什么问题?
- 为什么某些多模态训练会使用反向 KL,而不是正向 KL?
- GRPO 和 DAPO 的核心差异是什么?多模态场景如何改造?
- 多模态模型做 RL 训练时,如何防止奖励黑客?
- 多模态模型中的视觉 token 压缩为什么可能损失关键字段?如何改进?
面经 02 · 智能体与大模型应用工程(2026-06-11)
- 项目中本地缓存和 Redis 二级缓存的设计,你认为哪些链路会使用这个本地缓存?
- 缓存的更新是怎么想的?
- 本地缓存的过期时间大概是多久?
- 你认为用户量多少、什么场景下会用到两级缓存这种复杂的方案?
- 你用 MQ 去做异步订单,是怎么在自己的电脑上测试这一块的?
- 怎么保证 MQ 的消息只被接收一次?
- 什么场景下只处理一次?
- 秒杀的时候你 Redis 中的集合是一直都有效的吗?
- 假如你想要删这个 set,但在你要删的时候服务挂掉了,这种情况怎么办?
- 对于个人订单的数据,你认为应该持久化在 DB 中还是 Redis 中?
- Redis 的持久化有研究过吗?
- 智能体项目为什么使用 Spring AI 框架,而不用 Python 的那些框架?
- 你去比较过用 Java 以及其他语言实现同一个模块之间的复杂度吗?
- 你认为 Java 跟 Python 比起来,它的优势是什么?
- 项目中 RAG 是怎么设计的?
- 对于 RAG 知识库,一般情况下你是怎么往里面导入数据呢?是在另外一个入口吗?
- 智能体多轮对话的循环框架用的是哪个?
- 你觉得用 Java 做的话,怎么让 CPU 的利用率提高?Spring AI 这个选型你觉得它的优势在哪?
- 你这个项目里调用的模型是什么?
- 国内的大模型厂商和大模型都有哪些?
面经 03 · AI 应用研发(2026-05-30)
- agent 架构选用 LangGraph 或 LangChain 的原因是什么?核心考虑了框架的哪些优点?
- 工具链的具体流程主要是哪些节点?
- 工具会不会有响应比较慢的情况?这种异常情况如何处理?
- 日志查询如果时间跨度大或关键词没包括,怎么处理?
- RAG 里面的 TOPK 是什么样的?为什么是这个设置?
- TOP3、TOP5 哪个效果好一点?好在哪里?
- 检索或召回阶段有没有做哪些优化或不同方案的比较?
- 混合检索设计了哪些检索模式?各自是怎么样的排序或占比?
- 评测主要是评测什么维度(除了语料相关性)?
- 语料库大概是怎样的一个大小?涉及哪些文档或格式?
- 如果再做一套企业级的类似技术栈项目,大概要花多久?
- 模型训练项目主要做什么内容?
- 奖励模型主要在哪个训练阶段用?
- PPO 和 GRPO 是用在哪个阶段?
- 经过几个训练阶段各都有哪些提升?有没有效果的衡量指标?
- 对 GQA、kvcache 这些专业名词哪个印象比较深?可以稍微展开一下吗?训练过程中都有用到这些技术吗?
- 手撕:数组中满足其总和大于等于 target 的长度最小的子数组的长度
面经 04 · 智能体与大模型应用(2026-05-26)
- 如何解决大模型幻觉?
- 对模型微调那些算法了解吗?
- 项目的 skills 是怎么实现的?你是怎么写 skills 的?
- Spring AI 框架的 skills 调用更像 Claude Code 还是其他 Harness Agent?
- 你说看过 Claude 源码,Claude Code 学习经验总结?
- Claude Code 是给模型用 grep 检索,没有用 RAG 检索,这俩有什么区别?为什么没用 RAG?
- 讲讲 RAG 的混合召回
- URL 解析过程
- TCP 三次握手、四次挥手
- MySQL 的数据结构,讲讲 B+ 树
- Spring 的控制反转、AOP
- 你平时用什么做 AI coding?
面经 05 · 大模型算法(2026-05-08)
- 介绍第一个项目,追问实现细节
- 脑机接口是如何做的?如何处理时序数据?
- AI coding 一般怎么用?
- 介绍 DPO、PPO、GRPO
- 介绍 Dify 平台
- 介绍 Ms-swift 平台
- Flash Attention 原理
- 手撕:对着屏幕用 PyTorch 实现一个神经网络
- 如何训练模型学会论文翻译的风格?
- 第二个项目的 query 和论文总结是如何匹配搜索的?
- 开放题:如何训练一个信贷系统,输入个人信息,可以输出意见和额度?
面经 06 · 大模型算法(2026-05-03)
- 实习拷打:实习项目具体做了哪些内容?
- 依次介绍项目
- 当时大家都在做 RL,为什么我们还在 SFT?
- 这里面最大的问题是什么?有什么困难?
- 你觉得还有其他亮点可以说说吗?
面经 07 · 大模型推理 AI Infra(2026-05-02)
- 做过哪些相关工作?看过哪些经典文章?参与过哪些开源项目?
- 为什么要做 Prefill 和 Decode 分离?追问:PD 到底争夺什么资源?和「直接多给卡、资源翻倍」相比本质差异是什么?
- AF 分离的好处和坏处?
- 常见并行模式怎么看?怎么根据具体场景选择合适的并行模式?选择因素有哪些?
- 追问:Prefill、Decode 与 Attention、MOE 这四种组合,分别更适合什么并行策略?
- 你觉得一个优秀的大模型推理框架,核心技术点有哪些?追问:量化选择策略
- GEMM 核心优化方法,ncu 怎么用?
- 拷打算子项目,MLIR / LLVM 理解
面经 08 · AI 应用研发(2026-04-30)
- 你做的两个小项目分别是什么?
- 你之前做的这个高并发 AI 聊天系统,具体是一个什么产品?
- 它和 ChatGPT 这类聊天产品相比,有什么不同?
- 你当时在设计这个聊天系统时,上下文管理和 prompt 注入时机是怎么设计的?
- 你用过 Claude Code、Codex 这类 AI IDE 或者 AI 编程工具吗?
- 你主要是用它们的 CLI、桌面端,还是网页版?
《参考解析》
1. 票据场景「看起来正确但实际错误」的成因:多模态模型有很强的版面与语义先验,容易顺着「一张像发票的图应该长什么样」去补全,而不是逐字段核对图像内容,于是金额大小写不一致、税号或日期错一位(8 看成 3、O 与 0、1 与 7)、明细合计对不上、购方销方串位这类错误非常常见,而且输出读起来完全通顺。根因有三层:视觉编码器分辨率与 patch 粒度不足以看清小号字与印章;端到端损失里关键字段的字符级正确率没有被直接优化;训练数据以「格式正确」的合成票据为主,模型学到的是模板而不是校验。治理手段对应三层:关键区域高分辨率切图或先定位再识别,做字段级结构化监督,关键数字加 token 级 loss 权重,最后再叠一层规则校验(大小写金额互验、合计等于明细加总、日期与税号格式校验)并把校验失败回退到人工或重新识别。评测也要换成字段级准确率,而不是整串完全匹配。
2. 图像级、区域级与 token 级监督的分工:图像级监督(整图对应一段描述、一个问答答案或一个偏好排序)便宜、覆盖任务语义与指令跟随,能约束全局正确性,但信号太粗,局部错一个数字照样拿高分。区域级监督(bbox、版面元素、字段框)把监督对齐到实体,教模型「哪个像素区域对应哪个字段」,是 grounding 能力的来源,对票据、文档、GUI、图表这类结构化场景几乎是必需的。token 级监督最细,直接决定字符准确率与坐标回归精度,也是抑制「数字幻觉」的唯一有效粒度。三者的正确关系是分工而不是替代:图像级给任务定义和偏好排序,区域级给空间对齐,token 级给细粒度准确率。只在图像级上做偏好优化,几乎必然训出「描述全面、关键字段乱写」的模型。
3. SFT 与偏好优化阶段的 batch size:SFT 阶段 batch 太小,梯度噪声大、loss 剧烈抖动、对学习率敏感、吞吐低,多模态样本还容易出现长答案或高分辨率图主导一个 micro-batch;batch 太大则泛化变差(大 batch 倾向收敛到尖锐解),等效学习率需要同步放大,显存也扛不住,通常要靠梯度累积、序列 packing、序列并行来折中。多模态还要特别注意不同分辨率的样本显存峰值差异大,梯度累积时按 token 数加权而不是按样本数平均,否则长答案样本的梯度被稀释。偏好优化阶段的问题正好相反:DPO 这类方法靠对内的相对差构造隐式奖励,batch 太小则这个差值的估计方差极大、梯度不稳;GRPO 的组内均值方差归一化在组大小太小时 advantage 偏差明显。batch 太大又会让同一 prompt 上的 on-policy 分布变化过快、重要性采样比失真,需要配合 clip、更小的学习率和更频繁的校正。实践上 SFT 用大 batch 加 warmup 与 token 级加权,RL/偏好优化用小 batch 加组内多次采样。
4. 反向 KL 与正向 KL 的区别:RLHF 类目标通常是最大化期望奖励再减去对参考模型的 KL 约束,方向选哪个决定了策略的行为。反向 KL(π 对 π_ref 的 KL)是 mode-seeking,惩罚的是「策略在参考模型概率很低的地方放质量」,会把分布收拢到参考模型的少数高概率模式上,生成更尖锐、更不容易发散;正向 KL(π_ref 对 π 的 KL)是 mass-covering,要求策略覆盖参考模型的全部模式,会把概率质量摊平,在多模态生成里容易变成「什么都有可能」的平庸描述。偏好优化普遍选反向 KL,是因为它天然对应信任域:只允许在参考模型本来就不错的模式里挑更好的那个,训练更稳、不容易为了刷奖励跑到分布外,同时保留一定熵。正向 KL 更适合蒸馏和变分推断那种要求覆盖面完整的场景。多模态场景还有一个额外好处:视觉输入模糊时,反向 KL 会抑制模型「发散地编造」多种互相冲突的描述。
5. GRPO 与 DAPO 的核心差异:GRPO 去掉了 PPO 的 value network,对同一个 prompt 采样一组 G 个回答,用组内奖励的均值和标准差归一化得到 advantage,省掉 critic 的显存与训练成本。它的两个已知毛病是:组内全对或全错时标准差为零,advantage 全为 0、梯度消失,训练被简单题和废题吃掉;以及按样本长度平均会系统性偏向长回答。DAPO 在这两点上做了四组改动:解耦上下裁剪系数(clip-higher),抬高上界以维持熵、避免策略过早坍缩;动态采样,过滤掉全对和全错的 prompt 组,只保留中间难度以保证有效梯度;token 级 loss,按 token 而非按样本长度归一化,缓解长度偏差;超长与软长度惩罚,处理被截断的样本、不给「写得长就分高」留口子。多模态改造的要点是:奖励要换成视觉相关且可验证的信号(字段准确率、OCR 交叉核对、坐标 IoU、工具执行结果),rollout 时的图像分辨率与预处理必须和训练一致,token 级归一化要把视觉 token 排除在文本 loss 之外,长度惩罚还要防住「用大段无关文字描述图片」这种刷分方式。
6. 多模态 RL 中的奖励黑客与防御:奖励模型学到的往往只是相关性——回答更长、术语更多、格式更整齐、出现某些关键词就被判为好答案,策略很快会找到这些漏洞:堆长度、复述图片内容、把格式写得漂亮但内容错,甚至完全不看图也能拿高分。防御的第一原则是尽量用可验证奖励替换学出来的奖励:规则与程序化校验(字段格式、金额互验、代码单元测试、工具执行成功)、OCR 或另一模型做交叉核对、多奖励模型集成投票。第二是持续审计:定期用新标注数据检查奖励模型与策略的一致性,监控奖励曲线与真实评测集的分化。第三是约束优化空间:长度分箱归一化与长度惩罚、KL 或信任域约束、保留 held-out 真实评测。多模态还必须做「图像扰动测试」:遮住关键区域或改掉一个数字,如果奖励不下降,说明模型根本没在依赖视觉输入,此时无论 reward 多高都是假的。
7. 视觉 token 压缩为什么会丢关键字段:高分辨率图像切成 patch 后 token 数随面积增长,推理成本难以承受,所以普遍用 pooling、pixel-shuffle、Q-Former 或 Perceiver 重采样把视觉 token 压到几百个。问题是压缩对高频细节是无差别抹平的,而票据的关键字段往往只占一两百像素(小号数字、密集表格线、印章、手写签名),压缩后这些区域的信息先被平均掉,模型只能靠语言先验猜,于是出现「看图也对、答得也顺,就是数字错」。改进方向:自适应压缩率,按版面检测、文本密度或 OCR 置信度给区域分配 token 预算,关键字段区域保留原分辨率、背景纯色区域多压;多尺度特征并存,全局低分辨率加局部高分辨率裁剪;把 OCR 文本作为旁路 token 与视觉 token 拼接,让模型至少有精确文本可用;训练时对关键字段的 token 级 loss 加权,让优化目标明确惩罚压缩带来的信息损失;压缩后位置编码要做相应的坐标映射,否则 grounding 会整体错位。
8. 本地缓存与 Redis 二级缓存的设计:本地缓存(Caffeine、Guava)适合「读多写少、变更不频繁、能容忍秒级不一致、热点集中」的数据,典型如商品详情、库存快照、用户基础资料、字典与配置、权限元数据;订单、余额这类强一致数据不该放本地。更新策略以 Cache-Aside 为主:写库成功后删缓存而不是更新缓存,避免并发写导致新旧值乱序覆盖;本地缓存的失效靠 MQ 广播失效消息给所有实例,或者带版本号(缓存值里编码 version,读时对比 Redis 中的最新版本,落后就回源)加短 TTL 兜底。TTL 分层:本地 5 到 30 秒(安全要求高就压到秒级),Redis 几分钟到几十分钟,并加随机抖动防雪崩。是否值得引入两级缓存要看 QPS 是否已经让 Redis 网络往返成为瓶颈、热点是否足够集中:只有当少数 key 承担大部分读流量时,本地缓存的收益才盖得住多实例不一致带来的排查成本,否则单层 Redis 更省事。
9. MQ 幂等与「只消费一次」:主流 MQ 只承诺至少一次投递,所以「只被消费一次」必须在业务侧靠幂等实现,而不是指望中间件。做法是用唯一业务键(订单号加状态版本)建去重表或唯一索引,插入冲突即视为重复投递直接 ACK;或用 Redis SETNX 加状态机 CAS,把「判断是否处理过」和「更新状态」放在同一个事务或 Lua 脚本里保持原子;消费成功后再手动 ACK,失败进重试队列、超过次数进死信并告警。真正需要「只处理一次」语义的是有副作用的操作——扣款、扣库存、发券、发通知,纯查询可以重复执行。本地测试这一块,实用做法是用 Testcontainers 或 Docker 起真实的 RocketMQ / Kafka,直接调用消费者方法并人为制造重复投递、乱序、消费者中途抛异常和 broker 重启,用拦截器或日志统计实际处理次数;只测 happy path 是测不出幂等 bug 的。
10. 秒杀场景 Redis set 的有效期与容灾:秒杀用的用户去重集合不能简单地「永不过期」,否则内存随活动数量线性增长;设 TTL 又要小心活动跨零点或提前预热时 key 消失导致重复下单。常见做法是 key 按活动维度命名(活动 ID 入 key),活动结束后异步清理。至于「删到一半服务挂了」,本质原因是删除不是原子的:集合元素多时 SREM 只能分批,可能删掉一部分后进程退出,状态就变成「有的用户能再买、有的不能」。真正的兜底是不把 Redis 当真相源:用户是否已下单以 DB 的唯一索引(用户 ID 加活动 ID)为准,Redis 只是前置拦截层,库存扣减用 Lua 保证原子、订单异步落库,重启后按 DB 对账重建集合。工程上还常用「先改名再后台删」避免大 key 阻塞主线程,或用 UNLINK 异步删除,并对大 key 做拆分。
11. Java 与 Python 的选型,以及 Spring AI 的取舍:Java 的优势在工程侧:Spring 的事务、依赖注入、AOP、配置中心、Micrometer 可观测性、成熟的线程池与 JUC、JVM 的 JIT 与 GC 调优、长稳运行的运维工具链,加上团队存量系统和公司内网权限、审计、网关的接入成本低,类型系统也利于长期重构。Python 的优势在模型侧:PyTorch、Transformers、vLLM、评测工具与最新论文实现基本都首发在这里,迭代速度快。智能体项目选 Spring AI 通常是「必须与既有 Java 微服务同栈」的结果,好处是复用 Spring 的 HTTP 客户端、重试、熔断、指标与灰度能力,代价是模型生态和社区示例明显落后。多轮对话的循环框架,Python 侧主流是 LangGraph 的显式状态图加 checkpoint 持久化与中断恢复;Java 侧则多是 Spring AI 的 advisor 机制加自研状态机。要提高 CPU 利用率,思路是 IO 密集任务用虚拟线程或异步化、把模型流式输出与工具调用并行、对工具做批量化与结果缓存,而不是盲目加线程数。
12. RAG 的 TOPK 与混合检索:TOPK 不是越大越好:召回变多会引入噪声、拉长上下文、推高成本,还会因为关键信息落在中间位置而被稀释。常见起点是单跳事实型问答 k 取 3 到 5,多跳或汇总型问题取 5 到 10,更稳的做法是两段式——粗召回 20 到 50 条,再用 rerank 模型(cross-encoder 或 LLM 打分)截到 3 到 5 条。TOP3 与 TOP5 谁更好取决于问题类型和 rerank 质量,应该在自己的评测集上扫一遍再定,而不是凭感觉。混合检索的模式一般包含:BM25 或稀疏向量负责精确术语、编号、报错码,稠密向量负责语义改写,外加结构化过滤(时间、权限、标签);融合常用 RRF(按排名倒数相加,不需要归一化、跨检索器可比)或加权线性融合(需要先归一化分数)。评测维度除语料相关性外,还要看召回率与命中率、上下文相关性、忠实度(答案是否有引用支撑)、答案相关性、幻觉率,以及业务维度(格式正确、可直接执行、引用可点开),通常用 LLM-as-judge 大规模跑、再人工抽检校准评委。
13. Prefill 和 Decode 分离到底在争什么资源:Prefill 是计算密集型(长序列的大 GEMM,打满算力,能效高,对显存带宽相对不敏感),Decode 是访存密集型(每步只生成一个 token,却要反复读 KV cache 和权重,算术强度极低,瓶颈在 HBM 带宽和 KV cache 显存占用)。两者混布在同一张卡上会互相干扰:长 Prefill 任务把 Decode 的 TPOT 拖出抖动、尾延迟不可控,而它们各自最优的并行策略也不一样(Prefill 适合张量并行或序列并行放大算力,Decode 适合按 KV 分片或数据并行摊带宽与显存)。PD 分离就是把两类负载拆到不同实例池,各自按自己的瓶颈扩缩容,中间传 KV cache(此时 KV 传输带宽成为新瓶颈,要靠 RDMA / NVLink、分层传输和 prefix cache 复用来摊薄)。和「直接多给卡、资源翻倍」的本质差异在于:加卡只是把同一份混合负载摊到更多硬件上,干扰和尾延迟依然存在,通信占比上升后甚至更差,利用率也不会变好;PD 分离改变的是资源配比与调度粒度,让算力和带宽各自按需分配,本质是异构负载拆分加池化调度。
14. GQA 与 KV cache:KV cache 是自回归解码时缓存历史 token 的 K、V,避免每步重算历史,显存占用正比于层数 × 头数 × head_dim × 序列长度 × batch × 数据类型字节数,长上下文大 batch 下它会比模型权重还大,直接决定吞吐上限。MQA 让所有 query head 共享一份 K、V,最省显存但质量掉得明显;GQA 是折中,把 query head 分成若干组、组内共享一份 K、V,显存与带宽降到 MHA 的 1/G 而质量接近,解码阶段每步要读的 KV 变少,收益直接体现在带宽瓶颈上,同时允许更大 batch。训练侧 GQA 影响的是 attention 参数量与前反向计算,通常从头训练,或把 MHA 的 K、V 头做均值池化初始化再继续预训练。压成本还有一整套配套:KV cache 量化到 INT8 或 FP8、PagedAttention 按块分配减少碎片、prefix cache 复用公共前缀、投机解码提高每步产出。训练过程中一般不使用 KV cache,靠 FlashAttention 的分块计算加反向重算避免物化整个注意力矩阵,省的是显存而不是带宽。
15. 大模型幻觉,以及为什么代码检索用 grep 而不是 RAG:幻觉的来源是训练目标只优化似然、不区分「不知道」,加上长尾知识不足、上下文缺失时仍要输出流畅答案。工程手段是按层叠加:检索增强把答案锚定在证据上并强制给出引用,用「资料中没有」类样本做 SFT 允许模型拒答,工具调用与代码执行做事实校验,结构化输出加规则校验,解码侧用受限解码和引用回链。至于 Claude Code 这类编程 Agent 用 grep 检索而不用向量 RAG,是因为代码里的关键线索是精确符号——函数名、变量名、报错码、路径——精确匹配比 embedding 相似度更准;grep 零索引成本、随工作区实时变化、结果可解释可验证,而 RAG 需要维护索引与失效逻辑,还会把「最相关」变成概率性的近似匹配,往往漏掉真正的那一处调用点。二者并不互斥:超大规模代码库通常先做粗召回(符号索引或向量),再用 grep 精确定位,实际 Agent 更多是「grep 加读文件加迭代」的循环,把检索决策交给模型自己。