Skip to content

多模态接入实战:一张图片到底吃掉多少 token ​

很多团队接多模态大模型时,都是这样翻车的:

  • 按「一张图 ≈ 一次请求」做成本预算,上线后账单是预估的好几倍
  • 图片里的表格小字死活识别不出来,以为是模型不行
  • 把图片调清晰之后识别准了,成本又炸了

这三个现象背后是同一件事:图片不是一张「图」,它是一串长度可计算的 token。 搞不清这件事,成本和效果都调不动。


1. 图片是怎么变成 token 的 ​

语言模型只认识向量序列。要让模型「看图」,得先把图切碎、编码、再对齐到语言模型的维度上:

图片转成视觉 token 的流水线,以及 token 数随分辨率平方增长

关键是最后一步的数量关系:

视觉 token 数 ≈ (图片高度 ÷ patch 边长) × (图片宽度 ÷ patch 边长)

以 patch = 14×14 为例(CLIP ViT-L/14 这类常见配置):

图片分辨率patch 数视觉 token
224 × 22416 × 16256
336 × 33624 × 24576
448 × 44832 × 321024
1024 × 102473 × 735329

这是平方增长,不是线性

边长从 336 提到 1024,只涨了 3 倍;token 从 576 涨到 5329,涨了 9.3 倍。

换句话说,你为了「看得更清楚」把图放大一倍,成本要乘以四。 这是多模态成本失控的第一大来源。

别把这张表当精确计费依据

上面是按 patch 切分的理想估算,用来建立量级直觉。各家 API 的视觉 token 计算规则不同(有的按 512px 瓦片切分、有的会做 token 合并、有的对长边有额外缩放),而且规则会变。做预算时以你的供应商官方文档为准,本文的公式只用来判断「哪个方向能省钱、大概省多少」。


2. 一个直观的量级感受 ​

576 个视觉 token 是什么概念?

  • 一篇 400 字的中文文章,大约就是 500~700 个 token
  • 也就是说,一张 336×336 的图 ≈ 一篇文章
  • 而一张 1024×1024 的图(5329 token),已经超过很多模型单次请求的上下文预算

再考虑常见的多图场景:

场景图片数估算视觉 token
单图问答1 × 336²576
商品图 + 细节图2 × 448²2048
合同逐页识别10 × 1024²53,290 ❌ 直接超限

最后一行就是典型的翻车现场:按「10 张图」估成本觉得没事,按 token 一算根本放不下。


3. 把 token 压下来的四个手段 ​

按性价比从高到低排列,不要一上来就动分辨率:

3.1 先裁剪,只传需要的区域(最高杠杆) ​

绝大多数业务场景里,整张图的信息密度都很低——一张商品图你可能只关心标签,一张发票你只关心金额区域。

❌ 传整张 1024×1024  → 5329 token
✅ 裁出标签区域 224×224 → 256 token    省 95%

裁剪的另一个好处是效果反而更好:patch 粒度相对目标区域更细,小字更容易认出来。这是少见的「又省钱又提效果」的操作。

3.2 控制分辨率上限 ​

如果必须传整图,就在上传前统一压到模型的有效输入上限。

python
from PIL import Image
from io import BytesIO

MAX_SIDE = 1024          # 超过这个边长,token 数增长得毫无性价比

def normalize(path: str) -> bytes:
    img = Image.open(path).convert("RGB")
    w, h = img.size
    if max(w, h) > MAX_SIDE:
        scale = MAX_SIDE / max(w, h)
        img = img.resize((int(w * scale), int(h * scale)), Image.LANCZOS)

    buf = BytesIO()
    # 质量 80 对多数视觉任务已足够,体积能再降一半
    img.save(buf, format="JPEG", quality=80, optimize=True)
    return buf.getvalue()

💡 注意顺序:先裁剪再缩放。反过来会先把细节抹掉,再裁出来也是糊的。

3.3 同一张图别重复传 ​

多轮对话里最容易浪费的地方:用户第一轮发了图,后面每轮追问都重新带上图片。视觉 token 会被重复计费。

优先用支持「引用已发送图片」的会话机制;如果 API 不支持,就在第一轮把图片相关的信息抽成文本(比如让模型先输出图片描述或结构化字段),后续轮次只用文本对话。

3.4 选对模型 ​

