多模态输入
多模态输入让模型不仅能处理文本,还能理解图像、音频等其他形式的内容。RouteAPI 支持在 /v1/chat/completions(OpenAI 格式)和 /v1/messages(Claude 格式)上传递多模态内容,并会自动完成不同上游协议之间的格式转换。
1. 多模态概述
Section titled “1. 多模态概述”支持的模态类型
Section titled “支持的模态类型”| 模态类型 | 说明 |
|---|---|
| 图像(Vision) | PNG、JPEG、WebP、GIF 等格式,用于图像理解、OCR、图表分析 |
| 音频(Audio) | 部分模型支持音频输入,用于语音理解、转录等场景 |
| 视频(Video) | 部分模型支持视频帧输入,将视频拆分为关键帧序列 |
目前图像输入支持最为广泛,几乎所有主流视觉模型都支持。音频和视频输入取决于具体模型能力。
支持的视觉模型
Section titled “支持的视觉模型”以下模型支持图像输入(非完整列表):
| 模型系列 | 典型模型 ID |
|---|---|
| OpenAI GPT-4 Vision | gpt-4o, gpt-4-turbo, gpt-5.5 |
| Claude Vision | claude-sonnet-4-5, claude-opus-4-5 |
| Gemini Vision | gemini-2.0-flash, gemini-2.5-pro |
| Azure OpenAI | azure-gpt-4o |
先用模型列表接口确认模型在你账户下可用:
curl https://api.routeapi.ai/v1/models \ -H "Authorization: Bearer $ROUTEAPI_KEY"该接口不返回图像输入能力字段。是否支持视觉输入请以供应商文档或一次实际带图请求为准。
2. 图像输入基础
Section titled “2. 图像输入基础”支持的图像格式
Section titled “支持的图像格式”| 格式 | MIME Type | 说明 |
|---|---|---|
| PNG | image/png | 无损格式,适合截图、图表 |
| JPEG | image/jpeg | 有损压缩,适合照片 |
| WebP | image/webp | 现代格式,体积小质量高 |
| GIF | image/gif | 非动图格式(只取首帧) |
图像大小限制
Section titled “图像大小限制”不同模型对图像大小的限制不同,通用建议:
| 限制项 | 建议值 | 说明 |
|---|---|---|
| 单张图像大小 | < 20 MB | 超大图像会增加处理时间和成本 |
| 图像分辨率 | 长边 ≤ 2048px | 高分辨率会被自动缩放或分块处理 |
| Base64 编码后 | < 32 MB | 总请求大小受上游服务限制 |
建议在上传前压缩图像,在保证可读性的前提下降低分辨率,这样既能减少传输时间,也能降低 token 成本。
分辨率和成本考虑
Section titled “分辨率和成本考虑”图像会被转换为 token 计费。高分辨率图像消耗的 token 数远高于文本:
- 低分辨率模式(如 OpenAI 的
detail: "low"):固定约 85 tokens/图。 - 高分辨率模式(如
detail: "high"):根据图像尺寸分块,一张 2048×2048 的图可能消耗 800-1500 tokens。
生产环境建议根据实际需求选择分辨率模式,不需要精细识别时优先用 low 模式。
3. 图像传递方式
Section titled “3. 图像传递方式”图像有两种传递方式:URL 和 Base64 编码。
URL 方式
Section titled “URL 方式”传递一个公开可访问的图像 URL,由上游模型服务抓取:
优点:
- 请求体积小,不占用你的上传带宽。
- 适合已有 CDN 托管的图像。
缺点:
- 图像必须公开可访问,上游服务的 IP 必须能访问到。
- 如果图像加载失败(网络问题、鉴权、过期链接),请求会报错。
适用场景:已有公开图床、CDN 托管的图像,不需要临时上传。
Base64 编码方式
Section titled “Base64 编码方式”把图像读取为二进制数据,用 Base64 编码后直接嵌入请求:
优点:
- 无需公开可访问的 URL,适合私有图像。
- 请求自包含,不依赖外部服务可用性。
缺点:
- Base64 编码会让数据体积增大约 33%。
- 请求体积大,上传耗时长。
适用场景:用户上传的私有图像、本地文件、临时截图等无公开 URL 的场景。
两种方式对比
Section titled “两种方式对比”| 对比项 | URL 方式 | Base64 方式 |
|---|---|---|
| 请求体积 | 小(仅 URL 字符串) | 大(Base64 编码后约为原文件 1.33 倍) |
| 上传速度 | 快 | 慢 |
| 图像可访问性 | 必须公开可访问 | 无要求,私有图像可用 |
| 外部依赖 | 依赖图像服务器和上游抓取 | 无外部依赖 |
| 适用场景 | 公开图床、CDN | 用户上传、本地文件 |
4. OpenAI 格式图像输入
Section titled “4. OpenAI 格式图像输入”在 /v1/chat/completions 中,图像通过 content 数组传递,每个元素是一个内容块,用 type 区分文本和图像。
content 数组结构
Section titled “content 数组结构”content 可以是字符串(纯文本),也可以是数组(多模态):
{ "role": "user", "content": [ { "type": "text", "text": "这张图片里有什么?" }, { "type": "image_url", "image_url": { "url": "https://example.com/image.jpg" } } ]}image_url 结构
Section titled “image_url 结构”image_url 内容块的字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 固定为 "image_url" |
image_url.url | string | 是 | 图像 URL 或 Base64 Data URI |
image_url.detail | string | 否 | 分辨率模式: "low", "high", "auto"(默认) |
detail 参数
Section titled “detail 参数”detail 控制图像处理的分辨率和成本:
| 值 | 行为 | Token 消耗 |
|---|---|---|
"low" | 低分辨率模式,图像缩小到固定尺寸(如 512×512) | 固定约 85 tokens |
"high" | 高分辨率模式,图像分块处理,保留细节 | 按分块数量,通常几百到上千 tokens |
"auto" | 模型自动选择(默认) | 取决于模型策略 |
成本差异示例:
- 一张简单截图用
"low"可能只需 85 tokens(约 ¥0.0001)。 - 同一张图用
"high"可能消耗 800 tokens(约 ¥0.001)。
对于不需要识别小字、细节的场景(如「这是什么动物」「界面主题色是什么」),用 "low" 即可满足需求。需要 OCR、读取图表数值、识别小物体时才需要 "high"。
URL 方式完整示例
Section titled “URL 方式完整示例”{ "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", "detail": "high" } }, { "type": "text", "text": "描述这张图片的内容" } ] } ]}Base64 方式完整示例
Section titled “Base64 方式完整示例”Base64 需要使用 Data URI 格式:data:<mime_type>;base64,<encoded_data>。
{ "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD..." } }, { "type": "text", "text": "这张图片里有哪些文字?" } ] } ]}注意 Base64 字符串可能非常长,上面示例做了截断。实际使用时完整编码可能有几百 KB 到几 MB。
5. Claude 格式图像输入
Section titled “5. Claude 格式图像输入”在 /v1/messages 中,图像通过 content 数组的 image 类型块传递,结构与 OpenAI 格式有明显差异。
content 数组结构
Section titled “content 数组结构”{ "role": "user", "content": [ { "type": "image", "source": { "type": "base64", "media_type": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQEAYABgAAD..." } }, { "type": "text", "text": "描述这张图片" } ]}source 结构
Section titled “source 结构”source 字段指定图像来源,有两种方式:
Base64 方式
Section titled “Base64 方式”| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 固定为 "base64" |
media_type | string | 是 | MIME 类型,如 image/jpeg, image/png |
data | string | 是 | Base64 编码的图像数据(不带 data: 前缀) |
注意 Claude 格式的 Base64 不需要 Data URI 前缀,直接传编码字符串。
{ "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" }}URL 方式
Section titled “URL 方式”| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | 固定为 "url" |
url | string | 是 | 公开可访问的图像 URL |
{ "type": "image", "source": { "type": "url", "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" }}完整请求示例
Section titled “完整请求示例”{ "model": "claude-sonnet-4-5", "max_tokens": 1024, "messages": [ { "role": "user", "content": [ { "type": "image", "source": { "type": "url", "url": "https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg" } }, { "type": "text", "text": "这是什么昆虫?" } ] } ]}6. Gemini 格式图像输入
Section titled “6. Gemini 格式图像输入”Gemini 原生格式使用 parts 数组而非 content,结构差异较大。RouteAPI 会在内部完成转换,你使用 OpenAI 或 Claude 格式调用 Gemini 模型时无需关心原生格式细节。以下仅作参考。
parts 数组
Section titled “parts 数组”{ "contents": [ { "role": "user", "parts": [ { "text": "描述这张图片" }, { "inlineData": { "mimeType": "image/jpeg", "data": "/9j/4AAQSkZJRg..." } } ] } ]}inlineData(Base64)
Section titled “inlineData(Base64)”| 字段 | 说明 |
|---|---|
inlineData.mimeType | MIME 类型 |
inlineData.data | Base64 编码数据 |
fileData(URI)
Section titled “fileData(URI)”Gemini 也支持通过文件 URI 引用已上传到 Google 服务的文件:
{ "fileData": { "mimeType": "image/jpeg", "fileUri": "gs://bucket-name/path/to/image.jpg" }}实际使用中,通过 RouteAPI 调用 Gemini 模型时,使用 OpenAI 或 Claude 格式即可,RouteAPI 会自动转换。
7. 多图像输入
Section titled “7. 多图像输入”所有主流视觉模型都支持在一次请求中传递多张图像。
单次请求多张图像
Section titled “单次请求多张图像”在 content / parts 数组中放多个图像块:
OpenAI 格式:
{ "role": "user", "content": [ { "type": "text", "text": "对比这两张图片的差异" }, { "type": "image_url", "image_url": { "url": "https://example.com/image1.jpg" } }, { "type": "image_url", "image_url": { "url": "https://example.com/image2.jpg" } } ]}Claude 格式:
{ "role": "user", "content": [ { "type": "text", "text": "这两张图片有什么相同和不同之处?" }, { "type": "image", "source": { "type": "url", "url": "https://example.com/before.jpg" } }, { "type": "image", "source": { "type": "url", "url": "https://example.com/after.jpg" } } ]}图像顺序和引用
Section titled “图像顺序和引用”模型会按数组顺序理解图像。如果文本中用「第一张图」「第二张图」指代,模型会按出现顺序对应。建议把说明文本放在所有图像之前或之后,不要穿插在中间,这样语义更清晰:
{ "content": [ { "type": "text", "text": "第一张是用户界面截图,第二张是设计稿,请对比两者的差异并给出修改建议。" }, { "type": "image_url", "image_url": { "url": "..." } }, { "type": "image_url", "image_url": { "url": "..." } } ]}与文本混合排列
Section titled “与文本混合排列”也可以让文本和图像交替出现,用于逐步说明:
{ "content": [ { "type": "text", "text": "这是原始界面:" }, { "type": "image_url", "image_url": { "url": "https://example.com/old.jpg" } }, { "type": "text", "text": "这是改进后的界面:" }, { "type": "image_url", "image_url": { "url": "https://example.com/new.jpg" } }, { "type": "text", "text": "请总结改进点。" } ]}实际效果取决于模型对内容块顺序的理解能力,主流视觉模型通常都能正确处理。
8. 音频输入
Section titled “8. 音频输入”部分模型支持音频输入,用于语音理解、转录、情感分析等场景。目前支持程度不如图像广泛。
支持的音频格式
Section titled “支持的音频格式”取决于具体模型,常见格式包括:
- WAV(
audio/wav) - MP3(
audio/mpeg) - OGG(
audio/ogg) - FLAC(
audio/flac)
音频传递方式
Section titled “音频传递方式”与图像类似,音频也支持 URL 和 Base64 两种方式。以 OpenAI 格式为例(假设模型支持):
{ "role": "user", "content": [ { "type": "input_audio", "input_audio": { "data": "<base64-encoded-audio>", "format": "wav" } }, { "type": "text", "text": "转录这段音频并总结要点" } ]}实际字段名称和结构取决于模型协议,使用前请查阅所选模型的文档或通过模型列表接口确认 supports_audio_input 字段。
9. 完整应用示例
Section titled “9. 完整应用示例”以下示例展示图像理解的端到端实现,包括 curl、Python、Node.js 三种语言。
图像理解和描述
Section titled “图像理解和描述”给定一张图片,让模型描述其内容。
curl(OpenAI 格式,URL 方式):
curl https://api.routeapi.ai/v1/chat/completions \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" } }, { "type": "text", "text": "详细描述这张图片的内容和氛围" } ] } ] }'Python(OpenAI SDK,Base64 方式):
import base64import osfrom openai import OpenAI
client = OpenAI( api_key=os.environ["ROUTEAPI_KEY"], base_url="https://api.routeapi.ai/v1",)
# 读取本地图像并编码为 Base64with open("image.jpg", "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8")
response = client.chat.completions.create( model="gpt-4o", messages=[ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{image_data}" }, }, {"type": "text", "text": "这张图片里有什么?"}, ], } ],)
print(response.choices[0].message.content)Node.js(openai 包,URL 方式):
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.ROUTEAPI_KEY, baseURL: 'https://api.routeapi.ai/v1',});
const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'user', content: [ { type: 'image_url', image_url: { url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/320px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg', }, }, { type: 'text', text: '用一句话概括这张图片的主题' }, ], }, ],});
console.log(response.choices[0].message.content);图表和数据可视化分析
Section titled “图表和数据可视化分析”上传图表截图,让模型读取数据并分析:
Python(Claude 格式,Base64):
import base64import osfrom anthropic import Anthropic
client = Anthropic( api_key=os.environ["ROUTEAPI_KEY"], base_url="https://api.routeapi.ai",)
with open("chart.png", "rb") as f: image_data = base64.b64encode(f.read()).decode("utf-8")
message = client.messages.create( model="claude-sonnet-4-5", max_tokens=1024, messages=[ { "role": "user", "content": [ { "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": image_data, }, }, { "type": "text", "text": "这个图表显示了什么趋势?请提取关键数据点并给出分析。", }, ], } ],)
print(message.content[0].text)OCR 文字提取
Section titled “OCR 文字提取”从截图或照片中提取文字内容:
curl(OpenAI 格式,高分辨率):
curl https://api.routeapi.ai/v1/chat/completions \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [ { "role": "user", "content": [ { "type": "image_url", "image_url": { "url": "https://example.com/document.jpg", "detail": "high" } }, { "type": "text", "text": "提取图片中的所有文字,保持原有的格式和结构" } ] } ] }'OCR 场景建议用 "detail": "high" 以保证识别精度,尤其是小字或密集文本。
多图对比分析
Section titled “多图对比分析”对比两张或多张图片的差异:
Python(OpenAI 格式,多图):
from openai import OpenAIimport os
client = OpenAI( api_key=os.environ["ROUTEAPI_KEY"], base_url="https://api.routeapi.ai/v1",)
response = client.chat.completions.create( model="gpt-5.5", messages=[ { "role": "user", "content": [ { "type": "text", "text": "对比以下两张图片,找出它们之间的 5 个主要差异:", }, { "type": "image_url", "image_url": {"url": "https://example.com/before.jpg"}, }, { "type": "image_url", "image_url": {"url": "https://example.com/after.jpg"}, }, ], } ],)
print(response.choices[0].message.content)图文混合对话
Section titled “图文混合对话”在多轮对话中混合图像和文本:
from openai import OpenAIimport os
client = OpenAI( api_key=os.environ["ROUTEAPI_KEY"], base_url="https://api.routeapi.ai/v1",)
messages = [ { "role": "user", "content": [ { "type": "image_url", "image_url": {"url": "https://example.com/product.jpg"}, }, {"type": "text", "text": "这个产品的主要特点是什么?"}, ], }]
response = client.chat.completions.create(model="gpt-4o", messages=messages)messages.append(response.choices[0].message)print("第一轮:", response.choices[0].message.content)
# 继续追问(纯文本)messages.append({"role": "user", "content": "它适合什么样的用户群体?"})response = client.chat.completions.create(model="gpt-4o", messages=messages)print("第二轮:", response.choices[0].message.content)图像只需在首轮传递一次,后续轮次模型会记住图像内容(在上下文窗口内),无需重复上传。
10. 最佳实践
Section titled “10. 最佳实践”在上传图像前做必要的优化,既能降低成本也能提升响应速度:
| 优化项 | 建议 |
|---|---|
| 尺寸 | 长边控制在 2048px 以内,除非确实需要识别更多细节 |
| 格式 | 截图、图表用 PNG,照片用 JPEG,追求极致压缩可用 WebP |
| 压缩 | JPEG 质量 80-90% 即可,视觉差异很小但体积减少明显 |
| 裁剪 | 去掉无关区域(如大片空白、水印、边框),只保留关键内容 |
不要为了省 token 而把图像压缩到无法识别,模型识别不出来反而浪费。
多模态输入的成本主要由图像产生:
| 场景 | 典型 Token 消耗 | 成本估算(GPT-4o) |
|---|---|---|
低分辨率图像(detail: "low") | ~85 tokens | ¥0.0001 |
高分辨率小图(500×500,detail: "high") | ~200 tokens | ¥0.0003 |
高分辨率大图(2000×2000,detail: "high") | ~800 tokens | ¥0.0012 |
多张高分辨率图(5 张,detail: "high") | ~4000 tokens | ¥0.006 |
具体费率取决于所选模型,以上仅为示例。生产环境建议:
- 默认用
detail: "auto"或"low",让模型或用户需求决定分辨率。 - 只在明确需要精细识别(OCR、图表数据、小物体检测)时用
"high"。 - 记录每次请求的 token 用量(响应的
usage字段),识别成本异常。
多模态输入引入了额外的失败点,需要针对性处理:
图像格式不支持
Section titled “图像格式不支持”{ "error": { "message": "Unsupported image format", "type": "invalid_request_error" }}解决:确认 MIME 类型正确,或转换为 PNG/JPEG。
{ "error": { "message": "Image size exceeds limit", "type": "invalid_request_error" }}解决:压缩图像或降低分辨率后重试。
URL 无法访问
Section titled “URL 无法访问”{ "error": { "message": "Failed to fetch image from URL", "type": "invalid_request_error" }}解决:
- 确认 URL 公开可访问,不需要鉴权。
- 测试上游服务的 IP 能否访问该 URL(防火墙、地域限制)。
- 改用 Base64 方式,避免依赖外部服务。
Base64 解码失败
Section titled “Base64 解码失败”{ "error": { "message": "Invalid base64 encoding", "type": "invalid_request_error" }}解决:检查 Base64 编码是否完整、格式是否正确(OpenAI 格式需要 data: 前缀,Claude 格式不需要)。
| 风险 | 防护措施 |
|---|---|
| URL 图像泄漏 | 确认 URL 指向的图像不包含敏感信息,或使用带鉴权的临时链接 |
| Base64 大小攻击 | 限制用户上传图像的大小上限(如 20 MB),防止超大请求 |
| 注入攻击 | 不要把用户上传的图像 URL 直接拼接进系统命令或 SQL |
| 模型幻觉 | 图像理解结果可能不准确,高风险场景(医疗、法律、金融)需人工复核 |
- 视觉能力、支持的图像格式、最大图像数取决于所选模型,上线前请测试验证。
detail参数只在 OpenAI 格式下有意义,Claude 格式无对应参数。- 不同模型对分辨率的处理策略不同,相同图像在不同模型上的 token 消耗可能差异较大。
- 流式响应中,图像内容的处理结果通常会在流的早期或晚期一次性返回,而非逐字流式输出。
- 记录每次请求的 request ID、模型 ID、状态码和 token 用量,便于排查成本和质量问题。详见 错误与调试。