首页
/ Aya Vision 多模态视觉语言模型实战指南:基于 Transformers 的图像理解与生成

Aya Vision 多模态视觉语言模型实战指南:基于 Transformers 的图像理解与生成

2026-09-06 18:31:09作者:吴年前Myrtle

Aya Vision 是 Cohere Labs 发布于 2025 年的开源多模态视觉-语言模型(Vision-Language Model, VLM)家族,在本仓库(Transformers)中以 AyaVisionModel / AyaVisionForConditionalGenerationAyaVisionProcessor 等 API 形式提供完整支持。本文围绕 官方模型文档 展开,先厘清其"CommandR-7B 文本大模型 + SigLIP 视觉编码器"的混合架构与多语言设计,再给出基于 pipelineAutoModel/AutoProcessor、bitsandbytes 4-bit 量化的可运行推理方案,并覆盖单图问答、多图对比与批量推理三类高频场景。读完本文,你将能在本仓库环境中直接完成 Aya Vision 的加载、prompt 格式化、图像 token 展开与解码,并从源码层面理解其视觉特征投影、占位符替换与 token 计数校验等底层机制。

一、模型背景:合成标注、跨模态合并与多语言视觉理解

Aya Vision 是由 Cohere Labs 推出的开源权重多模态视觉-语言模型家族,其训练采用了两个关键技术:

  • 合成标注框架(Synthetic Annotation Framework):自动生成高质量的多语言图像描述,用于提升模型在多语言环境下对图像内容的理解与应答质量;
  • 跨模态模型合并(Cross-Modal Model Merging):在引入视觉能力的同时,通过模型合并技术防止语言模型原有文本能力发生退化。

从架构上看,Aya Vision 将 CommandR-7B 语言模型SigLIP 视觉编码器 组合在一起。该模型由 saurabhdash 与 yonigozlan 两位贡献者合入 Transformers,仓库中的完整实现位于 src/transformers/models/aya_vision/,包含以下文件:

二、架构纵深:从源码理解 Aya Vision 的三段式设计

AyaVisionModel.__init__ 的实现(见 modeling_aya_vision.py)可以看出,模型由三个子模块装配而成,是典型的 encoder-projector-decoder 三段式结构:

self.vision_tower = AutoModel.from_config(config.vision_config)          # SigLIP 视觉塔
self.multi_modal_projector = AyaVisionMultiModalProjector(config)        # 视觉-语言对齐投影层
self.language_model = AutoModel.from_config(config.text_config)          # CommandR-7B 语言模型

对应 配置实现__post_init__ 的默认装配逻辑:当未显式传入子配置时,vision_config 默认实例化为 siglip_vision_model(hidden_size=1152、patch_size=14、image_size=384、26 层、14 头、vision_use_head=False),text_config 默认实例化为 cohere2 语言模型。也就是说 Aya Vision 本质上是把 SigLIP 的视觉 token 序列经过一个投影适配器后,注入 CommandR-7B(cohere2 架构)的输入嵌入序列中做自回归生成。

2.1 多模态投影器:Pixel Shuffle 降采样 + SwiGLU

与常见 VLM 直接用一个线性层对齐不同,Aya Vision 的 AyaVisionMultiModalProjector 先对视觉序列做 pixel shuffle 降采样downsample_factor 默认 2),再依次经过 LayerNorm、全连接与 SwiGLU 门控,核心计算位于 modular_aya_vision.py

  • pixel_shuffle(B, H*W, D) 的视觉特征按空间排布重排,将高度与宽度维度各除以 downsample_factor、通道数乘以 downsample_factor²,从而以更少的序列长度承载同样的视觉信息,降低后续自回归的注意力开销;
  • 投影分支先做 linear_1 扩维,再沿最后一维 chunk(2) 拆成两份做 SwiGLUACT2FN["silu"] 门控),最后 linear_2 收缩到 text_config.hidden_size,与语言模型隐藏维度对齐;
  • layernorm 的 epsilon 由 adapter_layer_norm_eps 控制(默认 1e-6)。

