• 欢迎关注我的微信公众号“ Falost ” 右边扫描关注 --->>

多模态系列开篇:图片是上下文里漏算的一笔账——视觉模型怎么选、一张图折算多少 token?

AI / 大模型 神棍 307℃ 0评论

上篇(上下文工程收官)我留了个尾巴:文本 token 的三本账算完了,发现还有一类输入没算进去——图片。当时我凭感觉写下“一张截图可能比几千字还贵”,结果这周把 DeepSeek 官方 Vision 文档翻完,发现这话得修正:图片确实按像素折算 token,但官方给单张图设了封顶,一张顶格大截图折下来也就相当于 640 个汉字,到不了“几千字”。原因在于图片进 API 走的是一套跟文本完全不同的规则:能收图的只有一个模型、图片只能放在 user 消息里、传图有三种姿势、计价还带“自动缩放 + 封顶价”。这篇是“多模态”系列的开篇,我把“图片进上下文”这件事从头捋一遍。

一、为什么图片值得单开一个系列

动机很实在:做完上下文预算表之后,我给博客做了个“截图问答”的小工具,把报错截图丢给模型让它解释。结果一翻账单就发现,图片 token 混在输入里,用原来的对账方式根本看不出哪张图花了多少钱。再盘了盘手头的需求,绕不开图片的活一大堆:后台截图找 bug、设计稿转页面描述、发票 OCR、产品截图建知识库。上下文工程那几篇解决的是文本上下文怎么省,而图片的计价单位、缩放规则、缓存档位都不一样,不单独捋一遍,后面做图文混排的 RAG 一定会踩坑。

二、视觉模型怎么选:能收图的其实只有一个

先泼盆冷水:不是随便哪个模型都能看图。DeepSeek API 目前只有 deepseek-v4-flash-vision-exp 一个视觉模型收图,拿 v4-flash 文本模型传图会直接报 400,错误原文是 “This model does not support image”。所以“怎么选”落到我这儿是三个选择题:要不要看图、detail 用哪档、用哪种姿势传图。

要不要看图,答案沿用上下文预算表的路由思路:文本能答就别发图,发图至少几十 token 起步,纯文本能说清的问题挂图纯属浪费。detail 档位方面,image_url 里可以带 detail 参数:low 会把图先压到 512×512,官方原话是“细节不重要时更快更省”;high 和 original 保留原图,auto 目前等价于 original。我的默认是 low,只有要读小字(报错堆栈、表格里的数字)时才换 original。

传图有三种姿势,都是标准 OpenAI 格式——content 从字符串变成数组:

  1. base64 内联:本地文件最省事,data: URL 直接塞进 image_url。注意请求体上限 48MiB,base64/外链单图最大 32MiB。
    2. 外链 URL:模型自己去下载,URL 最长 8192 字符,60 秒内必须下完。
    3. Files API:先上传拿 file_id,之后反复引用同一张图不用重复传,单图上限放宽到 64MiB——同一张图要多次请求的场景我选它。

限制清单里我踩过的坑都标出来:图片只能出现在 user 消息里,放 system 或 assistant 直接 400;支持 JPEG/PNG/GIF/WebP,官方按文件内容识别格式、不看扩展名;单请求最多 600 张图,单边最长 8192px,超过 15 张时降到 4096px;所有图合计不超过 64MiB,带 file_id 可到 200MiB。最小可跑的 base64 示例:

from openai import OpenAI
import base64

client = OpenAI(api_key="<你的key>", base_url="https://api.deepseek.com")

with open("error.png", "rb") as f:
    b64 = base64.b64encode(f.read()).decode("utf-8")

resp = client.chat.completions.create(
    model="deepseek-v4-flash-vision-exp",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "这张报错截图的问题是什么?"},
            {"type": "image_url", "image_url": {
                "url": f"data:image/png;base64,{b64}",
                "detail": "low",
            }},
        ],
    }],
)
print(resp.choices[0].message.content)

三、一张图折算多少 token:官方口径和我算的账

官方 Vision 文档把折算规则写得很清楚:图片在推理前会被自动缩放——总像素数低于约 384×384 的图先等比放大,大图等比缩到像素总量约等于 800×800 的图;缩放完按尺寸折算 token,单张图封顶 384 token。所以 2000×2000 和 5000×5000 的图花一样的钱,都顶到 384。多张图各自独立折算,没有打包价。

