资讯

DeepSeek V4 多模态开源,我们把它的视觉链路拆了一遍

雷峰网·2026/9/1 10:38:00🔗 原文

📌 概要

图片不只被编码,还直接参与 Attention、MoE 与 Agent 推理。     作者丨 郑 佳 美     编辑丨 岑   峰                                                                                                         这不是一个全新的模型突然出现。早在 8 月 21 日,D

⚡ 关键要点

  • 图片不只被编码,还直接参与 Attention、MoE 与 Agent 推理。     作者丨 郑 佳 美     编辑
图片不只被编码,还直接参与 Attention、MoE 与 Agent 推理。

    作者丨郑佳美

    编辑丨岑   峰

                                                                                                       

这不是一个全新的模型突然出现。早在 8 月 21 日,DeepSeek 就已经把它接入 API,当时外界只能看到结果:V4 开始能处理图片,而且在 ApexBench、Agents' Last Exam、Chartography 等多模态 Agent 基准上整体提升。

现在不一样了。

随着权重和参考推理代码公开,V4 的视觉部分第一次可以直接拆开看。Vision Encoder 怎么处理图片,Aligner 怎么把视觉特征压进语言空间,视觉 Token 怎么进入 DFlash,MoE 又怎么给图片选择专家,这些东西都已经暴露出来。

拆完代码会发现,DeepSeek 做的并不是简单给 V4 接一个看图模块。

图片经过视觉编码以后,会被直接塞进 V4 原有的 Token 序列,继续参与长上下文 Attention、MoE 路由和后面的 Agent 推理。甚至连注意力窗口和专家路由,都专门为视觉 Token 改了规则。

所以这次开放权重之后,更值得研究的问题已经从 V4 会不会看图,变成了另一件事:

DeepSeek 到底是怎么把视觉塞进一个原本为长上下文和 Agent 设计的 V4 主干里的?

图片

01


视觉怎样进入 V4

先看一张图片怎样变成 V4 序列中的 Token。

视觉前端是一套 32 层 ViT,隐藏维度 1024,拥有 16 个 Attention Head,patch size 为 14。图片先经过尺寸调整,再被切成 14 × 14 的 patch,每个 patch 映射成一个 1024 维向量。

视觉位置编码使用二维 RoPE。代码会分别建立图像网格的横向和纵向坐标,再将两组位置写入 Attention。

对于网页和 GUI,这种设计很关键,因为界面语义大量存在于空间关系里:按钮位于哪个区域,表头和数据怎样对应,弹窗覆盖了什么内容,图例和图表之间是什么位置关系。ViT 在这里负责先把二维结构建出来。

问题出现在 ViT 后面。雷峰网

V4 主干隐藏维度是 4096,视觉侧只有 1024,而且 ViT 产生的 patch 数量仍然偏大。DeepSeek 在两者中间放了一个 Aligner,同时解决维度转换和 Token 压缩。

它会把相邻 3 × 3 个视觉特征放到一起,9 个 1024 维向量合并以后形成 9216 维输入,再经过 9216 → 4096 → 4096 的两层映射进入 V4。

打个比方,这个 Aligner就相当于向“老板”V4汇报的秘书,先将老板要处理的文件进行精炼汇总:横向缩小 3 倍,纵向缩小 3 倍,所以进入语言主干的视觉网格规模大致下降到原来的九分之一。

这一步非常关键。DeepSeek 没有直接降低 ViT 的观察密度,而是在视觉编码完成以后再压缩序列。前端仍然可以利用较密的 patch 读取页面细节,到了计算量更大的 V4 主干之前,再削减视觉 Token 数。

配置里的 vision_max_n_token = 384 也应该放在这里理解。

384 指的是进入 V4 序列后的单图预算,并非 ViT 只看 384 个 patch。ViT 前端实际处理的视觉单元更多,经过 3 × 3 Aligner 后,才被压缩成几百个语言侧视觉 Token。DeepSeek API 同样规定单张图片转换后的输入不超过 384 Token。雷峰网

对于单轮图像问答,这种限制可能只是一次计算取舍;对于 Agent,它直接决定每观察一次环境,需要往长上下文里新增多少内容。

随后还有一个很容易被忽略的细节:视觉 Token 并没有按照普通的逐行顺序进入 V4。

build_image_block() 会给图片加入 IMAGE_START、换行、Padding 和 IMAGE_END,然后把相邻两行视觉网格重新交织。代码还通过 COMPRESS_PAD_TO = 4,让视觉序列的位置与 4 Token 边界对齐。

V4 主干内部恰好大量存在 compress_ratio = 4 的压缩层,同时还交替使用 ratio 为 128 的层。仅凭公开代码还不能断言 N-layout 就是专门为 CSA 的 4 Token 压缩设计。

但两者的粒度明显一致:图像进入模型前已经主动改变二维网格的线性排列,并进行 4 Token 对齐,说明视觉序列的组织方式考虑了后面压缩主干的处理方式。

所以从像素到 V4,并非简单经历 ViT 加一个投影层。

更准确的路径是:图片先以较高密度建立二维表示,随后进行 3 × 3 空间压缩,再转换到 4096 维隐藏空间,接着重新组织视觉 Token 的排列,最后才进入 V4。

做到这一步,图片已经被改造成一种适合长上下文主干处理的序列。

新的问题随之出现:进入序列以后,V4 能不能直接把这些视觉 Token 当成文字处理?

图片

02


进入主干以后

答案从代码里看得很清楚:不能完全按照文字处理。

V4 会先正常生成文本 embedding,然后 merge_image_embeddings() 找到图片占位区域,把经过 ViT 和 Aligner 得到的视觉 embedding 原地写进去。

从隐藏层角度看,文字和图片此时已经进入同一个 4096 维空间。后面的 Transformer 可以让页面内容和自然语言指令直接发生交互,例如任务要求在文字 Token 中,当前网页状态位于视觉 Token 中,两者进入同一条推理序列。

不过 DeepSeek 特意保留了视觉 Token 的身份。

普通词表大小是 129280,而图像特殊 Token 被放在词表范围之外。主干只需要检查 input_ids >= vocab_size,就能判断当前位置来自图片。

为什么进入统一隐藏空间以后,还要留下这个标记?因为二维图片和文字序列的计算需求并不一样。

先看 Attention。V4 的普通局部滑窗只有 128 Token,而一张图片可以占接近 384 个语言侧 Token。如果完全按照文字的局部规则处理,一张完整截图可能被切成数段。

比如一个网页的表头在顶部,操作按钮位于页面下方。二维空间中它们属于同一张界面,但转换成一维视觉序列后,两者距离可能超过 128 Token。普通滑窗会削弱同一张图片内部远距离区域的直接联系。

代码因此加入了 get_image_visible()。它会识别 IMAGE_START 与 IMAGE_END,计算一个 Token 在当前图片范围内向左和向右还有多少视觉内容。V4 随后可以在普通局部窗口之外,扩展图片内部的可见范围。

代码甚至要求一整段图片必须在 prefill 阶段一次写入,不能在后续 decode 中把同一张图拆成几块追加。

这解决的是视觉的空间完整性。MoE 处理的是另一个问题:视觉 Token 应该调用哪些参数。

V4 拥有 256 个路由专家,每个 Token 会激活 6 个专家。视觉版本的 Router 中增加了单独的 bias_vl← 返回资讯流