2.2 视觉特征注入:get_image_features 与占位符替换

AyaVisionModel.get_image_features(见 modeling_aya_vision.py)强制以 output_hidden_states=True 跑视觉塔,再依据 vision_feature_layer 选择隐层(默认取最后一层 -1);当 vision_feature_select_strategy="default" 时会裁掉第 0 位的 CLS token(selected_image_feature[:, 1:]),"full" 则保留全部;投影结果 reshape 为 (batch, num_image_tokens, text_hidden_size) 后作为 pooler_output 返回。

forward 阶段(见 modular_aya_vision.py)通过 get_placeholder_mask 在文本嵌入序列中定位 <image> 占位 token,再执行 inputs_embeds.masked_scatter(special_image_mask, image_features)——把占位符嵌入原位替换为投影后的图像特征,最终与语言模型嵌入拼接成完整输入序列送进 CommandR-7B 解码。因为视觉特征在进入语言模型前已完成映射,单张图的 token 长度由 tile 数与 patch 数共同决定,这一细节会直接影响 KV cache 与显存占用。

2.3 注意力与训练能力

AyaVisionPreTrainedModel 显式声明支持 Flash Attention、SDPA(scaled dot-product attention)与 Flex Attention,并支持 gradient checkpointing(见 modeling_aya_vision.py),因此可无缝接入本仓库的 attn_implementation 选择机制。语言建模标签 labels(取值为 [0, vocab_size)-100,后者被忽略不参与损失)与 logits_to_keep 参数则沿用 LLaVA 系条件生成接口,见 AyaVisionForConditionalGeneration 的 docstring 示例(modeling_aya_vision.py)。

三、AyaVisionConfig:关键配置参数

AyaVisionConfigmodel_type = "aya_vision")通过 sub_configs 声明了两个子配置槽位 text_configvision_config,并提供了 image_token_id → image_token_index 的属性映射(见 configuration_aya_vision.py)。常用参数如下:

