视觉语言模型技术指南:图像是怎么"接入"语言模型的?视觉编码器、投影层与对齐机制详解
前一篇我们刚把 RAG 这条链路拆开。
如果说 RAG 解决的是"模型回答之前,怎么先去看外部资料",那从今天开始,系列要正式切进另一条非常关键的主线:
语言模型到底是怎么开始"看图"的?
很多人第一次接触 VLM 或 MLLM 时,会有一种很自然的直觉:
- LLM 负责理解文本
- 再加一个图像编码器
- 把图像信息喂进去
- 模型就能看图说话了
这个理解方向不算错,但太粗了。
真正一落到模型结构、训练流程和部署工程上,问题马上就会变得具体很多:
- 图像本来是像素,语言模型吃的是 token,中间到底怎么接?
- 视觉编码器为什么大多用 ViT / CLIP 这一类结构,而不是直接把原图扔给 LLM?
- projector 到底是什么,它为什么在很多多模态结构里存在感这么强?
- 图像到底被编码成多少视觉 token?这个数量受什么控制?
- cross-attention、MLP projector、Q-Former 这些接法有什么差别?
- 为什么图像分辨率一升,显存和延迟就很容易爆?
- 训练时到底在"对齐"什么?是图文配对就够了,还是还要多模态指令数据?
这些问题背后,本质上都在指向一件事:
VLM 不是简单给 LLM 加一双"眼睛",而是在语言模型主干之外,额外构造一套视觉表征、模态对齐和信息注入机制。
这篇文章,我想把这条链路从工程视角讲清楚。
我会重点讲六件事:
- 图像为什么不能直接喂给 LLM,视觉编码器到底在做什么
- 视觉 token 是怎么来的,patch size、resolution 为什么会直接影响成本
- projector / adapter 到底在解决什么问题
- 主流图像接入路线:MLP 投影、cross-attention、Q-Former 各自适合什么场景
- 训练时的"对齐"到底在对齐什么,为什么光有图文对还不够
- 部署时最容易踩的坑:视觉 token 爆炸、延迟上升、图文对齐不稳
如果你正在看 LLaVA、Qwen-VL、InternVL、MiniCPM-V,或者准备把多模态能力接进真实业务,这篇基本就是理解 VLM 结构的起点。
一、先说结论:图像不是"被语言模型直接理解",而是先被变成一种可被语言模型消费的离散或连续表示
很多入门介绍会把 VLM 说成:
- 图像输入
- 模型理解
- 文本输出
但这会隐藏一个最关键的事实:
语言模型本身并不天然理解像素。
LLM 之所以能工作,是因为它处理的是 token 序列。
而原始图像是:
- 宽和高构成的二维像素网格
- 每个像素包含 RGB 或其他通道值
- 空间结构强、冗余高
- 和文本 token 的统计结构完全不同
所以图像如果要"接入"语言模型,至少要先完成一层转换:
把像素空间里的视觉信息,压缩成某种语言模型可以继续处理的表示。
这个转换,一般就是视觉编码器在做。
1)视觉编码器不是简单提特征,而是在做"视觉世界的前端语义压缩"
它的工作不只是把图缩小,而是把原始图像变成:
- 更紧凑的表示
- 带有语义结构的表示
- 能和语言侧进一步对齐的表示
你可以把它类比成:
- tokenizer 把文本切成 token
- vision encoder 把图像切成 patch,并编码成视觉 embedding
当然这两个过程并不完全一样,但在系统角色上有点类似:
它们都在把原始模态,变成后续主干网络更容易处理的单位。
2)为什么不能直接把整张图片 flatten 之后送进 LLM?
原因很现实:
- 原始像素维度太高
- 视觉局部结构很强,直接展平会破坏空间归纳偏置
- LLM 对二维局部感受野并不天然友好
- 训练成本和序列长度会直接失控
所以现实里的多模态系统,几乎都会先让视觉侧自己做一轮编码。
这也是为什么 VLM 很少从"纯 LLM 主干"直接长出来,而是通常由:
- 一个视觉编码器
- 一个模态连接模块
- 一个语言模型主干
三部分组成。
二、视觉编码器为什么大多是 ViT / CLIP 路线?
今天主流 VLM 里,最常见的视觉前端基本都绕不开这几类:
- ViT
- CLIP Vision Encoder
- EVA / SigLIP / InternViT 等视觉 backbone
它们虽然训练目标不同,但工程上扮演的角色很接近:
先把图像切成 patch,再把 patch 编码成一串视觉 token 或视觉特征。
1)ViT 的基本思路,就是把图像 patch 化后当序列处理
这也是它和 LLM 更容易接轨的原因。
假设一张图分辨率是:
224 × 224
如果 patch size 是:
14 × 14
那么图像会被切成:
(224/14)×(224/14)=16×16=256 (224 / 14) \times (224 / 14) = 16 \times 16 = 256 (224/14)×(224/14)=16×16=256
个 patch。
每个 patch 再被映射成一个向量,后续通过 Transformer 继续编码。
于是图像就从二维像素网格,变成了一段长度约为 256 的视觉序列。
这一步非常关键。
因为从这里开始,视觉侧和语言侧至少在"序列化处理"这件事上开始变得兼容。
2)为什么很多多模态模型喜欢直接复用 CLIP vision encoder?
因为 CLIP 系列视觉编码器已经在大规模图文对数据上做过对齐预训练。
这意味着它天然有几个优势:
- 视觉特征语义性比较强
- 图文空间已经有一定对应关系
- 不需要从零开始学"图像里什么是可说的"
- 可以显著降低多模态系统的训练成本
所以像很多 LLaVA 路线的模型,本质上就是:
- 拿一个已经训练好的 vision encoder
- 再想办法把它的输出接进 LLM
这比从像素到语言完全端到端重新训,要现实得多。
3)视觉编码器选型,会直接影响精度、速度和显存
这里有几个常见参数会非常关键:
- backbone 规模:B / L / H 级别
- hidden size
- patch size
- 输入分辨率
- 是否支持高分辨率或动态分辨率
这些参数并不是"模型论文里的装饰品",而是会非常直接地影响:
- 视觉 token 数量
- 单张图的推理时延
- 显存消耗
- 多图场景能不能扛住
所以选视觉 backbone 时,不能只看 benchmark 分。
视觉前端在多模态系统里,本身就是吞吐和成本的大头之一。
三、视觉 token 是怎么来的?为什么 patch size 和 resolution 会直接决定系统成本?
这一点非常值得单独拿出来讲。
因为很多人第一次看 VLM,只注意"它能看图",却忽略了:
图像一旦进入序列模型,代价经常是按 token 算的。
1)图像分辨率越高,视觉 token 通常越多
如果 patch size 固定,resolution 一升,patch 数就会迅速上去。
举个最直观的例子。
当 patch size 固定为 14 × 14:
224 × 224→16 × 16 = 256个 patch448 × 448→32 × 32 = 1024个 patch
也就是说,边长翻倍,视觉 token 数会接近变成原来的 4 倍。
而 attention 的计算开销,对序列长度通常还不是线性上升。
这就是为什么高分辨率输入一上去,系统代价会突然变得很重。
2)patch size 越小,局部细节更丰富,但 token 成本更高
patch size 可以粗略理解成"每个视觉 token 覆盖多大图像区域"。
- patch 小:保留更多局部细节,但 token 更多
- patch 大:token 更少,但局部信息更粗
这就带来一个很典型的工程 trade-off:
- OCR、图表、小物体、细粒度定位任务,通常更吃高分辨率和更细粒度视觉 token
- 通用看图问答、粗粒度语义描述,对 patch 细度要求没那么极端
所以 VLM 的视觉分辨率参数,绝不是"开越高越好"。
它其实是在平衡:
- 精细视觉理解
- token 成本
- 显存预算
- 延迟约束
3)多图输入时,视觉 token 爆炸会更严重
单图都已经很贵了,多图场景会更明显。
假设每张图 576 个视觉 token,4 张图就是:
4 × 576 = 2304个视觉 token
如果再加上文本输入和长输出,整段上下文很快就会逼近模型窗口上限,或者让 prefill 成本大幅上升。
这就是为什么多图、长图、高清图这些能力,在 demo 上看起来很酷,但一进生产就必须非常认真地做 token 预算。
四、projector 到底是什么?它为什么在多模态模型里几乎绕不过去?
如果说视觉编码器负责把图片变成视觉特征,那么 projector 解决的就是下一步问题:
这些视觉特征,怎么才能被语言模型主干顺利接住?
因为视觉侧和语言侧往往并不天然兼容。
它们可能在这些方面都不一致:
- embedding 维度不同
- 特征分布不同
- 语义空间不同
- 序列组织方式不同
所以必须有一个中间模块,负责把视觉表示"翻译"成语言侧更容易消费的形式。
这类模块通常就被统称为:
- projector
- adapter
- connector
- bridging module
1)最基础的 projector,常常就是一层或多层 MLP
很多早期或轻量路线会用非常直接的做法:
- 取 vision encoder 输出
- 过一层线性映射或两层 MLP
- 把维度投到 LLM hidden size
- 再把这些视觉 token 当成前缀或插入序列送进 LLM
这种方法的优点很明显:
- 简单
- 参数量小
- 训练成本低
- 易于在已有 LLM + vision encoder 上快速搭建
LLaVA 一类路线之所以流行,很大程度上就是因为这条接法足够工程化。
2)projector 不是纯粹的"维度对齐层",它还承担分布对齐任务
很多人会把 projector 想成"改个 shape"。
这不完整。
它更重要的作用其实是:
把视觉侧的统计分布和语义组织方式,尽可能拉近到 LLM 能接受的区域。
因为 LLM 主干是在文本 token 分布上训练出来的。
如果你把一串完全陌生分布的向量硬塞进去,LLM 并不会自动神奇地懂。
所以 projector 本质上也在参与模态对齐。
3)projector 太弱或太小,可能接不上复杂视觉语义
这也是很多系统早期会遇到的问题。
如果 connector 容量太小,常见现象包括:
- 能做粗粒度图像描述
- 但细节定位能力弱
- OCR、图表、跨区域关系理解差
- 多图一致性不好
也就是说,视觉编码器再强,如果中间桥梁过窄,语言主干仍然很难真正吃到足够有效的信息。
五、图像接入 LLM 的主流路线有哪些?
从结构上看,主流 VLM 大致可以归成几条典型路线。
1)MLP projector 路线:简单、轻量、工程友好
这是最容易理解的一类。
基本思路是:
- vision encoder 输出一串视觉特征
- 通过 MLP / linear projector 映射到 LLM hidden size
- 把这些特征当作视觉 token 接入语言模型
优点:
- 实现简单
- 训练成本低
- 很适合在强 LLM 上快速做多模态扩展
缺点:
- 对复杂视觉细节的表达能力有限
- 很依赖 vision encoder 本身够强
- 对高阶图文交互的建模能力不一定最优
这条路线很适合:
- 工程上先把多模态能力接起来
- 追求较低训练门槛
- 已有强大文本主干,希望快速增加图像理解接口
2)cross-attention 路线:让语言侧和视觉侧做更显式交互
另一种思路是,不只是把视觉 token 当前缀塞进去,而是让语言侧在生成过程中显式 attend 到视觉信息。
这种做法通常会更灵活,因为它允许:
- 文本 token 在解码时动态选择关注哪些视觉区域
- 视觉和语言表示做更深层交互
优点:
- 图文交互建模能力更强
- 对复杂关系和细粒度理解更有潜力
缺点:
- 结构更复杂
- 训练和推理开销通常更高
- 工程实现复杂度也更高
3)Q-Former / query-based 路线:先用一小组查询向量从视觉侧抽取关键信息
这条路线的代表思想是:
不要把所有视觉 patch 都直接塞给 LLM,而是先通过一组 learnable queries,从视觉特征里抽出更紧凑的表示。
这样做的核心动机很现实:
- 原始视觉 token 太多
- 不可能什么都直接送入语言主干
- 需要先做一层信息压缩和选择
优点:
- 能在保持信息量的同时压缩 token 数
- 对大规模多模态预训练更友好
- 更适合做视觉信息摘要式注入
缺点:
- 结构更重
- 训练要求更高
- 中间抽取层本身也会引入设计复杂度
所以从工程角度看,这三条路线不是谁绝对更先进,而是:
你愿意用多少结构复杂度,换多少图文交互能力和 token 效率。
六、训练里说的"图文对齐",到底在对齐什么?
这是 VLM 里最容易被说空的一句话。
很多文章一提多模态训练,就会说"做图文对齐"。
但如果不拆开,很容易听完还是不知道模型到底学了什么。
更具体地说,图文对齐至少涉及三层:
1)语义对齐:图像内容和语言描述要能落到相近语义空间
最基础的是:
- 看到猫,文本"猫"不能离得太远
- 看到图表,模型要能建立图像结构与语言描述之间的对应
CLIP 类训练很大程度就在做这件事。
它让视觉编码器输出的表示,开始具备"能和文本互相对应"的语义性质。
2)接口对齐:视觉表示要变成 LLM 真能消费的输入
这一步很多时候由 projector / adapter 承担。
也就是说,哪怕视觉特征已经有语义,如果它的分布和 LLM 完全不兼容,语言主干还是很难稳定使用。
所以训练时不只是"图文匹配",还在学:
- 怎么把视觉表示接到语言主干
- 接进去之后,LLM 怎样在生成时利用它
3)任务对齐:模型不仅要"知道图里有什么",还要"知道怎么按任务回答"
这也是为什么单纯图文对预训练通常还不够。
因为真实多模态交互里,用户关心的不只是 caption。
他们会问:
- 图里哪个区域有异常?
- 这两张图差别在哪里?
- 菜单上第三行价格是多少?
- 图表趋势说明了什么?
- 这个截图下一步该点哪里?
这些都是任务化、多轮化、指令化的问题。
所以现代 VLM 一般还需要:
- 多模态指令微调
- OCR / grounding / chart / document 等专项数据
- 有时还会加思维链式、多步骤、多图数据
换句话说:
图文对齐让模型"能把图和字连起来",多模态指令训练才让模型"知道怎么围绕用户任务来用这条连接"。
七、为什么很多 VLM 看起来会"看图",但一到细节任务就不稳?
这是多模态系统里特别常见的落差。
demo 阶段看着不错,但一上复杂任务就开始暴露问题。
原因通常有这几类。
1)视觉 token 太粗,局部信息不够
如果分辨率低、patch 大,模型对细小目标、文字、小表格、本地布局就很容易不稳定。
2)projector 容量有限,复杂视觉关系传不过去
如果桥接层太窄,很多高阶语义在接入 LLM 之前就已经损失了。
3)训练数据偏 caption 风格,任务分布过窄
如果模型主要见过:
- "描述这张图"
却很少见过:
- OCR 问答
- 多图比较
- grounding
- 文档解析
- GUI 操作理解
那它自然会更擅长"说个大概",不擅长"做得很准"。
4)语言模型会补全流畅性,但不等于视觉证据真的足够
这和 RAG 有点像。
很多多模态幻觉,本质上也是:
- 模型语言侧太会说
- 视觉侧证据不够强
- 最终输出变成"像是看懂了",但其实在补洞
所以判断一个 VLM 够不够好,不能只看它 caption 是否顺。
更重要的是看:
- OCR 准不准
- grounding 稳不稳
- 多图一致性如何
- 高分辨率文档理解行不行
- 是否会稳定引用视觉证据
八、部署时最容易踩的坑:分辨率、视觉 token 和显存预算
如果你准备把 VLM 接进真实系统,这一段很重要。
1)视觉输入分辨率不是越高越好
高分辨率确实常常能带来更好的细节能力。
但代价也非常直接:
- 视觉 token 增多
- prefill 变重
- 显存占用上升
- 时延变长
- 多图并发能力下降
所以工程上更实际的做法通常是:
- 不同任务设不同分辨率档位
- OCR / 文档 / 图表走高分辨率路径
- 普通看图问答走中低分辨率路径
- 能裁剪就先裁剪,不要一上来整张大图硬喂
2)图片预处理策略会直接影响线上稳定性
比如:
- resize 是否失真
- 是否保留宽高比
- 是否做 tiling
- 多图输入顺序是否固定
- 颜色空间、旋转、裁边是否统一
这些看起来像"前处理小事",实际上会强烈影响模型行为一致性。
3)多图、多页 PDF、长文档场景要极其小心 token 预算
很多真实任务不是单图,而是:
- 多张商品图
- 多页文档
- 一整份合同
- 一串 GUI 截图
这时候如果没有做:
- 筛图
- 分页
- 局部裁剪
- 分阶段推理
很快就会出现:
- token 爆炸
- 延迟飙升
- 显存不足
- 回答质量反而下降
所以多模态部署里,一个很常见的正确思路是:
先做视觉输入管理,再做多模态生成。
别把所有图片无脑全塞进去。
九、如果现在要做一个能用的 VLM 系统,我会怎么建议起步?
如果你现在不是做研究论文,而是想做一个工程上能工作的多模态系统,我会更建议这样起步。
1)先明确任务类型,而不是先迷信某个模型名
先问清楚:
- 主要是 caption 还是问答?
- 单图还是多图?
- 偏 OCR、文档、图表,还是自然图像理解?
- 需要 grounding 吗?
- 输入分辨率大概有多高?
因为不同任务决定了:
- 该选什么视觉 backbone
- 是否需要高分辨率支持
- 是否要多图能力
- 是否要加强 OCR / doc understanding
2)先把视觉 token 成本算清楚
别只看模型参数量。
多模态系统里,真正容易被低估的是:
- 单图 token 数
- 多图叠加后 token 数
- 不同分辨率档位的时延差异
这会直接决定你的并发上限和 GPU 预算。
3)如果业务强调准确定位,别只看通用聊天体验
很多模型聊天体验不错,但:
- bounding / grounding 差
- OCR 不稳
- 表格解析容易错位
所以评测必须贴近任务,而不是只问几句"图里是什么"。
4)能分阶段就分阶段,不要一股脑端到端
例如:
- 文档任务:先页面筛选,再高分辨率解析
- 多图任务:先粗筛,再精看重点图
- GUI 任务:先定位区域,再做操作推理
这类 pipeline 化做法,通常比"把所有视觉内容一次性塞给模型"更稳、更便宜。
十、最后总结
图像之所以能"接入"语言模型,不是因为 LLM 自己突然学会了看像素。
而是因为多模态系统额外补上了几层关键结构:
- 视觉编码器把像素压成视觉表示
- patch 和 resolution 决定视觉 token 数量与细节粒度
- projector / adapter 把视觉特征接入 LLM 可消费的空间
- 对齐训练让图像和语言开始在同一任务框架里协同
- 指令微调和专项数据让模型学会围绕真实问题去使用视觉信息
所以一个 VLM 的本质,不是"LLM + 图片输入"这么简单。
更准确地说,它是:
在语言模型主干之外,增加了一整套视觉感知、模态桥接和任务对齐机制。
如果你现在正在选型或搭建多模态系统,我最建议优先盯住三件事:
- 视觉 token 成本有没有算清楚
- projector / 连接模块是否足够支撑任务复杂度
- 训练与评测是否真的覆盖了你关心的视觉任务,而不只是通用 caption
这三件事,往往比单纯换一个更大的底模,更决定系统最后是不是"真能用"。