Chat 模型 API

Img2Vid 通过多种公开 API 格式暴露当前激活的 Chat 模型,方便 code agent、后端服务和第三方集成在不依赖浏览器 UI 的情况下调用同一套 Chat 模型配置。

Chat API 与媒体生成 API 是分开的。Chat 模型列表使用 /api/v1/models;图片、视频、音频和音乐生成模型列表使用 /api/v1/media_models

认证

所有 Chat API 端点都需要服务端 API Key。

Authorization: Bearer $BUBLE_API_KEY

也支持使用 X-API-Key: $BUBLE_API_KEY

端点

Method Endpoint 格式 用途
GET /api/v1/models OpenAI 风格模型列表 列出当前激活的 Chat 模型。
POST /api/v1/chat/completions OpenAI Chat Completions 风格 创建 Chat 回复或流式 chunk。
POST /api/v1/messages Anthropic Messages 风格 创建 Message 回复或流式事件。
POST /api/v1beta/models/{model}:generateContent Gemini generateContent 风格 生成非流式模型内容。
POST /api/v1beta/models/{model}:streamGenerateContent Gemini streamGenerateContent 风格 流式生成模型内容。

OpenAI 兼容和 Anthropic 兼容端点使用 stream: true 开启流式输出。Gemini 兼容流式输出使用标准 :streamGenerateContent 方法,而不是在 :generateContent 中传 stream: true

获取 Chat 模型列表

GET /api/v1/models

请求示例

curl https://img2vid.net/api/v1/models \
  -H "Authorization: Bearer $BUBLE_API_KEY"

响应结构

{
  "object": "list",
  "data": [
    {
      "id": "openai/gpt-5.5",
      "object": "model",
      "created": 1778716800,
      "owned_by": "OpenAI",
      "name": "GPT-5.5",
      "description": "High-capability chat model.",
      "capabilities": {
        "reasoning": true,
        "attachments": true,
        "tools": true
      },
      "tags": ["chat"]
    }
  ]
}

模型字段

字段 说明
id 稳定模型 key,调用 Chat API 时作为 model 传入。
object 固定为 model
created 模型创建时间,Unix 秒级时间戳。
owned_by Vendor 或 Provider 展示名称。
name 模型展示名称。
description 可选的模型描述。
capabilities 基于当前 Chat 模型配置生成的公开能力标记。
tags 模型配置中的可选标签。

OpenAI 兼容 Chat Completions

POST /api/v1/chat/completions
Content-Type: application/json

请求体

字段 类型 必填 说明
model string 来自 /api/v1/models 的 Chat 模型 key。
messages array OpenAI 风格 Chat 消息。转换后至少需要一条非 system 消息。
stream boolean true 时返回 OpenAI 兼容的 Server-Sent Events。
temperature number 仅当所选模型配置暴露该 option 时才会转发。
top_p number 仅当所选模型配置暴露该 option 时才会转发。
stop string 或 array 仅当所选模型配置暴露该 option 时才会转发。
presence_penalty number 仅当所选模型配置暴露该 option 时才会转发。
frequency_penalty number 仅当所选模型配置暴露该 option 时才会转发。
response_format object 仅当所选模型配置暴露该 option 时才会转发。
seed number 仅当所选模型配置暴露该 option 时才会转发。
options object 所选 Chat 模型配置中定义的模型专属 options。
extra_body object 会在校验前合并到模型 options 中。
tools array OpenAI 兼容工具定义。需要模型支持 capabilities.tools
tool_choice string 或 object OpenAI 兼容工具选择。需要模型支持 capabilities.tools
parallel_tool_calls boolean OpenAI 兼容并行工具调用控制。需要模型支持 capabilities.tools
reasoning boolean 仅当模型配置支持 reasoning 时启用推理能力。
reasoning_effort string 或 boolean 当前按 reasoning 开关处理;provider 专属 effort 值应通过已配置的 options 传递。
max_tokens number 请求输出上限,可能会被 Img2Vid 计费预留上限进一步收紧。
max_completion_tokens number OpenAI 风格的另一种输出上限字段。

