GEMINI LABEN
SIRI — WWDC 2026で刷新版SiriがGoogle Geminiモデルで動くと確定。ただしEUではDMAによりiOS 27時点で提供されませんFLASH3.5 — Gemini 3.5 FlashがGA。エージェント・コーディングで持続的なフロンティア性能を発揮する最上位FlashモデルですIMAGE-GA — Gemini 3.1 Flash Image / 3.1 Pro Imageがネイティブ視覚モデルとしてGA。preview版は6/25に終了予定MANAGED-AGENTS — Gemini APIでManaged Agentsが公開プレビュー。Googleホストの隔離Linuxサンドボックスで自律エージェントを構築できますFILE-SEARCH — File Searchがマルチモーダル対応。gemini-embedding-2で画像のネイティブ埋め込み・検索が可能になりましたDEPRECATION — gemini-3.1-flash-image-preview / gemini-3-pro-image-previewは6/25に停止。GA版への移行をお早めにSIRI — WWDC 2026で刷新版SiriがGoogle Geminiモデルで動くと確定。ただしEUではDMAによりiOS 27時点で提供されませんFLASH3.5 — Gemini 3.5 FlashがGA。エージェント・コーディングで持続的なフロンティア性能を発揮する最上位FlashモデルですIMAGE-GA — Gemini 3.1 Flash Image / 3.1 Pro Imageがネイティブ視覚モデルとしてGA。preview版は6/25に終了予定MANAGED-AGENTS — Gemini APIでManaged Agentsが公開プレビュー。Googleホストの隔離Linuxサンドボックスで自律エージェントを構築できますFILE-SEARCH — File Searchがマルチモーダル対応。gemini-embedding-2で画像のネイティブ埋め込み・検索が可能になりましたDEPRECATION — gemini-3.1-flash-image-preview / gemini-3-pro-image-previewは6/25に停止。GA版への移行をお早めに
記事一覧/API / SDK
API / SDK/2026-05-04中級

Gemini の Function Calling で構造化出力を実装する — 複数ツール連携の設計パターン

Gemini API の Function Calling を使って信頼性の高い構造化出力を実装する方法を解説します。ツール定義のコツから複数ツール連携、エラー処理まで実践的に解説します。

Gemini API179Function Calling16構造化出力9ツール連携3Python52

Gemini の Function Calling を最初に試したとき、正直「JSON を返してもらえばいいだけでは」と思っていました。しかし、実際に本番環境で使い始めると、Function Calling と単なる JSON モードの差が明確に見えてきます。

最大の違いは「ツールを呼ぶタイミングをモデルが判断する」という点です。プロンプトの文脈によって必要なデータを選んで取得し、結果を統合して応答を構成する — この一連の流れを Gemini が自律的に実行します。今回は、この仕組みを実用的なコードで説明します。

Function Calling の基本構造

Function Calling は三段階のサイクルで動きます。

  1. ツール定義をモデルに渡してリクエストを送る
  2. モデルが function_call を返してくる(この時点ではツールはまだ実行されていない)
  3. ツールを実際に実行して結果をモデルに戻す

この「モデルはツールを呼ぶ指示を出すだけで、実行するのはアプリ側」という分離が重要です。

import google.generativeai as genai
 
genai.configure(api_key="YOUR_GEMINI_API_KEY")
 
# ツール定義
tools = [
    {
        "function_declarations": [
            {
                "name": "get_weather",
                "description": "指定した都市の現在の天気を取得する",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "city": {
                            "type": "string",
                            "description": "都市名(例: Tokyo, Osaka)"
                        },
                        "unit": {
                            "type": "string",
                            "enum": ["celsius", "fahrenheit"],
                            "description": "温度の単位"
                        }
                    },
                    "required": ["city"]
                }
            }
        ]
    }
]
 
model = genai.GenerativeModel("gemini-2.0-flash", tools=tools)
response = model.generate_content("東京の今日の天気は?")
 
# Function Call が含まれているか確認
for part in response.candidates[0].content.parts:
    if hasattr(part, "function_call"):
        print(f"呼び出し: {part.function_call.name}")
        print(f"引数: {dict(part.function_call.args)}")

ツール定義を書くときのコツ

description の質がモデルの判断精度に直接影響します。公式ドキュメントでは軽く触れられている点ですが、実際に試してみると差が歴然としています。

悪い例: "description": "天気を取得する"

良い例: "description": "指定した都市の現在の気温・天気状況・湿度を取得する。ユーザーが天候について質問したとき、または天気情報が意思決定に必要なときに使用する"

条件部分(「〜なときに使用する」)を書くと、モデルが不必要にツールを呼ぶ過検出を抑えられます。複数のツールが似た機能を持つ場合、この使い分けの指示が特に効果的です。

enum を使って選択肢を制限することも重要です。unit パラメータに enum: ["celsius", "fahrenheit"] を指定しておくと、モデルが予期しない値を渡してくるリスクがなくなります。

複数ツールを組み合わせる

