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-05-03中級

問い合わせフォームの対応を Gemini API で自動化する — 分類・優先度付け・Slack 通知まで

Gemini API を使って問い合わせフォームの内容を自動分類・優先度付けし、Slack に通知するシステムを Python で作る方法を解説。コード付きで今日から使えます。

gemini-api279python103automation34slack3structured-output20

一人でサービスやアプリを運営していると、問い合わせへの対応が思った以上に時間を奪っていることに気づきます。

「バグ報告なのか、機能要望なのか、それとも単純な使い方の質問なのか」を読んで判断して、緊急度を考えて、場合によっては別の担当に回す。一件一件は5分もかからない作業ですが、積み重なると午前中があっという間に消えていきます。

Gemini API を使えば、この分類・優先度付け作業を自動化できます。フォームから送られてきた問い合わせを Gemini API で解析し、Slack に整理された形で通知するシステムを Python で作る手順を順番にご紹介します。

作るものの全体像

システムの流れはシンプルです。

  • フォームから問い合わせが届く
  • Python スクリプトが Gemini API に内容を送る
  • Gemini API がカテゴリ分類・優先度スコアを JSON で返す
  • 結果を Slack の指定チャンネルに通知する

特別なインフラは不要です。Python と Gemini API キー、Slack の Webhook URL があれば今日から動かせます。既存のフォームツール(Google フォーム、Typeform、自作のお問い合わせページ)に関係なく導入できます。

環境の準備

必要なパッケージをインストールします。

pip install google-genai requests

環境変数を設定します。

export GEMINI_API_KEY="YOUR_GEMINI_API_KEY"
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

Gemini API キーは Google AI Studio から無料で取得できます。API の基本的な使い方については Gemini API クイックスタート も参考にしてください。

Slack の Webhook URL は、Slack のワークスペース管理画面から「Incoming Webhooks」アプリを有効化して作成します。特定のチャンネルに紐付けて発行されます。

Gemini API で問い合わせを分類する

核心部分のコードです。Gemini API に問い合わせ内容を送り、構造化された分析結果を受け取ります。

import os
import json
from google import genai
from google.genai import types
 
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
 
def classify_inquiry(subject: str, body: str) -> dict:
    """
    問い合わせを分類し、優先度スコアを付ける。
 
    Returns:
        {
          "category": str,
          "priority": int (1-5),
          "priority_reason": str,
          "summary": str,
          "suggested_response_time": str
        }
    """
    prompt = f"""
以下の問い合わせを分析してください。
 
件名: {subject}
本文: {body}
 
以下の形式でJSONを返してください:
{{
  "category": "bug_report | feature_request | usage_question | billing | other",
  "priority": 1から5の整数(5が最高優先度),
  "priority_reason": "優先度の判断理由を1文で",
  "summary": "問い合わせ内容を30文字以内で要約",
  "suggested_response_time": "即時対応 | 24時間以内 | 3営業日以内 | 1週間以内"
}}
 
優先度の基準:
- 5: サービス全体に影響するバグ、データ消失の可能性
- 4: 特定機能が使えない、決済に関する問題
- 3: パフォーマンス問題、一部機能の不具合
- 2: 機能要望、改善提案
- 1: 一般的な使い方の質問
"""
 
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=prompt,
        config=types.GenerateContentConfig(
            response_mime_type="application/json",
            temperature=0.1,  # 分類タスクは低めで安定させる
        ),
    )
 
    return json.loads(response.text)

temperature=0.1 に設定しているのには理由があります。分類タスクでは創造性より一貫性が重要で、同じ内容の問い合わせに対して毎回ほぼ同じ分類が返ってくるようにしたいからです。私が試したところ、temperature=0 だとモデルによっては JSON 以外の文字が先頭に混入することがあったので、0.1 が安定していました。

response_mime_type="application/json" を指定すると、Gemini が必ず JSON 形式で返してくれます。これを指定しない場合は markdown のコードブロックで包まれて返ってきて、パースが面倒になります。構造化出力についての詳しい解説は Gemini API 構造化出力ガイド を参考にしてください。

Slack に通知を送る

分類結果を視覚的に分かりやすく Slack に送ります。優先度に応じた色付けとメンションで、見落としを防ぎます。

import requests
from datetime import datetime
 
def send_slack_notification(inquiry_data: dict, classification: dict) -> bool:
    """
    分類結果を Slack に送信する。
    優先度別に色とメンションを変える。
 
    Returns:
        True if success, raises on error
    """
    category_emoji = {
        "bug_report": "🐛",
        "feature_request": "✨",
        "usage_question": "❓",
        "billing": "💳",
        "other": "📝",
    }
 
    priority_colors = {
        5: "#FF0000",  # 赤:緊急
        4: "#FF6600",  # オレンジ:高
        3: "#FFCC00",  # 黄:中
        2: "#00CC00",  # 緑:低
        1: "#999999",  # グレー:最低
    }
 
    category = classification.get("category", "other")
    priority = classification.get("priority", 1)
    emoji = category_emoji.get(category, "📝")
    color = priority_colors.get(priority, "#999999")
 
    # 優先度に応じたヘッダーテキスト
    if priority >= 5:
        header = f"🚨 <!channel> 緊急対応が必要な問い合わせ"
    elif priority >= 4:
        header = f"⚠️ 優先対応が必要な問い合わせ {emoji}"
    else:
        header = f"{emoji} 新しい問い合わせ(優先度 {priority})"
 
    payload = {
        "text": header,
        "attachments": [
            {
                "color": color,
                "fields": [
                    {
                        "title": "要約",
                        "value": classification.get("summary", ""),
                        "short": False,
                    },
                    {
                        "title": "カテゴリ",
                        "value": category,
                        "short": True,
                    },
                    {
                        "title": "優先度",
                        "value": f"{'⭐' * priority} ({priority}/5)",
                        "short": True,
                    },
                    {
                        "title": "推奨対応時間",
                        "value": classification.get("suggested_response_time", ""),
                        "short": True,
                    },
                    {
                        "title": "判断理由",
                        "value": classification.get("priority_reason", ""),
                        "short": False,
                    },
                    {
                        "title": "差出人",
                        "value": inquiry_data.get("email", "不明"),
                        "short": True,
                    },
                ],
                "footer": f"受信: {datetime.now().strftime('%Y-%m-%d %H:%M JST')}",
            }
        ],
    }
 
    response = requests.post(
        os.environ["SLACK_WEBHOOK_URL"],
        json=payload,
        timeout=10,
    )
    response.raise_for_status()
    return True

全体をまとめて動かす

エントリーポイントとなる関数です。エラーハンドリングも含めて本番で使える形にしてあります。

def handle_inquiry(inquiry_data: dict) -> dict:
    """
    問い合わせデータを受け取り、分類して通知する。
 
    inquiry_data:
        subject: 件名
        body: 本文
        email: 送信者メールアドレス
        name: 送信者名(任意)
    """
    try:
        # Gemini API で分類・優先度付け
        classification = classify_inquiry(
            subject=inquiry_data.get("subject", ""),
            body=inquiry_data.get("body", ""),
        )
 
        # Slack に通知
        send_slack_notification(inquiry_data, classification)
 
        return {"status": "success", "classification": classification}
 
    except json.JSONDecodeError as e:
        # Gemini が JSON 以外を返した場合のフォールバック
        print(f"JSON parse error: {e}")
        fallback = {
            "category": "other",
            "priority": 3,
            "priority_reason": "自動分類に失敗(手動確認が必要)",
            "summary": inquiry_data.get("subject", "")[:30],
            "suggested_response_time": "24時間以内",
        }
        send_slack_notification(inquiry_data, fallback)
        return {"status": "fallback", "error": str(e)}
 
    except requests.exceptions.RequestException as e:
        # Slack への通知が失敗した場合
        print(f"Slack notification failed: {e}")
        return {"status": "classified_but_notify_failed", "classification": classification}
 
    except Exception as e:
        print(f"Unexpected error: {e}")
        raise
 
# 動作確認
if __name__ == "__main__":
    test_inquiry = {
        "subject": "ログインできなくなりました",
        "body": "昨日まで使えていたのに、今朝からログインしようとすると「認証エラー」が表示されます。パスワードは変えていません。",
        "email": "tanaka@example.com",
        "name": "田中太郎",
    }
 
    result = handle_inquiry(test_inquiry)
    print(f"分類結果: {result['classification']}")
    # 期待する結果: category=bug_report, priority=4, suggested_response_time=24時間以内

実際に使ってみて分かったこと

このシステムを自分のサービスで2ヶ月ほど使ってみて、いくつか気づいたことがあります。

プロンプトの品質がそのまま分類精度に直結します。 カテゴリ名を日本語で定義するか英語で定義するか、優先度の基準をどれだけ具体的に書くかで、分類の一貫性が大きく変わりました。最初は日本語でカテゴリを定義していたのですが、英語の方が誤分類が少なかったです。

曖昧な問い合わせへの対応は思ったより賢い。 「使い方が分からない」だけの問い合わせは、どのカテゴリにすべきか難しそうですが、Gemini は文脈から usage_question に分類してくれることが多く、大体正しい判断でした。一方で、感情的に書かれた怒りのバグ報告は優先度を少し高めに評価する傾向があります。これは人間的には正しい判断だと思います。

コストは無視できる範囲です。 Gemini 2.5 Flash を使えば、問い合わせ1件あたりの API 料金は1円以下。月100件程度なら実質ゼロコストで運用できます。

エラーハンドリングについては Gemini API エラー処理ガイド も参考になります。

Google フォームと連携する

Google フォームを使っている場合は、Flask か FastAPI で Webhook エンドポイントを作り、Apps Script からそこに POST するのが最も手軽です。

from flask import Flask, request, jsonify
 
app = Flask(__name__)
 
@app.route("/webhook/inquiry", methods=["POST"])
def inquiry_webhook():
    data = request.get_json()
    if not data:
        return jsonify({"error": "Invalid JSON"}), 400
    result = handle_inquiry(data)
    return jsonify(result)
 
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)

Cloud Run にデプロイすれば、リクエストが来た時だけ起動するサーバーレス構成で月数百円から運用できます。Railway も設定が少なく個人開発者には使いやすいです。

全体を振り返って

問い合わせ対応を自動化して一番実感したのは「見落とし」がなくなったことです。以前は夜間に届いた緊急の問い合わせを翌朝まで気づかないことがありましたが、今は Slack への通知で即座に確認できます。

まずは既存のフォームにこの仕組みを繋いで、Slack の動作を確認してみてください。コードはそのままコピーして動かせる状態にしてあります。カテゴリ定義や優先度基準は、ご自身のサービスの性質に合わせて調整するとより精度が上がります。

シェア

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

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

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

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

関連記事

API / SDK2026-03-20
Gemini API × Python で AI データ分析エージェントを構築する — Code Execution・Function Calling・Structured Output 統合ガイド
Gemini API の Code Execution、Function Calling、Structured Output を組み合わせ、CSV/Excel を自動解析し可視化・レポート生成まで行う AI データ分析エージェントを Python で構築する実践ガイド。
API / SDK2026-07-13
responseSchema で $ref が使えず詰まったら — responseJsonSchema で再帰スキーマを本番で扱う
Gemini の responseSchema は OpenAPI サブセットで $ref/$defs が使えず、共有定義も再帰も表現できません。responseJsonSchema へ移行し、多言語フィールドの再利用とカテゴリ木の再帰を本番で扱う実装をまとめました。
API / SDK2026-07-05
使っているモデルの廃止予告だけを拾う — url-context に公式チェンジログを読ませる仕組み
画像モデルの停止を公開3日前に知って肝を冷やしました。url-context に公式チェンジログを直接読ませ、自分が実際に使っているモデルの廃止予告だけを構造化して差分通知する仕組みを、そのまま動く Python と運用で削った過検知の調整まで含めて組み立てます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →