Function Calling
Function Calling ・ ふぁんくしょんこーりんぐ
LLMが関数名と引数をJSONで書いた「呼び出しの依頼書」を返し、アプリが実行する仕組み。
✦ 30秒で試す — 航海天気を知らないAIが、今日の天気を正しく答えるこのあと、天気のAPIを実際に呼ぶのは?予想してみる概要
Function Calling(ツール呼び出し、Tool Use とも)は、LLM に「呼び出せる関数の一覧」をあらかじめ渡しておき、モデルが必要だと判断したときに「この関数を、この引数で呼んでほしい」という依頼を、決まった形の JSON で出力させる仕組みです。天気の API を呼ぶ、データベースを検索する、メールを送るといった、モデル単体ではできない処理を外の関数に任せ、その結果を会話に取り込めるようになります。
最初に押さえたいのは、名前に反してモデルが関数を実行するわけではないことです。モデルが出力するのは「呼び出しの依頼書」だけで、実際に関数を実行するのは開発者のアプリケーションです。モデルが依頼書を書き、アプリが確かめて実行し、結果をモデルに返す。この役割分担が仕組みの核心で、LLM を外の世界とつなぐ応用(AIエージェントなど)の土台になっています。
なぜ生まれたか
LLM は訓練データに含まれない情報 — 今日の天気、社内データベースの中身、最新のニュース — を知らず、聞かれるともっともらしい誤答を作ってしまうハルシネーションの問題を抱えていました。外部の API に聞けば正確に分かることを、モデルの記憶だけで答えさせるのは筋が悪い。そこで「答えを書かせる代わりに、関数を呼ぶ指示を書かせる」という考えが生まれましたが、初めはプロンプトで「この形式で出力して」と頼むしかありませんでした。モデルは平気で形式を崩し、アプリ側の解析が失敗する不安定さと隣り合わせでした。
これを変えたのが、2023年6月に OpenAI が API に加えた Function Calling です。関数の宣言を API の正式なパラメータとして受け取り、呼び出しの指示を決まったスキーマの構造化データとして返すことを、モデルの訓練と API の仕様の両方で支えました。同じ年の11月には、より一般的な「ツール」の形(tools パラメータ)に整理され、1回の応答で複数の関数を呼ぶ並列呼び出しも入りました。Anthropic や Google など各社も同じ形の機能を備え、「LLM の出力をプログラムで確実に処理する」ことが、ようやく実用的な信頼性で可能になりました。自由なテキストの世界と、型のあるプログラムの世界をつなぐ変換器が、標準で付いたのです。
詳細
往復のフローを順に追う
Function Calling は「宣言 → 依頼 → 実行 → 結果の返却 → 最終回答」という往復で動きます。
(1)アプリは、ユーザーの質問と一緒に「使える関数の一覧」を LLM に渡します。各関数は、名前・何をするかの説明・引数の型を、JSON Schema という形式で宣言します。(2)モデルは質問を読み、手持ちの知識で答えるか、関数を使うかを決めます。関数が必要なら、ふつうの文章の代わりに「関数名と引数」の構造化データを返します。このとき、1つ1つの呼び出しには ID が付きます。(3)アプリはその依頼を受け取り、対応する本物の処理 — 天気の API の呼び出しやデータベース検索 — を自分で実行します。(4)実行結果を、どの ID への返事かを添えて会話履歴に足し、もう一度モデルに送ると、(5)モデルは結果を踏まえた自然な回答を書きます。1回のやり取りに最低2回のモデル呼び出しが要ることは、費用とレイテンシを見積もるうえで大事な点です。
役割の境界 — 依頼書はモデル、実行はアプリ
この往復を「どこに何があるか」で見直すと、モデルとアプリの間に1本の境界線が引けます。モデルの側にあるのは、関数の宣言を読んで依頼書を書く力だけです。データベースの接続情報も、API キーも、実際に関数を動かす権限も、すべてアプリの側にあります。だからアプリは、依頼書を受け取ったら、そのまま実行せずに境界で確かめます — そんな名前の関数はあるか、引数は型と範囲に収まっているか、このユーザーにその操作を許してよいか。
この境界が、実務の落とし穴のほとんどを説明します。モデルの依頼書は確率的に生成された文章なので、存在しない関数名や範囲外の引数を返すことがあります。ユーザーの入力や、関数の結果として読み込んだ Web ページに悪意のある指示が紛れていれば、モデルはそれに引きずられた依頼書を書くかもしれません(プロンプトインジェクション。プロンプトエンジニアリングの記事を参照)。依頼書は「ユーザーの発話ひとつで作られうる、信頼できない入力」として扱い、認可の判断はモデルに任せず、境界のアプリ側で行います。
並列呼び出しと tool_choice
1回の応答で、複数の依頼書がまとめて返ってくることがあります。「東京と大阪の天気を比べて」と聞かれたモデルは、get_weather を東京と大阪で1本ずつ、合わせて2本の呼び出しを一度に返せます。これが並列ツール呼び出しで、アプリは2つを同時に実行し、それぞれの結果を呼び出し ID に対応づけて返します。往復の回数が減るので速くなりますが、互いに依存する呼び出し(検索してから、その結果で更新する)を並列にされると困るので、API によっては並列を止める設定もあります。
モデルに「関数を使うかどうか」を任せきりにしない指定もあります。多くの API には tool_choice にあたるパラメータがあり、auto(モデルが決める、既定)、required(必ずどれかの関数を呼ぶ)、none(関数を呼ばない)、関数名の指定(必ずこの関数を呼ぶ)を選べます。抽出の用途で必ず決まった関数の形で出力させたいときや、確認画面の直後には関数を使わせたくないときに使います。
スキーマ設計がすべてを決める
モデルが関数を正しく選び、正しい引数を組み立てられるかは、宣言したスキーマの質でほぼ決まります。関数の説明には「いつ使うべきか・いつ使うべきでないか」まで書き、引数名は見て分かる名前にし、選択肢は列挙型(enum)で縛ります。スキーマは人間向けの API ドキュメントであると同時に、モデルへの指示文でもあるのです。この意味で、スキーマ設計はプロンプトエンジニアリングの一分野です。関数の数が増えすぎると選択の精度が落ち、宣言そのものがコンテキストウィンドウを圧迫するので、作業に必要な関数だけを渡すのが定石です。
構造化出力という副産物
「決まったスキーマに従う JSON を確実に出させる」能力は、関数を呼ばない場面でも役立ちます。たとえば請求書の文章から金額・日付・宛先を抜き出したいとき、抽出結果を受け取るだけの関数を宣言すれば、モデルの出力を必ず解析できる構造化データとして受け取れます。この使い方は、のちに「構造化出力(Structured Outputs)」という独立した機能になりました。2024年8月に OpenAI が出力をスキーマに厳密に一致させるモードを加えたように、生成のときに文法で出力を縛り、スキーマ違反を起こさないことを保証する API が各社から出ています。自由な文章から型のあるデータへの変換は、LLM を既存のシステムに組み込むときの最頻出の使い方です。
実務での落とし穴
外部の API は失敗するものなので、エラーをモデルに返して言い直させるか、アプリ側でリトライするかの方針を決めておきます。同じ依頼が重複して実行されても安全なように冪等性を意識しておくと、何周もツールを呼ぶAIエージェントの繰り返し実行にも耐えます。削除や送金のような取り返しのつかない処理は、関数として直接渡さず、人の確認をはさむ設計にします。なお、関数の宣言と呼び出しの形式はモデル提供者ごとに少しずつ違います。その違いを吸収し、ツールを持つ側とモデルを使う側の接続を標準化するのが MCP です。
試問
天気アプリに LLM を組み込み、「東京の天気は?」に答えられるよう、天気の API を呼ぶ関数 get_weather を LLM に宣言しました。質問を受けてから回答が出るまでには、いくつもの仕事が発生します。それぞれの仕事を担うのは LLM か、アプリか。
Function Calling の往復で発生する仕事を、LLM がすることとアプリがすることに仕分けよ
項目を選んでから、入れる箱を選びます