384 是什么量级?按官方口径,1 个汉字 ≈ 0.6 token、1 个英文字符 ≈ 0.3 token。换算下来:384 token ≈ 640 个汉字 ≈ 1280 个英文字符。一张顶格截图,约等于往输入里塞了六百多字的材料——所以我在上篇预告里“一张截图可能比几千字还贵”的说法不准确,按封顶算到不了那个量级,这里修正一下。真正让图片变贵的是两种情况:一是让模型把图里内容逐行念出来(OCR 式提问)——输出 token 没有单图封顶、跟着问题走,输出单价还是缓存未命中输入的 3 倍(off-peak 下 0.66 对0.22);或是一次塞几十上百张图,每张独立计费、线性累加。

沿用上篇预算表的算法(off-peak、缓存未命中 0.22/百万):1 张 1920×1080 截图按顶格算 384 token,384 × 0.22 / 1000000 ≈ 0.008 美分;走缓存命中档(0.007/百万)更是几乎可以忽略。说到底,图片并不比文本“贵”,问题在于它“看不见”——混在 usage 里没法单独对账。我的做法还是上篇那套:把 resp[“usage”] 落日志。官方口径也是以 API 返回的 usage 为准,页面上的 Image Token Calculator 只供估算。

四、图片能不能进 RAG

能,但不是把图直接塞进我现在的向量库。文本 embedding 只认文字不认像素,图片得先“翻译”成文本,或者换一条多模态检索的路线。我盘下来是两条:

路线 A:图转文再检索(我现在在用的)。查询前先把图片交给视觉模型转成文字描述或 OCR 文本,存进现有的文本 RAG。优点是完全复用 RAG 进阶、RAG 评估那几篇的检索与评测体系,成本低、出问题好排查;缺点是转写有损,颜色、版式这类信息会丢。

路线 B:多模态检索(论文路线)。让视觉语言模型直接对图文混合文档建索引,代表工作是 ColPali(arXiv:2407.01449,2024),用 VLM 把整页文档编码成向量再检索,不依赖前置的文本抽取。缺点是得自己跑 VLM 推理,索引和检索链路全部重做,个人折腾成本不低。

我的结论:先把 A 走通,等文档量上来、纯文字检索明显漏召回时,再拿小批量数据跟 B 做一轮对比。实测对比下篇展开。

总结

一句话:图片进 API 不是“传个图就行”,它有自己的选型(模型、detail、传图姿势)、自己的计价(自动缩放 + 单张 384 token 封顶,顶格一张 ≈ 640 汉字)、自己的归宿(进 RAG 先图转文,多模态检索是下一阶段)。我的建议是先动手:用 detail=low 跑通一条 base64 传图,把 usage 记进日志,再谈优化。

下期预告

下篇我准备拿真实截图库做一次实测:路线 A 的“图转文”具体怎么做、转写质量怎么量化,再跟路线 B 的多模态检索(ColPali)比一轮召回效果,最后给出我这种个人开发者该选哪条。想一起折腾的,下篇见。

参考文献

DeepSeek API Docs:Vision(支持格式、三种传图方式、detail、token 折算与单图封顶、限制清单):
https://api-docs.deepseek.com/guides/vision

DeepSeek API Docs:Models & Pricing(deepseek-v4-flash-vision-exp 定价与峰谷时段):
https://api-docs.deepseek.com/quick_start/pricing

DeepSeek API Docs:Token & Token Usage(1 汉字 ≈ 0.6 token、Image Token Calculator):
https://api-docs.deepseek.com/quick_start/token_usage

Faysse et al.:ColPali: Efficient Document Retrieval with Vision Language Models(arXiv:2407.01449):
https://arxiv.org/abs/2407.01449

上一篇:上下文工程收官:怎么管住一次请求的 token 花销?我做了一张“上下文预算表”:
https://www.fedte.cc/p/838.html

转载请注明:Falost的小窝 » 多模态系列开篇:图片是上下文里漏算的一笔账——视觉模型怎么选、一张图折算多少 token?

如果你觉得这篇文章不错或者对你有帮助,想请我喝一杯咖啡,可以打赏
喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址