参数 默认值 说明
vision_config SigLIP(siglip_vision_model 视觉塔配置,可传 dict 或 PreTrainedConfig;dict 会在 __post_init__ 中被解析为对应架构的完整 config
text_config cohere2 语言模型配置,可传 dict 或 PreTrainedConfig
vision_feature_layer -1 选取视觉塔的第几层隐状态作为图像特征,支持 int 或层号列表(多层级联)
vision_feature_select_strategy "full" 仅允许 "default"(裁掉 CLS token)或 "full",否则 validate_architecture 会抛错
downsample_factor 2 视觉特征像素降采样因子
adapter_layer_norm_eps 1e-6 投影适配器中 LayerNorm 的 epsilon
image_token_index 255036 图像占位 token 在词表中的索引
tie_word_embeddings True 是否绑定输入输出词嵌入

四、处理器与 Prompt 格式化机制

图像本身无法进入语言模型,需要由 AyaVisionProcessor 把"文本 + 图像 URL/像素"混合消息转换成 input_idspixel_values。处理器组合了 SigLIP 的图像处理器与 Cohere 词元器,并维护一套专属的特殊 token(见 processing_aya_vision.py):

Token 默认值 含义
image_token <image> 消息模板中代表一张图的通用占位符
start_of_img_token <|START_OF_IMG|> 图像块序列起始标记
end_of_img_token <|END_OF_IMG|> 图像块序列结束标记
img_patch_token <|IMG_PATCH|> 单个视觉 patch 的文本标记
img_line_break_token <|IMG_LINE_BREAK|> 图像 patch 行内换行标记
tile_token TILE 多 tile 切片中非全局 tile 的编号前缀
tile_global_token TILE_GLOBAL 全局/封面 tile 标记

Aya Vision 的图像会被切成若干 tile(图块),replace_image_tokenprocessing_aya_vision.py)根据每张图的 num_patches 动态展开占位串:每个非全局 tile 记为 TILE_i + 若干 <|IMG_PATCH|>,最后追加一个 TILE_GLOBAL 及其 patch 串,整体夹在起始/结束标记之间;单 tile 图片则只含 TILE_GLOBAL 部分。每个 tile 的 patch 数量由 (img_size // patch_size) ** 2 决定,处理器默认 patch_size=28img_size=364,而处理器内部的 patch_size 实际等于 patch_size * downsample_factor

AyaVisionProcessorKwargs 还设置了两个关键默认值(processing_aya_vision.py):

  • padding_side="left":解码任务使用左填充,避免右侧 padding 干扰生成;
  • images_kwargs.crop_to_patches=True:图像处理默认按 tile 切分,可在调用时传入 crop_to_patches=False 覆盖(测试中也验证了该开关透传行为,见 test_processing_aya_vision.py)。

此外处理器实现了一个"多模态 token 数守恒"校验 _check_special_mm_tokens:对比文本中 <|IMG_PATCH|> 出现次数与 input_ids 中对应 token id 的数量,若二者不一致(典型原因是文本被 truncation="max_length" 截断),会抛出 ValueError 提醒增大 max_length 或关闭截断,从源头避免"图像 token 被截掉却仍有图像特征注入"这类静默错误。

五、快速上手一:Pipeline 一行式推理

pipeline 提供了最快的接入方式,将模型、图像处理器与 tokenizer 全部封装好,只需给定带图消息即可得到回答:

from transformers import pipeline

pipe = pipeline(model="CohereLabs/aya-vision-8b", task="image-text-to-text", device_map="auto")

# 消息中的图像由 url 字段给出,文本可任意使用目标语言
messages = [
    {"role": "user",
     "content": [
       {"type": "image", "url": "https://media.istockphoto.com/id/458012057/photo/istanbul-turkey.jpg?s=612x612&w=0&k=20&c=qogAOVvkpfUyqLUMr_XJQyq-HkACXyYUSZbKhBlPrxo="},
       {"type": "text", "text": "Bu resimde hangi anıt gösterilmektedir?"},
    ]},
]

outputs = pipe(text=messages, max_new_tokens=300, return_full_text=False)
print(outputs)

上面的土耳其语提问会被模型识别为面向图像内容的问题(这里指向伊斯坦布尔的地标),体现其多语言能力。task="image-text-to-text" 是图像到文本任务的通用 pipeline 名,return_full_text=False 用于只保留新生成的文本。若希望完全离线使用,可将 url 换成本地图片路径。

六、快速上手二:AutoModel + AutoProcessor 精细化推理

需要控制采样、批处理或部署到多卡时,使用 AutoModelForImageTextToTextAutoProcessor。模型加载与消息格式化流程如下:

from transformers import AutoModelForImageTextToText, AutoProcessor

model_id = "CohereLabs/aya-vision-8b"

processor = AutoProcessor.from_pretrained(model_id)
model = AutoModelForImageTextToText.from_pretrained(model_id, device_map="auto")

# 用 aya-vision 的 chat template 统一格式化消息
messages = [
    {"role": "user",
     "content": [
       {"type": "image", "url": "https://pbs.twimg.com/media/Fx7YvfQWYAIp6rZ?format=jpg&name=medium"},
       {"type": "text", "text": "चित्र में लिखा पाठ क्या कहता है?"},
    ]},
]

inputs = processor.apply_chat_template(
    messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt"
).to(model.device)

gen_tokens = model.generate(
    **inputs,
    max_new_tokens=300,
    do_sample=True,
    temperature=0.3,
)

print(processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))

要点说明:

  • apply_chat_template 会把 <image> 占位符按第四节的规则展开成实际的 tile/patch token 串,同时完成图像解码、归一化与 pixel_values 张量化,tokenize=True 表示直接返回 token 化结果;
  • add_generation_prompt=True 会追加助手的起始标记,让生成从正确位置开始;
  • 解码时通过 gen_tokens[0][inputs.input_ids.shape[1]:] 切除提示词部分,再用 skip_special_tokens=True 去掉图像块等特殊 token,还原纯文本回答;
  • 上面的印地语提问演示了模型对非拉丁文字的识别与应答能力。

七、多图场景:图间对比与联合推理

