ナレッジカットオフ:LLMに「窓」が必要な理由
バニラな(標準的な)LLMを、インターネットのない部屋に閉じ込められた優秀な研究者だと考えてみてください。彼らは学習データのカットオフ時点までは膨大な知識を持っていますが、現在の状況については何も知りません。GPT-4oやClaude 3.5 Sonnetに、シンガポールの倉庫にある自社の現在の在庫について尋ねれば、自信満々に、しかし完全に間違った数字を「ハルシネーション(もっともらしい嘘)」として回答するでしょう。これは嘘をついているのではなく、外部を確認するためのツールを持っていないだけなのです。
開発者はしばしば、AIを単なるテキスト生成器だと勘違いします。実際には、Function Calling(または「ツール利用」)によって、これらのモデルは能動的なエージェントへと進化します。単にチャットをするだけでなく、モデル自身がバックエンドスクリプトの起動、データベースへのクエリ、あるいはサードパーティAPIへのアクセスが必要なタイミングを判断します。私自身の本番環境では、たった一つの「search_order」ツールを追加しただけで、カスタマーサポートボットのハルシネーション率を70%以上削減できました。
コアロジック:AIはあなたのコードを実行しない
AIモデルがあなたのPythonスクリプトやSQLクエリを直接実行しているという根強い誤解がありますが、そうではありません。Function Callingは、実際にはアプリケーションとLLMの間で行われる「構造化された交渉」です。本質的には、AIに対して実行可能な能力の「メニュー」を提示しているのです。
ユーザーが質問すると、モデルは提供された「ツール」リストをスキャンし、意図に合うものがあるか確認します。一致するものが見つかると、AIは会話を一時停止し、構造化されたJSONオブジェクトを返します。このオブジェクトには、特定の関数名と必要な引数が含まれています。あなたのアプリケーションがそのコードをローカルで実行して結果を取得し、それをAIにフィードバックします。そこで初めて、モデルは最終的な回答を生成します。これは「主導権の乗っ取り」ではなく、「バトンの受け渡し」なのです。
精度が重要:JSONスキーマ
モデルの性能は、あなたの記述(説明文)に大きく左右されます。OpenAIもClaudeも、関数を理解するためにJSON Schemaのバリアントを使用します。パラメータをあいまいに説明すると、モデルはバックエンドをクラッシュさせるようなゴミデータを送ってくるでしょう。厳密に定義してください。例えば、関数に `user_id` が必要な場合は、その文字列がどのような形式か(例:「US-で始まる10桁のUUID」など)を正確にモデルに伝えてください。
実装ループ:定義、検出、実行
信頼性の高いエージェントを構築するには、次の3段階のアーキテクチャパターンに従ってください。
- 指示 (Instruction): ユーザーのプロンプトとツールの定義を一緒にAPIへ送信します。
- シグナル (Signal): モデルがツールの必要性を検出し、テキストの代わりに「tool_call」リクエストを返します。
- ループの完了 (Closing the Loop): あなたのコードがロジックを実行してデータを取得し、2回目のリクエストを送信することで、AIがその結果を解釈できるようにします。
OpenAIのFunction Callingの実装
現在、OpenAIはツール統合の分野で先頭を走っています。Chat Completions APIでは、tools 配列を使用して機能を定義します。以下は、リアルタイムの注文ステータスを確認するための実践的な例です。
import openai
import json
# 1. 厳密な説明文とともにツールを定義する
tools = [
{
"type": "function",
"function": {
"name": "get_order_status",
"description": "特定の注文IDのリアルタイムの配送状況を取得します。",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "ORD-555のような形式のユニークな注文識別子。"
}
},
"required": ["order_id"]
}
}
}
]
# 2. 初期リクエスト
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "注文 ORD-999 は今どこにありますか?"}],
tools=tools,
tool_choice="auto"
)
# 3. AIの意図を処理する
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
args = json.loads(tool_call.function.arguments)
# データベース呼び出しのモック: status = db.fetch(args['order_id'])
print(f"モデルのリクエスト: {tool_call.function.name} 引数: {args}")
GPT-4oは、整理されていない人間の入力から変数を抽出することに非常に長けています。ユーザーが「ORD-999をちょっと調べてくれる?」と言ったとしても, モデルは何の苦労もなくその文字列を order_id パラメータに正しくマッピングします。
ClaudeのTool Use(ツール利用)
AnthropicのClaude 3.5 Sonnetは、OpenAIよりわずかに厳格ですが、信頼性の高い構造でツールを扱います。ロジックは同じですが、レスポンスの処理においてツールIDを注意深く追跡する必要があります。Claudeは特に、他の多くのモデルよりも複雑で多段階の指示を正確に実行することで知られています。
import anthropic
client = anthropic.Anthropic()
tools = [
{
"name": "get_weather",
"description": "特定の都市の現在の天気を取得します。",
"input_schema": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "都市名と都道府県/国名"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
]
response = client.messages.create(
model="claude-3-5-sonnet-20240620",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "東京の気温は?"}]
)
print(response.content)
Claudeがツールを起動すると、stop_reason は tool_use になります。その後、特定の tool_result ブロックを使用して結果を返す必要があります。このように明示的に追跡を行うことで、すべてのアクションがユニークなIDに関連付けられるため、複雑なエージェント・チェーンのデバッグが非常に容易になります。
本番環境への最適化:実世界でのヒント
これまでに数十件の統合をデプロイしてきましたが、単なる「おもちゃ」と実用的な「ツール」を分ける3つのルールを見つけました。第一に、優雅に失敗させること(Fail Gracefully)です。APIがタイムアウトした場合は、そのエラーをAIに伝えてください。優れたモデルであれば、単にクラッシュするのではなく、ユーザーに謝罪したり代替案を提案したりできます。
第二に、コンテキスト(文脈)がすべてです。ツールに単に「get_data」という名前を付けてはいけません。「fetch_nyse_stock_prices_in_usd」のように名付けてください。メタデータの記述が具体的であればあるほど、AIが間違ったツールを選択する可能性は低くなります。これは「推測」と「計算された決定」の違いです。
最後に、セキュリティを疎かにしてはいけません。LLMにデータベースのレコード削除や資金移動の権限を与えるのは危険です。重要なアクションに対しては、必ず「Human-in-the-Loop(人間の介在)」による確認を実装してください。あなたが脳(AI)を提供しても、首輪(制御)も用意しなければなりません。
まとめ:エージェント主導の未来を築く
Function Callingは、AIにおける「エージェント化(Agentic)」へのシフトの基盤です。OpenAIやClaudeを既存のシステムに接続することで、単なるチャットの枠を超え、実際にタスクを実行するシステムへと進化させることができます。まずは小さく始めましょう。一つの内部APIを接続し、モデルがどのように相互作用するかを観察し、そこから拡張していってください。行動する能力こそが、チャットボットを価値ある「同僚」へと変えるのです。

