LLMが1回の応答で複数のツール(関数)を同時に呼び出す機能。独立した複数のデータ取得やアクションを並列実行することで、ラウンドトリップ回数を削減しレイテンシを改善する。
Parallel Tool Calls(並列ツール呼び出し)は、LLMが1回のレスポンスで複数の独立したツール呼び出しを同時に発行する機能である。従来のFunction Callingでは1回の応答につき1つのツール呼び出しのみが可能で、3つのAPIを呼ぶには3回のラウンドトリップ(モデル→クライアント→モデル→…)が必要だった。Parallel Tool Callsにより、独立した呼び出しを1回のレスポンスに束ねて返すことで、レイテンシを大幅に削減する。
User: 東京と大阪とNYの天気を教えて
Model → get_weather(東京) → 結果返却
Model → get_weather(大阪) → 結果返却
Model → get_weather(NY) → 結果返却
Model → 最終応答
合計: 3ラウンドトリップ
User: 東京と大阪とNYの天気を教えて
Model → [get_weather(東京), get_weather(大阪), get_weather(NY)] ← 1回で3件発行
クライアント: 3件を並列実行して結果を一括返却
Model → 最終応答
合計: 1ラウンドトリップ
| プロバイダ | 対応 | tool_calls形式 | 制御方法 |
|---|---|---|---|
| OpenAI GPT-4o | ○ | 配列で複数返却 | parallel_tool_calls: true/false |
| Anthropic Claude 4 | ○ | content配列内に複数tool_use | デフォルト有効 |
| Google Gemini 2.5 | ○ | functionCall配列 | デフォルト有効 |
| Mistral Large | ○ | tool_calls配列 | デフォルト有効 |
| Llama 3.1(vLLM) | △(モデル依存) | 実装依存 | サーバー設定 |
Parallel Tool Callsを活用するには、クライアント側で並列実行を適切に実装する必要がある。
モデルが返した複数のtool_callsをPromise.allで並列実行し、全結果を一括でモデルに返す。最も一般的なパターン。
Python では asyncio.gather で複数の非同期ツール呼び出しを並列実行する。
並列呼び出しの中に依存関係がある場合(例:ユーザーIDの取得→そのIDで注文履歴を検索)、モデルは自動的に逐次呼び出しに分割する。クライアント側で依存関係を判定する必要はない。
| シナリオ | 逐次呼び出し | 並列呼び出し | 改善率 |
|---|---|---|---|
| 3都市の天気取得(各200ms) | 600ms + 3RT | 200ms + 1RT | 66%削減 |
| 5つのDB検索(各500ms) | 2500ms + 5RT | 500ms + 1RT | 80%削減 |
| 混合(2独立+1依存) | 3RT | 2RT | 33%削減 |
RT = ラウンドトリップ(モデル呼び出し1回分のレイテンシ、通常200-2000ms)
全てのケースでParallel Tool Callsが最適なわけではない。以下の場合は parallel_tool_calls: false で無効化を検討する:
A: まれに発生する。例えば「東京の天気」だけ聞いたのに「大阪の天気」も並列で呼ぶケースがある。tool_choiceで特定の関数に絞るか、プロンプトで「必要な情報のみ取得してください」と指示することで抑制できる。
A: OpenAI GPT-4oでは1回のレスポンスで最大128個のtool_callsを返せる(toolsの定義上限と同じ)。実用的には5-10個が一般的で、それ以上はクライアント側の並列実行コストが支配的になる。
A: 可能。ストリーミング中にtool_callsが順次到着するため、各ツールの実行を到着次第開始することで更なるレイテンシ削減が可能。ただし全tool_callsが揃ってからまとめて実行するパターンの方が実装は単純。