~/tools / 在自己的伺服器上執行本機 LLM / Ollama OpenAI Converter
Ollama OpenAI Converter — 在 Ollama /api/chat 與 /v1/chat/completions 之間轉換聊天請求與回應
在 Ollama 原生的 /api/chat 與相容 OpenAI 的 /v1/chat/completions 之間,雙向轉換聊天請求,並把 /api/chat 的回應轉成 /v1/chat/completions 所回傳的回應。轉換依據 Ollama 自身的原始碼,工具會列出每一個被改名、被捨棄或沒有對應項目的欄位。資料不會離開你的瀏覽器。
已讀取為相容 OpenAI 的請求(/v1/chat/completions)。
- Ollama 不會讀取這些欄位,而是把它們捨棄:tool_choice
curl
送往 localhost:11434 上的 Ollama。如果 Ollama 在其他位置執行,請修改位址。
curl http://localhost:11434/api/chat -d '{"model":"qwen2.5:7b","messages":[{"role":"system","content":"Answer in one sentence."},{"role":"user","content":"What is the weather in Toronto?"},{"role":"assistant","content":"","tool_calls":[{"id":"call_1","function":{"name":"get_weather","arguments":{"city":"Toronto"}}}]},{"role":"tool","content":"11 degrees, cloudy","tool_name":"get_weather","tool_call_id":"call_1"}],"stream":false,"options":{"stop":["END"],"num_predict":200,"temperature":0.2},"tools":[{"type":"function","function":{"name":"get_weather","description":"Weather for a city","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}]}'Ollama /api/chat 請求
{
"model": "qwen2.5:7b",
"messages": [
{
"role": "system",
"content": "Answer in one sentence."
},
{
"role": "user",
"content": "What is the weather in Toronto?"
},
{
"role": "assistant",
"content": "",
"tool_calls": [
{
"id": "call_1",
"function": {
"name": "get_weather",
"arguments": {
"city": "Toronto"
}
}
}
]
},
{
"role": "tool",
"content": "11 degrees, cloudy",
"tool_name": "get_weather",
"tool_call_id": "call_1"
}
],
"stream": false,
"options": {
"stop": [
"END"
],
"num_predict": 200,
"temperature": 0.2
},
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string"
}
},
"required": [
"city"
]
}
}
}
]
}轉換的欄位
| 來源 | 轉換後 |
|---|---|
| tool_choice | 未帶過去 |
| stop | options.stop |
| max_tokens | options.num_predict |
| temperature | options.temperature |
| stream | stream(未設定,因此採用原本端點的預設值) |
/api/chat 預設串流,/v1/chat/completions 則不會。轉換後的請求一律會設定 stream,讓它的行為與原本的請求相同。
相容 OpenAI 的 API 沒有用於上下文長度(num_ctx)的欄位。Ollama 的文件建議在 Modelfile 中用 PARAMETER num_ctx 建立一個模型,並以該名稱呼叫。
轉換遵循 Ollama v0.40.14。在較早的版本中,當請求沒有送出 temperature 與 top_p 時,相容 OpenAI 的端點會把兩者設為 1.0,而 content 陣列為空的 assistant 訊息的工具呼叫會被附加到前一則訊息。
轉換依據 Ollama 的原始碼(v0.40.14,openai/openai.go)與 OpenAI 相容性頁面,並於 2026-11-06 以 Ollama 0.40.11 檢查。 Ollama:OpenAI 相容性
一切都在你的瀏覽器中完成。這個工具不會連線到任何地方。
Ollama 以兩個端點處理聊天請求:原生的 /api/chat,以及相容 OpenAI 的 /v1/chat/completions。第二個端點本身並不執行請求。在 Ollama 的原始碼(openai/openai.go)中,每個請求會先被轉換成 /api/chat 請求,回答再被轉換回來。這個工具在你的瀏覽器中做同樣的轉換。貼上請求本文或回應,它會偵測是哪一種。從 OpenAI 形式轉成 Ollama 時:max_tokens 變成 options.num_predict,單一的 stop 字串變成清單,temperature、top_p、seed 與各項懲罰參數移到 options,response_format 變成 format("json",或取自 json_schema.schema 的結構描述),reasoning_effort 變成 think(none 變成 false,minimal 變成 low,xhigh 與 ultra 變成 max),工具呼叫的引數從 JSON 字串變成物件,而 tool 訊息會依 tool_call_id 查出函式名稱。content 陣列的每個部分都會變成獨立的一則訊息,圖片必須是 JPEG、PNG 或 WebP 的 base64 data URL,圖片 URL 會被拒絕。Ollama 程式碼中沒有的欄位,例如 tool_choice、n、user、logit_bias 與 max_completion_tokens,會在不報錯的情況下被捨棄。在 Ollama 0.40.11 上的我們的測試中,max_completion_tokens 設為 3 的請求仍回傳了很長的回答,因為 Ollama 只讀取 max_tokens。反方向時,沒有 OpenAI 對應項目的 options,例如 num_ctx、top_k 與 min_p,只會被列出,不會被寫入。對於回應:done_reason 變成 finish_reason(模型呼叫了工具時,stop 變成 tool_calls),prompt_eval_count 與 eval_count 變成 usage,thinking 變成 reasoning,各項耗時則被捨棄。Ollama 把 id 寫成 chatcmpl- 後接一個隨機數字,這個工具則寫成 chatcmpl-0。我們用兩種方式檢查了轉換:把每個請求的兩種形式都連同除錯欄位 _debug_render_only 送給 Ollama 0.40.11(它會回傳模型實際會看到的提示),再比較兩份提示;以及把轉換後的回應與 /v1/chat/completions 的真實回答比對。
這個工具的核心邏輯以 MIT 授權開放原始碼。 github.com/seigo5555/toolkitbox-lib/src/ollama-openai.ts
使用情境
- 把為 OpenAI SDK 寫的程式碼改成 Ollama 的原生 API,或反過來,不必猜欄位名稱
- 找出為什麼你送給 /v1/chat/completions 的某個欄位沒有效果
- 看看期待 OpenAI 回應的用戶端會從 Ollama 收到什麼
使用方法
- 貼上 /v1/chat/completions 或 /api/chat 的請求本文,或是將 stream 設為 false 所送出的 /api/chat 回應。
- 方向維持自動,或在工具無法判斷你貼上的是哪一種形式時自行選擇。
- 複製轉換後的 JSON 或 curl 指令,並閱讀警告與轉換欄位的表格。
FAQ
為什麼轉換後的請求一律會設定 stream?
/api/chat 預設串流,/v1/chat/completions 則不會。如果原本的請求沒有設定 stream,轉換後的請求會帶上原本端點的預設值,讓兩者的行為相同。
如何透過相容 OpenAI 的 API 設定上下文長度?
沒有對應的欄位。Ollama 的文件建議在 Modelfile 中用 PARAMETER num_ctx 建立一個模型,再以該模型名稱呼叫 API。工具會把 options.num_ctx 列為沒有對應項目。
某個欄位被標示為「未帶過去」。Ollama 會拒絕這個請求嗎?
不會。Ollama 不會讀取程式碼中沒有的欄位,而是把它們捨棄。在 Ollama 0.40.11 上的我們的測試中,帶有 tool_choice、n、user、logit_bias 與 max_completion_tokens 的請求被接受而沒有報錯,而且 max_completion_tokens 並沒有限制回答的長度。
Ollama v0.40.14 改變了什麼?
在 v0.40.14 之前,當請求沒有送出 temperature 與 top_p 時,相容 OpenAI 的端點會把兩者設為 1.0。從 v0.40.14 起,會套用模型自己的預設值,與 /api/chat 相同。content 陣列為空且帶有工具呼叫的 assistant 訊息,處理方式也不同:在 0.40.11 上的我們的測試中,它的工具呼叫會被附加到前一則訊息。這個工具遵循 v0.40.14。
為什麼不能貼上 OpenAI 的回應?
Ollama 只會把原生回應轉成 OpenAI 形式,不會反過來,所以沒有可以照抄的轉換。請改貼 /api/chat 的回應。
我的資料會被傳送到任何地方嗎?
不會。轉換在你的瀏覽器中執行。curl 指令只是供你自行執行的文字。
相關文章
- 在自己的程式中呼叫本機模型:Ollama 的結構化輸出與 OpenAI-compatible API用 JSON Schema 限制本機模型的輸出,並從 OpenAI 風格的用戶端呼叫 Ollama:官方文件怎麼說,以及哪些功能不支援。
- 在小型 VPS 上監看 Ollama 的記憶體使用查看 Ollama 在記憶體中載入了什麼、保留多久,以及哪些設定會改變記憶體用量:ollama ps、keep_alive 與各項上限,內容出自官方 FAQ。
- 在自己的 VPS 上將 Dify 連接到 Ollama在自己的 VPS 上執行 Dify,並以 Ollama 作為模型:依官方文件說明安裝、外掛欄位、Docker 位址問題與 embedding。