GEMINI LABEN
NANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定ですNANOLITE — Nano Banana 2 Liteが登場しました。Googleで最も速く、最もコスト効率の高いGemini Imageモデルで、軽量な画像生成を安く回したい用途に向いていますOMNIFLASH — Gemini Omni Flashがpublic previewになりました。ネイティブにマルチモーダルなモデルで、企業や開発者が独自の動的な動画ワークフローを構築できますAGENTS — Managed Agentsが拡張されました。background: trueでサーバー側の非同期実行とポーリング、リモートMCPサーバー連携、対話をまたぐ認証情報のリフレッシュに対応しますMEMORY — Memory BankのIngestEvents APIが一般提供になりました。イベントの取り込みとメモリ生成を分離し、コンテンツを継続的にストリームできますTHROUGHPUT — Provisioned Throughputで、同一モデル・同一リージョンに対して最大7件の保留オーダーを提出できるようになりましたDEPRECATE — 画像生成モデルは8月17日に、Gemini Enterprise Agent PlatformのGrok 4.1系は8月20日に停止される予定です
記事一覧/API / SDK
API / SDK/2026-03-30初級

Gemini API × Python でテキスト分類・感情分析を実装する

Gemini API と Python を使ってテキスト分類や感情分析を実装する方法を解説。Structured Output でラベル付け精度を高め、カスタマーレビューやSNS投稿の自動仕分けを実現します。

gemini-api279python103テキスト分類感情分析2structured-output20自然言語処理2

テキスト分類と感情分析が求められる場面

ECサイトのカスタマーレビュー、SNS上のブランド言及、問い合わせメールの仕分け——。テキストデータを自動でカテゴリ分けし、感情の傾向を把握したい場面は増える一方です。従来は専用の NLP モデルを学習させる必要がありましたが、Gemini API の Structured Output を組み合わせると、学習データなしでも高精度なテキスト分類・感情分析パイプラインを Python で素早く構築できます。

環境準備と Gemini API キーの取得

まず、Python 環境と Gemini API キーを用意します。

API キーの取得

  1. Google AI Studio にアクセスします
  2. 左メニューから「Get API key」をクリックします
  3. 新しいプロジェクトを作成するか、既存のプロジェクトを選択して API キーを発行します

Python パッケージのインストール

pip install google-genai

接続テスト

from google import genai
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents="こんにちは、Gemini!テスト応答を返してください。"
)
print(response.text)
# 期待出力例: こんにちは!テスト応答です。何かお手伝いできることはありますか?

API キーが正しく設定されていれば、Gemini からの応答が表示されます。

Structured Output でテキスト分類を実装する

Gemini API の Structured Output(JSON スキーマ応答)を使うと、分類ラベルを厳密な形式で受け取れます。自由文ではなく構造化されたデータが返るため、後続処理に直接渡せる点が大きなメリットです。

分類スキーマの定義

from google import genai
from pydantic import BaseModel, Field
from enum import Enum
from typing import Optional
 
class Category(str, Enum):
    PRODUCT_QUALITY = "product_quality"
    SHIPPING = "shipping"
    CUSTOMER_SERVICE = "customer_service"
    PRICING = "pricing"
    OTHER = "other"
 
class Sentiment(str, Enum):
    POSITIVE = "positive"
    NEUTRAL = "neutral"
    NEGATIVE = "negative"
 
class TextClassification(BaseModel):
    category: Category = Field(description="テキストの主要カテゴリ")
    sentiment: Sentiment = Field(description="テキストの感情極性")
    confidence: float = Field(description="分類の確信度(0.0〜1.0)", ge=0.0, le=1.0)
    keywords: list[str] = Field(description="テキストから抽出した主要キーワード(最大5つ)")
    summary: str = Field(description="テキストの1行要約")

Pydantic モデルでスキーマを定義し、CategorySentiment を Enum で固定することで、返却されるラベルが予期しない値になることを防ぎます。

単一テキストの分類

client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
review = "注文から2日で届きました。梱包も丁寧で、商品の品質も期待通りです。ただ、説明書が英語のみだったのが少し残念でした。"
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=f"""以下のカスタマーレビューを分析してください。
 
レビュー: {review}
 
カテゴリ、感情、確信度、キーワード、要約を返してください。""",
    config={
        "response_mime_type": "application/json",
        "response_schema": TextClassification,
    }
)
 
result = TextClassification.model_validate_json(response.text)
print(f"カテゴリ: {result.category.value}")
print(f"感情: {result.sentiment.value}")
print(f"確信度: {result.confidence}")
print(f"キーワード: {result.keywords}")
print(f"要約: {result.summary}")
 
# 期待出力例:
# カテゴリ: product_quality
# 感情: positive
# 確信度: 0.82
# キーワード: ['梱包', '品質', '配送', '説明書', '英語']
# 要約: 商品品質と配送は良好だが、説明書が英語のみで改善の余地あり