不同模型的视觉 token 压缩策略差别很大,有的会在 projector 阶段做 token 合并。同样分辨率的图,不同模型消耗的 token 可能差好几倍。

选型时把「单位图片的 token 成本」和「识别准确率」放在一起比,而不是只比每百万 token 的单价。


4. 结构化输出:多模态最容易崩的地方 ​

视觉模型在「按格式输出」这件事上,比纯文本模型更不稳定——因为它多了一层不确定的输入。

4.1 三个稳定化手段 ​

手段做法适用
JSON Mode / 结构化输出用 API 原生的 JSON schema 约束模型支持时首选
Function Calling把要抽取的字段定义成工具参数字段较多、需要枚举值时
提示 + 校验重试明确给出字段与示例,解析失败就重试兜底方案

4.2 一定要做校验和重试 ​

不要假设模型一定返回合法 JSON:

python
import json
from pydantic import BaseModel, ValidationError

class Invoice(BaseModel):
    invoice_no: str
    total: float
    date: str


def extract(client, image_bytes: bytes, retries: int = 2) -> Invoice | None:
    for attempt in range(retries + 1):
        resp = client.chat.completions.create(
            model="your-vlm",
            response_format={"type": "json_object"},   # 支持时优先用
            messages=[{
                "role": "user",
                "content": [
                    {"type": "text", "text": "抽取发票号、金额、日期,返回 JSON。"},
                    {"type": "image_url", "image_url": {"url": to_data_url(image_bytes)}},
                ],
            }],
        )
        raw = resp.choices[0].message.content
        try:
            return Invoice.model_validate_json(raw)
        except (ValidationError, json.JSONDecodeError):
            if attempt == retries:
                return None
            # 把校验错误回灌给模型,比盲目重试有效得多
            continue
    return None

4.3 把「顺序」说清楚 ​

多图对比时,模型很容易张冠李戴。必须在文本里显式标号,别指望模型自己对齐:

❌ "比较这两张图"
✅ "图1 是改造前,图2 是改造后。请逐项对比图1和图2的差异。"

5. 什么时候不该降本 ​

降 token 不是无脑操作,以下几类场景降了就是错:

场景为什么不能降
医疗影像、工业缺陷检测细节本身就是判据,压缩即丢失信息
手写体、密集表格patch 粒度不够就直接认错
需要读小字的合同/票据应该裁剪后放大,而不是整体降分辨率
颜色/纹理判别JPEG 有损压缩会改变色值,建议用 PNG 或高质量 JPEG

判断准则

问自己一句:「我降分辨率之后,人还能看出结论吗?」 人能看出来的,模型大概率也能;人已经看不清的,别指望模型能补回来。


6. 踩坑清单 ​

现象原因解决
账单是预估的好几倍按「图片张数」估成本,没按 token 估用 (边长/patch)² 先估量级
图片调清晰后成本失控token 随边长平方增长只放大目标区域,别放大整图
图里小字识别不出来有效分辨率不足,patch 粒度太粗裁剪目标区域后再放大
多轮对话成本异常高每轮都重新传图,视觉 token 重复计费首轮抽成文本,或用图片引用机制
结构化输出时好时坏VLM 的格式遵循能力弱于纯文本模型JSON Mode / Function Calling + 校验重试
多图对比张冠李戴视觉 token 之间缺乏显式边界文本里显式标「图1/图2」并说明对应关系
先缩放后裁剪,结果很糊顺序错了,细节已被抹掉先裁剪,再缩放
同一张图不同模型 token 数差很多各家瓦片/patch 规则与压缩策略不同以官方文档为准,横向比「单位图片成本」

7. 小结 ​

要点说明
图片 = 一串可计算的 token(高 ÷ patch) × (宽 ÷ patch),与内容复杂度无关
增长是平方级的边长翻倍,token 翻 4 倍——这是成本失控的根源
最高杠杆是裁剪只传需要的区域,既省钱又提准确率
顺序很重要先裁剪、再缩放,反过来细节就没了
多轮别重复传图视觉 token 会被重复计费,首轮抽成文本
结构化输出要兜底VLM 格式遵循弱,必须校验 + 回灌错误重试
有些场景不能降细节即判据的场景,裁剪放大优于整体降分辨率
📖本文阅读--次|📊全站访问--次|👥访客--人