画像と動画と音声と PDF を、ひとつのリクエストにまとめて渡せる。Gemini 3.1 Pro のこの一点は、モダリティごとに別々のパイプラインを組んできた身からすると、設計の前提そのものを書き換えてしまいます。
とはいえ、混ぜれば動くという話でもありません。トークンの食い方も、精度の落ちどころも、モダリティごとに癖があります。本番で踏んだ実装レベルの勘所を集めました。
Part 1: 4つのモダリティの基礎実装
1. 画像処理の基礎
画像は最も基本的なモダリティです。URL ベース、ファイルベース、Base64 エンコードの3方式に対応しています。
import google.generativeai as genai
from pathlib import Path
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
# 方式1: ローカルファイル(推奨)
image_file = genai.upload_file(path="screenshot.png")
response = model.generate_content([
"このスクリーンショットの UI/UX 問題点を3つ指摘してください",
image_file
])
print(response.text)
# 出力例:
# 1. ボタンのコントラストが不十分です。WCAG AA基準に達していません
# 2. フォームラベルが左寄せで、入力フィールドから遠すぎます
# 3. エラーメッセージの文字色が赤のみで色覚多様性に非対応です
# ファイルのクリーンアップ
genai.delete_file(image_file.name)2. 動画処理の実装
動画処理は Gemini の最大の差別化機能です。制約として、最大 2 時間の動画に対応しています。
import google.generativeai as genai
import time
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
# 動画のアップロード(大容量ファイルはPOLLが必要)
video_file = genai.upload_file(path="youtube_video.mp4")
# ポーリングで処理完了を待機
print(f"ファイル状態: {video_file.state}")
while video_file.state.name == "PROCESSING":
time.sleep(2)
video_file = genai.get_file(video_file.name)
print(f" → {video_file.state.name}")
# 処理開始
response = model.generate_content([
"この動画の内容を:\n1. 5行で要約\n2. 主要なターニングポイント3つ\n3. 視聴者のターゲット層\nで分析してください",
video_file
])
print("=== 動画分析結果 ===")
print(response.text)
# クリーンアップ
genai.delete_file(video_file.name)3. 音声処理の詳細
音声ファイルは自動で文字起こしと内容理解が行われます。言語検出も自動です。
import google.generativeai as genai
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
# 音声ファイルのアップロード
audio_file = genai.upload_file(path="podcast_episode.mp3")
# 音声分析リクエスト
response = model.generate_content([
"""このポッドキャストについて以下を分析してください:
1. エピソードの概要(2段落)
2. 主な議論トピック(箇条書き5つ)
3. 出演者の主張の論理構成
4. 聴き手への実装可能なアクション3つ
""",
audio_file
])
print(response.text)
# 出力例:
# 【概要】
# このエピソードは AI と職業の未来について議論しています。
# ホストは3人のテック企業家をゲストに招待し、...
# 【議論トピック】
# - AI による雇用喪失の現実性
# - スキルのアップスケーリングの必要性
# ...4. PDF処理の実践
PDF は特に複雑な文書処理に活躍します。複数ページの自動分析が強力です。
import google.generativeai as genai
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
# PDF のアップロード
pdf_file = genai.upload_file(path="quarterly_report_2026.pdf")
# PDF 全体の分析
response = model.generate_content([
"""このレポートについて以下を提供してください(JSON形式):
{
"company": "企業名",
"period": "期間",
"revenue": "売上(数値のみ)",
"key_metrics": ["指標1", "指標2", ...],
"risks": ["リスク要因1", ...],
"future_outlook": "将来見通し(1段落)"
}
""",
pdf_file
])
import json
result = json.loads(response.text)
print(f"企業: {result['company']}")
print(f"売上: {result['revenue']}")
print(f"リスク: {result['risks']}")Part 2: ストリーミング対応マルチモーダルパイプライン
大量のマルチモーダルリクエストを処理する場合、ストリーミングは レスポンス時間を 40-60% 短縮 できます。
import google.generativeai as genai
import asyncio
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
async def stream_multimodal_analysis(image_path, video_path, prompt):
"""
マルチモーダルコンテンツをストリーミング処理
"""
# ファイルのアップロード
image = genai.upload_file(path=image_path)
video = genai.upload_file(path=video_path)
# ストリーミングリクエスト
response = await model.generate_content_async(
[prompt, image, video],
stream=True # ← 重要: ストリーミング有効化
)
# テキスト + メタデータをリアルタイム出力
full_response = ""
async for chunk in response:
text = chunk.text
print(text, end="", flush=True) # リアルタイム表示
full_response += text
# レート制限対策
await asyncio.sleep(0.01)
print() # 改行
# クリーンアップ
genai.delete_file(image.name)
genai.delete_file(video.name)
return full_response
# 実行例
prompt = """
このプレゼンテーション資料(画像)と実際の発表動画を分析して:
1. スライドの内容と発表内容の一貫性を評価
2. プレゼンテーションスキルの強み3つ
3. 改善提案3つ
を提示してください
"""
result = asyncio.run(stream_multimodal_analysis(
"slide.png",
"presentation.mp4",
prompt
))Part 3: Function Calling × マルチモーダルの統合
最も高度なテクニックは、Function Calling とマルチモーダル入力を組み合わせることです。これにより、AI が自動的に外部システムと連携できるようになります。
import google.generativeai as genai
import json
from datetime import datetime
genai.configure(api_key="YOUR_API_KEY")
# ステップ1: カスタム関数の定義
tools = [
{
"type": "function",
"function": {
"name": "save_document_analysis",
"description": "分析結果を DB に保存",
"parameters": {
"type": "object",
"properties": {
"document_id": {"type": "string"},
"summary": {"type": "string"},
"extracted_data": {"type": "object"},
"confidence_score": {"type": "number"}
},
"required": ["document_id", "summary", "extracted_data"]
}
}
},
{
"type": "function",
"function": {
"name": "send_alert",
"description": "重要度が高い場合はアラートを送信",
"parameters": {
"type": "object",
"properties": {
"severity": {"type": "string", "enum": ["low", "medium", "high"]},
"message": {"type": "string"}
},
"required": ["severity", "message"]
}
}
}
]
# ステップ2: マルチモーダル入力 + Function Calling
model = genai.GenerativeModel(
'gemini-3.1-pro',
tools=tools
)
# マルチモーダルコンテンツの準備
invoice_image = genai.upload_file(path="invoice.png")
invoice_pdf = genai.upload_file(path="invoice.pdf")
# AI の推論を実行
response = model.generate_content([
"""
この請求書(画像と PDF)を処理してください:
1. 請求者情報・品目・金額を抽出
2. 分析結果を DB に保存
3. 金額が ¥1,000,000 を超えていたらアラートを送信
""",
invoice_image,
invoice_pdf
])
# ステップ3: Function Call の結果を処理
if response.function_calls:
for function_call in response.function_calls:
func_name = function_call.name
args = function_call.args
print(f"🤖 AI が関数を呼び出しました: {func_name}")
print(f" パラメータ: {args}")
if func_name == "save_document_analysis":
# 実装例: DB に保存
print(f" → DB に保存: {args['document_id']}")
print(f" 要約: {args['summary']}")
print(f" 信頼度: {args['confidence_score']}")
elif func_name == "send_alert":
# 実装例: アラート送信
print(f" → ⚠️ アラート送信: {args['severity'].upper()}")
print(f" メッセージ: {args['message']}")
# クリーンアップ
genai.delete_file(invoice_image.name)
genai.delete_file(invoice_pdf.name)出力例:
🤖 AI が関数を呼び出しました: save_document_analysis
パラメータ: {'document_id': 'INV-2026-00145', 'summary': '株式会社 ABC から ...', ...}
→ DB に保存: INV-2026-00145
要約: 株式会社 ABC からのシステム開発費用請求書
信頼度: 0.96
🤖 AI が関数を呼び出しました: send_alert
パラメータ: {'severity': 'high', 'message': '請求金額が ¥1,500,000 で予算超過'}
→ ⚠️ アラート送信: HIGH
メッセージ: 請求金額が ¥1,500,000 で予算超過
Part 4: エラーハンドリングとレート制限対策
本番環境では、エラーハンドリングが不可欠です。
import google.generativeai as genai
import time
from typing import Optional
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
def process_multimodal_with_retry(
files: list,
prompt: str,
max_retries: int = 3,
backoff_factor: float = 2.0
) -> Optional[str]:
"""
リトライロジック付きマルチモーダル処理
"""
for attempt in range(max_retries):
try:
response = model.generate_content([prompt] + files)
# レート制限チェック
if hasattr(response, 'usage_metadata'):
print(f"トークン使用: {response.usage_metadata}")
return response.text
except genai.types.BlockedPromptException as e:
print(f"❌ ブロック: {e}")
return None
except genai.types.StopCandidateException as e:
print(f"⚠️ 中断: {e}")
return None
except Exception as e:
if attempt < max_retries - 1:
wait_time = 2 ** attempt * backoff_factor
print(f"⏳ リトライ({attempt + 1}/{max_retries}): {wait_time}秒待機")
time.sleep(wait_time)
else:
print(f"❌ 最終的に失敗: {e}")
return None
return None
# 使用例
files = [genai.upload_file(path="document.pdf")]
result = process_multimodal_with_retry(
files=files,
prompt="この文書を分析してください"
)
print(result)Part 5: パフォーマンス最適化とコスト削減
トークンカウントの活用
import google.generativeai as genai
genai.configure(api_key="YOUR_API_KEY")
model = genai.GenerativeModel('gemini-3.1-pro')
# 実際にリクエストする前にトークン数を推定
image = genai.upload_file(path="document.png")
token_count = model.count_tokens([
"この画像を詳細に分析してください",
image
])
print(f"推定トークン数: {token_count.total_tokens}")
print(f"入力: {token_count.prompt_tokens}, 出力: {token_count.candidates_tokens}")
# コスト計算(3.1 Pro: $0.0075/1K入力トークン)
estimated_cost = token_count.prompt_tokens * 0.0075 / 1000
print(f"推定コスト: ${estimated_cost:.4f}")バッチ処理でコスト 50% 削減
import google.generativeai as genai
genai.configure(api_key="YOUR_API_KEY")
# Batch API を使用(リアルタイム不要な場合)
requests = []
for i, (image_path, prompt) in enumerate([
("image1.png", "分析1"),
("image2.png", "分析2"),
]):
image = genai.upload_file(path=image_path)
requests.append({
"custom_id": f"request-{i}",
"generation_config": {"temperature": 1},
"safety_settings": [...],
"system_instruction": "You are ...",
"contents": [{
"role": "user",
"parts": [prompt, image]
}]
})
# バッチ投入(1回の処理で複数リクエスト)
# Batch API により、API コストが通常の 50% に削減されます
batch_response = genai.create_batch(requests=requests)
print(f"バッチID: {batch_response.name}")
print(f"ステータス: {batch_response.state}")まとめ
Gemini のマルチモーダル機能を最大活用するには:
- 4つのモダリティを統合する — 単一モダリティより明確に精度向上
- ストリーミングで高速化 — 40-60% のレスポンス短縮
- Function Calling で自動化 — AI が直接外部システムと連携
- エラーハンドリングで堅牢化 — 本番環境対応
- バッチ API でコスト削減 — API コストを 50% 圧縮
これらを組み合わせることで、単なる AI チャットボットではなく、本当の意味でビジネスに統合された AI システム が実現します。
個人開発の現場から — マルチモーダルは「入力の正規化」から
個人開発で Dolice Labs のアプリを回している私自身、Gemini で画像・動画・音声・PDF を混在して扱うとき、精度以前につまずいたのは入力フォーマットのばらつきでした。解像度や長さ、エンコードがまちまちのまま投げると、結果も安定しません。
私は前処理で、サイズ・長さ・形式を一定のレンジに正規化してから渡すようにしています。モデルの能力を引き出すより前に入力を整える——この一手間が、マルチモーダルでは精度とコストの両方に効いてくると感じています。
動画や長い音声では、丸ごと投げるより要点の区間を切り出して渡すほうが、精度もコストも良くなることが多いです。私はまず安価な方法で当たりをつけ、必要な区間だけ高精度に処理する二段構えにしています。全部を等しく丁寧に扱わないことが、現実的なコスト設計につながります。
出力側も、用途に合わせて構造化しておくと扱いが楽になります。私は抽出結果を必ず決まったスキーマに収め、後工程がモデルの自由文に振り回されないようにしています。入口と出口の両方を固定しておくのが、安定運用の近道だと感じています。
まとめ — 次のステップ
- 失敗パターンをまずログから抽出