ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-04-20中級

Antigravity × Python で Gemini API の Function Calling を使いこなす実践ガイド

Antigravity IDE で Python × Gemini API の Function Calling を実装する実践ガイド。天気APIや計算ツールとの連携例、エラーハンドリングまで、動作するコードで丁寧に解説します。

python26gemini-api7function-calling5antigravity435google-ai

Antigravity で Python を使い始めて最初の壁が「クイックスタートはできたけど、実際のアプリで役立つ機能を実装するには何を学べばいいか」という段階です。

テキスト生成はできます。ストリーミングもわかりました。でも、現実のアプリでは「AIが外部の API を呼んで、その結果を踏まえて答えを返す」という処理が必要になってきます。これを実現するのが Function Calling(ツール呼び出し) です。

今回は Antigravity × Python 環境で Gemini API の Function Calling を実装する方法を、動くコードを中心に説明します。

Function Calling とは(なぜ必要なのか

LLM は言語処理は得意ですが、現在時刻を正確に答えたり、リアルタイムの株価を調べたりはできません。「2026年4月の東京の天気は?」と聞いても、それっぽい回答を作るだけです。

Function Calling は、「モデルが特定の関数を呼び出したい」と判断したとき、その関数の名前と引数をJSON形式で返す仕組みです。アプリ側でその関数を実行し、結果をモデルに返すと、モデルは正確なデータを使って最終回答を生成します。

つまり:

  • アプリ側: 関数を定義し、実際に実行する
  • モデル側: どの関数をいつ呼ぶか判断し、引数を生成する

この役割分担がFunction Callingの本質です。

Antigravity での開発環境セットアップ

Antigravity を開いてターミナルから仮想環境を作ります。

# プロジェクトフォルダを作成
mkdir gemini-function-calling
cd gemini-function-calling
 
# 仮想環境
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
 
# 依存関係インストール
pip install google-generativeai python-dotenv

Antigravity の Python 拡張が有効になっていれば、仮想環境のインタープリタを自動検出してくれます。もし認識されない場合は Ctrl+Shift+PPython: Select Interpreter.venv/bin/python を選択してください。

.env ファイルに API キーを設定します:

GEMINI_API_KEY=YOUR_GEMINI_API_KEY

基本的な Function Calling の実装

まず最も単純な例で仕組みを理解します。「現在時刻を返す関数」を定義し、Gemini に渡します。

# basic_function_calling.py
import os
import json
import datetime
import google.generativeai as genai
from dotenv import load_dotenv
 
load_dotenv()
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
 
# ① 関数の定義(Gemini が呼び出す候補)
def get_current_time(timezone: str = "Asia/Tokyo") -> dict:
    """現在時刻を返す"""
    now = datetime.datetime.now()
    return {
        "time": now.strftime("%Y-%m-%d %H:%M:%S"),
        "timezone": timezone
    }
 
# ② Gemini に渡すツール定義(JSON Schema 形式)
tools = [
    {
        "function_declarations": [
            {
                "name": "get_current_time",
                "description": "現在の日時を取得します",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "timezone": {
                            "type": "string",
                            "description": "タイムゾーン(例: Asia/Tokyo, UTC)"
                        }
                    },
                    "required": []
                }
            }
        ]
    }
]
 
# ③ モデルとチャットを開始
model = genai.GenerativeModel("gemini-2.0-flash", tools=tools)
chat = model.start_chat()
 
# ④ ユーザーメッセージを送信
response = chat.send_message("今何時ですか?")
 
# ⑤ モデルが Function Call を要求しているか確認
for part in response.parts:
    if hasattr(part, "function_call"):
        func_call = part.function_call
        print(f"モデルが要求した関数: {func_call.name}")
        print(f"引数: {dict(func_call.args)}")
        
        # ⑥ 実際に関数を実行
        result = get_current_time(**dict(func_call.args))
        
        # ⑦ 実行結果をモデルに返す
        final_response = chat.send_message(
            genai.protos.Part(
                function_response=genai.protos.FunctionResponse(
                    name=func_call.name,
                    response={"result": result}
                )
            )
        )
        print(f"\nAI の回答: {final_response.text}")

実行すると以下のような出力になります:

モデルが要求した関数: get_current_time
引数: {}

AI の回答: 現在の時刻は 2026-04-20 09:00:00(Asia/Tokyo)です。

重要なのは のステップです。モデルは「この関数を実行してください」という指示を返しているだけで、実際の実行はアプリ側の責任です。

実用的な例:複数ツールの同時定義

現実のアプリでは複数の関数を定義することが多いです。「計算機能」と「単位変換」を組み合わせた例を見てみます。

# multi_tool_example.py
import os
import google.generativeai as genai
from dotenv import load_dotenv
 
load_dotenv()
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
 
# ツール実装
def calculate(expression: str) -> dict:
    """数式を評価する(安全な式のみ)"""
    allowed_chars = set("0123456789+-*/()., ")
    if not all(c in allowed_chars for c in expression):
        return {"error": "不正な文字が含まれています", "result": None}
    try:
        result = eval(expression)  # 本番では safer eval を使うこと
        return {"result": result, "expression": expression}
    except Exception as e:
        return {"error": str(e), "result": None}
 