支持的消息内容

messages[].content 可以是字符串,也可以是内容 part 数组。

Part 类型 支持字段 在 Img2Vid 内部的转换结果
text text 文本 part。
input_text text 文本 part。
image_url image_url 字符串,或 { "url": "..." } 图片类型文件附件。
file file.file_datafile.urlurl 文件附件,可带 media type 和文件名。

附件是否真正可用取决于所选 Chat 模型配置中允许的附件类型。

请求示例

curl https://img2vid.net/api/v1/chat/completions \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "messages": [
      {
        "role": "system",
        "content": "You are a concise product analyst."
      },
      {
        "role": "user",
        "content": "Summarize the main tradeoffs in this launch plan."
      }
    ],
    "temperature": 0.4,
    "reasoning": true,
    "max_completion_tokens": 800
  }'

响应结构

{
  "id": "chatcmpl-8c3d1f6b-5f04-4a8f-b75a-80f1c49e0a8d",
  "object": "chat.completion",
  "created": 1778716800,
  "model": "openai/gpt-5.5",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Here are the main tradeoffs..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 120,
    "completion_tokens": 260,
    "total_tokens": 380
  }
}

如果 provider 返回 reasoning 文本且模型支持该能力,响应中可能包含 message.reasoning_content。如果 provider 返回 reasoning token 或 cached input token,响应中可能包含 usage.completion_tokens_details.reasoning_tokensusage.prompt_tokens_details.cached_tokens

流式响应

设置 stream: true 可以接收 OpenAI 兼容的 Server-Sent Events:

curl https://img2vid.net/api/v1/chat/completions \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "Write a short launch summary."
      }
    ]
  }'

流式 chunk 使用 chat.completion.chunk 对象,并以 data: [DONE] 结束。

Anthropic 兼容 Messages

POST /api/v1/messages
Content-Type: application/json

请求体

字段 类型 必填 说明
model string 来自 /api/v1/models 的 Chat 模型 key。
system string 会转换为 system 消息。
messages array Anthropic 风格消息。转换后至少需要一条非 system 消息。
stream boolean true 时返回 Anthropic 兼容的 Server-Sent Events。
max_tokens number 请求输出上限,可能会被 Img2Vid 计费预留上限进一步收紧。
temperature number 仅当所选模型配置暴露该 option 时才会转发。
top_p number 仅当所选模型配置暴露该 option 时才会转发。
top_k number 仅当所选模型配置暴露该 option 时才会转发。
stop_sequences array 当所选模型支持时,会映射为内部 stop option。
options object 所选 Chat 模型配置中定义的模型专属 options。
tools array Anthropic 兼容工具定义。需要模型支持 capabilities.tools
tool_choice object Anthropic 兼容工具选择。需要模型支持 capabilities.tools
thinking boolean/object 仅当模型配置支持 reasoning 时启用推理能力。
reasoning boolean 另一种 reasoning 开关。

支持的消息内容

messages[].content 可以是字符串,也可以是内容 block 数组。

Block 类型 支持字段 在 Img2Vid 内部的转换结果
text text 文本 part。
image source.type: "url"source.url 图片文件附件。
image source.type: "base64"source.data Data URL 图片文件附件。
document source.type: "url"source.url 文档文件附件。

请求示例

curl https://img2vid.net/api/v1/messages \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "system": "You are a concise product analyst.",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "Summarize the main tradeoffs in this launch plan."
          }
        ]
      }
    ],
    "max_tokens": 800,
    "temperature": 0.4
  }'

响应结构

{
  "id": "msg_8c3d1f6b5f044a8fb75a80f1c49e0a8d",
  "type": "message",
  "role": "assistant",
  "model": "openai/gpt-5.5",
  "content": [
    {
      "type": "text",
      "text": "Here are the main tradeoffs..."
    }
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 120,
    "output_tokens": 260
  }
}

如果返回 reasoning 文本,响应中还会包含:

{
  "thinking": [
    {
      "type": "thinking",
      "thinking": "Reasoning text returned by the provider."
    }
  ]
}

流式响应

设置 stream: true 可以接收 Anthropic 兼容的 Server-Sent Events:

curl https://img2vid.net/api/v1/messages \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.5",
    "stream": true,
    "messages": [
      {
        "role": "user",
        "content": "Write a short launch summary."
      }
    ]
  }'

流式事件包括 message_startcontent_block_deltamessage_deltamessage_stop

Gemini 兼容 generateContent

POST /api/v1beta/models/{model}:generateContent
Content-Type: application/json

路径中的 {model} 是 Img2Vid Chat 模型 key。如果模型 key 中包含 /,可以作为路径层级传入,例如 /api/v1beta/models/openai/gpt-5.5:generateContent

:generateContent 用于非流式 Gemini 兼容请求。流式请求使用 :streamGenerateContent。不要在 :generateContent 中使用 stream: true

请求体

字段 类型 必填 说明
contents array Gemini 风格内容列表。转换后至少需要一条非 system 消息。
systemInstruction object 其中的 parts 会转换为 system 消息。
generationConfig object 支持 temperaturetopPtopKstopSequencesmaxOutputTokens
generation_config object generationConfig 的 snake-case 替代字段。
options object 所选 Chat 模型配置中定义的模型专属 options。
tools array Gemini 兼容工具声明。需要模型支持 capabilities.tools
toolConfig object Gemini 兼容工具配置。需要模型支持 capabilities.tools
reasoning boolean 仅当模型配置支持 reasoning 时启用推理能力。
thinkingConfig object 当前按 reasoning 开关处理;provider 专属字段需要通过已配置的 options 传递。

支持的 parts

Part 字段 在 Img2Vid 内部的转换结果
text 文本 part。
fileData.fileUri 文件附件 URL。
file_data.file_uri 文件附件 URL。
inlineData.data Base64 Data URL 附件。
inline_data.data Base64 Data URL 附件。

contents[].rolemodel 时会转换为 assistant 消息,其他 role 会转换为 user 消息。

请求示例

curl https://img2vid.net/api/v1beta/models/openai/gpt-5.5:generateContent \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemInstruction": {
      "parts": [
        {
          "text": "You are a concise product analyst."
        }
      ]
    },
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Summarize the main tradeoffs in this launch plan."
          }
        ]
      }
    ],
    "generationConfig": {
      "temperature": 0.4,
      "maxOutputTokens": 800
    }
  }'

响应结构

{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "text": "Here are the main tradeoffs..."
          }
        ]
      },
      "finishReason": "STOP",
      "index": 0
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 120,
    "candidatesTokenCount": 260,
    "totalTokenCount": 380
  },
  "modelVersion": "openai/gpt-5.5"
}

Gemini 兼容 streamGenerateContent

POST /api/v1beta/models/{model}:streamGenerateContent
Content-Type: application/json

请求体与 :generateContent 保持一致,但响应通过 Server-Sent Events 返回。

请求示例

curl https://img2vid.net/api/v1beta/models/openai/gpt-5.5:streamGenerateContent \
  -H "Authorization: Bearer $BUBLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Write a short launch summary."
          }
        ]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 800
    }
  }'

每个流式 chunk 都是一个 Gemini 兼容的 GenerateContentResponse JSON 对象。

SDK 示例

SDK 暴露与 HTTP API 相同的三类 Chat 协议。OpenAI 兼容和 Anthropic 兼容流式调用会由 SDK 自动设置 stream: true。Gemini 兼容流式调用使用专门的 streamGenerateContent / stream_generate_content 方法,并调用 /api/v1beta/models/{model}:streamGenerateContent

下面的片段假设你已经按快速开始初始化了 SDK client,并引入了对应语言需要的 SDK 类型。

JavaScript / TypeScript

const completion = await buble.chat.completions.create({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'Write a short launch summary.' }],
  max_completion_tokens: 800,
});

