GCP開発 Excuse AIで学ぶ生成AIアプリ構築(後編)
🔁 前編のおさらい
前編では、GCS→Pub/Sub→Cloud Run→GCS という
イベント駆動型のバッチ処理構成 を構築しました。
今回の後編では、Webフロントエンド・CI/CD・データ蓄積・分析基盤 を加え、
バッチ処理アプリから 本格的なWebサービス へと発展させていきます。
🌐 Phase 7:Webフロントエンドの追加
バッチ処理だけでは使い勝手が悪いため、Webフロントエンド を追加しました。


🔧 Cloud Runで2つのルートを統合
【ルート①:リアルタイム生成】NEW!
Webフロント → Pub/Sub → Cloud Run → Gemini API → Firestore
【ルート②:バッチ障害処理】既存
GCS(JSON) → Pub/Sub → Cloud Run → Gemini API → GCS + Firestore
💡 Pub/Subで疎結合を維持
どちらのルートも同じCloud Runで処理しますが、メッセージの属性で分岐:
# Pub/Sub標準形式では "message" が入っている
pubsub_message = envelope.get('message', {}) or {}
attributes = pubsub_message.get('attributes', {}) or {}
# ---------------------------
# 1) dataフィールド(Base64エンコードされたJSON)を優先的に読む
# フロントからの直POSTはこちらに必ず入っている想定
# ---------------------------
incident_data = None
raw = pubsub_message.get('data')
if raw:
try:
decoded = json.loads(b64decode(raw).decode('utf-8'))
if decoded.get('incident_id'):
# フロント直POST
incident_data = decoded
elif decoded.get('bucket') and decoded.get('name'):
# GCS通知
bucket_name = bucket_name or decoded.get('bucket')
object_id = object_id or decoded.get('name')
設計のメリット:
- フロントとバッチが疎結合
- 非同期処理でレスポンス高速
- 新しい入力元を追加しやすい
⚙️ Phase 8:CI/CDで開発サイクルを加速
🔧 構成
GitHub → Cloud Build → Cloud Run(自動デプロイ)
📋 Step 1: GitHub リポジトリとの連携
GCPコンソールから接続:
- Cloud Build > トリガー > 「トリガーを作成」
-
トリガー設定:
- イベント:「ブランチに push」
- ブランチ:
^main$ - 構成ファイル:
/cloudbuild.yaml
ここが少々難解でしたが、Connect Repositoryで以下のように別途Githubを選びました。


これでmainブランチへのpushが自動的にビルドをトリガーします。
🔐 Step 2: IAM設定(ここで3時間ハマった)
問題:Service Accountが自動作成されない
トリガー作成後、以下のエラーが発生:
ERROR: User [xxxx@cloudbuild.gserviceaccount.com]
does not have permission to act as service account
AIアシスタントの回答:
「デフォルトのService Accountが自動作成されます」ということを前提にChatGPTとClaudeで質疑が無限ループとなる。。
実際:
- この機能は 既に廃止済み
- 手動でService Accountを作成する必要がある
- AIの知識が古い情報のままだった
解決策:Service Accountの手動作成
2-1. Service Account作成
gcloud iam service-accounts create cloud-build-sa \
--display-name="Cloud Build Service Account"
2-2. 必要な権限を付与
# Cloud Run管理者権限
--role="roles/run.admin"
# Service Accountユーザー権限
--role="roles/iam.serviceAccountUser"
# ログ書き込み権限
--role="roles/logging.logWriter"
2-3. トリガーにService Accountを紐付け
GCPコンソール:
- Cloud Build > トリガー > 該当トリガーを編集
- 「Service Account」で作成したSAを選択
- 保存
📝 Step 3: cloudbuild.yaml の作成
steps:
- name: "gcr.io/cloud-builders/gcloud"
args:
- "run"
- "deploy"
- "excuse-ai-service"
- "--image=asia-northeast1-docker.pkg.dev/--"
- "--source=."
- "--region=asia-northeast1"
- "--allow-unauthenticated"
- "--memory=512Mi"
- "--timeout=300s"
- "-service-account=excuse-ai-sa@scenic-parity---" # コンテナ実行アカウント
options:
logging: CLOUD_LOGGING_ONLY
デプロイフロー:git push → Cloud Build起動(2〜3分)→ Cloud Run更新
💡 IAM設定で学んだこと
- AIも万能ではない:最新のGCP仕様変更に追いついていない
- 公式ドキュメント + コミュニティ:日本語のまとめ記事が解決の糸口に
- 専用SAを作成:デフォルトのCloud Build SAはもう存在しない
🗃️ Phase 9:Cloud RunでFirestoreに履歴データを残す
生成結果を永続化するため、Firestoreを導入。私見ですが、FirestoreはGCP的にはかなり推しの機能と思われます。RDBMSを作らなくても、JSON取り込みでこれだけの管理が可能です。
from google.cloud import firestore
db = firestore.Client()
try:
db.collection('excuses').document(inc_id).set(result)
except Exception as e:
print(f"[ERROR] Firestore書き込み失敗: {e}")
# 再試行しても二重生成の恐れ → ACKで握りつぶし
return 'Persist failed (ack)', 200

