本文へスキップ
Markdown で表示

ツール呼び出し、最初から最後まで

tool_choice を "auto" にした往復 1 回です。モデルがツールを要求したらコードが実行し、その結果を tool メッセージとして返して最終回答を受け取ります。このレシピは auto のみを扱います。ツールを呼ぶかどうかはモデルが決め、強制的な tool_choice は扱いません。

クイックスタート

python
import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.bricksum.com/v1", api_key=os.environ["KILN_API_KEY"])

tools = [{"type": "function", "function": {
    "name": "get_weather",
    "description": "Current weather for a city",  # required
    "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
}}]
messages = [{"role": "user", "content": "What's the weather in Seoul?"}]

first = client.chat.completions.create(model="qwen3-32b", messages=messages,
                                       tools=tools, tool_choice="auto", max_tokens=800)
choice = first.choices[0]
# The model may answer without calling the tool, so this is a check, not an index.
if not choice.message.tool_calls:
    print(f'no tool call, finish_reason: "{choice.finish_reason}"')
    print("answer:", choice.message.content)
else:
    # One reply can carry several tool calls; answer every one of them.
    messages.append(choice.message)
    for call in choice.message.tool_calls:
        print("tool call:", call.function.name, call.function.arguments)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps({"temp_c": 27})})
    final = client.chat.completions.create(model="qwen3-32b", messages=messages, max_tokens=800)
    print("final:", final.choices[0].message.content)

確認

スクリプトを実行します。1 回目の呼び出しの message.tool_calls には、city を含む JSON 引数とともに get_weather が入っています(項目が複数あることがあり、それぞれに tool メッセージを返します)。2 回目の呼び出しの message.content はモデル自身の言い回しのため実行のたびに変わりますが、渡した気温(27)に言及します。

expected output
tool call: get_weather {
  "city": "Seoul"
}
final: The current temperature in Seoul is **27 °C**.

設定リファレンス

  • tool_choice = "auto" — モデルがツールを呼ぶかどうかを決めます。"required" や関数を指定する強制選択には対応していません。qwen3-32b では、強制的なツール選択が明確なエラーなしに失敗します(2026-09-26 実測)。tool_choice を "required" にすると本文が平文 "Internal Server Error" の HTTP 500 が返り、関数を指定すると arguments が空の 200(finish_reason "stop")が返ります。どちらも 4xx ではないため、再試行では解決しません。tool_choice は "auto" のみを送ってください。
  • tools[].function.description = required — すべてのツールに必要です。ないと 400 で拒否されます。
  • parallel_tool_calls = not applied — モデルページで並列ツール呼び出しが対応となっているモデルでのみ適用され、qwen3-32b は該当しません。gpt-oss-120b での実測では 200 で受け付けられ、モデルは応答ごとに最大 1 つのツールしか呼び出しませんでした。qwen3-32b では parallel_tool_calls の設定が適用されません。これは応答のツール呼び出しが 1 つだけという意味ではありません。parallel_tool_calls: false を送っても、1 つの応答に複数のツール呼び出しが含まれることがあります。tool_calls のすべての項目に、それぞれ tool メッセージで応答してください。
  • max_tokens = 800 — reasoning トークンもこの上限内で課金されます。値が小さいと、tool_calls が出る前に finish_reason が "length" で終わることがあります。

制限事項

  • 強制的な tool_choice("required"、または特定の関数の指定)には対応していません。このレシピは "auto" のみを扱います。qwen3-32b では、強制的なツール選択が明確なエラーなしに失敗します(2026-09-26 実測)。tool_choice を "required" にすると本文が平文 "Internal Server Error" の HTTP 500 が返り、関数を指定すると arguments が空の 200(finish_reason "stop")が返ります。どちらも 4xx ではないため、再試行では解決しません。tool_choice は "auto" のみを送ってください。
  • qwen3-32b では parallel_tool_calls の設定が適用されません。これは応答のツール呼び出しが 1 つだけという意味ではありません。parallel_tool_calls: false を送っても、1 つの応答に複数のツール呼び出しが含まれることがあります。tool_calls のすべての項目に、それぞれ tool メッセージで応答してください。

トラブルシューティング

  • HTTP 500 Internal Server Error — リクエストの tool_choice が "required" です。qwen3-32b では 4xx ではなく平文の 500 で失敗します(2026-09-26 実測)。 tool_choice を "auto" にしてください。同じリクエストを再試行しても同じ 500 が返ります。
  • "arguments": "" — リクエストが tool_choice で関数を指定しています。qwen3-32b では arguments が空の 200(finish_reason "stop")が返り(2026-09-26 実測)、JSON.parse / json.loads が失敗します。 tool_choice を "auto" にし、どのツールを期待するかをプロンプトで説明してください。arguments をパースする前に tool_calls を確認してください。
  • "message": "missing or malformed API key" — KILN_API_KEY が未設定、失効している、またはスクリプトを実行するシェルに export されていません。 コンソール → API キーで新しいキーを発行し、再度 export してください。
  • "code": "model_not_found" — model フィールドが、自分のキーで GET /v1/models を呼んだときに返る ID ではありません。 モデルページか GET /v1/models で一覧を確認し、そこにある ID(例:"qwen3-32b")を model に設定してください。
  • finish_reason: "length" — モデルがツールを呼ぶかどうかの reasoning を終える前に max_tokens に達しました。 クイックスタートが送る 800 より大きく、たとえば 1600 に、1 回目の create 呼び出しの max_tokens を上げてください。
メモ
このページのスニペットは 2026-09-21 に openai 3.16.2 (Python 3.14.7), openai 7.20.0 (Node 24.12.0) の環境で Kiln API に対して実行し、動作を確認しています。 未確認の項目: この実行は gpt-oss-120b で行いました。ページは現在 qwen3-32b を使っており、このモデルではまだ実行していないため、以下の想定出力と異なる場合があります。両クイックスタートタブのツール非呼び出し分岐はこの実行の後に追加されたもので、ステージングではなくローカルのスタブサーバーでのみ確認しています。すべてのツール呼び出しに応答するループはさらにその後に追加されたもので(#760)、API に対して実行していません。