const stream = await buble.chat.completions.stream({
  model: 'openai/gpt-5.5',
  messages: [{ role: 'user', content: 'Write one sentence at a time.' }],
});

for await (const text of stream.toTextStream()) {
  process.stdout.write(text);
}

Python

completion = client.chat.completions.create(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "Write a short launch summary."}],
    max_completion_tokens=800,
)

for text in client.chat.completions.stream_text(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "Write one sentence at a time."}],
):
    print(text, end="")

Go

completion, err := client.Chat.Completions.Create(ctx, buble.ChatRequest{
	"model": "openai/gpt-5.5",
	"messages": []any{
		map[string]any{"role": "user", "content": "Write a short launch summary."},
	},
	"max_completion_tokens": 800,
})
if err != nil {
	return err
}

stream, err := client.Chat.Completions.Stream(ctx, buble.ChatRequest{
	"model": "openai/gpt-5.5",
	"messages": []any{
		map[string]any{"role": "user", "content": "Write one sentence at a time."},
	},
})
if err != nil {
	return err
}
defer stream.Close()

for stream.Next() {
	fmt.Print(stream.Text())
}

Rust

use futures_util::StreamExt;

let completion = client.chat().completions().create(serde_json::json!({
    "model": "openai/gpt-5.5",
    "messages": [
        { "role": "user", "content": "Write a short launch summary." }
    ],
    "max_completion_tokens": 800
})).await?;

let mut stream = client.chat().completions().stream_text(serde_json::json!({
    "model": "openai/gpt-5.5",
    "messages": [
        { "role": "user", "content": "Write one sentence at a time." }
    ]
})).await?;

while let Some(chunk) = stream.next().await {
    print!("{}", chunk?);
}

Swift

let completion = try await client.chat.completions.create([
    "model": "openai/gpt-5.5",
    "messages": [
        ["role": "user", "content": "Write a short launch summary."]
    ],
    "max_completion_tokens": 800
])

let stream = try await client.chat.completions.streamText([
    "model": "openai/gpt-5.5",
    "messages": [
        ["role": "user", "content": "Write one sentence at a time."]
    ]
])

for try await text in stream {
    print(text, terminator: "")
}

Dart / Flutter

final completion = await client.chat.completions.create({
  'model': 'openai/gpt-5.5',
  'messages': [
    {'role': 'user', 'content': 'Write a short launch summary.'},
  ],
  'max_completion_tokens': 800,
});

final stream = await client.chat.completions.streamText({
  'model': 'openai/gpt-5.5',
  'messages': [
    {'role': 'user', 'content': 'Write one sentence at a time.'},
  ],
});

await for (final text in stream) {
  print(text);
}

Elixir

{:ok, completion} =
  Buble.Chat.Completions.create(client, %{
    model: "openai/gpt-5.5",
    messages: [%{role: "user", content: "Write a short launch summary."}],
    max_completion_tokens: 800
  })

{:ok, stream} =
  Buble.Chat.Completions.stream_text(client, %{
    model: "openai/gpt-5.5",
    messages: [%{role: "user", content: "Write one sentence at a time."}]
  })

Enum.each(stream, &IO.write/1)

Java

var completion = client.chat().completions().create(Map.of(
        "model", "openai/gpt-5.5",
        "messages", List.of(Map.of("role", "user", "content", "Write a short launch summary.")),
        "max_completion_tokens", 800));

try (BubleStream stream = client.chat().completions().stream(Map.of(
        "model", "openai/gpt-5.5",
        "messages", List.of(Map.of("role", "user", "content", "Write one sentence at a time."))))) {
    while (stream.next()) {
        System.out.print(stream.text());
    }
}

.NET

var completion = await client.Chat.Completions.CreateAsync(new Dictionary<string, object?>
{
    ["model"] = "openai/gpt-5.5",
    ["messages"] = new[]
    {
        new Dictionary<string, object?>
        {
            ["role"] = "user",
            ["content"] = "Write a short launch summary."
        }
    },
    ["max_completion_tokens"] = 800
});

