多模态对话(OpenAI Responses 协议)

接口概述

支持图片、音频、文件的视觉理解大模型,兼容 OpenAI Responses API 格式:可对图片进行描述、分析、对比,支持音频转写与理解,支持文件内容提取与问答。

接口地址:

POST https://ai.jw-info.com/v1/responses

与 Chat Completions 协议的区别

Chat Completions 与 Responses 协议在字段命名和结构上有所不同:

概念Chat CompletionsResponses
消息列表messagesinput
系统提示messages[].role: "system"instructions(顶层字段)
用户消息内容content 数组input 数组
输出长度上限max_tokensmax_output_tokens
流式参数stream: truestream: true

请求头

请求头是否必填说明
Content-Typeapplication/json请求体格式
AuthorizationBearer {API_KEY}也可以用 x-api-key: {API_KEY},两种写法用同一把 Key
Acceptapplication/json响应格式

与纯文本的区别

在多模态场景下,input 是一个对象数组,每个对象代表一种内容类型;而纯文本场景中 input 可为字符串。

// 多模态:input 为数组
"input": [
  { "type": "input_text", "text": "描述这张图片" },
  { "type": "input_image", "image_url": "https://example.com/photo.jpg" }
]
// 纯文本:input 为字符串(仍支持,详见「OpenAI 兼容-Response」页)
"input": "你好,请帮我解答这个问题"

请求参数

顶层参数

参数名类型是否必填说明
modelstring模型名,见模型广场与文末「可用模型」
inputstring / array纯文本传字符串;多模态传内容条目数组(见下节)
instructionsstring系统级指令,用于设定角色与回答要求(替代 Chat 协议里的 system 消息)
max_output_tokensinteger输出长度上限(等价于 max_tokens
temperaturefloat采样温度,范围 [0, 2]
top_pfloat核采样,范围 [0, 1]
streamboolean是否流式返回(SSE),默认 false
tools / tool_choicearray / string工具定义与选择策略
previous_response_idstring引用上一轮响应 ID 做多轮对话

Content 类型详解

type字段说明
input_texttext(string)文本内容
input_imageimage_url(string)图片 URL,或 data:image/...;base64, 编码
input_imagedetail(string,可选)图片解析精度:low / high / auto(默认 auto
input_audioaudio_data(string)音频的 Base64 编码数据
input_audioaudio_format(string)音频格式:wav / mp3
input_filefile_id(string)已上传文件的 ID(与 file_data 二选一)
input_filefile_data(string)文件的 Base64 编码数据
input_filefilename(string,可选)文件名(带扩展名,便于识别类型)

约定:

项目说明
图片格式image/jpegimage/pngimage/gifimage/webp
图片地址公网可直接访问的 URL;地址不可达或格式不支持会返回图片相关错误
Base64 写法data:image/png;base64,……(前缀里的 MIME 类型要与实际格式一致)
多图input 数组里放多个 input_image 条目即可(用于对比、多页文档等)

请求示例

1. 图片 URL 方式

curl https://ai.jw-info.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的密钥" \
  -d '{
    "model": "qwen3.7-plus",
    "instructions": "你是一个专业的图片分析助手,请用中文回答。",
    "input": [
      { "type": "input_text", "text": "这张图片里有什么?请详细描述。" },
      { "type": "input_image", "image_url": "https://example.com/sample.jpg", "detail": "high" }
    ]
  }'
from openai import OpenAI

client = OpenAI(api_key="sk-你的密钥", base_url="https://ai.jw-info.com/v1")

resp = client.responses.create(
    model="qwen3.7-plus",
    instructions="你是一个专业的图片分析助手,请用中文回答。",
    input=[
        {"type": "input_text", "text": "这张图片里有什么?请详细描述。"},
        {"type": "input_image", "image_url": "https://example.com/sample.jpg", "detail": "high"},
    ],
)
print(resp.output_text)

2. 图片 Base64 方式

curl https://ai.jw-info.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的密钥" \
  -d '{
    "model": "qwen3.7-plus",
    "instructions": "你是一个 OCR 识别助手。",
    "input": [
      { "type": "input_text", "text": "请识别这张图片中的所有文字。" },
      { "type": "input_image", "image_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" }
    ]
  }'
import base64

from openai import OpenAI

client = OpenAI(api_key="sk-你的密钥", base_url="https://ai.jw-info.com/v1")


def encode_image(path: str) -> str:
    with open(path, "rb") as f:
        data = base64.b64encode(f.read()).decode("utf-8")
    return f"data:image/{path.rsplit('.', 1)[-1]};base64,{data}"


resp = client.responses.create(
    model="qwen3.7-plus",
    instructions="你是一个专业的图片分析助手。",
    input=[
        {"type": "input_text", "text": "这张图片中有什么物体?"},
        {"type": "input_image", "image_url": encode_image("photo.png")},
    ],
)
print(resp.output_text)

3. 多图对比

curl https://ai.jw-info.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的密钥" \
  -d '{
    "model": "qwen3.7-plus",
    "instructions": "你是一个专业的图片对比分析助手。",
    "input": [
      { "type": "input_text", "text": "请对比这两张图片,分析它们的异同。" },
      { "type": "input_image", "image_url": "https://example.com/image1.jpg" },
      { "type": "input_image", "image_url": "https://example.com/image2.jpg" }
    ]
  }'

4. 音频输入