選んだ理由:
- スキーマレスで開発初期に最適
-
SERVER_TIMESTAMPで正確な時刻を自動記録 - Cloud Functionsとの相性が良い
📈 Phase 10:BigQueryで集計と分析
Firestoreでは大規模集計が困難なため、BigQueryへ定期エクスポート。
🔧 構成
Firestore → Cloud Functions(定期実行) → BigQuery
Cloud Scheduler設定:

Cloud Run Function実装:
from google.cloud import firestore, bigquery
def firestore_to_bq(request):
db = firestore.Client()
bq = bigquery.Client()
rows = []
for doc in db.collection("excuse_history").stream():
rows.append(doc.to_dict())
table_id = "<PROJECT_ID>.excuse_ai.logs"
bq.insert_rows_json(table_id, rows)
return "OK"
なぜ定期実行か:
- 分析は日次で十分(リアルタイム性不要)
- ストリーミング挿入よりコスト削減
- Cloud Run Functionsでサーバーレス運用
📊 Phase 11:Looker Studioで可視化
BigQueryをLooker Studioに接続し、ダッシュボード化。

主な可視化指標:
- 難易度分布:難易度別の円グラフ
- 日付別件数:日毎の発生件数推移
BigQueryを直接データソースに接続し、URLだけで共有可能。
🏗️ 全体アーキテクチャ(完成版)

🧠 学びと気づき
1. アーキテクチャは段階的に成長
Cloud Run + Gemini(最小構成)
↓
+ Pub/Sub(イベント駆動)
↓
+ Firestore(データ保存)
↓
+ Webフロント(リアルタイム化)
↓
+ CI/CD(自動化)
↓
+ BigQuery + Looker(分析基盤)
2. Pub/Subが設計の要
- フロントとバッチを疎結合に保つ
- 非同期処理で負荷を分散
- 拡張しやすい
3. マネージドサービスの組み合わせ
各サービスは単機能だが、組み合わせると強力:
- Pub/Sub + Cloud Run:イベント駆動のスケーラブル処理
- Firestore + BigQuery:リアルタイム保存 + 大規模分析
- GitHub + Cloud Build:自動CI/CD
4. Obserbilityは最初から組み込む
後から追加するのではなく、最初からログ・データ保存・分析基盤を設計する。
5. AIだけに頼らない
Cloud BuildのService Account問題で学んだこと:
- AIの知識は最新とは限らない
- 公式ドキュメント + 日本語コミュニティ情報を併用
6. コストは意外と安い
フルマネージド構成で全機能を実装しても 月数百円。
従量課金で使わなければほぼ0円。
🎯 まとめ
| Phase | 実装内容 | 効果 |
|---|---|---|
| Phase 7 | Webフロント追加 | バッチ→Webサービス化 |
| Phase 8 | CI/CD構築 | 開発サイクル高速化 |
| Phase 9 | Firestore導入 | 履歴データ蓄積 |
| Phase 10 | BigQuery + ETL | 大規模分析基盤 |
| Phase 11 | Looker Studio | 定量評価可視化 |
Excuse AIは「遊び心のあるテーマ」から始まりましたが、
結果として クラウドAIアプリのおすすめ構成の一例 が作れたのではないかと思います。
🌟 おわりに
結構な長編となりましたが、読んでいただき、ありがとうございました!
GCP学習を始めた当初から、「机上の資格学習」ではなく
「実際に動くものを作りながら理解する」ことができないかと試行錯誤してきました。
結果として Excuse AI は、アプリ開発・CI/CD・分析基盤までを
網羅する実践例になったかなと思います。
そして何より、この段階にいたると「学習」というより技術を道具にして、
「物を作る楽しさ」をとても感じられました。
AIとの協業により、実装自体は1週間ほどで仕上がっています。
Discussion