OllamaのAPIを使う前に

OllamaはローカルPCでLLMを動かすためのツールです。ollama serve を実行(またはアプリとして起動)すると、デフォルトで http://localhost:11434 にREST APIサーバーが立ち上がります。このAPIを使ってPythonやNode.jsからローカルLLMを呼び出せます。

まずモデルをダウンロードしておきます。

ollama pull llama3.2
ollama pull nomic-embed-text  # エンベディング用

OllamaのREST APIの基本

Ollamaは独自のAPIとOpenAI互換APIの両方を提供しています。

独自API(/api/chat)

POST http://localhost:11434/api/chat
Content-Type: application/json

{
  "model": "llama3.2",
  "messages": [
    {"role": "user", "content": "こんにちは"}
  ],
  "stream": false
}

OpenAI互換API(/v1/chat/completions)

POST http://localhost:11434/v1/chat/completions

OpenAI SDKをそのまま使いたい場合は互換エンドポイントが便利です。既存コードの base_url を変えるだけで移行できます。

PythonからOllamaを使う

公式Pythonライブラリの使用

pip install ollama
import ollama

# シンプルなチャット
response = ollama.chat(
    model="llama3.2",
    messages=[
        {"role": "user", "content": "Pythonでフィボナッチ数列を生成するコードを書いて"}
    ]
)
print(response["message"]["content"])

ストリーミングで逐次出力

import ollama

for chunk in ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "量子コンピュータについて説明して"}],
    stream=True
):
    print(chunk["message"]["content"], end="", flush=True)

stream=True にすると、トークンが生成されるたびに逐次的にデータが届きます。チャットUIのように文字が流れる表示に使えます。

マルチターン会話

import ollama

history = []

def chat(user_message: str) -> str:
    history.append({"role": "user", "content": user_message})
    response = ollama.chat(model="llama3.2", messages=history)
    assistant_message = response["message"]["content"]
    history.append({"role": "assistant", "content": assistant_message})
    return assistant_message

print(chat("私の名前はケイタです"))
print(chat("私の名前は何でしたか?"))  # 会話履歴から答えられる

エンベディングの取得

import ollama

response = ollama.embeddings(
    model="nomic-embed-text",
    prompt="このテキストをベクトルに変換する"
)
vector = response["embedding"]  # 768次元のリスト
print(f"ベクトル次元数: {len(vector)}")

Node.jsからOllamaを使う

npm install ollama
import { Ollama } from "ollama";

const ollama = new Ollama({ host: "http://localhost:11434" });

// チャット(非ストリーミング)
const response = await ollama.chat({
  model: "llama3.2",
  messages: [{ role: "user", content: "JavaScriptの非同期処理を説明して" }]
});
console.log(response.message.content);

// ストリーミング
const stream = await ollama.chat({
  model: "llama3.2",
  messages: [{ role: "user", content: "AIの歴史を教えて" }],
  stream: true
});

for await (const chunk of stream) {
  process.stdout.write(chunk.message.content);
}

Next.js APIルートでの使用例

// app/api/chat/route.ts
import { Ollama } from "ollama";
import { NextRequest } from "next/server";

export async function POST(req: NextRequest) {
  const { message } = await req.json();
  const ollama = new Ollama();
  
  const encoder = new TextEncoder();
  const stream = new ReadableStream({
    async start(controller) {
      const response = await ollama.chat({
        model: "llama3.2",
        messages: [{ role: "user", content: message }],
        stream: true
      });
      for await (const chunk of response) {
        controller.enqueue(encoder.encode(chunk.message.content));
      }
      controller.close();
    }
  });
  
  return new Response(stream);
}

Claude APIとの使い分け

OllamaとClaude APIはそれぞれ得意領域が異なります。

Ollamaを選ぶ場面

  • データをクラウドに送りたくないプライバシー重視の用途
  • 大量リクエストを処理するバッチ処理でAPI費用を抑えたい
  • 開発・テスト環境でコストをゼロにしたい
  • 特定のオープンソースモデルをファインチューニングして使いたい

Claude APIを選ぶ場面

  • 最高品質の回答が必要な本番サービス
  • 大きなコンテキスト(200K tokens)が必要な場面
  • 安定したSLA(稼働保証)が必要なビジネス用途
  • マルチモーダル(画像入力)が必要な場面

まとめ

OllamaのAPIはシンプルなREST設計で、Pythonも Node.jsも公式ライブラリで簡単に呼び出せます。OpenAI互換エンドポイントも用意されているため、既存のOpenAIコードをほぼ変えずにローカルLLMに切り替えられます。プロトタイプはOllamaで低コストで試し、本番はClaude APIに切り替えるというハイブリッド戦略が実践的です。