await foreach (var text in client.Chat.Completions.StreamTextAsync(new Dictionary<string, object?>
{
    ["model"] = "openai/gpt-5.5",
    ["messages"] = new[]
    {
        new Dictionary<string, object?>
        {
            ["role"] = "user",
            ["content"] = "Write one sentence at a time."
        }
    }
}))
{
    Console.Write(text);
}

PHP

$completion = $client->chat()->completions()->create([
    'model' => 'openai/gpt-5.5',
    'messages' => [
        ['role' => 'user', 'content' => 'Write a short launch summary.'],
    ],
    'max_completion_tokens' => 800,
]);

foreach ($client->chat()->completions()->streamText([
    'model' => 'openai/gpt-5.5',
    'messages' => [
        ['role' => 'user', 'content' => 'Write one sentence at a time.'],
    ],
]) as $text) {
    echo $text;
}

Ruby

completion = client.chat.completions.create(
  model: "openai/gpt-5.5",
  messages: [
    { role: "user", content: "Write a short launch summary." }
  ],
  max_completion_tokens: 800
)

client.chat.completions.stream_text(
  model: "openai/gpt-5.5",
  messages: [
    { role: "user", content: "Write one sentence at a time." }
  ]
).each do |text|
  print text
end

Gemini 方法名

语言 非流式 流式
JavaScript / TypeScript buble.chat.gemini.generateContent(model, body) buble.chat.gemini.streamGenerateContent(model, body)
Python client.chat.gemini.generate_content(model, **body) client.chat.gemini.stream_generate_content(model, **body)
Go client.Chat.Gemini.GenerateContent(ctx, model, body) client.Chat.Gemini.StreamGenerateContent(ctx, model, body)
Rust client.chat().gemini().generate_content(model, body) client.chat().gemini().stream_generate_content(model, body)
Swift client.chat.gemini.generateContent(model, body) client.chat.gemini.streamGenerateContent(model, body)
Dart / Flutter client.chat.gemini.generateContent(model, body) client.chat.gemini.streamGenerateContent(model, body)
Elixir Buble.Chat.Gemini.generate_content(client, model, body) Buble.Chat.Gemini.stream_generate_content(client, model, body)
Java client.chat().gemini().generateContent(model, body) client.chat().gemini().streamGenerateContent(model, body)
.NET client.Chat.Gemini.GenerateContentAsync(model, body) client.Chat.Gemini.StreamGenerateContentAsync(model, body)
PHP $client->chat()->gemini()->generateContent($model, $body) $client->chat()->gemini()->streamGenerateContent($model, $body)
Ruby client.chat.gemini.generate_content(model, body) client.chat.gemini.stream_generate_content(model, body)

Options 与能力开关

Chat 模型 options 会根据所选模型的 UI options 配置进行校验。temperaturetop_ptop_kstop 等标准字段只有在所选模型暴露对应 option 时才会被转发。模型专属参数应放在 options 中传递。

reasoning 是请求级能力开关。它只有在所选模型的 capabilities 标记支持时才会生效。

Tool calling 使用各公开协议的标准字段。如果请求包含标准 tool 字段,但所选模型没有暴露 capabilities.tools,API 会返回 tools_not_supported

错误格式

Chat API 使用与媒体 API 相同的公开错误结构。

{
  "error": {
    "code": "missing_model",
    "message": "model is required."
  }
}

常见 Chat API 错误:

Code HTTP 含义
missing_api_key 401 未提供 API Key。
invalid_api_key 401 API Key 无效、未激活或已删除。
invalid_request_body 400 请求体不是 JSON object。
missing_model 400 缺少必填模型 key。
invalid_messages 400 没有提供有效消息。
invalid_message_role 400 消息 role 不是 systemuserassistanttool
unsupported_method 404 Gemini 兼容路由不是 :generateContent:streamGenerateContent
model_not_found 404 模型未激活、不存在,或不可作为 Chat 模型调用。
tools_not_supported 400 请求向不支持 tool calling 的模型传入了工具字段。
internal_error 500 服务端非预期错误。