curl https://ai.jw-info.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的密钥" \
  -d '{
    "model": "qwen3.7-plus",
    "instructions": "你是一个语音转文字助手。",
    "input": [
      { "type": "input_text", "text": "请将这段录音内容转写成文字。" },
      {
        "type": "input_audio",
        "audio_data": "UklGRiQAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQAAAAA=",
        "audio_format": "wav"
      }
    ]
  }'

5. 文件输入

curl https://ai.jw-info.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-你的密钥" \
  -d '{
    "model": "qwen3.7-plus",
    "instructions": "你是一个专业的文档分析助手。",
    "input": [
      { "type": "input_text", "text": "请总结这份文件的主要内容。" },
      { "type": "input_file", "file_data": "VGhpcyBpcyBhIHNhbXBsZSBmaWxlIGNvbnRlbnQu", "filename": "report.pdf" }
    ]
  }'

file_data 是文件内容的 Base64 编码;若文件已上传到平台并拿到 ID,可改用 file_id

6. 纯文本(兼容模式)

input 直接给字符串即为纯文本对话:

{
  "model": "qwen3.7-plus",
  "instructions": "你是一个有用的助手。",
  "input": "你好,请介绍一下你自己"
}

响应格式

响应格式与纯文本 Responses API 相同。

响应参数

参数名类型说明
idstring本次响应的唯一标识,可作为 previous_response_id 回传
objectstring固定值 response
created_atinteger创建时间戳(Unix 秒)
modelstring实际使用的模型名称
outputarray输出内容列表
output[].typestring输出类型,正常回答为 message
output[].rolestring角色,固定值 assistant
output[].contentarray内容片段数组
output[].content[].typestring内容类型:output_text(文本)或 refusal(拒绝回答)
output[].content[].textstring文本内容
statusstring响应状态:completedin_progress
usage.input_tokensinteger输入消耗的 token 数(图片 / 音频 / 文件折算后计入)
usage.output_tokensinteger输出消耗的 token 数
usage.total_tokensinteger总 token 消耗

响应有两种形状:多数模型返回上表的普通对象;部分模型返回单个 response.completed 事件体(与流式帧同形),此时字段在 response.* 下(response.output[]response.usage)。按需取即可,示例见下。

非流式响应示例

普通对象:

{
  "id": "resp_xxxxxxxxxxxxx",
  "object": "response",
  "created_at": 1710000000,
  "model": "qwen3.7-plus",
  "status": "completed",
  "output": [
    {
      "id": "msg_xxxxxxxxxxxxx",
      "type": "message",
      "role": "assistant",
      "content": [
        { "type": "output_text", "text": "这张图片展示了一座位于海边的灯塔……", "annotations": [] }
      ]
    }
  ],
  "usage": { "input_tokens": 150, "output_tokens": 80, "total_tokens": 230 }
}

单个事件体(部分模型):

{
  "type": "response.completed",
  "response": {
    "id": "resp_xxxxxxxxxxxxx",
    "status": "completed",
    "output": [
      { "type": "message", "role": "assistant",
        "content": [ { "type": "output_text", "text": "图片里是一只橘猫……" } ] }
    ],
    "usage": { "input_tokens": 150, "output_tokens": 80, "total_tokens": 230 }
  }
}

流式响应(stream=true)

event: response.created            # 响应已创建
event: response.output_text.delta  # 多次,delta 为增量文本
event: response.completed          # response.usage 在这里给最终用量

每帧的 data: 是一个 JSON 对象,例如:

event: response.output_text.delta
data: {"type":"response.output_text.delta","delta":"这是","item_id":"msg_xxx","output_index":0,"content_index":0}

读取时兼容两种形状(Python):

data = resp.get("response") or resp      # 普通对象 / 事件体都取到同一层
text = data["output"][0]["content"][0]["text"]
usage = data["usage"]

错误格式

模型侧报错时,接口返回 502,detail 里带上原始错误正文,便于定位:

{
  "error": {
    "message": "Invalid image URL: connection timeout",
    "type": "invalid_request_error",
    "code": "invalid_image_url"
  }
}

常见错误码:

错误码说明
invalid_request_error请求参数错误
invalid_image_url图片 URL 无法访问或格式不支持
invalid_audio_format音频格式不支持
rate_limit_exceeded请求频率超限
context_length_exceededToken 数量超出模型限制
authentication_errorAPI Key 无效

完整的 HTTP 状态码(401 / 402 / 429 / 502 等)与排查速查见「错误码」页。

可用模型

以下模型支持多模态输入,并同样支持纯文本对话:

模型供应商最大 Token说明
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-m3MiniMax128KMiniMax 多模态模型
doubao-seed-2.0-pro豆包128K豆包旗舰多模态
doubao-seed-2.0-lite豆包128K豆包轻量多模态
doubao-seed-2.0-mini豆包128K豆包极速多模态
kimi-k3月之暗面128KKimi 旗舰多模态
kimi-k2.7-code月之暗面128KKimi 代码多模态
kimi-k2.6月之暗面128KKimi 多模态
kimi-k2.5月之暗面128KKimi 多模态

模型广场上带「视觉理解」标签的模型都支持图片输入;音频与文件输入只有部分模型支持,以实际调用结果为准。 本协议的支持度是模型级的:个别模型未开启相关能力时会直接报错说明,遇到时改用 /v1/chat/completions 调同一模型即可(模型名与计费不变)。

计费说明

  • 图片、音频、文件都会被折算成输入 token,与文本一起按该模型的输入单价计费;输出按输出单价计费。
  • 每次调用的费用记入控制台「费用中心」,接口响应本身不返回费用。
  • 余额不足会返回 402,需要管理员在控制台手工授信。

在模型广场查看支持「视觉理解」的模型 →