目次

Ollama ツール呼び出しチュートリアル:Function Calling の使い方

言語モデルは今日の天気やデータベースの内容を知りませんし、正確な計算も得意ではありません。ツール呼び出し(tool calling、function calling とも呼ばれます)を使うと、モデルは「プログラムに関数の実行を依頼」し、その結果に基づいて回答できます。

ツールに対応したモデルのみ利用できます。ollama.com のモデルページには tools と表示されます。たとえば qwen3、llama3.1、gpt-oss、mistral などです。

動作の流れ

1. あなた:質問 + 使用可能なツールの説明 ──────────▶ モデル
2. モデル:「get_weather(city="東京") を呼び出してください」◀──
3. あなたのプログラムが get_weather("東京") を実行 → "24°C、曇り"
4. あなた:結果を送り返す ─────────────────────▶ モデル
5. モデル:「東京は現在 24 度で曇りです。薄手の上着を持っていくとよいでしょう。」

モデル自体がプログラムを実行することはありません。どのツールをどの引数で呼び出すかを決めるだけです。実際に実行するのはあなたのプログラムなので、実行できる処理を完全に制御できます。

Python の例

ollama Python パッケージでは、Python 関数をそのままツールとして渡せます。関数の型アノテーションと docstring から、ツールの説明が自動生成されます。

from ollama import chat


def get_weather(city: str) -> str:
    """
    都市の現在の天気を調べます。

    Args:
        city: 都市名。例:「東京」

    Returns:
        天気の説明
    """
    fake_data = {"東京": "24°C、曇り", "大阪": "29°C、晴れ"}
    return fake_data.get(city, "データが見つかりません")


tools = {"get_weather": get_weather}
messages = [{"role": "user", "content": "東京と大阪の現在の天気は?"}]

response = chat(model="qwen3:8b", messages=messages, tools=[get_weather])
messages.append(response.message)

# モデルは一度に複数のツール呼び出しを要求することがあります
for call in response.message.tool_calls or []:
    fn = tools[call.function.name]
    result = fn(**call.function.arguments)
    print(f"{call.function.name}({call.function.arguments}) を呼び出しました → {result}")
    messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})

final = chat(model="qwen3:8b", messages=messages)
print(final.message.content)

ポイント:

  1. モデルの応答(tool_calls を含む)を messages に追加します。
  2. 各ツールの実行結果を role: "tool" として追加します。
  3. もう一度 chat を呼び出すと、モデルは結果に基づいて回答します。

呼び出し回数をモデルに任せる

「まず為替レートを調べてから金額を計算する」など、複数のツールを続けて呼び出す必要がある質問もあります。モデルがツール呼び出しを要求しなくなるまで、ループで処理します。

from ollama import chat


def get_exchange_rate(currency: str) -> float:
    """外貨 1 単位を日本円に換算する為替レートを取得します。currency は USD、JPY などです。"""
    return {"USD": 32.1, "JPY": 0.21}.get(currency.upper(), 0.0)


def multiply(a: float, b: float) -> float:
    """a と b を掛け算します。"""
    return a * b


tools = {f.__name__: f for f in [get_exchange_rate, multiply]}
messages = [{"role": "user", "content": "350 米ドルはおよそ何円ですか?"}]

while True:
    response = chat(model="qwen3:8b", messages=messages, tools=list(tools.values()))
    messages.append(response.message)
    if not response.message.tool_calls:
        break
    for call in response.message.tool_calls:
        result = tools[call.function.name](**call.function.arguments)
        messages.append({"role": "tool", "tool_name": call.function.name, "content": str(result)})

print(response.message.content)

実際に使うときは、モデルが無限ループに陥らないよう、呼び出し回数に上限を設けてください。

REST API でツールを定義する

Python パッケージを使わない場合は、JSON Schema でツールを記述します。

curl http://localhost:11434/api/chat -d '{
  "model": "qwen3:8b",
  "messages": [{ "role": "user", "content": "東京の天気は?" }],
  "stream": false,
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "都市の現在の天気を調べます",
      "parameters": {
        "type": "object",
        "properties": {
          "city": { "type": "string", "description": "都市名" }
        },
        "required": ["city"]
      }
    }
  }]
}'

応答内の message.tool_calls:

"tool_calls": [
  { "function": { "name": "get_weather", "arguments": { "city": "東京" } } }
]

実行後、結果を {"role": "tool", "tool_name": "get_weather", "content": "24°C、曇り"} として messages に追加し、もう一度送信します。

ツールの説明を書く

モデルはツールの名前と説明だけを手掛かりに、いつ使うか、引数をどう指定するかを判断します。

  • 関数名で用途が明確に伝わるようにします。search_orders は query1 より適切です。
  • 説明には、どんな場合に使うか、引数の形式と例を明記します。
  • 引数はできるだけ少なくし、型を明確にします。列挙型(enum)を使える場合は使います。
  • ツールを増やしすぎないようにします。小型モデルはツールが十数個あると選択を誤りやすくなります。

セキュリティに関する注意

  • ツールはユーザー入力に基づいてモデルが呼び出します。ユーザーが入力を制御できる場合、間接的にあなたのツールを呼び出せることになります。
  • 任意のコードや SQL を実行したり、データを削除したりできるツールは提供しないでください。
  • 支払い、メール送信、削除などの副作用を伴う操作は、実行前にユーザーの確認を求めてください。
  • モデルが渡す引数を検証し、無条件に信頼しないでください。

更新日 2026年10月12日