文件
聊天完成
Kunavo 的 /v1/chat/completions 端點為 Claude 和 GPT 系列提供 OpenAI 聊天完成協定。串流、工具和 JSON 輸出可透過相同的 SDK 使用;reasoning_effort 的作用取決於模型系列,本頁會逐一說明。
端點:POST /v1/chat/completions。請求和回應格式與 OpenAI 的聊天完成 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 訊息格式。 |
temperature | 0..2 | 取樣溫度。預設值為 1。對此表列出的模型無效。 |
top_p | 0..1 | 核採樣。例外情況與 temperature 相同。 |
max_tokens | int | 輸出上限;若同時傳送 max_,則以它為準。對 GPT 模型而言,推理 token 也計入此上限。Claude 請求若兩者皆未傳送,則使用 4,096。 |
stream | bool | 以 SSE 串流傳送區塊。請見下文。 |
tools | array | 函式/工具定義。Claude 和 GPT 都支援工具使用。 |
tool_choice | auto| | 強制使用指定工具,或讓模型自行決定。 |
response_ | object | JSON 輸出。Claude 會強制套用 json_,但不會強制套用 json_object — 各模型系列的詳細說明請見 JSON 輸出。 |
reasoning_ | string | 僅適用於 GPT 模型 — 會以 reasoning. 傳遞。不會傳遞給 Claude。請見 推理。 |
seed | int | 在支援時使用決定性取樣。 |
stop | string|array | 硬性停止序列。 |
temperature、top_p 或 top_k。Kunavo 會在向這些模型送出請求前移除這三個欄位,不會將供應商的 400 錯誤傳回給您,因此這三個欄位對這些模型無效。串流
設定 stream=True。Kunavo 會以 OpenAI 的完全相同格式傳送伺服器傳送事件:每個區塊都是帶有 choices[0].delta.content 的 chat.completion.chunk。最後的用量資料會隨 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)工具/函式呼叫
所有供應商都支援工具呼叫。請以 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_schema | json_object |
|---|---|---|
| Claude | 強制套用。會以 Anthropic 的結構化輸出(output_)傳送;回覆會符合您的 schema。已於 2026-09-24 在 Kunavo 提供的所有 Claude 模型上驗證。 | 不會強制套用。Anthropic 沒有不指定 schema 的 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 schemaClaude 有四點須知:
- 結構描述幾乎會依您撰寫的樣子傳送給 Anthropic。Anthropic 要求物件必須設定
additionalProperties: false,因此,對於已列出屬性但尚未設定此欄位的物件,Kunavo 會補上這項設定 — 這正是 Pydantic 的model_json_schema()所產生的情況。Anthropic 仍會拒絕以下內容,並傳回指出問題的 400 錯誤:未封閉的物件(additionalProperties設為非false的值,或未列出屬性且未設定additionalProperties),以及oneOf— 請改用anyOf。其餘限制列於Anthropic 的結構化輸出頁面。 strict和name會被忽略:Anthropic 對所有接受的 schema 一律強制套用,無論是否為 strict。- schema 無法與最後一則
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_ | 用量中的推理 token |
|---|---|---|
| GPT | 會在 GPT-6 Astra、GPT-6 Sol、GPT-6 Luna、GPT-5.6 Sol、GPT-5.6 Terra和GPT-5.5 上以原值傳遞至 Responses API 的 reasoning.。可接受的值由模型本身決定;在 GPT-6 Sol 和 GPT-6 Luna 上,none 會關閉推理,而 max 是最高等級。 | 計入 completion_,並以 completion_ 分項列出,按輸出費率計費。 |
| Claude | 不會傳遞。Anthropic 請求是依固定欄位清單建立 — model、max_、messages、stream、temperature、top_、top_、stop、tools、tool_ 和 response_ — 因此 reasoning_、thinking 及清單以外的其他欄位都會在此處捨棄。 | 不會提供分項明細。Anthropic 會將任何思考內容計入其 output_,這也是 completion_ 回報的內容。 |
# 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)thinking 原樣傳遞給 Anthropic。提示快取
長系統提示、參考文件、少量範例 — 任何穩定的前綴都可在上游快取,供後續呼叫重用,費用只需輸入價格的一小部分。快取命中會以 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)cache_creation_input_tokens / cache_read_input_tokens 用量欄位——請使用 原生 Messages API。 這個端點同樣會快取系統提示和工具定義,單一請求中可以設定多個斷點,並以 cache_creation_input_tokens 回報快取寫入、以 prompt_tokens_details.cached_tokens 回報快取讀取;只有原生端點會原樣轉送您的請求本文,而不新增任何斷點。用量物件
每個回應(以及串流回應的最後一個區塊)都包含 usage 物件:
| 欄位 | 意義 |
|---|---|
prompt_ | 我們向您計費的輸入 token 數,包含快取 token。 |
prompt_ | 快取輸入:prompt_ |
completion_ | 我們計費的輸出 token。在 GPT 模型上,這包括推理 token;在 Claude 上,這是 Anthropic 的 output_ |
completion_ | GPT 模型:completion_ |
total_tokens | prompt_ |
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 v1 | Kunavo v1 |
|---|---|---|
| 端點路徑 | /v1/ | /v1/ |
| 串流 | SSE、chat. | 完全相同:delta 結構相同 |
| 工具呼叫 | tools / tool_calls | Claude 和 GPT 均完全相同 |
| 視覺輸入 | 多模態本機模型中的 image_url 區塊 | 相同的區塊;URL 或 base64 data URI |
| api_key | 佔位值,會忽略 | 有效的 Kunavo 金鑰 |
| model | 已下載的標籤(llama3.2) | 託管模型代稱(claude-sonnet-5) |
| usage 額外欄位 | 只有 token 數量 | 另含 cached_ |
| 不只聊天 | 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 聊天完成契約,並已逐欄說明,因此您可以直接比較兩者的功能範圍。簡而言之,兩者的請求和回應格式相同 — Ollama 針對本機下載的模型,在 http://localhost:11434/v1 提供服務;Kunavo 則針對託管的 Claude 和 GPT 模型,在 https://api.kunavo.com/v1 提供服務。
Kunavo 的 /v1/chat/completions 與 Ollama 的 OpenAI API 相容嗎?
相容 — 兩者都實作相同的 OpenAI 聊天完成契約,因此以 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,並透過 Anthropic 原生 /v1/messages 端點提供 Claude。也有兩項必須如實說明的限制:/v1/audio/speech、/v1/audio/transcriptions 和 /v1/embeddings 雖已實作傳輸格式,但目前後端都尚未啟用任何模型,因此目前無法成功呼叫;此外,Kunavo 和 Ollama 不同,不會在本機執行模型。GET /v1/models 始終是可呼叫模型的權威清單。