Aya Vision 支持在同一条消息中放置多张图片,适合"识别并对比多个地标/物体"类任务。只需在 content 列表中依次放入多个 {"type": "image"} 条目,处理器会为每张图生成对应的占位与像素输入,模型在自回归时通过各自的占位符区分不同图像:

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText

processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b")
model = AutoModelForImageTextToText.from_pretrained("CohereForAI/aya-vision-8b", device_map="auto")

messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg"},
            {"type": "image", "url": "https://thumbs.dreamstime.com/b/golden-gate-bridge-san-francisco-purple-flowers-california-echium-candicans-36805947.jpg"},
            {"type": "text", "text": "These images depict two different landmarks. Can you identify them?"},
        ],
    },
]

inputs = processor.apply_chat_template(
    messages, padding=True, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt"
).to(model.device)

gen_tokens = model.generate(**inputs, max_new_tokens=300, do_sample=True, temperature=0.3)

gen_text = processor.tokenizer.decode(gen_tokens[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
print(gen_text)

八、批量推理:多组对话一次前向

当需要同时处理多条不同图像的对话(如离线评测、服务端批处理)时,把每条对话构造成一个独立的 message 列表,再组合成 batch_messages 一次性交给 apply_chat_template;处理器负责对齐各样本的 token 序列并统一 padding:

import torch
from transformers import AutoProcessor, AutoModelForImageTextToText

processor = AutoProcessor.from_pretrained("CohereForAI/aya-vision-8b")
model = AutoModelForImageTextToText.from_pretrained("CohereForAI/aya-vision-8b", device_map="auto")

batch_messages = [
    [  # 第 1 条对话:单图
        {"role": "user", "content": [
            {"type": "image", "url": "https://huggingface.co/roschmid/dog-races/resolve/main/images/Border_Collie.jpg"},
            {"type": "text", "text": "Describe what you see."},
        ]},
    ],
    [  # 第 2 条对话:双图对比
        {"role": "user", "content": [
            {"type": "image", "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg"},
            {"type": "image", "url": "https://thumbs.dreamstime.com/b/golden-gate-bridge-san-francisco-purple-flowers-california-echium-candicans-36805947.jpg"},
            {"type": "text", "text": "These images depict two different landmarks. Can you identify them?"},
        ]},
    ],
]

batch_inputs = processor.apply_chat_template(
    batch_messages,
    padding=True,
    add_generation_prompt=True,
    tokenize=True,
    return_dict=True,
    return_tensors="pt",
).to(model.device)

batch_outputs = model.generate(**batch_inputs, max_new_tokens=300, do_sample=True, temperature=0.3)

for i, output in enumerate(batch_outputs):
    response = processor.tokenizer.decode(output[batch_inputs.input_ids.shape[1]:], skip_special_tokens=True)
    print(f"Response {i+1}:\n{response}\n")

注意批内各对话的图数、文本长度均可不一致,处理器会按最长序列填充;配合默认的左填充策略,逐条解码并切除各自的提示长度即可还原每个回答。仓库处理测试中对"批量图像重建顺序正确性"有专门断言(见 test_processing_aya_vision.py),说明 batching 时 pixel_valuesinput_ids 会按顺序严格对齐,可以放心使用。

九、显存优化:bitsandbytes 4-bit 量化推理

大模型在低精度下表示权重可显著降低显存占用。关于支持的量化后端总览,可参考 Quantization overview。对于 Aya Vision,官方示例使用 bitsandbytes 将权重量化为 4-bit(32B 版模型通常建议走这条路):

import torch

from transformers import AutoModelForImageTextToText, AutoProcessor, BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bit_use_double_quant=True,
)

processor = AutoProcessor.from_pretrained("CohereLabs/aya-vision-32b", use_fast=True)
model = AutoModelForImageTextToText.from_pretrained(
    "CohereLabs/aya-vision-32b",
    quantization_config=bnb_config,
    device_map="auto",
)

inputs = processor.apply_chat_template(
    [{"role": "user", "content": [
        {"type": "image", "url": "https://huggingface.co/roschmid/dog-races/resolve/main/images/Border_Collie.jpg"},
        {"type": "text", "text": "Describe what you see."},
    ]}],
    padding=True,
    add_generation_prompt=True,
    tokenize=True,
    return_tensors="pt",
).to(model.device)

generated = model.generate(**inputs, max_new_tokens=50)
print(processor.tokenizer.decode(generated[0], skip_special_tokens=True))

BitsAndBytesConfigload_in_4bit=True 开启 4-bit 加载,bnb_4bit_quant_type="nf4" 使用信息论上更优的 NF4 数据类型,bnb_4bit_compute_dtype=torch.bfloat16 让反量化后的矩阵运算仍以 bf16 计算,bit_use_double_quant=True 对量化常数做二次量化以进一步省显存。量化加载同样需要 device_map="auto" 才能配合 accelerate 完成分片放置;需要说明的是,量化主要在推理侧降低显存峰值,若追求可复现的输出建议关闭采样或固定随机种子。

十、核心 API 一览与输出结构

除本文已演示的用法外,模型文档 还为如下组件维护了完整的 autodoc API 参考,可在代码中使用:

  • AyaVisionProcessor:组合 SigLIP 图像处理器与 tokenizer,负责 chat template 展开、图像 patch 化、token 计数校验等,核心方法是 __call__ 与继承自 ProcessorMixinapply_chat_template
  • AyaVisionConfig:控制视觉塔/语言模型子配置、特征层选择与投影器参数(见第三节参数表);
  • AyaVisionModel:不含语言建模头的骨干模型(vision_tower + projector + language_model),提供 get_image_features 方法,可直接提取投影后的图像特征供下游使用;
  • AyaVisionForConditionalGeneration:面向图像到文本任务的顶层模型,继承 LLaVA 系 for_causal_lm 接口,forward 支持 labels(语言建模损失)与 logits_to_keep,并封装了 generate

两类输出结构也值得留意(定义见 modeling_aya_vision.py):AyaVisionCausalLMOutputWithPast 在标准 LM 输出基础上增加了 image_hidden_states(尺寸 (batch, num_images, seq_len, hidden_size)),AyaVisionModelOutputWithPast 同样携带 image_hidden_states,便于调试或实现需要显式图像特征的二次开发。

十一、实践注意事项

综合官方文档与源码,在实际使用 Aya Vision 时有几点值得注意:

  1. 消息必须走 chat template:直接用 tokenizer 处理混合消息会导致图像占位无法展开为 tile/patch token 串,务必使用 processor.apply_chat_template 格式化,如本文第五至九节所示;
  2. 警惕文本截断导致的 token 失配:处理器会在格式化后校验 <|IMG_PATCH|> 的文本数量与 token id 数量是否一致,一旦 truncation="max_length" 截掉了图像占位就会抛错,此时应调大 max_length 或关闭截断;
  3. 图片 token 数可观:每个 tile 包含 (img_size / patch_size)²<|IMG_PATCH|>,多 tile 大图会在输入序列中占据可观长度,会直接影响 KV cache 显存与生成延迟,量化与批大小设定时应把这点计入预算;
  4. 多语言提问效果更佳的场景无需额外翻译:模型在土耳其语、印地语等非英语提示下仍可工作,这也是其合成多语言标注框架的设计目标之一;
  5. 不同实现文件以 modular 为准:若阅读 modeling_aya_vision.py 时想追溯设计意图,其内容由 modular_aya_vision.py 生成,修改源码需作用在 modular 文件上再重新生成,模型测试见 test_modeling_aya_vision.py

Aya Vision 以 CommandR-7B + SigLIP 的组合、多语言视觉理解和低比特量化的友好支持,为图像问答、图文对比与多模态内容生成提供了开箱即用的选择。将本节 pipeline、AutoModel、多图、批量与量化五类方案组合起来,即可在 Transformers 中搭建一套完整的 Aya Vision 图像到文本推理工作流。

登录后查看全文
热门项目推荐
相关项目推荐