response_schema に Pydantic モデルを渡すだけで、Gemini が指定した JSON 形式で応答を返します。パースエラーを気にする必要がないため、後続のデータ処理がシンプルになります。

バッチ処理で大量テキストを一括分類する

実務では、数百〜数千件のレビューを一度に処理したい場面があります。ループ処理にリトライロジックを加えた実装を見てみましょう。

import time
from google import genai
from google.genai.errors import ClientError
 
client = genai.Client(api_key="YOUR_GEMINI_API_KEY")
 
reviews = [
    "商品自体は素晴らしいのですが、配送に1週間以上かかりました。",
    "カスタマーサポートの対応がとても親切で感動しました。",
    "この価格帯でこの品質は正直驚きです。コスパ最高。",
    "届いた商品が写真と全く違いました。返品手続きも面倒です。",
    "普通に使えています。特に不満はありません。",
]
 
def classify_review(review_text: str, max_retries: int = 3) -> Optional[TextClassification]:
    """レビューを分類する(リトライ付き)"""
    for attempt in range(max_retries):
        try:
            response = client.models.generate_content(
                model="gemini-2.5-flash",
                contents=f"以下のカスタマーレビューを分析してください。\n\nレビュー: {review_text}",
                config={
                    "response_mime_type": "application/json",
                    "response_schema": TextClassification,
                }
            )
            return TextClassification.model_validate_json(response.text)
        except ClientError as e:
            if "429" in str(e):
                wait = 2 ** attempt
                print(f"レート制限に到達。{wait}秒後にリトライします...")
                time.sleep(wait)
            else:
                print(f"エラー: {e}")
                return None
    return None
 
# バッチ実行
results = []
for i, review in enumerate(reviews):
    print(f"処理中: {i + 1}/{len(reviews)}")
    result = classify_review(review)
    if result:
        results.append({"review": review, "classification": result})
    time.sleep(0.5)  # レート制限を考慮した間隔
 
# 結果の集計
from collections import Counter
 
sentiment_counts = Counter(r["classification"].sentiment.value for r in results)
category_counts = Counter(r["classification"].category.value for r in results)
 
print(f"\n--- 感情分布 ---")
for sentiment, count in sentiment_counts.most_common():
    print(f"  {sentiment}: {count}件")
 
print(f"\n--- カテゴリ分布 ---")
for category, count in category_counts.most_common():
    print(f"  {category}: {count}件")
 
# 期待出力例:
# --- 感情分布 ---
#   positive: 2件
#   negative: 2件
#   neutral: 1件
# --- カテゴリ分布 ---
#   shipping: 1件
#   customer_service: 1件
#   pricing: 1件
#   product_quality: 2件

ポイントは time.sleep(0.5) でリクエスト間隔を空けることと、429 エラー時に指数バックオフでリトライすることです。大量データを処理する場合は、さらに Gemini API 本番環境パイプラインアーキテクチャ で解説しているバッチ API の活用も検討してみてください。

多言語テキストの感情分析

Gemini はマルチリンガル対応のため、日本語・英語・中国語など複数言語のテキストを同じパイプラインで処理できます。

class MultilingualAnalysis(BaseModel):
    detected_language: str = Field(description="検出された言語コード(ja, en, zh など)")
    sentiment: Sentiment
    confidence: float = Field(ge=0.0, le=1.0)
    translated_summary: str = Field(description="日本語での1行要約")
 
multilingual_texts = [
    "This product exceeded my expectations! Highly recommended.",
    "配送が遅すぎます。二度と利用しません。",
    "产品质量一般,但价格很合理。",
]
 
for text in multilingual_texts:
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=f"以下のテキストを分析してください。言語を検出し、感情を判定してください。\n\nテキスト: {text}",
        config={
            "response_mime_type": "application/json",
            "response_schema": MultilingualAnalysis,
        }
    )
    result = MultilingualAnalysis.model_validate_json(response.text)
    print(f"言語: {result.detected_language} | 感情: {result.sentiment.value} | 要約: {result.translated_summary}")
 
# 期待出力例:
# 言語: en | 感情: positive | 要約: 期待を超える商品品質で強く推奨
# 言語: ja | 感情: negative | 要約: 配送遅延への強い不満
# 言語: zh | 感情: neutral | 要約: 品質は普通だが価格は妥当

言語ごとにモデルを切り替える必要がなく、1 つのプロンプトで多言語対応できるのが Gemini の強みです。

カスタムカテゴリで柔軟に分類する

ビジネスの要件に合わせて分類カテゴリを自由にカスタマイズできます。問い合わせメールの自動振り分けを例に見てみましょう。

class TicketPriority(str, Enum):
    URGENT = "urgent"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
 
class TicketCategory(str, Enum):
    BUG_REPORT = "bug_report"
    FEATURE_REQUEST = "feature_request"
    BILLING = "billing"
    ACCOUNT = "account"
    GENERAL = "general"
 
class SupportTicket(BaseModel):
    category: TicketCategory
    priority: TicketPriority
    sentiment: Sentiment
    requires_human: bool = Field(description="人間のオペレーターへのエスカレーションが必要か")
    suggested_response: str = Field(description="推奨される初回応答文(50文字以内)")
 
ticket_text = "ログインできなくなりました。パスワードリセットのメールも届きません。急ぎで対応してほしいです。"
 
response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=f"""以下のサポート問い合わせを分析し、カテゴリ・優先度・感情・エスカレーション要否・推奨応答を判定してください。
 
問い合わせ: {ticket_text}""",
    config={
        "response_mime_type": "application/json",
        "response_schema": SupportTicket,
    }
)
 
ticket = SupportTicket.model_validate_json(response.text)
print(f"カテゴリ: {ticket.category.value}")
print(f"優先度: {ticket.priority.value}")
print(f"感情: {ticket.sentiment.value}")
print(f"エスカレーション: {'必要' if ticket.requires_human else '不要'}")
print(f"推奨応答: {ticket.suggested_response}")
 
# 期待出力例:
# カテゴリ: account
# 優先度: urgent
# 感情: negative
# エスカレーション: 必要
# 推奨応答: ログインの件、早急に確認いたします。担当者より折り返しご連絡します。

requires_human フィールドを追加することで、自動応答で済む問い合わせと人間の対応が必要な問い合わせを自動で仕分けできます。

精度を高めるプロンプト設計のコツ

テキスト分類の精度は、プロンプトの書き方に大きく左右されます。以下のテクニックを活用してください。

System Instruction の活用

response = client.models.generate_content(
    model="gemini-2.5-flash",
    contents=review_text,
    config={
        "system_instruction": """あなたはテキスト分類の専門家です。
以下のルールに従って分類してください:
- 複数のカテゴリに該当する場合は、最も顕著なものを1つ選ぶ
- 確信度は慎重に設定する(0.9以上は明確な場合のみ)
- 皮肉や反語表現に注意する(例:「素晴らしいですね(笑)」は negative)
- 顔文字・絵文字も感情判定の手がかりにする""",
        "response_mime_type": "application/json",
        "response_schema": TextClassification,
    }
)

Few-shot 例の追加

few_shot_prompt = """以下のレビューを分類してください。
 
## 分類例
レビュー: 「最高の商品です!」→ category: product_quality, sentiment: positive, confidence: 0.95
レビュー: 「まあ普通かな」→ category: product_quality, sentiment: neutral, confidence: 0.70
レビュー: 「返金してほしい」→ category: billing, sentiment: negative, confidence: 0.90
 
## 分類対象
レビュー: {review_text}"""

Few-shot 例を 2〜3 個追加するだけで、境界線上のケース(ポジティブ寄りのニュートラルなど)の判定精度が向上します。Structured Output の詳しい設定方法については Gemini API の JSON Mode と構造化出力ガイド も参考にしてください。

全体を振り返って

Gemini API の Structured Output を活用すると、学習データなしでテキスト分類・感情分析パイプラインを短時間で構築できます。Pydantic モデルでスキーマを定義し、Enum でカテゴリと感情ラベルを固定することで、安定した分類結果を得られるのがポイントです。

今回紹介したパターンは、カスタマーレビューの分析だけでなく、問い合わせメールの振り分け、SNS モニタリング、アンケート集計など、幅広い用途に応用できます。まずは Gemini API クイックスタートガイド で API キーを発行し、小さなデータセットから試してみてください。

シェア

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

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

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

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

関連記事

API / SDK2026-07-13
responseSchema で $ref が使えず詰まったら — responseJsonSchema で再帰スキーマを本番で扱う
Gemini の responseSchema は OpenAPI サブセットで $ref/$defs が使えず、共有定義も再帰も表現できません。responseJsonSchema へ移行し、多言語フィールドの再利用とカテゴリ木の再帰を本番で扱う実装をまとめました。
API / SDK2026-05-16
Firebase Crashlytics のクラッシュログを Gemini API で自動分析した記録 — 個人開発アプリ v2.1.0 での実証
Firebase Crashlytics の生ログを Gemini API に渡して根本原因とコード修正案を自動生成するパイプラインを、個人開発の壁紙アプリ v2.1.0 の実開発で検証した記録です。RecyclerView クラッシュの Before/After 付き。
API / SDK2026-05-03
問い合わせフォームの対応を Gemini API で自動化する — 分類・優先度付け・Slack 通知まで
Gemini API を使って問い合わせフォームの内容を自動分類・優先度付けし、Slack に通知するシステムを Python で作る方法を解説。コード付きで今日から使えます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →