OllamaのOpenAI互換APIをPythonで切り替えるコード例

OllamaのOpenAI互換APIをPythonで切り替えるコード例

※本記事にはプロモーション(広告・アフィリエイトリンク)を含みます。

Ollamaにはバージョン0.1.24からOpenAI互換のエンドポイントが実装されています(執筆時点)。既存のOpenAI APIコードの接続先を2行変えるだけでローカルLLMに切り替えられるため、開発・検証環境の切り替えがシンプルになります。この記事ではrequestsライブラリでの直叩きと、openaiライブラリのbase_urlを差し替える方法の両方を、動作するコードとともに解説します。

OllamaのOpenAI互換エンドポイントの仕様

公式ドキュメントによると、OllamaのOpenAI互換エンドポイントのベースURLは以下です。

http://localhost:11434/v1

執筆時点で対応しているエンドポイントは次の通りです。

エンドポイント 対応するOpenAI API
POST /v1/chat/completions Chat Completions
POST /v1/completions Completions(レガシー)
POST /v1/embeddings Embeddings
GET /v1/models モデル一覧

リクエストとレスポンスのJSON構造はOpenAI API仕様に準拠しています。ただしtool_callsの動作など、モデル依存の機能は使用するモデルが対応しているかどうかで変わります。

requestsで直接叩く最小コード

openaiライブラリを使わず、requestsだけでChat Completionsを呼ぶ例です。

import requests

OLLAMA_BASE_URL = "http://localhost:11434/v1"
MODEL = "llama3.1"  # ollama list で確認したモデル名を指定

def chat(messages: list[dict]) -> str:
    payload = {
        "model": MODEL,
        "messages": messages,
        "stream": False,
    }
    resp = requests.post(
        f"{OLLAMA_BASE_URL}/chat/completions",
        json=payload,
        timeout=120,
    )
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"]

if __name__ == "__main__":
    reply = chat([{"role": "user", "content": "日本語で自己紹介して"}])
    print(reply)

"stream": Falseを明示しているのは重要なポイントです。省略するとモデルによってはストリーミングレスポンスが返り、resp.json()がパース失敗する場合があります。timeoutは120秒に設定していますが、モデルの初回ロード時間は環境によって異なります。

モデル名はollama listで確認します。

$ ollama list
NAME                    ID              SIZE    MODIFIED
llama3.1:latest         ...             4.7 GB  ...
gemma3:latest           ...             5.3 GB  ...

model引数には"llama3.1"でも"llama3.1:latest"でも動作します。

openaiライブラリのbase_urlを書き換える

既存コードがすでにopenaiライブラリを使っている場合は、OpenAI()の引数を2つ変えるだけです。

from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",   # 空文字は例外になるので dummy 値を入れる
)

response = client.chat.completions.create(
    model="llama3.1",
    messages=[{"role": "user", "content": "Pythonでフィボナッチ数列を返す関数を書いて"}],
)
print(response.choices[0].message.content)

api_keyに"ollama"と入れているのは、openaiライブラリが空文字を受け付けず例外を投げるためです。Ollama側ではこの値を検証しないので、任意の文字列で構いません。

既存コードの切り替え差分

変更前後を並べると最小差分は2行です。

# ---- 変更前(OpenAI)----
client = OpenAI(api_key="sk-...")

# ---- 変更後(Ollama)----
client = OpenAI(
    base_url="http://localhost:11434/v1",
    api_key="ollama",
)

.chat.completions.create(...)以下は変更不要です。model引数だけをollama listで確認したモデル名に変えてください。

環境変数でOpenAIとOllamaを切り替えたい場合は次のように書けます。

import os
from openai import OpenAI

USE_OLLAMA = os.getenv("USE_OLLAMA", "false").lower() == "true"

if USE_OLLAMA:
    client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
else:
    client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

開発時はUSE_OLLAMA=trueを設定してローカルで検証し、本番は環境変数を外す、という使い方ができます。

つまずきやすい点

Ollamaが起動していない

接続できない場合はまずollama serveが動いているか確認します。systemdで管理している場合はsystemctl status ollamaで状態を確認できます。

リモートマシンのOllamaに接続する

Ollamaはデフォルトで127.0.0.1:11434のみにバインドされています。LAN内の別マシンから接続するにはOLLAMA_HOST=0.0.0.0を設定します。

# /etc/systemd/system/ollama.service.d/override.conf
[Service]
Environment="OLLAMA_HOST=0.0.0.0"

設定後はsystemctl daemon-reload && systemctl restart ollamaを実行します。Ollamaには認証機能がないため、外部ネットワークへの公開は別途アクセス制限が必要です。

usageフィールドのトークンカウント

Ollamaのレスポンスにはusageフィールドが含まれますが、執筆時点ではトークン数のカウント実装がモデルによって異なる場合があります。OpenAIとの厳密な比較には使わず、デバッグ用の参考値として扱うのが安全です。

タイムアウトの調整

大きいモデルは初回のロードに時間がかかります。timeout=120を基準に、使うモデルのサイズに応じて調整してください。モデルのパラメータ数が大きいほどロード時間は長くなる傾向があります。

まとめ

OllamaのOpenAI互換エンドポイントを使えば、base_urlとapi_keyの2行を変えるだけで既存のOpenAIコードをローカルLLMに切り替えられます。requestsでの直叩きもopenaiライブラリ経由も同じJSON構造を使うので、どちらの実装でも最小限の変更で動作確認できます。

まずollama listで手元のモデルを確認し、model引数に正しい名前を渡すところから始めてみてください。どのモデルが用途に合うかは、Ollama gemma3とllama3.1の日本語精度・速度をRTX 3060で比較するが参考になります。

この記事で触れたもの

よくある質問

OllamaのOpenAI互換エンドポイントのURLは何ですか?

公式ドキュメントによるとデフォルトのベースURLは`http://localhost:11434/v1`です。`/v1/chat/completions`や`/v1/models`などのパスに対応しています(執筆時点)。

openaiライブラリでOllamaを使うときapi_keyに何を入れればいいですか?

任意の文字列で構いません。`openai`ライブラリが空文字を拒否するため`"ollama"`などdummy値を入れます。Ollama側ではこの値を検証しないので認証には使われません。

OllamaをPythonから呼ぶとタイムアウトエラーになります

大きいモデルは初回ロードに時間がかかります。`requests.post()`の`timeout`引数を120秒以上に設定し、それでも解消しない場合はさらに延ばしてください。環境によって異なります。

LAN内の別PCからOllamaに接続できますか?

Ollamaはデフォルトでローカルホストのみにバインドされています。systemdのunit overrideに`Environment="OLLAMA_HOST=0.0.0.0"`を追記して再起動すると、LAN内の別マシンからも接続できます。