~/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引き継がれません
stopoptions.stop
max_tokensoptions.num_predict
temperatureoptions.temperature
streamstream(未指定なので、元のエンドポイントの既定値)

/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 から何を受け取るかを確認する

使い方

  1. /v1/chat/completions か /api/chat のリクエスト本文、または stream を false にして送った /api/chat のレスポンスを貼り付けます。
  2. 方向は自動のままにするか、貼り付けた形をツールが判別できないときは自分で選びます。
  3. 変換後の 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 コマンドは、あなたが実行するための文字列にすぎません。

関連する記事

関連ツール