Google Cloudで最新為替を取得するエージェントを作成してみた

記事タイトルとURLをコピーする

G-gen の奥田です。当記事では、Google Cloud (旧称 GCP)のエージェント構築サービスを利用し、最新のドル・円レートを取得するエージェントを構築したので解説します。

はじめに

Conversational Agents とは

Conversational Agents とは、Google Cloud が提供する会話型 AI プラットフォームです。

2024年後半から2025年初頭にかけて、Vertex AI Agents (Playbook とデータストア機能) コンソールと Dialogflow CX コンソールが、単一の会話型エージェントコンソールに統合され、サービス名称も変更になりました。

Conversational Agents の名称の変遷

Conversational Agents(旧称 Dialogflow CX)では、生成的(Generative)なエージェントである Playbook と、決定論的(Deterministic)なエージェントである Flow を構築できます。当記事では、Playbook を利用して生成 AI エージェントを開発します。

なお Playbook は、Google の生成 AI エージェントサービスである Google Agentspace とも統合可能です。

Playbook とは

Playbook とは、生成 AI エージェントを構築するためのフルマネージドサービスです。生成 AI の機能を活かし、エンドユーザーの意図を理解して、応答を生成したり、人間の代わりにタスクを実行できます。

Playbookは以前、前述のとおり、AI Applications(旧称 Vertex AI Agent Builder)の Agents と呼ばれていましたが、改称されました。AI Applications の詳細は、以下の記事をご参照下さい。

blog.g-gen.co.jp

今回の記事では、単一の Playbook から構成される、シングルエージェント構成を実装します。

ツールとは

ツールとは、生成 AI エージェントが外部システムに接続して知識にアクセスしたり、複雑なタスクを実行したりするために使用する機能です。ツールは、Playbook から呼び出されます。

ツールの種類は以下のとおりです。

  • 組み込みツール
  • OpenAPI ツール
  • データストアツール
  • コネクタツール
  • Function ツール

当記事では、OpenAPI ツールを利用します。

OpenAPI ツールとは

OpenAPI ツールとは、OpenAPI Specification(OAS) に基づいた API 定義ファイルを用いて定義するツールです。

OpenAPI スキーマにより、API とやり取りするデータの形式を細かく定義します。

認証方式としては、Dialogflow のサービスエージェント認証、サービスアカウント認証、API キー、OAuth、Bearer トークンなどがサポートされています。当記事では、Dialogflow のサービスエージェント認証を使用します。

OpenAPI を利用して関数を呼び出す方法は、他社パブリッククラウドのエージェントでも同様のことが実現可能です。詳しくは以下の記事をご覧ください。

blog.g-gen.co.jp

システム構成と手順の概要

構成図

当記事では、以下のような構成でエージェントを構築しました。

実装手順

以下の順序で環境を構築しました。

  1. API の有効化/取得
  2. Cloud Run functions の構築
  3. Conversational Agent の作成
  4. Tool の構築
  5. Playbook の構築

API の有効化/取得

Google Cloud プロジェクトで、今回の構成に必要な Google Cloud サービスの API を有効化します。

gcloud services enable \
aiplatform.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
cloudfunctions.googleapis.com \
dialogflow.googleapis.com \
discoveryengine.googleapis.com \
logging.googleapis.com \
run.googleapis.com

また、今回は Currency Layer API から USD/JPY の為替レートを取得します。事前に Currency Layer API のユーザー登録を行い、API キーを取得しておきます。

Cloud Run functions の構築

Python のバージョン

当記事では、Python 3.12.3 を使用しました。

$ python --version
Python 3.12.3

ディレクトリ構成

プロジェクトの構成は、以下のとおりです。

currency/
├── main.py
└── requirements.txt

requirements.txt の作成

以下のライブラリを requirements.txt に定義します。

functions-framework>=3.0.0
requests
pytz
Flask 
google-cloud-logging

main.py の開発

Python スクリプトでは、以下のような処理で Currency Layer API から USD/JPY レートと取得時刻を取得します。

  1. API キーのチェック
    • 環境変数から API キーを取得
    • API キーが未設定の場合、エラーメッセージを返す
  2. API リクエスト
    • 取得した API キーを用いて、外部 API へリクエストを送信し、為替レートデータを取得
  3. データ処理
    • API からのレスポンスが成功したかを確認する。失敗した場合はエラーメッセージを返す
    • 取得したタイムスタンプを日本時間(JST)に変換
    • USD/JPY の為替レートをレスポンスから抽出
  4. レスポンス
    • 抽出した為替レートと変換後のタイムスタンプを JSON 形式で返す
  5. エラー処理
    • API リクエストのタイムアウト、接続エラー、レスポンスの解析エラーなど、発生しうる様々なエラーを取得
    • エラー発生時には、適切なエラーメッセージを JSON 形式で返す

また、15行目の Currency Layer API の API キーは Cloud Run functions のデプロイ時に設定します。当記事は簡易的な検証のため、API キーを Cloud Run functions の環境変数に格納しましたが、これはセキュアな方法ではありません。本番環境では、Secret Manager に格納するなどを検討してください。

