面灵AI→

小红书多模态算法秋招二面面经(约 40 题 + 手撕)

轮次
二面
时间
2026-09
来源
牛客网

《面试题目》

  1. 多模态大模型中,视觉编码器和 LLM 之间的连接方式有哪些?各有什么优劣?
  2. 为什么不用更简单的平均池化?
  3. 多模态模型产生幻觉的主要原因是什么?怎么通过后训练、RAG、规则缓解?
  4. 如果让你做小红书笔记的图文内容理解,怎么设计模型架构?
  5. 你做的多模态项目中,视觉编码器用的是什么?为什么选它?
  6. 多模态训练中,如果文本模态主导决策、图像被忽略,怎么发现和解决?
  7. 对比学习在图文匹配中怎么用?InfoNCE 的温度系数怎么调?
  8. 如果一篇笔记包含多张图片,怎么融合多图信息?注意力机制怎么设计?
  9. 你怎么评估多模态模型的内容理解效果?评测集怎么构建?
  10. 如果让你设计一个「内容安全审核 Agent」,怎么处理图文混合违规?
  11. 大模型 SFT 阶段,过拟合和欠拟合分别有什么表现?怎么调优?
  12. 你在大模型项目中为何选择或舍弃强化学习?PPO、DPO、GRPO 分别适用什么场景?
  13. 大模型训练中出现内容复读、语句冗余,核心成因是什么?从数据、算法、参数三个维度怎么优化?
  14. 大模型训练中出现 OOM,你常用的显存优化技术有哪些?
  15. 简述主流 Agent 的核心组成架构。LangGraph 在落地应用中的短板是什么?
  16. 多智能体协作场景中,如何设计通信机制和任务分配策略?
  17. 你怎么看 RAG 和长上下文模型的关系?会互相替代吗?
  18. 如果让你优化小红书搜索的 Query 理解,你会用大模型做什么?
  19. 你平时怎么跟进 AI 前沿技术?最近读过什么有意思的论文?
  20. 如果让你从零做一个多模态内容理解 Agent,技术选型是什么?
  21. 小红书的笔记有很多短文本加图片,怎么设计模型?
  22. 如果让你做「笔记推荐理由生成」,怎么保证吸引人且不重复?
  23. 多模态模型在移动端部署,怎么优化推理速度?
  24. 如果让你设计一个「封面图质量评估」模型,你会怎么做?
  25. 你怎么评估生成内容的质量?除了人工评估还有哪些方法?
  26. 如果让你设计一个「多模态搜索 Agent」,用户上传图片搜相似笔记,你会怎么做?
  27. 向量检索在多模态场景怎么用?图片和文本怎么映射到同一空间?
  28. 如果让你做「视频内容理解」,和多图理解有什么不同?
  29. 你怎么看多模态大模型在内容社区的应用前景?
  30. 如果让你设计一个「智能创作助手」,帮用户生成笔记文案和配图,你会怎么做?
  31. 生成的内容怎么保证不侵权?
  32. 你怎么评估生成内容的「创意」程度?
  33. 如果让你优化多模态模型的推理成本,你会从哪些层面入手?
  34. 你了解哪些多模态的开源模型?有没有做过微调?
  35. 如果让你做多模态模型的蒸馏,你会怎么做?
  36. 你怎么看多模态模型在电商场景的应用?
  37. 如果让你设计一个「多模态客服 Agent」,用户发图片问问题,你怎么处理?
  38. 你最近关注多模态领域的哪些新技术?
  39. 你觉得多模态大模型的下一个突破点在哪?
  40. 手撕:实现一个函数,给定一个二维矩阵,将其顺时针旋转 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) 空间,但下标极易写错,除非面试官明确要求,转置加翻转更稳。