def convert_units(value: float, from_unit: str, to_unit: str) -> dict:
    """単純な単位変換(km⇔miles, kg⇔lbs)"""
    conversions = {
        ("km", "miles"): lambda v: v * 0.621371,
        ("miles", "km"): lambda v: v * 1.60934,
        ("kg", "lbs"): lambda v: v * 2.20462,
        ("lbs", "kg"): lambda v: v / 2.20462,
    }
    key = (from_unit.lower(), to_unit.lower())
    if key in conversions:
        result = conversions[key](value)
        return {"result": round(result, 4), "from": f"{value} {from_unit}", "to": f"{result:.4f} {to_unit}"}
    return {"error": f"{from_unit}{to_unit} の変換は対応していません"}
 
# ツール名と関数のマッピング
TOOL_FUNCTIONS = {
    "calculate": calculate,
    "convert_units": convert_units,
}
 
tools = [
    {
        "function_declarations": [
            {
                "name": "calculate",
                "description": "数学的な計算式を評価します",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "expression": {"type": "string", "description": "評価する数式(例: 2 + 3 * 4)"}
                    },
                    "required": ["expression"]
                }
            },
            {
                "name": "convert_units",
                "description": "単位変換を行います(km⇔miles, kg⇔lbs)",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "value": {"type": "number", "description": "変換する値"},
                        "from_unit": {"type": "string", "description": "変換元の単位"},
                        "to_unit": {"type": "string", "description": "変換先の単位"}
                    },
                    "required": ["value", "from_unit", "to_unit"]
                }
            }
        ]
    }
]
 
def chat_with_tools(user_message: str) -> str:
    """ツール付きチャットの汎用関数"""
    model = genai.GenerativeModel("gemini-2.0-flash", tools=tools)
    chat = model.start_chat()
    
    response = chat.send_message(user_message)
    
    # Function Call のループ処理(複数回呼ばれる可能性もある)
    max_iterations = 5
    for _ in range(max_iterations):
        func_calls = [p for p in response.parts if hasattr(p, "function_call")]
        if not func_calls:
            break  # Function Call がなければ最終回答
        
        # 全ての Function Call を実行して結果を返す
        function_responses = []
        for part in func_calls:
            fc = part.function_call
            func = TOOL_FUNCTIONS.get(fc.name)
            if func:
                result = func(**dict(fc.args))
            else:
                result = {"error": f"Unknown function: {fc.name}"}
            
            function_responses.append(
                genai.protos.Part(
                    function_response=genai.protos.FunctionResponse(
                        name=fc.name,
                        response={"result": result}
                    )
                )
            )
        
        response = chat.send_message(function_responses)
    
    return response.text
 
# テスト
print(chat_with_tools("42 * 1.08 の計算と、その結果を km から miles に変換して"))
# 期待: 計算結果 45.36 を miles 変換した 28.18 miles が返される

max_iterations のループが重要です。Gemini がFunction Callを複数回要求する場合(例:計算してから変換)、このループで処理します。上限を設けないと無限ループになる可能性があるので、実際のプロダクトでは必ずガードを入れてください。

Antigravity でのデバッグのコツ

Function Calling でつまずきやすいのが「なぜ関数が呼ばれないのか」という問題です。Antigravity のデバッグパネルを使ったトラブルシューティングの方法を紹介します。

レスポンスの中身を詳しく見るには:

# デバッグ用:レスポンスの構造を出力
def debug_response(response):
    print("--- レスポンス構造 ---")
    print(f"候補数: {len(response.candidates)}")
    for i, candidate in enumerate(response.candidates):
        print(f"候補 {i}: finish_reason={candidate.finish_reason}")
        for j, part in enumerate(candidate.content.parts):
            if hasattr(part, "text"):
                print(f"  Part {j}: テキスト = {part.text[:100]}")
            elif hasattr(part, "function_call"):
                print(f"  Part {j}: Function Call = {part.function_call.name}({dict(part.function_call.args)})")

finish_reasonSTOP なら通常終了、MAX_TOKENS ならトークン上限超過です。関数が呼ばれない場合は、ツール定義の description が曖昧すぎることが多いです。「いつ、どんな場合に使う関数か」を具体的に書くとモデルが適切に判断しやすくなります。

全体を振り返って:次のステップへ

Function Calling を覚えると、「AI + リアルデータ」のアプリが作れるようになります。今回作ったコードをベースに、まず手元にある API(天気、地図、自社DB)との連携を試してみてください。

Gemini API の Function Calling に関しては、Google GenAI SDK for Python の公式ドキュメントに多くのサンプルがあります。特に tool_config を使った「特定のツールだけ強制的に呼ぶ」設定は、チャットボットの動作を安定させる際に役立ちます。

Python で AI アプリ開発

シェア

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

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

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

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

関連記事

アプリ開発2026-05-03
Antigravityで『uv add transformers』が通らない時の見落としやすい原因と対処法
Antigravity上のPythonプロジェクトでuv add transformersが失敗する、あるいは追加後もImportErrorになる時に確認すべきポイントを、実際に詰まった順序で整理します。
アプリ開発2026-04-23
Antigravity Python API を本番で落とさない — リトライ・タイムアウト・サーキットブレーカー実装ガイド
Antigravity で開発する Google Gen AI SDK アプリケーションを本番環境で安定稼働させるための、リトライ・タイムアウト・サーキットブレーカー・バックプレッシャー設計を、動作する Python コードと運用経験から体系的に解説します。
Agents & Manager2026-04-19
Antigravity AIエージェント設計:マルチモーダル対応の本番実装パターン
Google Antigravity(Gemma 4)を使ったマルチモーダルAIエージェントの設計・実装を解説。画像・テキスト統合処理、Function Calling、Tool Use、本番環境での状態管理とエラーハンドリングまで網羅します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →