最新情報を聞くと、もっともらしい古い答えが返ってきた
個人開発でアプリの告知文を Gemini に下書きさせていたとき、「直近のリリース状況を踏まえて」と頼んだのに、数か月前の状態を前提にした文章が返ってきました。モデルは学習時点までの知識で答えるので、当然といえば当然です。
この「最新を知らない」「手元のデータを見られない」という壁を越える仕組みが、外部ツール連携です。Gemini には、アプリ画面から使う連携機能と、API から呼び出す tools パラメータの二系統があります。両方を押さえておくと、用途に応じて使い分けられます。
アプリ画面から使う標準の連携機能
Gemini アプリ(ブラウザ・モバイル)では、設定画面から Google 系サービスとの連携をオン/オフできます。質問の内容に応じて、必要なときだけ自動で呼び出される設計です。
Google 検索
ニュース・時事・リアルタイムの数値が必要な質問で自動的に働き、検索結果を回答に反映します。
- 「今日の東京の天気は?」
- 「直近の AI 関連ニュースを 3 行でまとめて」
- 「ある企業の最新の決算発表はいつ?」
Google マップ
場所の検索、経路、店舗やホテルの情報を取得します。
- 「渋谷駅から東京タワーまでの行き方」
- 「この周辺でレビュー評価の高いイタリアン」
YouTube
動画の検索と関連コンテンツの提案を行います。
- 「Python の機械学習チュートリアル動画を探して」
Google フライト & ホテル
フライトやホテルを検索・比較します。
- 「来月の東京〜パリの最安フライト」
連携機能は個別にオン/オフできます。使わない連携を切っておくと、意図しない外部呼び出しを避けられます。
API から使う:検索グラウンディング
開発者が同じことをプログラムから行うときは、tools パラメータを使います。まずは検索グラウンディングです。モデルが必要と判断したときだけ Google 検索を実行し、その結果を根拠(グラウンディング)として回答を組み立てます。
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
response = client.models.generate_content(
model="gemini-3.5-flash",
contents="東京の現在の天気を、出典つきで教えてください",
config=types.GenerateContentConfig(
tools=[types.Tool(google_search=types.GoogleSearch())],
),
)
print(response.text)
# グラウンディング根拠(参照元)を取り出す
meta = response.candidates[0].grounding_metadata
if meta and meta.grounding_chunks:
for chunk in meta.grounding_chunks:
print("Source:", chunk.web.uri)
else:
print("(このリクエストでは検索は使われませんでした)")モデルは「外部情報が要る」と判断したときだけ検索します。天気のように明らかに最新が必要な質問では grounding_chunks が返りますが、一般知識で答えられる質問では検索されず grounding_metadata が空になります。根拠が無いケースを必ず分岐で受けるのが、本番で安定させるコツです。空を前提にしないコードにしておくと、想定外のクラッシュを防げます。
API から使う:Function Calling の実行ループ
検索グラウンディングは Google 側が中身を実行してくれますが、自分のデータベースや社内 API を叩きたい場合は Function Calling を使います。ここで多くの入門記事が省略しがちなのが、**「モデルが関数を呼びたいと言ってきた後、誰が実際に実行するのか」**という往復です。実行するのは私たちのコードです。
流れは「①関数を宣言 → ②モデルが呼び出しを要求 → ③こちらで関数を実行 → ④結果をモデルに返す → ⑤最終回答」の 5 段階です。
from google import genai
from google.genai import types
client = genai.Client(api_key="YOUR_API_KEY")
# ① 関数を宣言する
get_weather = types.FunctionDeclaration(
name="get_weather",
description="指定した都市の現在の天気を返す",
parameters={
"type": "object",
"properties": {
"city": {"type": "string", "description": "都市名"},
},
"required": ["city"],
},
)
tools = [types.Tool(function_declarations=[get_weather])]
# 実際に呼ばれるローカル実装(本来は API を叩く想定)
def run_get_weather(city: str) -> dict:
fake_db = {"東京": "晴れ・24度", "大阪": "曇り・22度"}
return {"city": city, "weather": fake_db.get(city, "データなし")}
contents = [
types.Content(role="user", parts=[types.Part(text="東京の天気は?")]),
]
# ② モデルに最初の問い合わせ
resp = client.models.generate_content(
model="gemini-3.5-flash",
contents=contents,
config=types.GenerateContentConfig(tools=tools),
)
part = resp.candidates[0].content.parts[0]
if part.function_call:
call = part.function_call
# ③ こちらで関数を実行
result = run_get_weather(**dict(call.args))
# ④ モデルの呼び出しと、その実行結果を会話履歴に積む
contents.append(resp.candidates[0].content)
contents.append(
types.Content(
role="tool",
parts=[types.Part(
function_response=types.FunctionResponse(
name=call.name, response=result,
)
)],
)
)
# ⑤ 結果を踏まえた最終回答を得る
final = client.models.generate_content(
model="gemini-3.5-flash",
contents=contents,
config=types.GenerateContentConfig(tools=tools),
)
print(final.text)ポイントは ④ で、モデルの呼び出し(function_call)と、その実行結果(function_response)の両方を会話履歴に積んでから最終回答を求めることです。実行結果だけを返すと、モデルは「何を聞かれて何を返したのか」の文脈を失い、的外れな回答になります。私自身、ここを片方だけ積んで半日悩んだことがあります。
本番で気をつけている 4 点
外部ツールを挟むと、単発のテキスト生成にはなかった考慮事項が増えます。個人開発で運用しながら、私が毎回確認している点を挙げます。
- レイテンシ:ツール呼び出しはネットワーク往復を伴うため、応答が遅くなります。ユーザー向け画面では「検索中…」のような中間表示を入れると体感が大きく変わります。
- コスト:グラウンディング検索や複数回の往復は、その分の課金が発生します。無料枠で試算してから本番のレート設計に入ると安全です。
- 引用の扱い:
grounding_chunksの出典 URL は、回答の信頼性を読者に示す材料になります。表示する場合はリンク切れも想定しておきます。 - 関数の暴発防止:必要なツールだけを
toolsに渡します。宣言を増やしすぎると、モデルが意図しない関数を選ぶ確率が上がります。
個人開発での使い分け
私の場合、アプリの告知文やリリースノートのように「事実の鮮度」が要る下書きには検索グラウンディングを、社内のメトリクスや在庫のように「手元にしかないデータ」を絡めるときは Function Calling を選びます。アプリの収益データ(AdMob のレポートなど)を読み込ませて要約させるのも後者の使いどころです。
アプリ画面の連携機能は、まず手で触って挙動を掴むのに向いています。API の tools は、その挙動を自動化に落とし込む段階で効いてきます。
どのモデルでツールを呼ぶか
ツール連携を組むときは、モデル選びも結果を左右します。私の運用では、検索グラウンディングや一段の Function Calling のように比較的軽い往復は速度重視で gemini-3.5-flash に寄せ、複数のツールを連鎖させて段階的に判断させたいときだけ上位モデルを検討します。
Flash 系は応答が速くコストも抑えやすいため、ユーザーの操作に同期して走らせる機能と相性が良いです。逆に、夜間バッチのように人を待たせない処理で、ツールの選択や引数の組み立てに精度がほしい場面では、上位モデルへ切り替える価値があります。まず Flash で組んでみて、関数の選択ミスや引数の取りこぼしが目立つようなら上位モデルへ、という順序が無駄がありません。
なお、モデル名を指定せずに API を呼ぶと既定のモデルが使われ、その既定はアップデートで変わり得ます。自動化では model を明示して固定しておくと、ある日突然挙動が変わって慌てる事態を避けられます。
次の一歩
手元の Gemini API キーで、まずは上の検索グラウンディングのコードをそのまま動かし、grounding_chunks が返る質問と返らない質問を一つずつ試してみてください。空のケースを体験しておくと、Function Calling の往復を組むときの設計判断がぐっと楽になります。
お読みいただきありがとうございました。手を動かす際の足がかりになれば嬉しいです。