多模态对话(Anthropic Messages 协议)
接口概述
支持图片的视觉理解模型,兼容 Anthropic Messages 格式:把 messages[].content 从字符串换成内容块数组、放入图片即可,可对图片做描述、文字识别与多图对比。
POST https://test.jw-info.com/v1/messages
| 项目 | 说明 |
|---|---|
| 输入类型 | 文本 + 图片(本协议当前不支持音频与文件输入) |
| 图片写法 | image 内容块,源数据放 source(公网 URL 或 Base64 二选一) |
| 图片格式 | image/jpeg、image/png、image/gif、image/webp |
| 多图 | 一次请求可放多张图(数组里多个 image 内容块),可做对比分析 |
| 纯文本用法 | 不带图片的纯文本对话见「Anthropic 兼容-Messages」页 |
| 音频 / 文件 | 需要音频或文件输入时,用「OpenAI 兼容-Chat(多模态)」或「OpenAI 兼容-Response(多模态)」页的写法 |
请求头
| 请求头 | 值 | 是否必填 | 说明 |
|---|---|---|---|
| Content-Type | application/json | 是 | 请求体格式 |
| x-api-key | {API_KEY} | 是 | 也可以用 Authorization: Bearer {API_KEY}——同一把密钥的两种传法,不需要建两套密钥 |
| anthropic-version | 2023-06-01 | 否 | 建议携带,行为更稳定 |
与纯文本的区别
| 项目 | 纯文本 | 多模态 |
|---|---|---|
| 系统提示词 | 顶层 system 字段 | 同左 |
messages[].content | 字符串 | 内容块数组(每个元素是一个 content block) |
max_tokens | 必填 | 必填 |
// 多模态:content 为内容块数组
{
"model": "qwen3.7-plus",
"system": "你是一个专业的图片分析助手。",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "描述这张图片" },
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "/9j/4AAQSkZJRg……"
}
}
]
}
]
}
// 纯文本:content 仍是字符串(同样可用,详见「Anthropic 兼容-Messages」页)
{
"model": "qwen3.7-plus",
"system": "你是一个有用的助手。",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "你好,请介绍一下你自己" }
]
}
Content 类型详解
| type | 字段 | 说明 |
|---|---|---|
| text | text(string) | 文本内容 |
| image | source(object) | 图片源信息 |
| image → source | type(string) | 源类型:base64 或 url |
| image → source | media_type(string) | 图片 MIME 类型:image/jpeg / image/png / image/gif / image/webp |
| image → source | data(string) | 图片的 Base64 编码数据(type 为 base64 时使用) |
| image → source | url(string) | 图片地址(type 为 url 时使用) |
其余请求参数(model、temperature、top_p、stream、tools 等)与纯文本一致,见「Anthropic 兼容-Messages」页。
示例
1. 图片 URL 方式
curl https://test.jw-info.com/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: sk-你的密钥" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "qwen3.7-plus",
"system": "你是一个专业的图片分析助手,请用中文回答。",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "这张图片里有什么?请详细描述。" },
{
"type": "image",
"source": { "type": "url", "url": "https://example.com/sample.jpg" }
}
]
}
]
}'
import base64
from anthropic import Anthropic
client = Anthropic(api_key="sk-你的密钥", base_url="https://test.jw-info.com/v1")
def describe_image(image_path: str, prompt: str = "描述这张图片") -> str:
"""发送图片给模型并获取描述"""
with open(image_path, "rb") as f:
image_data = base64.b64encode(f.read()).decode("utf-8")
ext = image_path.rsplit(".", 1)[-1].lower()
media_type = {"jpg": "image/jpeg", "jpeg": "image/jpeg", "png": "image/png",
"gif": "image/gif", "webp": "image/webp"}.get(ext, "image/jpeg")
message = client.messages.create(
model="qwen3.7-plus",
system="你是一个专业的图片分析助手,请用中文回答。",
max_tokens=1024,
messages=[{
"role": "user",
"content": [
{"type": "text", "text": prompt},
{"type": "image", "source": {"type": "base64",
"media_type": media_type,
"data": image_data}},
],
}],
)
return message.content[0].text
print(describe_image("photo.png", "这张图片中有什么物体?"))
2. 图片 Base64 方式
curl https://test.jw-info.com/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: sk-你的密钥" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "qwen3.7-plus",
"system": "你是一个 OCR 识别助手。",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "请识别这张图片中的所有文字。" },
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
}
}
]
}
]
}'
本地图片先编码再发送:
import base64
def local_image_block(image_path: str, mime: str = "image/jpeg") -> dict:
"""本地图片 -> Anthropic image 内容块"""
with open(image_path, "rb") as f:
data = base64.b64encode(f.read()).decode("utf-8")
return {"type": "image",
"source": {"type": "base64", "media_type": mime, "data": data}}
3. 多图对比
curl https://test.jw-info.com/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: sk-你的密钥" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "qwen3.7-plus",
"system": "你是一个专业的图片对比分析助手。",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "请对比这两张图片,分析它们的异同。" },
{ "type": "image", "source": { "type": "url", "url": "https://example.com/image1.jpg" } },
{ "type": "image", "source": { "type": "url", "url": "https://example.com/image2.jpg" } }
]
}
]
}'
# 与示例 1 相同,只是 content 数组里放多个 image 内容块
content = [
{"type": "text", "text": "请对比这两张图片,分析它们的异同。"},
{"type": "image", "source": {"type": "url",
"url": "https://example.com/image1.jpg"}},
{"type": "image", "source": {"type": "url",
"url": "https://example.com/image2.jpg"}},
]
4. 纯文本(兼容模式)
纯文本对话仍然支持把 content 直接写成字符串,无需数组形式(完整参数见「Anthropic 兼容-Messages」页):
{
"model": "qwen3.7-plus",
"system": "你是一个有用的助手。",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "你好,请介绍一下你自己" }
]
}
响应格式
响应格式与纯文本 Anthropic Messages 相同。
| 字段 | 类型 | 说明 |
|---|---|---|
| id | string | 本次请求的唯一标识 |
| type | string | 固定 message |
| role | string | 固定 assistant |
| model | string | 实际使用的模型名称 |
| content | array | 内容块数组 |
| content[].type | string | text(正文)/ thinking(思考过程)/ tool_use(工具调用) |
| content[].text | string | type 为 text 时的正文 |
| stop_reason | string | 停止原因:end_turn / max_tokens / stop_sequence / tool_use |
| stop_sequence | string | 触发的停止词(stop_reason 为 stop_sequence 时出现) |
| usage.input_tokens | integer | 输入 token 数(图片会折算成输入 token) |
| usage.output_tokens | integer | 输出 token 数 |
成功响应:
{
"id": "msg_xxxxxxxxxxxxx",
"type": "message",
"role": "assistant",
"model": "qwen3.7-plus",
"content": [
{
"type": "text",
"text": "这张图片展示了一座位于海边的灯塔,天空晴朗,海浪轻轻拍打着礁石……"
}
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 150, "output_tokens": 80 }
}
流式响应(stream: true)事件顺序:
event: message_start
event: content_block_start
event: content_block_delta # 多次,delta.text 为增量文本
event: content_block_stop
event: message_delta # 最终用量在这里(usage.output_tokens)
event: message_stop
event: message_start
data: {"type":"message_start","message":{"id":"msg_xxx","type":"message","role":"assistant","content":[],"usage":{}}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"这张"}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"图片"}}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"input_tokens":150,"output_tokens":80}}
event: message_stop
data: {"type":"message_stop"}
message_start里的usage可能是空对象,最终用量以message_delta为准。
错误格式
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "Invalid image source: unsupported media type"
}
}
| 错误类型 | 说明 |
|---|---|
invalid_request_error | 请求参数错误 |
invalid_image_source | 图片源无效或格式不支持 |
rate_limit_error | 请求频率超限 |
context_length_exceeded | Token 数量超出模型限制 |
authentication_error | 密钥无效或已禁用 |
状态码与错误处理约定见「错误码」页。
可用模型
以下模型均支持图片输入,模型名照模型广场的写法传入:
| 模型 | 供应商 | 上下文 | 说明 |
|---|---|---|---|
| qwen3.7-plus | 通义千问 | 128K | 旗舰多模态模型 |
| qwen3.6-plus | 通义千问 | 128K | 高性能多模态 |
| qwen3.6-flash | 通义千问 | 128K | 轻量快速多模态 |
| qwen3.5-plus | 通义千问 | 128K | 上一代旗舰 |
| qwen3.5-flash | 通义千问 | 128K | 上一代轻量版 |
| qwen3.5-122b-a10b | 通义千问 | 128K | 大参数 MoE 模型 |
| qwen3.5-397b-a17b | 通义千问 | 128K | 超大参数 MoE 模型 |
| qwen3.5-35b-a3b | 通义千问 | 128K | 轻量 MoE 模型 |
| minimax-m3 | MiniMax | 128K | MiniMax 多模态模型 |
| doubao-seed-2.0-pro | 豆包 | 128K | 豆包旗舰多模态 |
| doubao-seed-2.0-lite | 豆包 | 128K | 豆包轻量多模态 |
| doubao-seed-2.0-mini | 豆包 | 128K | 豆包极速多模态 |
| kimi-k3 | 月之暗面 | 128K | Kimi 旗舰多模态 |
| kimi-k2.7-code | 月之暗面 | 128K | Kimi 代码多模态 |
| kimi-k2.6 | 月之暗面 | 128K | Kimi 多模态 |
| kimi-k2.5 | 月之暗面 | 128K | Kimi 多模态 |
以上模型同样支持纯文本对话(见「Anthropic 兼容-Messages」页)。模型广场上带「视觉理解」标签的模型都支持图片输入。
注意事项
- 协议支持度是模型级的:个别模型不支持本协议,调用会返回错误并说明原因——换支持该协议的模型,或改用
/v1/chat/completions调同一个模型即可,模型名与计费都不变。 - 本协议只收文本与图片:传音频、文件会返回参数错误;需要这两类输入请用「OpenAI 兼容-Chat(多模态)」或「OpenAI 兼容-Response(多模态)」页的写法。
- 图片地址需公网可直接访问;地址不可达或格式不受支持时会返回图片相关错误。
- 单张图片不宜过大:过大的图会显著增加输入 token 消耗,必要时先压缩或缩放。
计费
- 图片会折算成输入 token,与文本一起按模型的输入单价计费;输出按输出单价计费。
- 每次调用的费用记入控制台「费用中心」,接口响应本身不返回费用信息。
- 账户余额不足时调用前直接返回
402,请管理员在控制台「费用中心」手工授信。