背景と前提
Google AI StudioはAIアプリケーションの開発に便利ですが、エンタープライズ環境でのプロダクション運用には向きません。Vertex AIは以下の理由からエンタープライズ規模のGeminiデプロイに不可欠です:
SLA(サービスレベルアグリーメント) : 99.95%の可用性保証
VPC統合 : プライベートネットワーク内でモデルを実行
規制対応 : HIPAA、SOC 2、FedRampなどのコンプライアンス要件対応
エンタープライズ課金 : 組織全体での一元管理、コスト配分
高度なセキュリティ : IAMロール管理、監査ログ、顧客管理キー
ここで整理するのは実装レベルでのVertex AI Geminiのプロダクション運用について、認証から監視、コスト最適化まで網羅します。
ℹ️ このガイドは、Google Cloud プロジェクトの管理者アクセスを持つ開発者向けです。プロジェクトの作成と初期設定が完了していることを前提とします。
認証設定の実装
サービスアカウントの作成
Vertex AIでのAPI呼び出しは、サービスアカウントを通じて行われます。Google AI Studioとは異なり、個人のAPIキーは使用しません。
# プロジェクトIDを設定
export PROJECT_ID = "your-project-id"
export SERVICE_ACCOUNT_NAME = "gemini-production"
# サービスアカウントを作成
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME \
--project= $PROJECT_ID \
--display-name= "Gemini Production Service Account"
# Vertex AI ユーザーロールを付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member= "serviceAccount:${ SERVICE_ACCOUNT_NAME }@${ PROJECT_ID }.iam.gserviceaccount.com" \
--role= "roles/aiplatform.user"
# Cloud Logging への書き込み権限を付与
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member= "serviceAccount:${ SERVICE_ACCOUNT_NAME }@${ PROJECT_ID }.iam.gserviceaccount.com" \
--role= "roles/logging.logWriter"
JSON認証キーの生成
# JSON キーを生成
gcloud iam service-accounts keys create ~/gemini-key.json \
--iam-account=${ SERVICE_ACCOUNT_NAME }@${ PROJECT_ID }.iam.gserviceaccount.com
⚠️ JSON キーは秘密情報です。バージョン管理システムに含めないでください。環境変数または Secret Manager 経由で管理してください。
Application Default Credentials (ADC) の活用
本番環境では、ADCを使用してサービスアカウント認証を自動化します:
# ローカル開発環境で ADC を設定
export GOOGLE_APPLICATION_CREDENTIALS = " $HOME /gemini-key.json"
# Cloud Run デプロイ時は、サービスアカウントをコンテナに割り当てます
Python での初期化方法
Vertex AI SDKを使用した初期化:
import vertexai
from vertexai.generative_models import GenerativeModel
# Vertex AI を初期化
vertexai.init( project = "your-project-id" , location = "us-central1" )
# Google AI SDK との比較(非推奨)
# from google import genai
# client = genai.Client(api_key="your-api-key") # <- プロダクションには不適切
Vertex AIの初期化にはいくつかの利点があります:
認証自動化 : ADCを通じた自動認証
リージョン指定 : リージョン内でのレイテンシ最適化
クォータ管理 : プロジェクトレベルでのAPI呼び出し制限
Vertex AI Geminiの基本的な呼び出し
シンプルなテキスト生成
from vertexai.generative_models import GenerativeModel
model = GenerativeModel( "gemini-2.0-flash" )
response = model.generate_content( "Explain quantum computing in simple terms" )
print (response.text)
ストリーミング応答の処理
プロダクション環境では、ストリーミングを使用してレイテンシを削減します:
response = model.generate_content(
"Write a comprehensive guide on cloud architecture" ,
stream = True
)
for chunk in response:
print (chunk.text, end = "" , flush = True )
複数の会話ターンを含むチャット
from vertexai.generative_models import GenerativeModel
model = GenerativeModel( "gemini-2.0-flash" )
chat = model.start_chat()
response1 = chat.send_message( "What is machine learning?" )
print (response1.text)
response2 = chat.send_message( "How is it different from deep learning?" )
print (response2.text)
# チャット履歴は自動的に管理されます
プロビジョニングスループットの最適化
概念と利点
Provisioned Throughputは、固定のトークン処理容量をあらかじめ予約するモデルです。以下のような場合に有効です:
予測可能な負荷 : 日中に一定のトラフィック
ピークパフォーマンス : キューイングなしで低レイテンシを保証
コスト削減 : 月単位で100万トークン以上処理する場合
スループット予約の作成
# 1,000 トークン/分の予約を作成
gcloud ai operations create-throughput \
--provisioned-model-display-name= "gemini-flash-prod" \
--model-id= "gemini-2.0-flash" \
--input-token-rate=1000 \
--project= $PROJECT_ID \
--region=us-central1
予約スループットの使用
from vertexai.generative_models import GenerativeModel
# プロビジョニングされたモデルを使用
model = GenerativeModel(
"projects/ {PROJECT_ID} /locations/us-central1/endpoints/ {ENDPOINT_ID} "
)
response = model.generate_content( "Your prompt here" )
コスト比較
ℹ️ **Pay-per-token モデル**: 1M 入力トークン = $0.15、出力 = $0.60
**Provisioned Throughput**: 月額固定料金で、月間トークン数が一定以上なら割安
通常、月間1億トークン以上の使用が見込まれる場合、Provisioned Throughput が有利です。
セーフティフィルタと内容フィルタリング
ハーム分類の設定
Geminiは、以下の4つのハーム分類に対して安全フィルタを適用します:
from vertexai.generative_models import (
GenerativeModel,
HarmCategory,
HarmBlockThreshold,
)
model = GenerativeModel( "gemini-2.0-flash" )
# セーフティ設定を定義
safety_settings = [
{
"category" : HarmCategory. HARM_CATEGORY_UNSPECIFIED ,
"threshold" : HarmBlockThreshold. BLOCK_NONE ,
},
{
"category" : HarmCategory. HARM_CATEGORY_HATE_SPEECH ,
"threshold" : HarmBlockThreshold. BLOCK_MEDIUM_AND_ABOVE ,
},
{
"category" : HarmCategory. HARM_CATEGORY_DANGEROUS_CONTENT ,
"threshold" : HarmBlockThreshold. BLOCK_MEDIUM_AND_ABOVE ,
},
{
"category" : HarmCategory. HARM_CATEGORY_HARASSMENT ,
"threshold" : HarmBlockThreshold. BLOCK_ONLY_HIGH ,
},
{
"category" : HarmCategory. HARM_CATEGORY_SEXUALLY_EXPLICIT ,
"threshold" : HarmBlockThreshold. BLOCK_MEDIUM_AND_ABOVE ,
},
]
response = model.generate_content(
"Your prompt here" ,
safety_settings = safety_settings
)
エンタープライズカスタムフィルタレイヤー
セーフティ設定では不十分な場合、カスタムフィルタリング層を実装します:
import re
from enum import Enum
class ContentPolicyViolation ( Enum ):
"""組織のポリシー違反タイプ"""
COMPETITOR_MENTION = "competitor_mention"
CONFIDENTIAL_DATA = "confidential_data"
DISALLOWED_PRODUCT = "disallowed_product"
CONFIDENTIAL_PATTERNS = {
ContentPolicyViolation. COMPETITOR_MENTION : [
r " \b( competitor_a | competitor_b )\b " ,
],
ContentPolicyViolation. DISALLOWED_PRODUCT : [
r " \b( legacy_product_x | sunset_service )\b " ,
],
}
def check_policy_compliance (text: str ) -> tuple[ bool , list[ str ]]:
"""入力テキストのポリシー違反をチェック"""
violations = []
for violation_type, patterns in CONFIDENTIAL_PATTERNS .items():
for pattern in patterns:
if re.search(pattern, text, re. IGNORECASE ):
violations.append(violation_type.value)
return len (violations) == 0 , violations
# 使用例
user_prompt = "How do we compete with competitor_a on feature X?"
is_compliant, violations = check_policy_compliance(user_prompt)
if not is_compliant:
print ( f "ポリシー違反: { violations } " )
# リクエストを拒否またはログを記録
else :
response = model.generate_content(user_prompt)
Cloud Run でのデプロイメント
Flask アプリケーションの実装
プロダクション環境では、Geminiをマイクロサービスとして公開します:
# main.py
import os
import logging
from datetime import datetime
from typing import Optional
from flask import Flask, request, jsonify, Response
import vertexai
from vertexai.generative_models import GenerativeModel, HarmCategory, HarmBlockThreshold
from google.cloud import logging as cloud_logging
# Cloud Logging を設定
logging_client = cloud_logging.Client()
logging_client.setup_logging()
app = Flask( __name__ )
# Vertex AI を初期化
PROJECT_ID = os.environ.get( "GCP_PROJECT_ID" )
LOCATION = os.environ.get( "GCP_LOCATION" , "us-central1" )
vertexai.init( project = PROJECT_ID , location = LOCATION )
# モデルを初期化
model = GenerativeModel( "gemini-2.0-flash" )
# セーフティ設定
SAFETY_SETTINGS = [
{
"category" : HarmCategory. HARM_CATEGORY_HATE_SPEECH ,
"threshold" : HarmBlockThreshold. BLOCK_MEDIUM_AND_ABOVE ,
},
{
"category" : HarmCategory. HARM_CATEGORY_DANGEROUS_CONTENT ,
"threshold" : HarmBlockThreshold. BLOCK_MEDIUM_AND_ABOVE ,
},
]
@app.route ( "/generate" , methods = [ "POST" ])
def generate ():
"""テキスト生成エンドポイント"""
try :
data = request.get_json()
prompt = data.get( "prompt" )
stream = data.get( "stream" , False )
if not prompt:
return jsonify({ "error" : "prompt is required" }), 400
# リクエストをログ記録
logging.info(
"generate_request" ,
extra = {
"prompt_length" : len (prompt),
"stream" : stream,
"timestamp" : datetime.utcnow().isoformat(),
},
)
# ストリーミング応答
if stream:
def generate_stream ():
try :
response = model.generate_content(
prompt,
stream = True ,
safety_settings = SAFETY_SETTINGS ,
)
for chunk in response:
yield f "data: { chunk.text }\n\n "
except Exception as e:
logging.error( f "Streaming error: { str (e) } " )
yield f "data: [ERROR] { str (e) }\n\n "
return Response(generate_stream(), mimetype = "text/event-stream" )
# 非ストリーミング応答
response = model.generate_content(
prompt,
safety_settings = SAFETY_SETTINGS ,
)
return jsonify({
"response" : response.text,
"finish_reason" : response.candidates[ 0 ].finish_reason.name,
})
except Exception as e:
logging.error( f "Generation error: { str (e) } " )
return jsonify({ "error" : str (e)}), 500
@app.route ( "/health" , methods = [ "GET" ])
def health ():
"""ヘルスチェックエンドポイント"""
return jsonify({ "status" : "healthy" }), 200
if __name__ == "__main__" :
port = int (os.environ.get( "PORT" , 8080 ))
app.run( host = "0.0.0.0" , port = port, debug = False )
Dockerfile
FROM python:3.11-slim
WORKDIR /app
# 依存関係をインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードをコピー
COPY main.py .
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
CMD [ "python" , "main.py" ]
requirements.txt
Flask==3.0.0
google-cloud-aiplatform==1.41.0
google-cloud-logging==3.8.0
vertexai==0.12.0
Cloud Run へのデプロイメント
# イメージをビルドしてArtifact Registryにプッシュ
gcloud builds submit --tag gcr.io/ $PROJECT_ID /gemini-api:latest
# Cloud Run にデプロイ
gcloud run deploy gemini-api \
--image gcr.io/ $PROJECT_ID /gemini-api:latest \
--platform managed \
--region us-central1 \
--service-account=${ SERVICE_ACCOUNT_NAME }@${ PROJECT_ID }.iam.gserviceaccount.com \
--memory 4Gi \
--cpu 4 \
--timeout 900 \
--max-instances 100 \
--set-env-vars "GCP_PROJECT_ID= $PROJECT_ID ,GCP_LOCATION=us-central1"
# サービスのURLを取得
gcloud run services describe gemini-api --region us-central1 --format 'value(status.url)'
ℹ️ Cloud Run は、リクエストがない場合は自動的にスケールダウンするため、ビジー時の予期しない料金増加を最小限に抑えられます。
Cloud Monitoring によるモニタリング
レイテンシ・エラー率ダッシュボードの設定
# Cloud Run メトリクスのダッシュボードを作成
gcloud monitoring dashboards create --config-from-file=- << EOF
{
"displayName": "Gemini API Production Dashboard",
"mosaicLayout": {
"columns": 12,
"tiles": [
{
"width": 6,
"height": 4,
"widget": {
"title": "Request Latency (p95)",
"xyChart": {
"dataSets": [
{
"timeSeriesQuery": {
"timeSeriesFilter": {
"filter": "resource.type= \" cloud_run_revision \" AND metric.type= \" run.googleapis.com/request_latencies \" AND resource.label.service_name= \" gemini-api \" "
}
}
}
]
}
}
},
{
"xPos": 6,
"width": 6,
"height": 4,
"widget": {
"title": "Error Rate",
"xyChart": {
"dataSets": [
{
"timeSeriesQuery": {
"timeSeriesFilter": {
"filter": "resource.type= \" cloud_run_revision \" AND metric.type= \" run.googleapis.com/request_count \" AND resource.label.service_name= \" gemini-api \" AND metric.response_code_class= \" 5xx \" "
}
}
}
]
}
}
}
]
}
}
EOF
構造化ログの実装
import logging
import json
from google.cloud import logging as cloud_logging
# Cloud Logging クライアントをセットアップ
logging_client = cloud_logging.Client()
handler = cloud_logging.handlers.CloudLoggingHandler(logging_client)
logging.getLogger().addHandler(handler)
# 構造化ログの書き込み
def log_generation_event (
prompt_length: int ,
response_length: int ,
latency_ms: float ,
success: bool ,
error: Optional[ str ] = None ,
):
"""生成イベントを構造化ログで記録"""
log_entry = {
"event" : "gemini_generation" ,
"prompt_tokens" : estimate_tokens(prompt_length),
"response_tokens" : estimate_tokens(response_length),
"latency_ms" : latency_ms,
"success" : success,
"timestamp" : datetime.utcnow().isoformat(),
}
if error:
log_entry[ "error" ] = error
logging.info(json.dumps(log_entry))
def estimate_tokens (text_length: int ) -> int :
"""テキスト長からトークン数を推定(約4文字=1トークン)"""
return max ( 1 , text_length // 4 )
アラートルールの設定
# エラー率が5%を超えた場合にアラート
gcloud alpha monitoring policies create \
--notification-channels=CHANNEL_ID \
--display-name= "Gemini API High Error Rate" \
--condition-display-name= "Error Rate > 5%" \
--condition-threshold-value=0.05 \
--condition-threshold-duration=300s
コスト管理とクォータ
予算アラートの設定
# 月額予算を$1,000に設定
gcloud billing budgets create \
--billing-account=BILLING_ACCOUNT_ID \
--display-name= "Gemini API Budget" \
--budget-amount=1000 \
--threshold-rule=percent=50 \
--threshold-rule=percent=90 \
--threshold-rule=percent=100 \
--notifications-rule=pubsub-topic=projects/ $PROJECT_ID /topics/billing-alerts
API クォータの管理
# Vertex AI API クォータを確認
gcloud compute project - info describe \
-- format = 'value(quotas[name="aiplatform.googleapis.com/requests"].usage)'
プロジェクト別の課金分離
複数プロジェクトを使用することで、コスト配分を管理します:
# 開発環境
gcloud config set project dev-project
# ...開発作業...
# 本番環境
gcloud config set project prod-project
# ...本番運用...
TypeScript / Node.js での実装例
Node.js での Gemini 呼び出し
import {VertexAI} from "@google-cloud/vertexai" ;
const vertexAI = new VertexAI ({
project: process.env. GCP_PROJECT_ID ,
location: process.env. GCP_LOCATION || "us-central1" ,
});
const model = vertexAI. getGenerativeModel ({
model: "gemini-2.0-flash" ,
});
async function generateContent ( prompt : string ) : Promise < string > {
const response = await model. generateContent ({
contents: [
{
role: "user" ,
parts: [
{
text: prompt,
},
],
},
],
});
return response.response.candidates?.[ 0 ].content.parts[ 0 ].text || "" ;
}
// 使用例
( async () => {
const result = await generateContent (
"Explain quantum computing in 100 words"
);
console. log (result);
})();
Express.js でのマイクロサービス
import express, { Request, Response } from "express" ;
import { VertexAI } from "@google-cloud/vertexai" ;
import { CloudLoggingTransport } from "@google-cloud/logging-winston" ;
import winston from "winston" ;
const app = express ();
app. use (express. json ());
const vertexAI = new VertexAI ({
project: process.env. GCP_PROJECT_ID ,
location: "us-central1" ,
});
const logger = winston. createLogger ({
transports: [
new CloudLoggingTransport ({
projectId: process.env. GCP_PROJECT_ID ,
}),
new winston.transports. Console (),
],
});
app. post ( "/generate" , async ( req : Request , res : Response ) => {
try {
const { prompt , stream } = req.body;
if ( ! prompt) {
return res. status ( 400 ). json ({ error: "prompt is required" });
}
const model = vertexAI. getGenerativeModel ({
model: "gemini-2.0-flash" ,
});
if (stream) {
res. setHeader ( "Content-Type" , "text/event-stream" );
res. setHeader ( "Cache-Control" , "no-cache" );
const streamResponse = await model. generateContentStream ({
contents: [{ role: "user" , parts: [{ text: prompt }] }],
});
for await ( const chunk of streamResponse.stream) {
const text =
chunk.candidates?.[ 0 ].content.parts[ 0 ].text || "" ;
res. write ( `data: ${ text } \n\n ` );
}
res. end ();
} else {
const response = await model. generateContent ({
contents: [{ role: "user" , parts: [{ text: prompt }] }],
});
res. json ({
response: response.response.candidates?.[ 0 ].content.parts[ 0 ].text,
});
}
} catch (error) {
logger. error ( "Generation error" , error);
res. status ( 500 ). json ({ error: String (error) });
}
});
const port = process.env. PORT || 8080 ;
app. listen (port, () => {
console. log ( `Server listening on port ${ port }` );
});
プロダクション チェックリスト
本番環境へのデプロイ前に、以下の項目を確認してください:
項目 セキュリティ 信頼性 コスト
サービスアカウント認証 ✅ - -
IAM ロール最小化 ✅ - -
VPC サービスコントロール ✅ - -
API キー(非使用) ✅ - -
レート制限(400エラー) - ✅ -
リトライロジック - ✅ -
ヘルスチェック - ✅ -
Cloud Run タイムアウト設定 - ✅ -
エラーロギング ✅ ✅ -
構造化ログ - ✅ ✅
予算アラート - - ✅
Provisioned Throughput - ✅ ✅
モニタリングダッシュボード - ✅ ✅
セーフティフィルタ設定 ✅ - -
カスタムポリシーフィルタ ✅ - -
個人開発者の視点から(実体験メモ)
ここまでの要点
Vertex AI上でのGeminiプロダクションデプロイメントは、以下の重要なポイントで成功します:
認証 : サービスアカウント + ADC による堅牢な認証
スケーリング : Provisioned Throughput による予測可能なパフォーマンス
安全性 : ハームフィルタ + カスタムポリシーレイヤー
監視 : Cloud Monitoring と構造化ログによるリアルタイム可視化
コスト : 予算アラートとクォータ管理による支出制御
このガイドで示した実装パターンを組み合わせることで、エンタープライズグレードのAIサービスを構築できます。
さらなる情報は、Google Cloud AI Platform ドキュメント を参照してください。
Google AI Studio と Vertex AI の違い
Gemini には 2 つの主要なアクセス方法があります。
項目 Google AI Studio Vertex AI
対象 個人開発者・プロトタイプ エンタープライズ
認証 API キー Google Cloud IAM
SLA なし 99.9% 稼働保証
データリテンション Google のデータ利用方針適用 エンタープライズポリシー
リージョン グローバル リージョン指定可能
価格 従量課金 従量課金 + コミット割引
エンタープライズ用途や医療・金融などの規制業種では Vertex AI が推奨されます。
セットアップ
1. Google Cloud プロジェクトの準備
# gcloud CLI をインストール後
gcloud projects create my-gemini-project
gcloud config set project my-gemini-project
# Vertex AI API を有効化
gcloud services enable aiplatform.googleapis.com
# 認証設定
gcloud auth application-default login
2. Python クライアントのインストール
pip install google-cloud-aiplatform
3. 基本的な呼び出し
import vertexai
from vertexai.generative_models import GenerativeModel
# 初期化(プロジェクト・リージョンを指定)
vertexai.init(
project = "my-gemini-project" ,
location = "us-central1"
)
model = GenerativeModel( "gemini-3-flash-preview" )
response = model.generate_content( "Pythonでフィボナッチ数列を実装してください" )
print (response.text)
チャット(マルチターン会話)
model = GenerativeModel( "gemini-3-flash-preview" )
chat = model.start_chat()
responses = [
chat.send_message( "こんにちは!React を始めたいのですが" ),
chat.send_message( "useState の使い方を教えてください" ),
chat.send_message( "実際のカウンターアプリのコード例を見せてください" ),
]
for response in responses:
print (response.text)
print ( "---" )
ストリーミング
response = model.generate_content(
"日本の歴史について長文で教えてください" ,
stream = True
)
for chunk in response:
print (chunk.text, end = "" , flush = True )
システムインストラクション
model = GenerativeModel(
"gemini-3-flash-preview" ,
system_instruction = """あなたは経験豊富なソフトウェアエンジニアです。
コードの説明は常に日本語で行い、具体的な例を示してください。
セキュリティのベストプラクティスも合わせて説明してください。"""
)
response = model.generate_content( "SQLインジェクションの防ぎ方を教えてください" )
print (response.text)
本番環境でのベストプラクティス
エラーハンドリング
from google.api_core import exceptions
import time
def generate_with_retry (model, prompt, max_retries = 3 ):
for attempt in range (max_retries):
try :
return model.generate_content(prompt)
except exceptions.ResourceExhausted:
if attempt == max_retries - 1 :
raise
wait_time = 2 ** attempt # Exponential backoff
print ( f "Rate limit hit. Waiting { wait_time } s..." )
time.sleep(wait_time)
コスト管理
Vertex AI では使用量のモニタリングと予算アラートを設定できます。
# 予算アラートの設定(Google Cloud Console でも可能)
gcloud billing budgets create \
--billing-account=BILLING_ACCOUNT_ID \
--display-name= "Gemini Budget Alert" \
--budget-amount=10000JPY \
--threshold-rules=percent=50,percent=90,percent=100
Vertex AI のメリット
VPC Service Controls
企業のVPC内でGemini APIを呼び出せるため、データがインターネットを経由しません。
監査ログ
すべてのAPI呼び出しがCloud Audit Logsに記録され、コンプライアンス要件に対応できます。
プライベートエンドポイント
専用のプライベートエンドポイントを使って、パブリックインターネットを経由しないAPI呼び出しが可能です。
全体を振り返って
Vertex AI は、エンタープライズ環境で Gemini を安全・安定して運用するための基盤です。
IAM ベースの認証でセキュアなアクセス制御
SLA 保証・リージョン指定による信頼性
VPC 統合・監査ログによるコンプライアンス対応
Google Cloud の他サービスとのシームレスな統合
本番環境や機密データを扱う用途では、Google AI Studio より Vertex AI を選択することを強く推奨します。