~/tools / ローカルLLMをサーバーで動かす / Ollama OpenAI Converter
Ollama OpenAI Converter — Ollama と OpenAI 互換 API の形式を変換
チャットのリクエストを、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 互換のエンドポイントはこの2つを 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 の2つのエンドポイントで受け付けます。後者は、それだけでリクエストを実行するわけではありません。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 データ URL でなければなりません。画像の URL は拒否されます。tool_choice、n、user、logit_bias、max_completion_tokens のように Ollama のコードにないフィールドは、エラーなしで捨てられます。Ollama 0.40.11 での私たちのテストでは、max_completion_tokens を 3 にしたリクエストでも長い答えが返りました。Ollama が読むのは max_tokens だけだからです。逆方向では、num_ctx、top_k、min_p のように OpenAI に対応するものがない options は、書き出されずに一覧に載ります。レスポンスでは、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 に送り(モデルに見えるプロンプトが返ります)、2つのプロンプトを比べる方法と、変換したレスポンスを /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 互換のエンドポイントはこの2つを 1.0 にしていました。v0.40.14 からは、/api/chat と同じようにモデル自身の既定値が使われます。content の配列が空でツール呼び出しを持つ assistant メッセージの扱いも変わりました。0.40.11 での私たちのテストでは、そのツール呼び出しは前のメッセージに付けられました。このツールは v0.40.14 に従います。
OpenAI のレスポンスを貼り付けられないのはなぜですか?
Ollama が変換するのは、独自のレスポンスから OpenAI の形への一方向だけで、逆の変換はないため、写すべき変換がありません。代わりに /api/chat のレスポンスを貼り付けてください。
データはどこかに送られますか?
いいえ。変換はブラウザの中で行われます。curl コマンドは、あなたが実行するための文字列にすぎません。
関連する記事
- ローカルモデルを自分のコードから呼び出す: Ollama の構造化出力と OpenAI 互換 APIJSON Schema でローカルモデルの出力を制約し、OpenAI 形式のクライアントから Ollama を呼び出す方法。公式ドキュメントの内容と、未対応の機能をまとめました。
- 小さなVPSでOllamaのメモリを見張るOllamaがメモリに何を載せ、どれだけの間そこに置き、どの設定で変わるのかを見ます。ollama ps、keep_alive、各種の上限を、公式FAQから。
- 自分のVPSでDifyとOllamaをつなぐ自分のVPSでDifyを動かし、モデルにOllamaを使う方法です。インストール、プラグインの入力欄、Dockerのアドレスの問題、埋め込みを公式ドキュメントからまとめました。