はじめに
Function Calling(Tool Useとも呼ばれる)は、LLMが外部システム、API、ツールと連携できる機能です。これにより、LLMはテキスト生成器から実際のアクションを取ることができる強力なエージェントに変わります。
この章を終えると、以下のことができるようになります:
- LLM Function Calling用のJSON Schemaでツールを定義する
- 完全なFunction Callingワークフローを実装する
- MCP(Model Context Protocol)標準に準拠したツールを設計する
- ツール使用アプリケーションでエラーを適切に処理する
- 複雑なタスクのために複数のツールをオーケストレーションする
Function Callingの基礎
Function Callingとは
Function Callingにより、LLMは以下のことができます:
- 利用可能なツールとその機能を理解する
- ユーザーのリクエストに基づいてツールを使用するタイミングを決定する
- ツール用に適切にフォーマットされた引数を生成する
- ツールの結果を応答に組み込む
JSON Schemaでのツール定義
ツールはJSON Schemaを使用して定義され、関数名、説明、パラメータを記述します:
ツール定義の例
{
"type": "function",
"function": {
"name": "get_weather",
"description": "特定の場所の現在の天気を取得します。気温、状態、湿度を返します。",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "都市名、例:'東京'、'ニューヨーク'、'ロンドン'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度単位(デフォルト:celsius)"
}
},
"required": ["location"]
}
}
}
完全なFunction Callingの例
OpenAI Function Calling
from openai import OpenAI
import json
client = OpenAI()
# ツールを定義
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "場所の現在の天気を取得",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "都市名"}
},
"required": ["location"]
}
}
}
]
# 実際の関数実装
def get_weather(location: str) -> dict:
# 本番では天気APIを呼び出す
return {"location": location, "temperature": 22, "unit": "celsius", "condition": "晴れ"}
# ステップ1: ツール付きでユーザーメッセージを送信
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "東京の天気は?"}],
tools=tools
)
# ステップ2: モデルがツールを使用したいか確認
message = response.choices[0].message
if message.tool_calls:
# ステップ3: ツールを実行
tool_call = message.tool_calls[0]
arguments = json.loads(tool_call.function.arguments)
result = get_weather(**arguments)
# ステップ4: ツール結果をモデルに返送
final_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": "東京の天気は?"},
message,
{"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)}
]
)
print(final_response.choices[0].message.content)
Model Context Protocol(MCP)
MCPはAnthropicが開発したオープンスタンダードで、LLMを外部データソースやツールに接続します。異なるLLMプロバイダーやアプリケーション間で機能する統一インターフェースを提供します。
MCPアーキテクチャ
MCPの概念
| 概念 | 説明 |
|---|---|
| ホスト | MCPサーバーに接続するアプリケーション(Claude Desktop、IDE) |
| サーバー | ツール、リソース、プロンプトを提供するサービス |
| ツール | LLMが呼び出せる関数(Function Callingと同様) |
| リソース | LLMが読み取れるデータ(ファイル、データベースレコード) |
| プロンプト | サーバーが提供する再利用可能なプロンプトテンプレート |
MCPサーバーの構築
シンプルなMCPサーバー(Python)
from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio
# サーバーインスタンスを作成
server = Server("weather-server")
# ツールを定義
@server.list_tools()
async def list_tools():
return [
Tool(
name="get_weather",
description="都市の現在の天気を取得",
inputSchema={
"type": "object",
"properties": {
"city": {"type": "string", "description": "都市名"}
},
"required": ["city"]
}
)
]
# ツール実行を実装
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "get_weather":
city = arguments["city"]
weather_data = fetch_weather(city) # 実際の天気API呼び出し
return [TextContent(
type="text",
text=f"{city}の天気: {weather_data['temp']}度, {weather_data['condition']}"
)]
# サーバーを実行
async def main():
async with mcp.server.stdio.stdio_server() as (read, write):
await server.run(read, write)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
エラーハンドリング
堅牢なエラーハンドリングはツール使用アプリケーションにとって重要です。ツールはネットワーク問題、無効な入力、レート制限、外部サービスの停止により失敗する可能性があります。
包括的なエラーハンドリング
def execute_tool(tool_name: str, arguments: dict):
"""包括的なエラーハンドリング付きでツールを実行"""
try:
if not validate_arguments(tool_name, arguments):
raise ToolError("無効な引数が提供されました", recoverable=True)
if tool_name == "get_weather":
return get_weather(**arguments)
else:
raise ToolError(f"不明なツール: {tool_name}", recoverable=False)
except ConnectionError as e:
return {
"error": True,
"type": "network_error",
"message": f"サービスに接続できません: {e}",
"suggestion": "サービスが一時的に利用できない可能性があります。再試行してください。"
}
except RateLimitError as e:
return {
"error": True,
"type": "rate_limit",
"message": "APIレート制限を超えました",
"retry_after": e.retry_after,
"suggestion": f"{e.retry_after}秒後に再試行してください。"
}
マルチツールオーケストレーション
複雑なタスクは複数のツールの調整を必要とすることがよくあります。効果的なオーケストレーションには、ツールシーケンスの計画と依存関係の処理が含まれます。
チェーンされたツール実行
def handle_complex_request(user_message: str, max_iterations: int = 5):
"""複数のツール呼び出しが必要な可能性のあるリクエストを処理"""
messages = [{"role": "user", "content": user_message}]
for i in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
# モデルが完了したか確認(ツール呼び出しなし)
if not assistant_message.tool_calls:
return assistant_message.content
# リクエストされたすべてのツールを実行
for tool_call in assistant_message.tool_calls:
result = execute_tool(
tool_call.function.name,
json.loads(tool_call.function.arguments)
)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
return "許可されたステップ内でタスクを完了できませんでした。"
セキュリティの考慮事項
セキュリティベストプラクティス
- 入力検証:実行前に常にツール入力を検証
- 最小権限の原則:ツールには必要な権限のみを与える
- レート制限:ツール呼び出しのレート制限で悪用を防止
- 監査ログ:セキュリティレビューのためにすべてのツール実行をログ
- サンドボックス化:危険なツールは隔離環境で実行
- ユーザー確認:破壊的アクションには確認を要求
演習問題
演習1:ツール定義(難易度:易)
課題:以下を含むtranslate_textツールのJSON Schemaを定義してください:
- 必須:翻訳するテキスト、ターゲット言語
- オプション:ソース言語(未指定時は自動検出)
- サポート言語のenum
演習2:エラーハンドリング(難易度:中)
課題:以下を行うfetch_stock_priceツールのエラーハンドリングを実装してください:
- リトライロジック付きのネットワークエラー処理
- 株式シンボルの検証
- 市場クローズシナリオの処理
演習3:MCPサーバー(難易度:中)
課題:「メモ取り」アプリケーション用のMCPサーバーを設計してください。以下のツールを含む:
create_notesearch_notesupdate_notedelete_note
演習4:マルチツールオーケストレーション(難易度:上級)
課題:以下のツールを持つ「旅行計画アシスタント」のシステムプロンプトとツール定義を作成してください:
- フライト検索
- ホテル予約
- 天気予報
- 通貨換算
演習5:セキュリティ実装(難易度:上級)
課題:以下を含むセキュアなツール実行ラッパーを実装してください:
- 入力サニタイズ
- レート制限(1分あたり最大10コール)
- 監査ログ
- ユーザーロールに基づく権限チェック
章のまとめ
重要ポイント
- Function Calling:明確に定義されたツールインターフェースを通じてLLMが外部システムと連携できるようにする
- スキーマ設計:明確な説明と適切なパラメータ定義が信頼性の高いツール使用に不可欠
- MCP:異なるプラットフォーム間でLLMをツールとリソースに接続するオープンスタンダード
- エラーハンドリング:優雅なリカバリーを伴う包括的なエラーハンドリングを常に実装
- マルチツールオーケストレーション:複雑なタスクにはツールシーケンスの計画と並列/チェーン実行の処理が必要
- セキュリティ:入力を検証し、最小権限を使用し、破壊的アクションには確認を要求
次のステップ
第5章では、すべてを実践プロジェクトでまとめます:
- ドキュメント分析システムの構築
- マルチモーダルアプリケーション向けビジョンプロンプティング
- コスト最適化のためのプロンプトキャッシング
- 本番デプロイメントの考慮事項
参考文献
- OpenAI. (2024). Function Calling Documentation
- Anthropic. (2024). Model Context Protocol Specification
- Google. (2024). Gemini Function Calling Guide
更新履歴
- 2026-01-12:v2.0 MCP対応を含む初版リリース