小红书多模态算法秋招二面面经(约 40 题 + 手撕)
- 轮次
- 二面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 多模态大模型中,视觉编码器和 LLM 之间的连接方式有哪些?各有什么优劣?
- 为什么不用更简单的平均池化?
- 多模态模型产生幻觉的主要原因是什么?怎么通过后训练、RAG、规则缓解?
- 如果让你做小红书笔记的图文内容理解,怎么设计模型架构?
- 你做的多模态项目中,视觉编码器用的是什么?为什么选它?
- 多模态训练中,如果文本模态主导决策、图像被忽略,怎么发现和解决?
- 对比学习在图文匹配中怎么用?InfoNCE 的温度系数怎么调?
- 如果一篇笔记包含多张图片,怎么融合多图信息?注意力机制怎么设计?
- 你怎么评估多模态模型的内容理解效果?评测集怎么构建?
- 如果让你设计一个「内容安全审核 Agent」,怎么处理图文混合违规?
- 大模型 SFT 阶段,过拟合和欠拟合分别有什么表现?怎么调优?
- 你在大模型项目中为何选择或舍弃强化学习?PPO、DPO、GRPO 分别适用什么场景?
- 大模型训练中出现内容复读、语句冗余,核心成因是什么?从数据、算法、参数三个维度怎么优化?
- 大模型训练中出现 OOM,你常用的显存优化技术有哪些?
- 简述主流 Agent 的核心组成架构。LangGraph 在落地应用中的短板是什么?
- 多智能体协作场景中,如何设计通信机制和任务分配策略?
- 你怎么看 RAG 和长上下文模型的关系?会互相替代吗?
- 如果让你优化小红书搜索的 Query 理解,你会用大模型做什么?
- 你平时怎么跟进 AI 前沿技术?最近读过什么有意思的论文?
- 如果让你从零做一个多模态内容理解 Agent,技术选型是什么?
- 小红书的笔记有很多短文本加图片,怎么设计模型?
- 如果让你做「笔记推荐理由生成」,怎么保证吸引人且不重复?
- 多模态模型在移动端部署,怎么优化推理速度?
- 如果让你设计一个「封面图质量评估」模型,你会怎么做?
- 你怎么评估生成内容的质量?除了人工评估还有哪些方法?
- 如果让你设计一个「多模态搜索 Agent」,用户上传图片搜相似笔记,你会怎么做?
- 向量检索在多模态场景怎么用?图片和文本怎么映射到同一空间?
- 如果让你做「视频内容理解」,和多图理解有什么不同?
- 你怎么看多模态大模型在内容社区的应用前景?
- 如果让你设计一个「智能创作助手」,帮用户生成笔记文案和配图,你会怎么做?
- 生成的内容怎么保证不侵权?
- 你怎么评估生成内容的「创意」程度?
- 如果让你优化多模态模型的推理成本,你会从哪些层面入手?
- 你了解哪些多模态的开源模型?有没有做过微调?
- 如果让你做多模态模型的蒸馏,你会怎么做?
- 你怎么看多模态模型在电商场景的应用?
- 如果让你设计一个「多模态客服 Agent」,用户发图片问问题,你怎么处理?
- 你最近关注多模态领域的哪些新技术?
- 你觉得多模态大模型的下一个突破点在哪?
- 手撕:实现一个函数,给定一个二维矩阵,将其顺时针旋转 90 度,要求原地旋转。
《参考解析》
视觉编码器与 LLM 的连接方式:主流是三类。① MLP projector(LLaVA 系):ViT 的 patch token 直接过两层 MLP 投到 LLM 的词嵌入维度再拼进输入序列,比如 CLIP ViT-L/14@336 出 24×24=576 个 patch token、每个 1024 维,projector 做 1024→4096→4096(GELU)。结构最简单、token 与空间位置一一对应,细节问答和 OCR 强;代价是序列被拉长(576 个视觉 token 往往比整句 prompt 还长),推理成本高。② Query-based 压缩(BLIP-2 / InstructBLIP 的 Q-Former):3264 个可学习 query 通过 cross-attention 从 ViT 特征里抽取信息,输出 token 数固定且少,训练时只更新 Q-Former,参数效率极高;代价是固定 query 数对密集文本、小目标这类需要细粒度信息的任务有损,且要额外一轮图文对预训练。③ Cross-attention 注入(Flamingo):Perceiver Resampler 压出固定视觉特征,再用 tanh 门控(初始化为 0)的 gated cross-attention 插进 LLM 各层之间。视觉信息每层都能访问、不占输入序列长度,但改了 LLM 结构,KV cache、量化、vLLM 这些生态适配都很麻烦。另外还有两条实用分支:AnyRes 切图(LLaVA-NeXT 把高分辨率图切成 45 个子图各出 576 token 再拼全局缩略图)和动态分辨率(Qwen2-VL 的 naive dynamic resolution + M-RoPE,token 数随原图尺寸变)。
为什么不用平均池化:三个层面。① 信息层面:把 576 个 patch 在空间上平均成一个向量,等于把位置信息边际化掉,「左边是猫、右边是狗」「表格第三行第二列」这类问题从表示上就不可能答对。② 能力层面:平均是固定权重的线性聚合,等价于一个恒等权重的注意力,模型没有机会按当前问题去挑相关 patch;而 patch token + projector 方案把选择权交给 LLM 的 self-attention,cross-attention 方案里 query 更是显式地做选择。③ 预训练目标层面:CLIP 的全局 [CLS] 特征本来就是为整图对整句的粗粒度对齐训的,直接拿来喂生成模型天然丢细节,LLaVA 的消融显示用全局特征替 patch token 会在细节类基准上明显掉点。要压 token 数应该做空间降采样而不是池化到 1 个向量——Qwen-VL 的 merger、InternVL 的 pixel shuffle(1024→256,4 倍降采样)都是这个思路,很多面试官问「池化」其实想问的就是这个区别。
多模态幻觉的成因与三层缓解:成因分三类。数据/训练侧:网图配文噪声(alt-text 与图无关)、语言先验过强(LLM 从纯文本预训练里继承了「香蕉是黄的」,看到黑白照片仍答黄色,POPEv2、MMHal-Bench 里大量是这类 object hallucination)、监督信号只奖励流畅不奖励有据。架构侧:视觉 token 分辨率受限导致细节丢失,projector 没训好造成模态错位,LLM 干脆忽略视觉 token 靠语言先验编。解码侧:高温采样、beam search 的 length penalty 逼着模型凑长度,没证据时倾向吐高先验词。缓解按三层来:① 后训练(最有效)——SFT 阶段专门构造「图里没有 X」的纠错样本;偏好优化阶段用 MMHal 这类标注把「有据可依」的回答排在前面,或引入 grounded reward(答案里提到的物体必须能被检测器/分割器在图里找到,否则扣分,RLHF-V、LLaVA-RLHF 的思路);解码侧还可以用 VCD(Visual Contrastive Decoding),对原图和加噪图各前向一次,用两次 logits 之差压掉纯语言先验产生的 token。② RAG——先用检测/分割/OCR 把「图里到底有什么」抽成结构化事实(物体清单、OCR 文本、颜色属性、笔记标签),作为可追溯证据拼进 prompt,并允许模型回答「图中未显示」。③ 规则——输出侧做确定性校验:实体白名单(答案里的实体必须出现在检测结果里)、数字与 OCR 一致性、素材质量分或 OCR 置信度低于阈值就走拒答模板。上线顺序上规则放最后一道,宁可漏答不误答。
InfoNCE 温度系数:损失是 L = -log[ exp(sim(z_i,z_i+)/τ) / Σ_k exp(sim(z_i,z_k)/τ) ],sim 取归一化后的点积。τ 直接控制 softmax 的锐度,也就控制了「推开负样本的力度」:τ 小(0.01 量级)把 logits 放大 100 倍,分布接近 one-hot,梯度集中在最难的负样本上,判别性强但训练不稳、容易被假负样本带偏;τ 大(0.5)分布接近均匀,负样本被平摊,表示区分度弱。梯度视角看,τ 是每个负样本梯度权重的温度——Wang & Liu 那篇 “Understanding the Behaviour of Contrastive Loss” 给过结论:存在一个与正样本相似度分布相关的临界温度,只有低于它,训练才真正在惩罚难负样本。调法上,CLIP 的做法是把温度参数化成可学习的 logit_scale,初始化 ln(1/0.07)≈2.659(即 τ=0.07),并 clamp 到 ≤100(τ≥0.01),这是最稳的默认值。经验区间:batch 2561024 用小 τ(0.050.1);batch ≥8192 时负样本足够多,τ 反而要适当放开到 0.1~0.2,SigLIP 干脆把 softmax 换成 pairwise sigmoid loss,绕开全局归一化在超大 batch 下的动态范围压缩问题。手调时盯两个信号:验证集 R@1,以及可学习温度是否一路滑到 clamp 下界——一路下滑通常不是 τ 的问题,而是数据里有假负样本(同一张图配了不同 caption 被当成负样本)或 batch 太小,先洗数据再动温度。
PPO / DPO / GRPO 的适用场景:① PPO 是在线 RL,要 policy、reference、reward、critic 四份模型(critic 与 policy 同规模,显存约 4 倍),用 GAE 估优势、clip 比值约束步长、KL 惩罚钉住 reference。适合有可靠 verifier 或高质量 RM、能大量采样、算力充足、追求天花板的任务(数学/代码 RL、InstructGPT 那条线)。代价是工程复杂、超参多(clip ε、KL 系数、GAE λ)、采样贵、训练容易崩。② DPO 把带 KL 约束的 RLHF 目标解析地转成对偏好对的分类损失:L = -log σ(β·[log(π(y_w)/π_ref(y_w)) - log(π(y_l)/π_ref(y_l))]),只要 policy + reference(ref 甚至可以用关掉 LoRA adapter 的方式省掉一份权重),一轮离线数据就能训,β 常取 0.1(0.010.5)。适合有偏好对、预算有限、要快速对齐风格的场景;缺点是只吃离线分布、没有在线探索,容易过拟合偏好数据,天花板低于在线 RL。③ GRPO 去掉 critic:同一 prompt 采 G 个回答(常用 864),用组内奖励的均值和标准差归一化出优势 A_i = (r_i - mean(r)) / std(r),再套 PPO 的 clip 目标。省掉一份 value model(显存大约省 1/3 到 1/2),也不需要训 value 的额外不稳定性,特别适合「reward 能自动判定」的任务(数学答案对错、代码单测通过)——DeepSeek-R1 就是这个路线;如果 reward 来自主观打分,效果就退化成依赖 RM 质量。选型一句话:有 verifier 且算力够 → GRPO(或 PPO);只有偏好对且要快 → DPO;连偏好对都缺 → 先用强模型蒸馏偏好对,再做 DPO;工程上常见组合是先 SFT 打底、DPO 低成本对齐、最后 GRPO/PPO 冲能力。
显存优化技术清单:先算账——训练显存 ≈ 参数 + 梯度 + 优化器状态 + 激活 + 通信缓冲。Adam 混合精度下每参数约 16~18 字节(fp16 权重 2 + fp16 梯度 2 + fp32 master 4 + Adam 的 m/v 各 4),7B 模型光静态占用就 ~120 GB,所以优化是必需的而不是可选的。手段按性价比排:bf16 混合精度(避开 fp16 的 loss scale 溢出,只在需要处保留 fp32 master);激活重计算(gradient/selective checkpointing,不存中间激活、反向重算,激活显存降到 O(√L) 量级,代价约 20%~30% 计算时间);ZeRO 三档 / FSDP(ZeRO-1 分优化器状态、ZeRO-2 再分梯度、ZeRO-3 连参数一起分,7B 在 8 卡 ZeRO-3 下单卡能压到十几 GB,代价是每层都要 all-gather 的通信开销);CPU / NVMe offload(DeepSpeed ZeRO-Offload、ZeRO-Infinity,属于「跑得起来」而非「跑得快」);张量并行与序列/上下文并行(Megatron TP;长上下文 >32k 时激活是主要矛盾,CP 基本是必选项);微调侧用 LoRA / QLoRA(4-bit NF4 量化基座 + paged optimizer,7B 单卡 24G 可训,QLoRA 论文里 65B 单卡 48G 可训)。再加几条实操:FlashAttention-2/3 让注意力不再物化 L×L 矩阵,从 O(L²) 降到 O(L);PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True 治碎片;缩小 micro-batch 用梯度累积补回等效 batch;序列打包提高利用率。排查顺序是先定位再选药:torch.cuda.max_memory_allocated() 看是参数侧还是激活侧爆的——第一步前向就 OOM 是参数加优化器装不下(走 ZeRO/LoRA),中间层 OOM 是激活爆(走 checkpointing/SP/FA),optimizer step 或 save 时 OOM 是优化器状态(走 ZeRO-1/offload)。
手撕:二维矩阵原地顺时针旋转 90 度:n×n 的方阵,顺时针 90° 等价于「先沿主对角线转置,再把每一行左右翻转」,原地、O(n²) 时间、O(1) 额外空间。
def rotate(matrix):
n = len(matrix)
for i in range(n):
for j in range(i + 1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
for i in range(n):
matrix[i].reverse()
正确性:元素 (i, j) 经转置到 (j, i),再经行翻转落到 (j, n-1-i);而顺时针 90° 的目标映射正是 new[j][n-1-i] = old[i][j],两者一致。逆时针 90° 只需把第二步换成上下翻转(matrix.reverse())。复杂度:每个元素恰好参与一次转置交换和一次行内交换,时间 O(n²);只用了两个下标变量,空间 O(1)。边界必须提一句:n=0 或 n=1 直接返回;如果给的是 m×n 非方阵,「原地」在定义上就不成立(结果尺寸变成 n×m),只能新开矩阵,此时映射为 new[j][m-1-i] = old[i][j]——面试里先反问一句「是方阵吗」是加分项。另一个等价写法是环形四元组轮换:外层 for i in range(n//2)、内层 for j in range(i, n-1-i),把 (i,j) → (j,n-1-i) → (n-1-i,n-1-j) → (n-1-j,i) 四个位置循环赋值,同样 O(1) 空间,但下标极易写错,除非面试官明确要求,转置加翻转更稳。