PythonからGemini APIを呼ぶなら、公式SDKのgoogle-genaiを入れ、client.interactions.create()で書くのが2026年11月時点の標準です。2026年6月にInteractions APIが正式版になり、従来のgenerate_contentはレガシー扱いになりました。さらに11月6日公開のgoogle-genai 3.0.0で、既定のAPIバージョンとHTTPクライアントが変わり、Python 3.10では入らなくなっています。本記事では、環境の準備から、テキスト生成と会話の継続、ストリーミング、画像入力、Pydanticを使った構造化出力、関数呼び出し、エラーと再試行の扱いまでを、コピーして動かせるコードで順に説明します。
まとめ:Gemini APIのPython実装はInteractions APIと3.0.0前提で書く
新しく書くコードは、google-genai 3.0.0以上とPython 3.11以上を前提にします。呼び出しはclient.interactions.create()に統一し、応答の文字列はoutput_textで受け取ります。会話を続けるときは前回のidをprevious_interaction_idに渡すだけで、履歴を自分で組み立てる必要はありません。
業務で使う前に決めておくことは2つです。1つは保存の扱いで、Interactions APIは既定でやり取りをサーバーに保存します(有料枠55日・無料枠1日)。保存させたくない処理にはstore=Falseを付けます。もう1つは再試行で、SDKが429と5xxを自動で再試行するため、自前のリトライを重ねると呼び出し回数が膨らみます。
既存のgenerate_contentのコードは今も動きます。Batch APIや自動関数呼び出しを使っている処理は、Interactions APIがまだ対応していないので、無理に移さずそのまま残す方針です。Gemini APIそのものの全体像は親記事のGemini APIとは?できること・料金・始め方とInteractions APIの最小コードにまとめています。
Gemini APIをPythonで使う準備:google-genaiの導入とキー
準備はPythonの版の確認、SDKの導入、APIキーの読み込みの3段階です。古い解説記事でpip install google-generativeaiと書かれているものは旧SDKで、公式のライブラリ一覧では2025年11月30日に非推奨となり、保守もされていません。
Python 3.11以上の仮想環境へgoogle-genai 3.0.0を入れる手順
PyPIのgoogle-genaiは、2026年11月6日に3.0.0が公開されました。動作要件は3.0.0からPython 3.11以上で、10月23日公開の2.33.0までは3.10以上でした。3.10の環境でpip install -U google-genaiを実行すると、エラーにならずに2.33.0が入るので、版を確かめてから先へ進みます。
# Python の版を確認する(3.11 以上が必要)
python3 --version
# プロジェクト専用の仮想環境を作って有効にする
python3 -m venv .venv
source .venv/bin/activate # Windows は .venv\Scripts\activate
# SDK と、構造化出力で使う pydantic を入れる
pip install -U "google-genai>=3.0.0" pydantic
# 入った版を確認する(Version: 3.0.0 以上ならよい)
pip show google-genai
requirements.txtにはgoogle-genai>=3.0.0,<4のように上限も書いておくと、次の大きな版上げで既定値が変わったときに、本番だけ挙動が変わる事故を防げます。SDKそのものの位置づけや旧SDKからの書き換えはGoogle Gen AI SDKとは?google-genaiの導入とAgent Platform切替・旧SDK移行で扱っています。
環境変数GEMINI_API_KEYとwith文でのgenai.Client()初期化
APIキーは環境変数GEMINI_API_KEYに置き、引数なしのgenai.Client()で読み込ませます。SDKのREADMEによると、GOOGLE_API_KEYも設定されている場合はそちらが優先されます。別のGoogleのAPI用にこの変数を入れた開発機では、意図しないキーで送られる点に注意してください。キーの発行手順はGemini APIキーの取得方法:AI Studioでの発行・環境変数・制限と漏洩時の失効にあります。
クライアントはwith文で作ると、ブロックを抜けたときに内部のHTTP接続が閉じられます。バッチ処理のように多数の呼び出しを続けるスクリプトでは、閉じ忘れによる接続の取り残しを避けられる書き方です。次のh3以降のコード片は、最初の例で作ったclientをそのまま使う前提で書いています。
Interactions APIで書く最初の生成コードと会話の続け方の違い
ここからが本題の呼び出しです。Interactions APIでは、入力をinput、役割の指定をsystem_instruction、生成の設定をgeneration_configに渡します。
interactions.createで役割と生成設定を指定する最初のコード
次のコードは、社内ヘルプデスクの役割を与えて1回だけ回答させる最小構成です。モデルIDは2026年11月時点で公式の例に使われているgemini-3.8-flashにしています。
from google import genai
# 環境変数 GEMINI_API_KEY を読む。with を抜けると接続を閉じる
with genai.Client() as client:
interaction = client.interactions.create(
model="gemini-3.8-flash",
system_instruction="あなたは社内ヘルプデスクの担当者です。回答は3文以内にします。",
input="VPNにつながらないとき、最初に確認することは何ですか?",
generation_config={
"max_output_tokens": 500, # 出力トークンの上限
"thinking_level": "low", # 思考の深さ。速さと費用を優先する
},
)
print(interaction.output_text)
print("ID:", interaction.id) # 会話を続けるときに使う
古い記事でよく見るtemperatureは、ここでは指定していません。テキスト生成の公式ページによると、Gemini 4とGemini 3.6以降のモデルはtemperature・top_p・top_kの値を無視し、非推奨の警告ヘッダーを返します。出力のぶれを抑えたいなら、指示文で形式を固定するか、後述の構造化出力を使います。
previous_interaction_idとstore=Falseで会話を続ける方式
2回目以降の質問で前の文脈を引き継ぐ方法は2つあります。1つはサーバー側に履歴を持たせる方式で、前回のinteraction.idをprevious_interaction_idに渡します。
first = client.interactions.create(
model="gemini-3.8-flash",
input="当社の始業は9時、終業は18時です。",
)
second = client.interactions.create(
model="gemini-3.8-flash",
input="20時まで働いたら残業は何時間ですか?",
previous_interaction_id=first.id, # 前回の文脈を引き継ぐ
)
print(second.output_text)
Interactions APIの概要ページには、引き継がれるのは会話の中身だけで、system_instructionとgeneration_configは毎回指定し直す必要があると書かれています。2回目で役割の指定を省くと、回答の口調や長さが変わります。
もう1つはstore=Falseを付け、履歴を手元のリストで持って毎回送る方式です。既定の保存は有料枠で55日、無料枠で1日です。顧客情報を含む問い合わせのように、外部に残したくないやり取りはこちらにします。ただしstore=Falseではprevious_interaction_idとバックグラウンド実行が使えません。
generate_contentで書かれた既存コードとの対応表
検索で見つかるPythonのサンプルの多くは、まだclient.models.generate_content()で書かれています。概要ページの説明では、このAPIはレガシー扱いになった一方で、引き続き完全にサポートされています。読み替えに必要なのは、次の対応関係です。
| 用途 | generate_content | Interactions API |
|---|---|---|
| 入力 | contents | input |
| 応答の文字列 | response.text | output_text |
| 会話の継続 | chats.create | previous_interaction_id |
| ストリーミング | generate_content_stream | stream=True |
| JSONの指定 | response_schema | response_format |
移すべきでない処理もあります。概要ページは、Batch API、Python限定の自動関数呼び出し、明示的なキャッシュの3つをInteractions APIで「まだ使えない」機能に挙げています。これらに依存するコードはgenerate_contentのまま残し、新規の処理だけInteractions APIで書くのが安全です。書き換えの全手順は公式の移行ガイドにあります。
ストリーミング・画像入力・構造化出力をPythonで書くコード例
チャット画面や帳票の読み取りのような業務処理で、使う頻度が高い3つの書き方です。いずれも同じclient.interactions.create()に引数を足すだけで実装できます。
stream=Trueのstep.deltaで逐次表示しトークン数を取る
長い回答を待たせずに表示したいときはstream=Trueを付けます。ストリーミングの公式ページによると、本文はstep.deltaイベントで少しずつ届き、最後のinteraction.completedイベントに使用量が入ります。
stream = client.interactions.create(
model="gemini-3.8-flash",
input="Pythonで社内向けAPIを作るときの注意点を5つ挙げてください。",
stream=True,
)
for event in stream:
if event.event_type == "step.delta" and event.delta.type == "text":
print(event.delta.text, end="", flush=True) # 届いた分から表示
elif event.event_type == "interaction.completed":
usage = event.interaction.usage
print("\n入力:", usage.total_input_tokens, "出力:", usage.total_output_tokens)
使用量はここで記録しておくと、月末の請求額を待たずに処理ごとの費用を追えます。思考に使ったトークンはtotal_thought_tokensに別に計上されるので、費用の見積もりでは出力トークンと合わせた記録が必要です。単価はGemini APIの料金と無料枠:モデル別単価・課金設定・費用の計算コードで確認できます。
client.files.uploadで画像を渡すマルチモーダル入力
画像を読ませるときは、先にclient.files.upload()でファイルを上げ、返ってきたuriとmime_typeをinputのリストに入れます。テキストの指示と画像を並べて渡す形です。
uploaded = client.files.upload(file="receipt.jpg") # 読ませたい画像
interaction = client.interactions.create(
model="gemini-3.8-flash",
input=[
{"type": "text", "text": "この領収書の発行日・発行者・合計金額を読み取ってください。"},
{"type": "image", "uri": uploaded.uri, "mime_type": uploaded.mime_type},
],
)
print(interaction.output_text)
読み取った値を後続のシステムに渡すなら、自由文で返させず、次のh3の構造化出力と組み合わせます。自由文のままでは「合計:1,100円(税込)」のような表記揺れを、受け取る側で吸収する処理が要ります。
Pydanticとresponse_formatでJSONを受け取り検証する
決まった項目を確実に受け取りたいときは、Pydanticで型を定義し、そのJSONスキーマをresponse_formatに渡します。構造化出力の公式ページの書き方に沿った例です。
from pydantic import BaseModel, Field
class Receipt(BaseModel):
issued_on: str = Field(description="発行日。YYYY-MM-DD 形式")
issuer: str = Field(description="発行者の名称")
total_yen: int = Field(description="税込の合計金額(円)")
# uploaded は前のh3で client.files.upload() した画像
interaction = client.interactions.create(
model="gemini-3.8-flash",
input=[
{"type": "text", "text": "この領収書から項目を抽出してください。"},
{"type": "image", "uri": uploaded.uri, "mime_type": uploaded.mime_type},
],
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Receipt.model_json_schema(),
},
)
receipt = Receipt.model_validate_json(interaction.output_text) # 型の検証まで行う
print(receipt.total_yen)
スキーマの制約がすべて効くわけではありません。公式ページによると、minLength・maxLength・uniqueItemsなどは生成時に適用されず、エラーにもならずに無視されます。文字数の上限や重複の禁止は、受け取った後にPydanticの検証で確かめる対象です。入れ子が深すぎるスキーマは400 INVALID_ARGUMENTで拒否されるので、階層は浅く保ちます。
関数呼び出しをPythonで組む手順:ツール定義から結果の返却まで
関数呼び出し(Function Calling)は、在庫の照会や予約の登録のように、モデルの判断を受けて自社のシステムを動かす処理に使います。モデルが関数を実行するわけではありません。モデルは呼ぶべき関数名と引数を返すだけで、実行はPython側で行います。
toolsに関数宣言を渡しfunction_callの引数で実行する
関数呼び出しの公式ページの手順は、宣言を渡す、function_callのステップを受け取る、実行する、結果をfunction_resultで返す、の4段階です。次のコードは在庫照会の関数で、この流れを1つにまとめています。
import json
def get_stock(sku: str) -> dict:
"""自社の在庫DBを引く関数(ここではダミーの値を返す)"""
return {"sku": sku, "quantity": 12}
stock_tool = {
"type": "function",
"name": "get_stock",
"description": "商品コード(SKU)から現在の在庫数を返す",
"parameters": {
"type": "object",
"properties": {"sku": {"type": "string", "description": "商品コード"}},
"required": ["sku"],
},
}
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="商品A-100の在庫はありますか?",
tools=[stock_tool],
)
for step in interaction.steps or []:
if step.type == "function_call" and step.name == "get_stock":
result = get_stock(**step.arguments) # 実行はアプリ側
interaction = client.interactions.create(
model="gemini-3.8-flash",
input=[{
"type": "function_result",
"name": step.name,
"call_id": step.id, # どの呼び出しへの結果かを示す
"result": [{"type": "text", "text": json.dumps(result, ensure_ascii=False)}],
}],
tools=[stock_tool],
previous_interaction_id=interaction.id,
)
print(interaction.output_text)
モデルが返す引数は、そのまま信用しません。step.argumentsは宣言したスキーマに沿った値になりますが、存在しない商品コードや、権限のない利用者のデータを指す値も来ます。関数の入口で値の形式と利用者の権限を確かめてから、DBに問い合わせます。
自動関数呼び出しが未対応の現状と自前ループの利点・tool_choice指定
generate_contentには、Pythonの関数をそのままtoolsに渡すと実行と結果の返却までSDKが行う、自動関数呼び出しがあります。概要ページによると、この機能はInteractions APIではまだ使えません。前のh3のように、実行と返却のループを自分で書きます。
手間は増えますが、業務システムではこの方が扱いやすい場面が多くあります。関数を呼ぶ前に権限を確かめる、実行の記録を監査ログに残す、更新系の関数だけ人の承認を挟む、といった処理をループの中に差し込めるからです。必ず関数を呼ばせたいときはgeneration_config={"tool_choice": "any"}を指定します。
本番で詰まるgoogle-genai 3.0.0の変更点とエラー・再試行の扱い
手元で動いたコードが、サーバーに載せた途端に止まる原因の多くは、SDKの版の違いとエラー処理です。3.0.0は破壊的変更を含む大きな版上げなので、既存の環境を更新する前に確認します。
3.0.0でAPIの既定がv1・HTTPクライアントがhttpx2に変わった影響と戻し方
SDKのCHANGELOGによると、3.0.0の破壊的変更は2つです。Gemini Developer APIへの既定の接続先がv1betaからv1に変わり、HTTPクライアントがhttpxからhttpx2に変わりました。httpxは既定では入らなくなり、SSL証明書の検証にはOSの証明書ストアを使います。
影響が出やすいのは2つの場面です。ベータ版でだけ提供されている機能を呼んでいるコードと、社内プロキシの独自の証明書やhttpx.Clientを直接渡しているコードです。止まった場合は、次の環境変数で以前の挙動に戻してから原因を調べます。
# Developer API でも v1beta を使う(Agent Platform 側は v1beta1 になる)
export GOOGLE_GENAI_API_VERSION=beta
# 従来の httpx に戻す(先に pip install "google-genai[httpx]" が必要)
export GOOGLE_GENAI_HTTP_CLIENT=httpx
どちらも暫定の回避策です。戻したまま放置せず、ベータ版の機能に依存している箇所を洗い出して、v1で動く書き方に直します。
errors.APIErrorの捕捉とSDKの自動再試行に任せる範囲
トラブルシューティングの公式ページによると、Python SDKは429と5xxのエラーを、初回約1秒・最大60秒の間隔をあけて最大4回まで自動で再試行します。アプリ側でも同じ再試行を重ねると、1回の失敗が十数回の呼び出しに膨らみかねません。アプリ側では、再試行を使い切った後の失敗だけを扱います。
from google.genai import errors
try:
interaction = client.interactions.create(model="gemini-3.8-flash", input="こんにちは")
except errors.APIError as e:
if e.code in (400, 402, 403):
# 入力・残高・キーの問題。再試行しても直らないので記録して止める
raise
# 429・5xx はSDKが再試行した後の失敗。キューに戻すなど後で処理する
print("一時的な失敗:", e.code, e.message)
公式ページは、400・402・403を再試行しないよう求めています。402はPrepayの残高切れ、403はキーやプロジェクトの権限の問題で、時間を置いても結果は変わりません。夜間バッチで402を再試行し続け、朝まで同じエラーを出し続けるような運用は避けます。
PythonでGemini APIを直接書く範囲と外部へ任せる範囲の判断基準
ここまでのコードで、社内ツールの試作や小さな自動化は組めます。本番の業務システムに組み込む段階で、どこまで自前で書くかを決めておきます。
Developer APIのPython実装で進めてよい条件と見送る条件
APIキーで呼ぶDeveloper APIのままで進めてよいのは、利用者が社内に限られ、扱うデータが公開情報か社内の一般的な文書にとどまる場合です。キーの管理と上の再試行の方針が決まっていれば、PythonのスクリプトやFastAPIのサーバーから直接呼んで問題ありません。
次のどれかに当たるなら、Developer APIのままでは進めません。顧客との契約で可用性やデータの処理場所を約束する。Google Cloudの権限管理で呼び出し元を絞りたい。監査でアクセスの記録を求められる。この場合の呼び出し先はVertex AI(現Gemini Enterprise Agent Platform)です。google-genaiなら同じコードのまま接続先だけを切り替えられ、違いはVertex AIとGemini APIの違い:認証・SLA・データ保存・所在地・料金を比較で整理しています。Go言語で書く場合はGoでGemini APIを使う実装手順が対応します。
業務システムへのGemini組み込みを内製せず外部の開発会社に任せる判断
本番で必要になるのは、Gemini APIの呼び出しコードだけではありません。関数呼び出しの権限チェック、構造化出力の検証、保存設定、版の固定と更新の手順、エラー時のキューと再処理が一式で要ります。3.0.0のような破壊的変更を含む版上げは今後も起きる前提で、更新を検証する担当が要ります。
社内にPythonで業務システムを保守できる担当がいなければ、呼び出し部分だけを内製し、残りを外部に任せる方が早く安定します。既存の業務システムにGeminiを組み込む設計と実装は、一創の生成AI開発・AI受託開発で要件整理から相談を受けています。
Gemini APIをPythonで使うときのよくある質問と回答
PythonでGemini APIを使い始めるときに検索の多い質問に、公式ドキュメントとSDKの記述をもとに答えます。
Gemini APIはPythonから無料で使えますか?
使えます。Google AI Studioで発行したAPIキーを、課金を設定していないプロジェクトで使えば無料枠で呼べます。無料枠にはモデルごとのレート制限があり、送った入力と出力はGoogleの製品改善に使われる扱いです。Interactions APIの保存期間も無料枠は1日です。顧客のデータを送る処理は、課金を設定した有料枠のプロジェクトで動かしてください。
google-generativeaiとgoogle-genaiはどちらを使えばよいですか?
google-genaiを使います。google-generativeaiは旧SDKで、公式のライブラリ一覧では2025年11月30日に非推奨となり、保守も止まっています。Interactions APIや新しいモデルの機能は使えません。import google.generativeai as genaiで始まるサンプルは旧SDKなので、from google import genaiの書き方に読み替えてください。
Python 3.10の環境ではgoogle-genaiを使えませんか?
3.0.0以降は入りません。3.0.0の動作要件はPython 3.11以上で、3.10では2.33.0(2026年10月23日公開)が最後の対応版です。2.33.0でもInteractions APIは使えますが、今後の機能追加と修正は3.x系に入ります。業務で使うなら、Python本体を3.11以上に上げてから導入してください。
temperatureを指定しても出力が変わらないのはなぜですか?
Gemini 4とGemini 3.6以降のモデルが、temperature・top_p・top_kの値を無視するためです。テキスト生成の公式ページは、これらの指定を削除するよう案内しています。出力を安定させたいときは、指示文で形式と長さを具体的に指定するか、response_formatでJSONのスキーマを渡してください。
どのモデルIDを指定すればよいですか?
2026年11月時点の公式ドキュメントのコード例は、ほぼすべてgemini-3.8-flashを使っています。速さと費用の釣り合いがよく、まずはこれで動かして、精度が足りない処理だけ上位のモデルに替えるのが手堅い進め方です。各モデルの差分はGemini 3.8 Flashとは?3.7からの差分・料金・移行コードで確認できます。
関連記事
- Gemini APIとは?できること・料金・始め方とInteractions APIの最小コード【2026年10月】:本記事の親。APIの全体像とできること。
- Google Gen AI SDKとは?google-genaiの導入とAgent Platform切替・旧SDK移行【2026年10月】:SDKの位置づけと旧SDKからの書き換え。
- Gemini APIキーの取得方法:AI Studioでの発行・環境変数・制限と漏洩時の失効【2026年10月】:Pythonから呼ぶ前のキーの発行と管理。
- GoでGemini APIを使う実装手順|SDK v1.77・Interactions API・エンドポイントURL:同じ処理をGo言語で書く場合。
- Gemini API CLIとは?gemini-apiの導入・使い方とGemini CLIとの違い【2026年11月】:コードを書かずにコマンドラインから試す方法。