文档

文档

聊天补全

Kunavo 的 /v1/chat/completions 端点为 Claude 和 GPT 系列提供 OpenAI chat completions 协议。可通过同一 SDK 使用 streaming、tools 和 JSON 输出;reasoning_effort 的作用取决于模型系列,本页面会说明具体情况。

端点:POST /v1/chat/completions。请求和响应格式与 OpenAI chat completions API 完全一致,包括流式传输以及可选的 tool_calls / reasoning_tokens 字段。

基本调用

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "system", "content": "You are a senior staff engineer."},
        {"role": "user", "content": "Pros and cons of postgres LISTEN/NOTIFY for a job queue?"},
    ],
    max_tokens=800,
)
print(resp.choices[0].message.content)

参数

接受所有标准 OpenAI 参数。其中有些只适用于特定供应商 — 转换器会传递各上游支持的参数。

参数类型备注
model字符串(必填)/v1/models 中任意已启用的模型代号。
messages数组(必填)标准 OpenAI 消息格式。
temperature0..2采样温度。默认值为 1。对本表所列模型无效。
top_p0..1核采样。与 temperature 一样存在例外。
max_tokensint输出上限;同时发送时以 max_completion_tokens 为准。对于 GPT 模型,推理令牌也计入该上限。Claude 请求若两者都未发送,则默认值为 4,096。
streambool以 SSE 形式传输分块。详见下文。
toolsarray函数 / 工具定义。Claude 和 GPT 均支持工具调用。
tool_choiceauto|none|named强制使用特定工具,或让模型自行决定。
response_formatobjectJSON 输出。在 Claude 上会强制执行 json_schema,不会强制执行 json_object — 各系列的详细说明请参见 JSON 输出。
reasoning_effortstring仅适用于 GPT 模型 — 将其作为 reasoning.effort 转发。不会转发给 Claude。参见 推理。
seedint在支持的情况下进行确定性采样。
stopstring|array硬性停止序列。
Claude Fable 5.1、Claude Fable 5、Claude Opus 5.5、Claude Opus 5、Claude Opus 4.8、Claude Opus 4.7和Claude Sonnet 5 不接受 temperature、top_p 或 top_k。Kunavo 会从发往这些模型的请求中移除这三项,而不是把供应商返回的 400 错误直接返回给您,因此它们对这些模型不起作用。

流式传输

设置 stream=True。Kunavo 会按 OpenAI 的完全相同格式发送服务器推送事件:每个分块都是带有 choices[0].delta.content 的 chat.completion.chunk。最终 usage 负载会随 data: [DONE] 一同发送。

stream = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "Explain B-trees in one paragraph."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)
所有聊天模型都支持流式传输。对于 Claude(使用 Anthropic 协议的上游),我们会将 Anthropic 事件流实时转换为 OpenAI 增量内容 — 您的 SDK 不会察觉差异。

工具 / 函数调用

所有供应商均支持工具调用。请将工具定义为 JSON schema;模型会在消息中返回 tool_calls;您执行工具后,再将结果作为 role: "tool" 消息传回。

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string"},
                "unit": {"type": "string", "enum": ["c", "f"]},
            },
            "required": ["city"],
        },
    },
}]

resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{"role": "user", "content": "What's the weather in Tokyo?"}],
    tools=tools,
    tool_choice="auto",
)

# Inspect tool calls the model wants to make
for call in resp.choices[0].message.tool_calls or []:
    print(call.function.name, call.function.arguments)

JSON 输出(response_format)

response_format 用于请求 JSON 输出。由于各模型系列的请求会被转换成不同的上游机制,因此其保证程度取决于模型系列:

系列json_schemajson_object
Claude强制执行。 请求会以 Anthropic 的结构化输出格式(output_config.format)发送;回复会受到您的架构约束。已于 2026-09-24 在 Kunavo 提供服务的每个 Claude 模型上完成检查。不强制执行。 Anthropic 没有不指定架构的 JSON 模式,因此该参数会被接受但忽略 — 回复可能以说明文字或代码围栏开头。
GPT作为 Responses API 的 text.format 转发,但当前上游并非在每次请求中都会应用该设置。解析前请先验证。作为 text.format 转发。
import json

resp = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{"role": "user", "content": "Jane Doe <jane@example.com> wants the Pro plan."}],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "signup",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "email": {"type": "string"},
                    "plan": {"type": "string", "enum": ["free", "pro", "enterprise"]},
                },
                "required": ["name", "email", "plan"],
                "additionalProperties": False,
            },
        },
    },
)
signup = json.loads(resp.choices[0].message.content)  # constrained to the schema

使用 Claude 时,有四点需要了解:

  • 架构会基本按原样发送给 Anthropic。Anthropic 要求对象包含 additionalProperties: false,因此 Kunavo 会为列出属性的对象添加该字段,并保持未设置状态 — 这正是 Pydantic 的 model_json_schema() 所生成的内容。Anthropic 仍会拒绝以下内容,并返回指出问题的 400 错误:未封闭的对象(additionalProperties 设置为任何非 false 的值,或未列出属性且未设置 additionalProperties),以及 oneOf — 请改用 anyOf。其余限制请参见Anthropic 的结构化输出页面。
  • strict 和 name 均会被忽略:Anthropic 会强制执行它接受的所有架构,无论是否为 strict。
  • 架构不能与最后一条 assistant 消息(预填充内容)同时使用;Anthropic 会返回 400 错误。
  • 当 max_tokens 在对象生成到一半时耗尽,JSON 会被截断,且 finish_reason 为 "length"。

视觉 / 多模态输入

支持 vision 能力的模型可以接受图像内容块。您可以使用 HTTPS URL 或 data: base64 URI。

# Pass an image URL or a base64 data URI as part of a multimodal message
resp = client.chat.completions.create(
    model="claude-haiku-4-5",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What's in this image?"},
            {"type": "image_url", "image_url": {
                "url": "https://example.com/cat.jpg"
            }},
        ],
    }],
)
print(resp.choices[0].message.content)

目录中的视觉能力模型包括 Claude Opus 5.5 — 其余模型请参见模型列表。

对于 https 图像,Kunavo 会自行下载文件并将其以内联形式交给模型,因为某些上游会忽略直接提供的图像 URL。限制:每个请求最多 16 张图像,每张图像 5 MB,总计 20 MB,每次下载最长 10 秒。无法获取的图像会导致错误,并指出对应图像,不会被跳过。

推理

此端点上的推理控制如何生效取决于模型系列,因为各系列的请求会被转换为不同的上游 API:

系列reasoning_effortusage 中的推理令牌
GPT在 GPT-6 Astra、GPT-6 Sol、GPT-6 Luna、GPT-5.6 Sol、GPT-5.6 Terra和GPT-5.5 上按原值转发为 Responses API 的 reasoning.effort。可接受的值由模型本身决定;在 GPT-6 Sol 和 GPT-6 Luna 上,none 会关闭推理,max 为最高级别。计入 completion_tokens,并单独列为 completion_tokens_details.reasoning_tokens,按输出费率计费。
Claude不会转发。 Anthropic 请求根据固定字段列表构建 — model、max_tokens、messages、stream、temperature、top_p、top_k、stop、tools、tool_choice 和 response_format — 因此 reasoning_effort、thinking 及所有其他不在列表中的字段都会在此处丢弃。不单独统计。Anthropic 会将任何思考内容计入其 output_tokens,这也正是 completion_tokens 所报告的内容。
# GPT models: reasoning_effort is forwarded as the Responses API's
# reasoning.effort. Reasoning tokens are part of completion_tokens.
resp = client.chat.completions.create(
    model="gpt-6-sol",
    messages=[{"role": "user", "content": "Plan a 3-week MLOps migration."}],
    reasoning_effort="high",
)
details = resp.usage.completion_tokens_details   # absent when no reasoning ran
print(details.reasoning_tokens if details else 0)
Claude 的扩展思考功能通过原生 Messages API调用,该 API 会将 thinking 原样传递给 Anthropic。

