本記事は arXiv:2307.16789 の解説記事です。
論文概要(Abstract)
Qin, Liang, Ye ら (2023) は、LLMに大量のReal-world APIを使いこなさせるための学習フレームワーク ToolLLM を提案している。RapidAPIプラットフォームから16,000以上のRESTful APIを収集し、49,000件の命令-API呼び出しペアからなるデータセット ToolBench を構築。さらに、API呼び出し時の探索を木構造で最適化する DFSDT(Depth-First Search-based Decision Tree) アルゴリズムと、LLM-as-Judgeによる評価フレームワーク ToolEval を提案している。
この記事は Zenn記事: Function Calling×Structured Outputs実装入門:3社APIで型安全なツール連携を構築する の深掘りです。
情報源
- arXiv ID: 2307.16789
- URL: https://arxiv.org/abs/2307.16789
- 著者: Yujia Qin, Shihao Liang, Yining Ye et al.
- 発表年: 2023
- 分野: cs.CL, cs.AI
背景と動機(Background & Motivation)
Zenn記事ではOpenAI・Claude・GeminiのFunction Calling APIを用いた3社統一的なツール呼び出しパターンを解説しているが、これらはAPIプロバイダーが提供するクローズドモデルの機能である。オープンソースLLM(LLaMA、Mistral等)で同等のFunction Calling能力を実現するには、ツール呼び出しに特化したfine-tuningが必要となる。
従来のツール学習研究は、数十〜数百のAPIに限定されており、実世界の多様なAPIカバレッジには不十分だった。著者らは、RapidAPIの16,000以上のAPIを対象とすることで、LLMが未知のAPIにも汎化可能なツール使用能力を獲得することを目指している。
主要な貢献(Key Contributions)
- 貢献1: 16,000+ RESTful APIと49,000件の命令-ツール呼び出しペアからなる大規模データセット ToolBench を構築
- 貢献2: ツール呼び出しの探索を木構造で効率化する DFSDT アルゴリズムを提案し、単純なChain-of-Thought比で成功率を約20%改善
- 貢献3: LLM-as-Judgeベースの自動評価フレームワーク ToolEval を構築し、Pass Rate・Win Rateの2指標でツール呼び出し能力を定量評価
技術的詳細(Technical Details)
ToolBenchデータセット構築
データセットは以下のパイプラインで構築される:
Step 1: API収集 RapidAPIから49カテゴリ・16,000+のAPIを収集。各APIについてエンドポイント、パラメータ、レスポンス形式のメタデータを取得する。
Step 2: 命令生成 ChatGPTを用いて、各APIに対する自然言語の命令文を自動生成する。命令は3つのレベルで生成される:
| レベル | 説明 | 例 |
|---|---|---|
| Single-tool | 1つのAPIで完結 | 「東京の天気を教えて」 |
| Intra-category | 同カテゴリの複数API | 「今日の天気と明日の予報を比較」 |
| Inter-category | 異なるカテゴリのAPI | 「東京の天気と関連ニュースを検索」 |
Step 3: 解答軌跡の収集 ChatGPTがDFSDTアルゴリズムを用いてAPIを実行し、成功した軌跡をfine-tuningデータとする。
DFSDTアルゴリズム
従来のReActパターンでは、API呼び出しが失敗した場合にリカバリーが困難だった。DFSDTは探索を木構造でモデル化し、失敗時にバックトラックして別の経路を試行する:
\[\text{DFSDT}(\text{node}) = \begin{cases} \text{expand}(\text{node}) & \text{if depth} < d_{\max} \\ \text{backtrack}(\text{node}) & \text{if failed} \\ \text{return result} & \text{if success} \end{cases}\]ここで $d_{\max}$ は最大探索深度である。
アルゴリズムの疑似コード:
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
from typing import Any
def dfsdt_search(
model: Any,
query: str,
tools: list[dict],
max_depth: int = 5,
max_retries: int = 3,
) -> dict | None:
"""DFSDT: Depth-First Search Decision Tree
失敗時にバックトラックして別のツール/引数を試行する
木構造探索アルゴリズム。
Args:
model: LLMモデル
query: ユーザーの自然言語クエリ
tools: 利用可能なツール定義のリスト
max_depth: 最大探索深度
max_retries: 各ノードでのリトライ上限
Returns:
成功時はツール呼び出し結果、失敗時はNone
"""
stack: list[dict] = [{"query": query, "history": [], "depth": 0}]
while stack:
node = stack.pop()
if node["depth"] >= max_depth:
continue # 深度制限超過、バックトラック
# モデルにツール選択と引数生成を要求
action = model.select_tool(
query=node["query"],
tools=tools,
history=node["history"],
)
# ツール実行
result = execute_tool(action["tool"], action["args"])
if result["success"]:
if result["is_final"]:
return result # タスク完了
# 成功: 次ステップを探索
stack.append({
"query": node["query"],
"history": node["history"] + [action, result],
"depth": node["depth"] + 1,
})
else:
# 失敗: 別のツール/引数で再試行
for retry in range(max_retries):
alt_action = model.select_tool(
query=node["query"],
tools=tools,
history=node["history"] + [action, result],
exclude=[action["tool"]],
)
alt_result = execute_tool(alt_action["tool"], alt_action["args"])
if alt_result["success"]:
stack.append({
"query": node["query"],
"history": node["history"] + [alt_action, alt_result],
"depth": node["depth"] + 1,
})
break
return None # 全探索失敗
ToolEval評価フレームワーク
ToolEvalは2つの指標でツール呼び出し能力を評価する:
Pass Rate: タスクが正常に完了した割合
\[\text{Pass Rate} = \frac{|\{t \in T \mid \text{success}(t)\}|}{|T|}\]Win Rate: GPT-4をJudgeとして、ToolLLMの出力とChatGPTの出力を比較した勝率
\[\text{Win Rate} = \frac{|\{t \in T \mid \text{judge}(t, \text{ToolLLM}) > \text{judge}(t, \text{ChatGPT})\}|}{|T|}\]実装のポイント(Implementation)
入力形式: ツール定義はJSONスキーマとしてシステムプロンプトに埋め込む。Zenn記事のPydantic変換パターンと同様、各APIのパラメータ定義がモデルへの入力となる。
1
2
3
4
5
6
7
8
9
10
11
12
13
# ToolBenchのツール定義形式(JSON Schema準拠)
tool_definition = {
"name": "weather_api",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"country": {"type": "string", "description": "Country code (ISO 3166)"}
},
"required": ["city"]
}
}
fine-tuningデータ形式: 成功したDFSDT軌跡をinstruction-tuningデータに変換。各ターンはThought → Action → Action Input → Observationの形式。
制約と注意点:
- RapidAPIへのサブスクリプションが必要(実APIへのアクセス時)
- 2023年7月時点のAPIスナップショットであり、新規APIへの汎化にはfine-tuning更新が必要
- ToolEvalのGPT-4審査には再現性の課題がある(APIバージョン依存)
実験結果(Results)
著者らの報告する主要な実験結果(論文Table 3, Figure 4より):
| 手法 | Pass Rate (Single) | Pass Rate (Multi) | Win Rate vs ChatGPT |
|---|---|---|---|
| ChatGPT + ReAct | 67% | 53% | 50%(ベースライン) |
| ChatGPT + DFSDT | 74% | 67% | — |
| ToolLLM-7B + DFSDT | 71% | 59% | 53% |
- DFSDTはReActに比べてPass Rateを+7〜14%改善していると著者らは報告している
- ToolLLM-7BはLLaMA-2-7Bベースのfine-tuningモデルであり、7Bパラメータでもマルチツールタスクの約60%を完了できると著者らは主張している
- Win Rateでは、ToolLLM-7BがChatGPTを53% vs 47%でわずかに上回ったと報告されている
実運用への応用(Practical Applications)
Zenn記事のFunction Calling実装と関連する実運用上のポイント:
- オープンソースLLMでのFunction Calling: vLLMやllama.cppでToolLLMを展開することで、APIプロバイダーに依存しないFunction Callingが実現可能。Zenn記事のInstructorライブラリとの組み合わせで型安全性も確保できる
- DFSDTのリトライ戦略: Zenn記事で触れられている「ツール呼び出し失敗時のリトライ」を木構造探索で体系化したもの。Instructorの
max_retriesパラメータと同様の考え方だが、ツール選択自体の再試行も含む - スキーマの重要性: ToolBenchのツール定義はJSON Schema準拠であり、Zenn記事のPydantic v2ベースのスキーマ管理と互換性がある
関連研究(Related Work)
- Gorilla (Patil et al., 2023): APIハルシネーション削減に特化したretrieval-aware fine-tuning。ToolLLMがDFSDTで探索を最適化するのに対し、GorillaはAPIドキュメントのretrievalで精度向上を図る
- RestGPT (Song et al., 2023): RESTful APIとの接続に特化したフレームワーク。ToolLLMと異なり、APIのHTTPメソッド・ステータスコードの理解に重点を置く
- BFCL (Patil et al., 2024): Function Callingの標準ベンチマーク。ToolEvalとは異なり、AST(抽象構文木)ベースの自動評価を採用
まとめと今後の展望
ToolLLMは、LLMのFunction Calling能力を16,000以上のReal-world APIで体系的に学習するフレームワークを確立した。DFSDTアルゴリズムによる木構造探索は、Zenn記事で解説されている線形的なツール呼び出しパターンを拡張し、複雑なマルチツールタスクへの対応を可能にしている。
オープンソースLLMでのFunction Calling実装を検討する際、ToolBenchデータセットとToolEval評価フレームワークは、モデル選択・fine-tuning戦略の指針として有用である。
参考文献
- arXiv: https://arxiv.org/abs/2307.16789
- Code: https://github.com/OpenBMB/ToolBench
- Weights: HuggingFace: ToolLLM-7B
- Related Zenn article: https://zenn.dev/0h_n0/articles/b2d1df91e5f5de