実用的なアプリケーションでは、複数のツールを組み合わせて使うことがほとんどです。Gemini は一つのリクエストで複数のツール呼び出しを返すことがあります(parallel function calling)。

def handle_function_calls(response, tool_implementations):
    """Function Call を処理して結果を返す"""
    function_results = []
 
    for part in response.candidates[0].content.parts:
        if not hasattr(part, "function_call"):
            continue
        
        fc = part.function_call
        func_name = fc.name
        func_args = dict(fc.args)
        
        if func_name not in tool_implementations:
            function_results.append({
                "function_response": {
                    "name": func_name,
                    "response": {"error": f"Unknown function: {func_name}"}
                }
            })
            continue
        
        try:
            result = tool_implementations[func_name](**func_args)
            function_results.append({
                "function_response": {
                    "name": func_name,
                    "response": {"result": result}
                }
            })
        except Exception as e:
            function_results.append({
                "function_response": {
                    "name": func_name,
                    "response": {"error": str(e)}
                }
            })
    
    return function_results
 
# 実際のツール実装
def get_weather(city: str, unit: str = "celsius") -> dict:
    # 実際の天気APIを呼ぶ想定
    return {"city": city, "temperature": 22, "condition": "晴れ", "unit": unit}
 
def get_news(topic: str, max_results: int = 3) -> list:
    # 実際のニュースAPIを呼ぶ想定
    return [{"title": f"{topic}のニュース{i}", "url": f"https://example.com/{i}"} for i in range(max_results)]
 
tool_implementations = {
    "get_weather": get_weather,
    "get_news": get_news
}

一つ注意点があります。Gemini が複数のツール呼び出しを一度に返した場合、それぞれの実行は独立しているため、並列実行しても問題ありません。asyncio.gather() で同時実行すると応答時間を短縮できます。

エラーと不確実性への対処

ツールがエラーを返した場合、Gemini はそれを踏まえて応答を修正します。ただし、エラーの情報を適切に伝えないと、モデルが憶測で回答してしまうことがあります。

def safe_tool_response(func_name: str, result=None, error=None) -> dict:
    """ツール応答を構造化して返す"""
    if error:
        return {
            "function_response": {
                "name": func_name,
                "response": {
                    "success": False,
                    "error": str(error),
                    "suggestion": "別の方法で試してください"
                }
            }
        }
    return {
        "function_response": {
            "name": func_name,
            "response": {
                "success": True,
                "data": result
            }
        }
    }

success フラグと suggestion を含めると、モデルがエラーを適切に処理して「このツールが失敗したが、代替手段を試みる」という判断ができるようになります。

実プロジェクトでの活用例

私が実際に使った事例として、「アプリのレビュー分析ツール」があります。App Store のレビューテキストを Gemini に渡し、Function Calling で以下のツールを定義しました。

  • categorize_review — レビューをカテゴリに分類(UI/バグ/機能要望/など)
  • extract_sentiment — 感情スコアと主要キーワードを抽出
  • flag_urgent — 緊急対応が必要なレビュー(クラッシュ報告など)にフラグを立てる

これを単純な JSON モードで実装しようとすると、1レビューに対して 3 回 API を呼ぶ必要があります。Function Calling では、Gemini が文脈から「このレビューはこの 3 つのツールを使って処理すべき」と判断して一度にまとめて実行します。API 呼び出し回数が 1/3 になり、コストも大幅に下がりました。

はじめの一歩

まずは単一ツールで試してみてください。description の書き方を変えながら、モデルがツールを呼ぶタイミングがどう変わるかを観察するのが一番の学習になります。

公式の Gemini API ドキュメント には基本的な使い方が整理されています。ここに書いた「複数ツールの並列実行」と「エラーレスポンスの構造化」は、実際に使って気づいた実践的な補足として参考にしてください。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API / SDK2026-04-23
Gemini API の Parallel Function Calling を本番で使いこなす — 並列ツール実行の設計パターンと落とし穴
Gemini API の Parallel Function Calling をレスポンス速度と信頼性の両面から本番運用する設計パターンを解説。並列実行の仕様、DAG設計、部分失敗対策、監視までを実装コード付きで詳しく紹介します。
API / SDK2026-03-16
Gemini 3 Thought Signatures:エージェントAIの推論チェーンを保持する
Gemini 3で導入されたThought Signatures(思考シグネチャ)の仕組みと実装方法を解説。Function CallingやマルチターンエージェントでAPIを正しく使うためのPythonコード例付きガイドです。
API / SDK2026-06-04
AdMob レポートの判定は Gemini にやらせない — 構造化出力を「抽出」に限定する設計
AdMob レポートからフロア(eCPM 下限値)を決めるとき、Gemini に判定そのものをやらせるのは危険です。構造化出力は「乱れたレポートを型付きデータに抽出する」工程だけに限定し、しきい値判定は決定論的なコードに置く——その設計理由と実装を、実際の 42 グループ運用の判定ルールとともにまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →