本記事は To Call or Not to Call: A Framework to Assess and Optimize LLM Tool Calling(Wu et al., 2026年5月)の解説記事です。
論文概要(Abstract)
LLMエージェントにおけるツール呼び出し(Function Calling)は常に有益とは限らない。冗長な呼び出しや性能を低下させる呼び出しが存在する。本論文は「必要性(Necessity)」「有用性(Utility)」「予算制約(Affordability)」の3次元でツール呼び出しの判断を評価するフレームワークを提案し、7つのフロンティアモデルで実証分析を行った。さらに、モデルの隠れ状態から訓練した軽量推定器でツール呼び出し意思決定を改善できることを示している。
この記事は Zenn記事: Function Callingスキーマ設計パターン:3社APIで堅牢なツール定義を構築する の深掘りです。
情報源
- arXiv ID: 2605.00737
- URL: https://arxiv.org/abs/2605.00737
- 著者: Qinyuan Wu, Soumi Das, Mahsa Amani, et al.
- 発表年: 2026
- 分野: cs.CL, cs.AI
背景と動機(Background & Motivation)
現代のLLMエージェントはWeb検索やコード実行などの外部ツールを呼び出す機能を持つが、「いつツールを呼ぶべきか」に関する原則的な判断基準が欠如している。著者らは、実際のモデル動作を分析した結果、以下の問題を指摘している:
- モデルが高い内部知識を持つ場面でもツールを呼び出し、外部情報がノイズとなって性能を低下させるケースが約34%存在する
- 予算制約(APIコストやレイテンシ)を課しても、モデルは制約を守れず過剰にツールを呼び出す傾向がある
- モデルの「ツールが必要だ」という認識と、実際にツールが役立つかどうかには系統的な乖離がある
この問題は、Zenn記事で解説した「20ツール制限」やdynamic tool retrievalの文脈と直結する。ツール数を絞るだけでなく、そもそも各ターンでツールを呼ぶべきかの判断が重要であることを本論文は示している。
主要な貢献(Key Contributions)
- 貢献1: 合理的選択理論に基づき、ツール呼び出しを「必要性」「有用性」「予算制約」の3軸で評価するフレームワークの提案
- 貢献2: 規範的分析(最適なツール配分)と記述的分析(実際のモデル動作)の双方を組み合わせた実証的評価手法
- 貢献3: モデルの隠れ状態(hidden states)から訓練した軽量推定器(Latent Need/Utility Estimator)によるツール呼び出し制御の実現
技術的詳細(Technical Details)
3次元評価フレームワーク
著者らは合理的選択理論を参照し、ツール呼び出し判断を以下の3次元で形式化している。
次元1: 必要性(Necessity)
モデルがツールなしで十分な性能を出せるかを評価する。具体的には、ツールなし設定(No Tool)での性能スコア $s^{NT}(x)$ を閾値と比較する:
\[N^{\star}(x) = \begin{cases} 1 & \text{if } s^{NT}(x) < \tau_{\text{need}} \\ 0 & \text{otherwise} \end{cases}\]ここで $x$ はタスクインスタンス、$\tau_{\text{need}}$ はタスク依存の性能閾値である。
次元2: 有用性(Utility)
ツール呼び出しによる実際の性能変化を3値ラベルで定義する:
\[U^{\star}(x) = \begin{cases} +1 & \text{if } s^{AT}(x) - s^{NT}(x) > \epsilon \\ -1 & \text{if } s^{AT}(x) - s^{NT}(x) < -\epsilon \\ 0 & \text{otherwise} \end{cases}\]ここで $s^{AT}(x)$ はAlways Tool設定(常にツールを呼ぶ)での性能スコア、$\epsilon$ は有意差閾値を表す。
重要な発見: No Tool性能が高い場合(モデルが既に正答を知っている場合)、ツール呼び出しが負の有用性を持つ確率は34%に達する。これは外部検索結果がモデルの正しい内部知識を上書きしてしまう現象による。
次元3: 予算制約(Affordability)
限られた予算下で最大の性能改善を得るために、最適配分を定式化する:
\[\text{maximize} \sum_{x \in \mathcal{X}} \Delta^{\star}(x) \cdot \mathbb{1}[\text{call}(x)]\] \[\text{subject to} \sum_{x \in \mathcal{X}} \mathbb{1}[\text{call}(x)] \leq B\]ここで $\Delta^{\star}(x) = s^{AT}(x) - s^{NT}(x)$ は限界有用性、$B$ は予算(最大呼び出し回数)である。最適解は $\Delta^{\star}(x)$ の降順で上位 $B$ 件を選択する貪欲アルゴリズムで得られる。
実験設定
評価モデル(6つのオープンソースモデル + 1クローズドソース):
| モデル | パラメータ数 | 特徴 |
|---|---|---|
| GPT-OSS-120B | 120B | MoEアーキテクチャ |
| Qwen3-30B-A3B | 30B (3B活性) | MoE、軽量 |
| Qwen3-30B-IT | 30B | Instruction Tuned |
| Gemma3-27B-IT | 27B | Google系 |
| Mistral3.1-24B-IT | 24B | Mistral系 |
| Llama3.2-3B-IT | 3B | 最小モデル |
ツール: Google Search(SerpAPI)およびPerplexity Search。各クエリで最大5件の検索結果を返す。
データセット:
- Entity Task: ChatGPTの実ログから抽出した500エンティティについて説明文を生成
- InvivoQuery Task: ユーザーの実際のリクエストから抽出した500の事実質問
- BFCL Task: Berkeley Function Calling Leaderboard(Function Calling精度評価)
隠れ状態ベースの軽量推定器
著者らは、モデルの最終トークンの隠れ状態表現が「ツールの必要性・有用性」を予測するのに有効であることを発見した。
Latent Need Estimator (LNE)
No Tool設定でのモデルの最終トークン隠れ状態 $h^{NT}(x) \in \mathbb{R}^d$ を入力とし、2クラスMLP分類器を訓練する:
\[\hat{N}(x) = \sigma(W_2 \cdot \text{ReLU}(W_1 \cdot h^{NT}(x) + b_1) + b_2)\]ここで $\sigma$ はシグモイド関数、$W_1, W_2, b_1, b_2$ は学習パラメータである。
Latent Utility Estimator (LUE)
2つのバリアントを提案:
- LUE_x: No Tool設定の隠れ状態のみを使用
- LUE_{x,d_F}: ツール説明文を含めたAlways Tool設定の隠れ状態を使用
Controller Framework
推定器をもとに、ツール呼び出しの優先度付けを行うコントローラーを構築する:
1
2
3
4
5
6
7
8
9
10
11
def controller_allocate(instances, budget, lue_model):
"""LUE推定器に基づくツール呼び出し予算配分"""
scores = [(x, lue_model.predict_utility(x)) for x in instances]
scores.sort(key=lambda pair: pair[1], reverse=True)
allocated = []
for x, score in scores[:budget]:
if score > 0:
allocated.append(x)
return allocated
主要な実験結果
知覚と真実の乖離
論文Table 2より、モデルの「知覚された必要性(Perceived Need)」と「真の必要性(True Need)」の間に系統的な乖離が存在する:
| モデル | True Need率 | Perceived Need率 | 乖離 |
|---|---|---|---|
| GPT-OSS-120B | 60% | 75% | +15% (過剰) |
| Qwen3-30B-A3B | 65% | 80% | +15% (過剰) |
| Llama3.2-3B | 72% | 68% | -4% (過少) |
著者らはこの乖離を「モデルは内部的に一貫性を持つ(知覚された必要性と実際の呼び出しは相関する)が、その知覚が真の性能改善と一致しない」と分析している。
予算制約下での性能
論文の主要な発見として、最適配分と自律的判断(self-decision)の間に大きなギャップが存在する:
- GPT-OSS-120B: 最適配分で300回呼び出し時のスコア0.83 vs. 自律判断500回で0.78
- Qwen3-30B-IT: 最適配分284回で0.87 vs. 自律判断452回で0.82
- Llama3.2-3B: 最適配分249回で0.87 vs. 自律判断340回で0.74
つまり、ツールを呼ぶ回数を減らしつつ性能を向上させることが可能であり、その鍵は「どのインスタンスでツールを呼ぶか」の選択にある。
推定器の効果
LUEコントローラー適用後の性能改善(論文Table 4より):
| モデル | Self-decision | LUE_x Controller | 改善 |
|---|---|---|---|
| GPT-OSS (Entity) | 0.73 | 0.78 | +0.05 |
| GPT-OSS (InvivoQuery) | 0.56 | 0.59 | +0.03 |
| Qwen3-A3B (Entity) | 0.78 | 0.81 | +0.03 |
実装のポイント
Function Callingシステムへの応用
本論文の知見をFunction Callingシステムに適用する場合、以下の設計指針が導ける:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from dataclasses import dataclass
from typing import Optional
import numpy as np
@dataclass
class ToolCallDecision:
"""ツール呼び出し判断の構造体"""
instance_id: str
necessity_score: float
utility_score: float
should_call: bool
reason: str
class ToolCallController:
"""論文のフレームワークに基づくツール呼び出し制御"""
def __init__(
self,
necessity_threshold: float = 0.5,
utility_threshold: float = 0.1,
budget_per_turn: int = 3,
):
self.necessity_threshold = necessity_threshold
self.utility_threshold = utility_threshold
self.budget_per_turn = budget_per_turn
def evaluate_tool_calls(
self,
candidates: list[dict],
model_confidence: float,
) -> list[ToolCallDecision]:
"""候補ツール呼び出しを評価し、優先度順に返す"""
decisions = []
for candidate in candidates:
necessity = self._estimate_necessity(
candidate, model_confidence
)
utility = self._estimate_utility(candidate)
should_call = (
necessity > self.necessity_threshold
and utility > self.utility_threshold
)
decisions.append(ToolCallDecision(
instance_id=candidate["id"],
necessity_score=necessity,
utility_score=utility,
should_call=should_call,
reason=self._explain_decision(necessity, utility),
))
decisions.sort(key=lambda d: d.utility_score, reverse=True)
return decisions[:self.budget_per_turn]
def _estimate_necessity(
self, candidate: dict, model_confidence: float
) -> float:
"""モデルの内部確信度から必要性を推定"""
return 1.0 - model_confidence
def _estimate_utility(self, candidate: dict) -> float:
"""ツールの有用性を推定(実装では隠れ状態ベース推定器を使用)"""
relevance = candidate.get("relevance_score", 0.5)
recency = candidate.get("recency_score", 0.5)
return relevance * 0.7 + recency * 0.3
def _explain_decision(
self, necessity: float, utility: float
) -> str:
if necessity < self.necessity_threshold:
return "モデルの内部知識で十分(ツール不要)"
if utility < self.utility_threshold:
return "ツールの有用性が低い(ノイズリスク)"
return "ツール呼び出し推奨"
Zenn記事との関連
本論文の知見は、Zenn記事で解説した以下の設計パターンと直結する:
- description設計の「When-Not」原則: 本論文は「ツールを使わない条件」の重要性を定量的に裏付ける。descriptionに「使わない条件」を明記することで、モデルの過剰な呼び出しを抑制できる
- 20ツール制限とdynamic tool retrieval: 本論文の予算制約分析は、ツール数を絞る根拠を理論的に提供する
- strict modeの意義: 呼び出し自体の精度だけでなく、「呼ぶかどうか」の判断精度も重要であることを示す
実験結果の詳細分析
ツール呼び出しが有害になるケース
論文Figure 3より、No Tool性能が高い場合(モデルが正答を知っている場合)にツールを呼ぶと:
- 34%のケースで性能低下(負の有用性)
- 原因:外部検索結果がモデルの正しい内部知識と矛盾する情報を含む
- 結果:モデルが外部情報を過信し、元々正しかった回答を変更してしまう
この現象は「知識衝突(Knowledge Conflict)」と呼ばれ、特にWeb検索ツールで顕著に発生する。
モデルサイズと推定器の効果
著者らは、小さいモデルほど推定器の効果が大きいことを報告している:
- Llama3.2-3B: 推定器により最大+0.13の性能改善
- GPT-OSS-120B: 推定器により+0.05の性能改善
これは、大きなモデルほど内部的な判断が既に良好であるため、外部制御の余地が小さいことを示唆する。
関連研究
- Toolformer(Schick et al., 2023): LLMに自律的なツール呼び出しを学習させる先駆的研究。本論文はToolformerの「いつ呼ぶか」の判断を定量的に評価する枠組みを提供
- ART(Paranjape et al., 2023): 自動推論とツール使用の統合。本論文は推論なしでも隠れ状態から有用性を予測できることを示す
- Berkeley Function Calling Leaderboard: 本論文のBFCLタスクの基盤。呼び出し精度だけでなく「呼ぶべきか」の判断も評価すべきことを主張
まとめ
本論文は、Function Callingシステムにおいて「いつツールを呼ぶか」の判断が「どう呼ぶか」と同等以上に重要であることを実証的に示した。主な知見は以下の通りである:
- ツール呼び出しの有用性はモデルの内部知識レベルに強く依存し、高確信時のツール呼び出しは34%の確率で有害
- モデルの知覚(「ツールが必要だ」)と真の有用性の間に系統的な乖離が存在する
- 隠れ状態ベースの軽量推定器で、モデル自体を変更することなくツール呼び出し判断を改善できる
- 最適配分により、呼び出し回数を40%削減しつつ性能を5%向上させることが可能
Function Callingのスキーマ設計においても、「いつ使うか」「いつ使わないか」をdescriptionに明記するパターンの有効性を裏付ける重要な研究である。