提示缓存

较长的系统提示、参考文档或少量示例 — 任何稳定前缀都可以缓存在上游,并在后续调用中以远低于输入价格的费用重放。缓存命中会在 usage 对象中显示为 prompt_tokens_details.cached_tokens。

GPT 模型会自动缓存 — 无需更改请求。cached_tokens 是 prompt_tokens 的子集,按较低的缓存读取费率计费。

Claude 只会缓存到 cache_control 断点为止,而对于较长的提示,此端点会为您设置断点:设在系统提示、工具定义,以及对话中已有助手回合时的最后一条消息上。若要自行选择前缀,请像下面这样将 cache_control 附加到内容块;Kunavo 会保留您设置的断点,只在您留空的位置添加自己的断点:

# Claude caches prefixes you mark with cache_control. Attach it to a content
# block; later calls reusing that prefix read it at ~10% of the input price.
resp = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "text",
                "text": LONG_DOCUMENT,            # the stable, reused prefix
                "cache_control": {"type": "ephemeral"},
            },
            {"type": "text", "text": "Summarize the document above."},
        ],
    }],
)
print(resp.usage.prompt_tokens_details.cached_tokens)
如需全面控制 Claude 提示缓存——包括缓存系统提示和工具定义、设置多个断点,以及使用原生的 cache_creation_input_tokens / cache_read_input_tokens 用量字段——请使用 原生 Messages API。 此端点同样会缓存系统提示和工具定义,一个请求中可以设置多个断点,并以 cache_creation_input_tokens 报告缓存写入、以 prompt_tokens_details.cached_tokens 报告缓存读取;只有原生端点才会原样转发您的请求体而不添加任何断点。

用量对象

每个响应(以及流式传输的最后一个数据块)都包含一个 usage 对象:

字段含义
prompt_tokens我们计费的输入 token 数,包含缓存 token。
prompt_tokens_details.cached_tokens缓存输入量,是 prompt_tokens 的子集,按较低的缓存读取费率计费。
completion_tokens我们计费的输出 token。对于 GPT 模型,这包括推理 token;对于 Claude,这对应 Anthropic 的 output_tokens。
completion_tokens_details.reasoning_tokensGPT 模型:completion_tokens 中用于推理的部分。该值为零时不返回,Claude 模型也不报告该值。
total_tokensprompt_tokens + completion_tokens。

Ollama OpenAI 兼容接口 — /v1/chat/completions

Ollama 通过 http://localhost:11434/v1 上的 OpenAI 兼容 API 提供本地模型,实现了本页所述的同一套 /chat/completions 合约。因此,两者在客户端可互换:任何基于 Ollama v1 API 编写的程序,只需更改 base URL 和模型,即可调用 Kunavo。

from openai import OpenAI

# Before — Ollama's OpenAI-compatible API, local models
client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",                       # ignored locally
)
resp = client.chat.completions.create(
    model="llama3.2",
    messages=[{"role": "user", "content": "Summarize this changelog."}],
)

# After — the same call against hosted frontier models.
# Two lines changed. Everything below them is untouched.
client = OpenAI(
    base_url="https://api.kunavo.com/v1",   # <- was localhost:11434/v1
    api_key=os.environ["KUNAVO_API_KEY"],
)
resp = client.chat.completions.create(
    model="claude-sonnet-5",  # <- was llama3.2
    messages=[{"role": "user", "content": "Summarize this changelog."}],
)

切换服务提供商时通常会出问题的部分在这里不会出问题,因为两者使用相同的线路格式:

功能Ollama v1Kunavo v1
端点路径/v1/chat/completions/v1/chat/completions
流式传输SSE,chat.completion.chunk完全一致 — delta 结构相同
工具调用tools / tool_callsClaude 和 GPT 完全一致
视觉输入多模态本地模型上的 image_url 块相同的区块;URL 或 base64 数据 URI
api_key占位符,会被忽略真实的 Kunavo key
model已拉取的标签(llama3.2)托管模型的 slug(claude-sonnet-5)
usage 扩展字段仅 token 数量还包含 cached_tokens 和 reasoning_tokens
不止聊天completions、embeddings还包括图像、视频和音频端点
要同时保留两者?从环境变量读取 base_url、model 和密钥,并按环境切换——本地模型用于离线迭代,在质量至关重要时使用托管模型,同时沿用同一套代码。完整演练涵盖 Ollama 的 OpenAI 接口支持和不支持的功能,详见 Ollama OpenAI 兼容 API 指南。

Ollama 的 OpenAI 兼容 /v1/chat/completions 端点官方文档在哪里?

Ollama 在其自有代码库的 docs/openai.md 中介绍了 OpenAI 兼容层,该文档是了解本地服务器实现了哪些 OpenAI 字段的权威参考。本页面是 Kunavo 托管式 /v1/chat/completions 端点的对应参考:同样遵循 OpenAI chat completions 合约,并在上文逐字段说明,您可以直接比较这两个接口。简而言之,两者的请求和响应格式相同 — Ollama 在 http://localhost:11434/v1 上提供服务,使用本地拉取的模型;Kunavo 在 https://api.kunavo.com/v1 上提供服务,使用托管的 Claude 和 GPT 模型。

Kunavo 的 /v1/chat/completions 与 Ollama 的 OpenAI API 兼容吗?

兼容 — 两者都实现了相同的 OpenAI chat completions 合约,因此,基于 Ollama 的 http://localhost:11434/v1 编写的客户端可以直接用于 https://api.kunavo.com/v1,无需修改。请求字段(messages、temperature、max_tokens、stream、tools、tool_choice、response_format、stop、seed)和响应字段(choices[].message、流式传输时的 choices[].delta、usage)均相同。托管模型会带来预期的差异:api_key 需要使用真实密钥,而非占位符;model 需要使用 claude-sonnet-5 这样的托管模型代号,而非 llama3.2 这样的已拉取模型标签;usage 还包含本地模型不会报告的 cached_tokens 和 reasoning_tokens。

如何将 Ollama 应用迁移到托管的 Claude 或 GPT?

只需修改两行:将 base_url 从 http://localhost:11434/v1 改为 https://api.kunavo.com/v1,并将 model 从本地标签改为托管模型代号。使用真实的 Kunavo 密钥,而不是 Ollama 会忽略的占位符。由于 SSE 和 tool_calls 格式完全相同,流式传输、工具调用和视觉处理代码路径都无需更改。

我可以在开发时继续使用 Ollama,并在生产环境中使用托管模型吗?

可以,而且这是很常见的配置 — 从环境变量读取基础 URL、模型和密钥,并根据环境进行切换。两端使用相同的 OpenAI 协议,因此无需维护第二套代码路径:离线迭代时使用本地 Llama 或 Qwen,需要高质量结果时使用托管的 Claude 或 GPT。工具定义和流式处理程序可以原样共用。

Kunavo 在 Ollama 的兼容接口基础上增加了哪些 OpenAI 端点?

Ollama 的 OpenAI 兼容接口包括 /chat/completions、/completions、/embeddings 和 /models。Kunavo 使用同一个密钥增加了媒体端点:/v1/images/generations、/v1/images/edits、/v1/video/generations、/v1/videos 和 /v1/audio/music;此外还有 Claude 使用的原生 Anthropic /v1/messages 端点。另有两点需要说明:/v1/audio/speech、/v1/audio/transcriptions 和 /v1/embeddings 虽已实现对应的线路格式,但目前没有启用任何模型,因此暂时无法成功调用;并且 Kunavo 不像 Ollama 那样在本地运行模型。GET /v1/models 始终是确认当前可调用模型的权威来源。

接下来