main.py のソースコードは以下のとおりです。

import functions_framework
import os
import requests
import datetime
import pytz
import logging
import json
from flask import Response
# ロギングの設定
logging.basicConfig(level=logging.INFO)
# 環境変数から API キーを取得
api_key = os.environ.get("CURRENCY_LAYER_API_KEY")
base_url = "https://apilayer.net/api/live"
# --- HTTP リクエストを受け取る関数 ---
@functions_framework.http
def get_currency_rate(request):
"""
HTTP GET リクエストを受け取り、USD/JPY の為替レートを取得して JSON で返す関数。
Args:
request (flask.Request): Flaskリクエストオブジェクト。リクエストメソッド、
ヘッダー、クエリパラメータなどが含まれる。
この関数ではrequestの内容は直接利用しない。
Returns:
flask.Response: JSON形式のレスポンス、またはエラーレスポンス。
成功時: {"rate": <レート>, "timestamp_jst": "<JSTタイムスタンプ>"}
失敗時: {"error": "<エラーメッセージ>"} と適切なHTTPステータスコード
"""
# API キーのチェック(関数が呼び出されるたびにチェックする)
if not api_key:
logging.error("環境変数 'CURRENCY_LAYER_API_KEY' が設定されていません。")
error_response = json.dumps({"error": "Server configuration error: API key missing"})
return Response(error_response, status=500, mimetype='application/json')
params = {
"access_key": api_key,
"currencies": "JPY",
"source": "USD",
"format": 1
}
try:
logging.info("為替レート API へのリクエストを開始します...")
response = requests.get(base_url, params=params, timeout=10) # タイムアウトを設定
response.raise_for_status() # ステータスコードが200番台以外の場合にエラー
data = response.json()
logging.info("APIからのレスポンスを正常に受信しました。")
if not data.get('success', False):
error_info = data.get('error', {})
api_error_msg = f"API Error: Code={error_info.get('code')}, Info='{error_info.get('info')}'"
logging.error(api_error_msg)
error_response = json.dumps({"error": "Failed to retrieve data from currency API", "details": api_error_msg})
# API側の問題なので 502 Bad Gateway や 503 Service Unavailable が適切かもしれない
return Response(error_response, status=502, mimetype='application/json')
# タイムスタンプを日本時間 (JST)に変換
formatted_datetime = None
timestamp = data.get('timestamp')
if timestamp:
try:
jst = pytz.timezone('Asia/Tokyo')
datetime_utc = datetime.datetime.fromtimestamp(timestamp, tz=pytz.utc)
datetime_jst = datetime_utc.astimezone(jst)
formatted_datetime = datetime_jst.strftime('%Y-%m-%d %H:%M:%S %Z%z')
logging.info(f"Timestamp (JST): {formatted_datetime}")
except Exception as e:
logging.warning(f"タイムスタンプの変換中にエラー: {e}. 元のタイムスタンプ: {timestamp}")
# タイムスタンプ変換エラーは致命的ではない場合もあるので、処理は続行するかもしれない
# レートの取得
quotes = data.get('quotes')
if quotes and 'USDJPY' in quotes:
usdjpy_rate = quotes['USDJPY']
logging.info(f"USDJPY: {usdjpy_rate}")
# 成功時のレスポンスデータを作成
result_data = {
"rate": usdjpy_rate,
"timestamp_jst": formatted_datetime # 変換失敗時は None になる
}
success_response = json.dumps(result_data)
return Response(success_response, status=200, mimetype='application/json')
else:
logging.warning("レスポンスに USDJPY のレートが含まれていませんでした。")
logging.debug(f"受信したQuotes: {quotes}")
error_response = json.dumps({"error": "Currency data not found in API response", "received_quotes": quotes})
return Response(error_response, status=500, mimetype='application/json') # 内部サーバーエラーとして扱う
except requests.exceptions.Timeout:
logging.error("API へのリクエストがタイムアウトしました。")
error_response = json.dumps({"error": "Request to currency API timed out"})
return Response(error_response, status=504, mimetype='application/json') # Gateway Timeout
except requests.exceptions.RequestException as e:
logging.error(f"API へのリクエスト中にエラーが発生しました: {e}")
error_response = json.dumps({"error": "Error connecting to currency API", "details": str(e)})
return Response(error_response, status=502, mimetype='application/json') # Bad Gateway
except KeyError as e:
logging.error(f"レスポンスデータの解析中にキーエラーが発生しました: {e}")
logging.error(f"受信データ: {data}") # デバッグ用に受信データをログ出力
error_response = json.dumps({"error": "Error parsing API response", "missing_key": str(e)})
return Response(error_response, status=500, mimetype='application/json')
except Exception as e:
logging.exception(f"予期せぬエラーが発生しました: {e}") # スタックトレースもログに出力
error_response = json.dumps({"error": "An unexpected internal server error occurred", "details": str(e)})
return Response(error_response, status=500, mimetype='application/json')

Cloud Run function 実行用サービスアカウントの作成

Cloud Run functions を実行するサービスアカウントを作成し、権限を付与します。

PROJECT_ID="your-project-id" # プロジェクトID
SA_NAME="currencytest" # サービスアカウント名
SA_DESCRIPTION="My Cloud Functions Service Account for currency test " # サービスアカウントの説明
SA_DISPLAY_NAME="My Function SA for currencytest" # Cloud Console に表示される名前
gcloud iam service-accounts create "$SA_NAME" \
--project="$PROJECT_ID" \
--description="$SA_DESCRIPTION" \
--display-name="$SA_DISPLAY_NAME"
# 権限付与
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
--member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/artifactregistry.reader"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/run.invoker"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/containeranalysis.occurrences.viewer"

Cloud Run functions のデプロイ

FUNCTION=currencytest
YOUR_API_KEY=”Currency Layer API の API キー”
gcloud functions deploy ${FUNCTION} \
--gen2 \
--project=${PROJECT_ID} \
--region=us-central1 \
--entry-point=get_currency_rate \
--runtime=python312 \
--service-account="${SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
--trigger-http \
--allow-unauthenticated \
--timeout=540 \
--set-env-vars CURRENCY_LAYER_API_KEY=${YOUR_API_KEY}

繰り返しになりますが、API キーのような機密情報を環境変数に設定する方法は推奨されません。実際の環境では、Secret Manager に格納することを検討してください。

Conversational Agent の作成

Google Cloud コンソールから「AI Applications」を選択し、「アプリを作成する」を押下します。

アプリケーションの種類は「会話型エージェント」を選択します。

「Build your own」を選択します。

エージェント名、Location、Time Zone、Default Language を記入します。

Conversational Start は「Playbook」を選択します。

Tool の構築

Tool の設定を行います。

今回設定した値は以下のとおりです。

設定項目 名称
Tool name Currency-Calculator
Type OpenAPI
Description API を呼び出し、USD/JPY レートを表示します。

今回設定した OpenAPI スキーマは以下のとおりです。

openapi: 3.0.0
info:
title: Currency Rate API
version: 1.0.0
description: Get USD/JPY currency rate.
servers:
- url: [デプロイした Cloud Run functions の URL]
paths:
/:
get:
summary: Get USD/JPY currency rate
description: Retrieves the current USD/JPY currency exchange rate from an external API.
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
rate:
type: number
format: float
description: The USD/JPY exchange rate.
timestamp_jst:
type: string
format: date-time
description: The timestamp of the exchange rate in JST (Japan Standard Time).
'500':
description: Internal server error
content:
application/json:
schema:
type: object
properties:
error:
type: string
description: Error message.
'502':
description: Bad Gateway
content:
application/json:
schema:
type: object
properties:
error:
type: string
description: Error message from the external API.
details:
type: string
description: Detailed error message from the external API.
'504':
description: Gateway Timeout
content:
application/json:
schema:
type: object
properties:
error:
type: string
description: Error message indicating a timeout.

Playbook の構築

設定項目

以下の設定値で Playbook を構築します。

設定項目 設定値
Playbook Name Currency-Calculator-Playbook
Goal ツールを使い、日本円から US ドルの換算レートを表示します。
Instructions ${TOOL:Currency-Calculator}を呼び出し、日本円から USドルの換算レートを表示します。

動作検証

設定後はコンソール右上の吹き出しボタンからプレビュー画面を呼び出し、動作を検証します。

Example の格納

動作検証後、回答例を『Examples』に格納します。

カジュアルな質問(例:今日の為替は?)でも回答させたい場合は、カジュアルな質問文からツールを呼び出した会話例を登録します。

デプロイ

作成したアプリケーションは、Conversational Agents の Integration 機能を利用することで様々なサービスへ接続可能です。

以下のサービスには、Conversational Agents がネイティブに対応しています。

  • Dialogflow CX Phone Gateway
  • Dialogflow CX Messenger
  • Messenger from Meta
  • Workplace from Meta
  • LINE
  • Slack
  • Google Chat

他にも Google によって公開されているオープンソースの統合ライブラリも存在します。詳細は、以下のドキュメントを参照してください。

また前述の通り、Google Agentspace への接続も可能です。

応用

今回は簡易的な検証のため、ドル・円の為替レートと取得時刻のみを抽出しましたが、本事例を応用することで、ユーザーに為替レートを取得する国を指定させたり、過去の為替レートを取得するなど、複雑なタスクを実行するエージェントも構築可能です。

また、今回は単一の Playbook での実装でしたが、複数の Playbook を組み合わせることで、マルチエージェントシステムを構築可能です。こちらについては、以下の動画でデモを交えて紹介しています。

www.youtube.com

Risa(記事一覧)

クラウドソリューション部クラウドデベロッパー課
Google Cloudの可能性に惹かれ、2024年4月G-genにジョイン。
Google Cloud Partner Top Engineer 2025
Google Cloud 11 資格保有。日々修行中です!