Gemini API を使っていると「なぜかこの時間帯だけ遅い」「同じコードなのにタイムアウトが出る日と出ない日がある」という状況に遭遇することがあります。レスポンス速度の問題は原因が複数絡んでいることが多く、どこから手をつければいいかわからなくなりがちです。
遅延とタイムアウトを引き起こす原因を4つのカテゴリに整理し、それぞれの診断方法と対処法をまとめます。
原因カテゴリ1: モデルが過負荷状態
Gemini API では、特定の時間帯や特定のモデルに高い負荷がかかっている場合、"this model is overloaded right now" というエラーや、応答速度の大幅な低下が起きることがあります。
診断方法: エラーメッセージに overloaded が含まれているか確認します。また、同じリクエストを別のモデル(例: Gemini 3.1 Pro の代わりに Gemini 3.1 Flash)で試して速度が改善するか確認します。
対処法: エクスポネンシャルバックオフ付きのリトライ実装が有効です。
import google.generativeai as genai
import time
import random
genai.configure(api_key="YOUR_GEMINI_API_KEY")
def call_with_retry(model, prompt: str, max_retries: int = 5):
"""エクスポネンシャルバックオフでリトライするAPI呼び出し"""
for attempt in range(max_retries):
try:
response = model.generate_content(prompt)
return response
except Exception as e:
error_msg = str(e).lower()
# 過負荷・レート制限・サービス利用不可の場合はリトライ
if any(word in error_msg for word in ["overloaded", "quota", "503", "429"]):
wait_time = (2 ** attempt) + random.uniform(0, 1)
print(f"リトライ待機: {wait_time:.1f}秒 (試行 {attempt + 1}/{max_retries})")
time.sleep(wait_time)
else:
raise # リトライ対象外のエラーは即座に再スロー
raise Exception(f"{max_retries}回のリトライがすべて失敗しました")
model = genai.GenerativeModel("gemini-3.1-flash") # Flashは過負荷になりにくい
result = call_with_retry(model, "あなたのプロンプトをここに")原因カテゴリ2: リクエスト設計の問題
API が遅い場合、モデル側ではなくリクエストの設計自体に問題があることがあります。
max_output_tokens が不必要に大きい
max_output_tokens を大きくするほど、モデルは「最大限まで出力しようとする」可能性があり、実際の出力が短くてもレスポンスが遅くなることがあります。実際に必要な出力量に合わせた値を設定してください。
# ❌ 不必要に大きな値
config = {"max_output_tokens": 8192}
# ✅ 用途に合わせた値
config_short = {"max_output_tokens": 512} # 短い回答・分類タスク
config_medium = {"max_output_tokens": 2048} # 通常の説明・要約
config_long = {"max_output_tokens": 8192} # 長文生成・詳細な技術記事ストリーミングを使っていない
長い出力が必要な場合、ストリーミングを使うと「最初の文字が表示されるまでの時間(Time to First Token)」を大幅に短縮できます。ユーザーに応答を見せるUI では、ストリーミングが体験を大きく改善します。
model = genai.GenerativeModel("gemini-3.1-pro")
# ストリーミングで応答を受け取る
for chunk in model.generate_content("長い記事を書いてください", stream=True):
print(chunk.text, end="", flush=True)
print() # 最後に改行原因カテゴリ3: クォータ制限
Gemini API には分間・日間のリクエスト上限があります。上限に達した場合、429 Too Many Requests エラーか、応答速度の著しい低下が起きます。
診断方法: Google AI Studio のダッシュボード(aistudio.google.com)でクォータ使用量を確認します。
import time
class RateLimitedAPIClient:
"""クォータ制限を考慮したAPIクライアント"""
def __init__(self, requests_per_minute: int = 60):
self.rpm_limit = requests_per_minute
self.min_interval = 60.0 / requests_per_minute
self.last_request_time = 0.0
def call(self, model, prompt: str):
# 前回のリクエストから必要な間隔を空ける
elapsed = time.time() - self.last_request_time
if elapsed < self.min_interval:
time.sleep(self.min_interval - elapsed)
self.last_request_time = time.time()
return model.generate_content(prompt)
client = RateLimitedAPIClient(requests_per_minute=30) # 余裕を持って設定原因カテゴリ4: ネットワーク・リージョンの問題
Gemini API は Google のグローバルインフラ上で動いていますが、アクセス元のリージョンによってレイテンシが変わります。日本からアクセスする場合、us-central1 ではなく asia-northeast1(東京)のエンドポイントを使うことで遅延を改善できる場合があります。
また、プロキシや VPN を経由している環境では、それが原因でレイテンシが増加していることもあります。
診断コード: シンプルなレイテンシ計測をしてみましょう。
import time
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-3.1-flash")
# レイテンシを計測する
times = []
for i in range(5):
start = time.time()
model.generate_content("「はい」とだけ返してください")
elapsed = time.time() - start
times.append(elapsed)
print(f"試行 {i+1}: {elapsed:.2f}秒")
print(f"\n平均: {sum(times)/len(times):.2f}秒")
print(f"最大: {max(times):.2f}秒")このテストで平均が 3 秒を超えていれば、ネットワーク経路かモデルの過負荷が原因の可能性が高いです。1 秒以内であれば、遅いのはあなたのコードの他の部分かもしれません。
素早い診断フロー
遅延の問題に当たったときの確認順序はこうです。
まず google ai studio でモデルのステータスを確認します。ダッシュボード上に過負荷の表示があれば、リトライ実装で対処します。次にクォータ使用量を確認し、上限に近ければリクエスト間隔を広げます。それでも遅ければ、上記の計測コードで実際のレイテンシを数値化してから原因を絞り込む——この順序が効率的です。
遅延の問題のほとんどは、リトライ実装の導入とストリーミングへの切り替えで体感が大きく改善します。まずこの 2 つを試してみてください。
最初に確認すべきこと
ネットワーク遅延の測定
まず、ネットワーク層の遅延を測定します:
import time
import google.generativeai as genai
api_key = "YOUR_GEMINI_API_KEY"
genai.configure(api_key=api_key)
# 簡単なテスト実行
start = time.time()
model = genai.GenerativeModel("gemini-2.5-flash")
response = model.generate_content("こんにちは")
latency = time.time() - start
print(f"総レスポンス時間: {latency:.2f}秒")
print(f"テキスト: {response.text[:50]}")レスポンス時間が 2〜3秒なら問題ありません。5秒以上の場合は以下の対処が必要です。
APIキーのリージョン確認
特定のリージョンで利用すると、地理的な距離の影響を受けます:
- 日本から呼び出す場合:
asia-southeast1(シンガポール)が最短 - 米国から呼び出す場合:
us-central1(アイオワ)が最短
import vertexai
from vertexai.generative_models import GenerativeModel
# asia-southeast1 で最短レスポンス
vertexai.init(project="YOUR_PROJECT", location="asia-southeast1")
model = GenerativeModel("gemini-2.5-pro")
response = model.generate_content("テスト")モデル選択による最適化
Gemini には複数のモデルがあり、モデルごとにレスポンス速度が異なります。
レスポンス速度の比較
| モデル | 推論速度 | 用途 |
|---|---|---|
| Gemini Flash Lite | 最速(50ms前後) | リアルタイムアプリ |
| Gemini Flash | 高速(100-200ms) | チャット、軽い処理 |
| Gemini Pro | 中速(500ms-1秒) | 複雑な推論 |
| Gemini Deep Think | 遅い(5-30秒) | 深い思考が必要 |
高速化のルール: タスクに応じて最速のモデルを選ぶ
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
# ❌ 遅い: すべてに Gemini Pro を使う
model = genai.GenerativeModel("gemini-2.5-pro")
# ✅ 高速: タスク別にモデルを切り替える
def classify_sentiment(text):
# 軽いタスク → Flash Lite
model = genai.GenerativeModel("gemini-2.5-flash-lite")
response = model.generate_content(f"テキストの感情を判定: {text}")
return response.text
def analyze_document(text):
# 複雑なタスク → Pro
model = genai.GenerativeModel("gemini-2.5-pro")
response = model.generate_content(f"詳細分析: {text}")
return response.textトークン数と処理時間の関係
入力トークン数が多いほど、レスポンス時間は長くなります。
トークン数の測定と最適化
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-pro")
# トークン数を事前に測定
def count_tokens(text):
response = model.count_tokens(text)
return response.total_tokens
# 長いテキストの場合
long_text = "..." * 1000 # 大量のテキスト
tokens = count_tokens(long_text)
print(f"トークン数: {tokens}")
# 最適化: 不要な部分を削除
def optimize_input(text):
# 余分な空行、コメント、メタデータを削除
lines = [l.strip() for l in text.split('\n') if l.strip()]
return '\n'.join(lines)
optimized = optimize_input(long_text)
optimized_tokens = count_tokens(optimized)
print(f"最適化後: {optimized_tokens}トークン(削減: {tokens - optimized_tokens})")トークン削減のテクニック
1. 不要なコンテンツの削除
# ❌ 不要: HTMLタグ、CSSコード、コメント全てを含める
html_content = "<html><head>...</head><body>...</body></html>"
# ✅ 効率的: テキスト本文のみ抽出
from html.parser import HTMLParser
class TextExtractor(HTMLParser):
def __init__(self):
super().__init__()
self.text = []
def handle_data(self, data):
self.text.append(data.strip())
def get_text(self):
return " ".join(self.text)
extractor = TextExtractor()
extractor.feed(html_content)
clean_text = extractor.get_text()2. キャッシング戦略
import json
from datetime import datetime, timedelta
# 簡単なキャッシュ実装
cache = {}
def cached_generate(prompt, model_name="gemini-2.5-flash"):
cache_key = f"{model_name}:{hash(prompt)}"
# キャッシュをチェック(24時間有効)
if cache_key in cache:
entry = cache[cache_key]
if datetime.now() - entry["timestamp"] < timedelta(hours=24):
return entry["response"]
# キャッシュミス: APIを呼び出し
model = genai.GenerativeModel(model_name)
response = model.generate_content(prompt)
# 結果をキャッシュ
cache[cache_key] = {
"response": response.text,
"timestamp": datetime.now()
}
return response.textストリーミングによる応答時間の改善
ストリーミングを有効にすると、完全な結果を待たずに部分的なレスポンスを即座に受け取れます。これはユーザー体験を大幅に向上させます。
ストリーミング実装
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-pro")
# ❌ 非ストリーミング: すべての結果を待つ
response = model.generate_content("長い記事を生成してください")
print(response.text)
# ✅ ストリーミング: リアルタイムで結果を表示
print("生成中: ", end="", flush=True)
for chunk in model.generate_content("長い記事を生成してください", stream=True):
print(chunk.text, end="", flush=True)
print("\n完了")ストリーミングのベストプラクティス
import asyncio
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
async def stream_to_user():
"""ストリーミングレスポンスをWebsocket経由でユーザーに配信"""
model = genai.GenerativeModel("gemini-2.5-pro")
prompt = "Pythonの非同期処理について詳しく説明してください"
for chunk in model.generate_content(prompt, stream=True):
# JSONフォーマットで送信
message = {
"type": "stream_chunk",
"text": chunk.text,
"timestamp": str(datetime.now())
}
await websocket.send_json(message)
# 次のチャンク受信前に小休止(ユーザーが読む時間を確保)
await asyncio.sleep(0.01)
# 完了通知
await websocket.send_json({"type": "stream_end"})バッチ処理による効率化
複数のリクエストを連続で処理する場合、バッチAPIを使用すると効率が向上します。
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY")
model = genai.GenerativeModel("gemini-2.5-pro")
# バッチ処理: 複数のテキストを一括処理
texts = [
"りんごについて説明してください",
"みかんについて説明してください",
"バナナについて説明してください"
]
# ❌ 遅い: 順序実行(3回のAPIコール)
results = []
for text in texts:
response = model.generate_content(text)
results.append(response.text)
# ✅ 高速: 並列実行(最大5個同時)
import concurrent.futures
def process_text(text):
response = model.generate_content(text)
return response.text
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
results = list(executor.map(process_text, texts))タイムアウト設定の調整
ネットワークタイムアウトが短すぎる場合、本来成功するリクエストが失敗します。
import google.api_core.gapic_v1.client_info as grpc_client_info
from google.generativeai import client_options
# タイムアウトを 60 秒に設定
options = client_options.ClientOptions(
api_endpoint="generativelanguage.googleapis.com"
)
import google.generativeai as genai
genai.configure(api_key="YOUR_GEMINI_API_KEY", client_options=options)
# リトライロジック付きのラッパー
import time
def generate_with_retry(prompt, max_retries=3, timeout_seconds=30):
model = genai.GenerativeModel("gemini-2.5-pro")
for attempt in range(max_retries):
try:
response = model.generate_content(prompt)
return response.text
except Exception as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt # 指数バックオフ
print(f"失敗({attempt + 1}回目). {wait_time}秒待機後、再試行...")
time.sleep(wait_time)
else:
print(f"最大リトライ回数に達しました")
raise全体を振り返って
Gemini API のレスポンス遅延を解決するには:
- モデル選択を最適化 — タスクに最速のモデルを選ぶ
- 入力トークン数を削減 — 不要なコンテンツを削除
- ストリーミング有効化 — リアルタイムでチャンク配信
- バッチ処理で並列化 — 複数リクエストを同時実行
- リージョン選択 — 地理的に最短拠点を選ぶ
これらの施策により、ほとんどのレスポンス遅延を解決できます。