バックエンド モジュールをシステムと統合する

バックエンド モジュールは、大量の機能関連メッセージを処理し、エージェント デスクトップ UI とやり取りするためのインフラストラクチャを提供します。このチュートリアルでは、バックエンド モジュールをエージェント システムに統合するプロセスについて説明します。

バックグラウンド モジュールのコンセプトと構造の詳細については、バックエンド モジュールの基本に関するドキュメントをご覧ください。

前提条件

  1. 構成していない場合は、Google Cloud CLI をインストールします。
  2. Dialogflow から必要なイベント通知の種類ごとに Cloud Pub/Sub トピックを作成します。後でバックエンドをデプロイするために、トピック ID とトピック名をメモしておきます。
  3. Pub/Sub トピックを使用して、Agent Assist コンソール会話プロファイルを構成します。

自動デプロイ

デプロイは、 Google Cloud 自動化スクリプトまたは Terraform によって自動化できます。

自動化スクリプト

詳しくは、./deploy.sh をご覧ください。

Terraform の変更を適用する

デプロイは、gcloud CLI 自動化スクリプトまたは Terraform を使用して自動化できます。Terraform の変更を適用する前に、次の手順を完了します。

  1. アカウントに次の IAM ロールを付与します。
    • Project IAM Admin(roles/resourcemanager.projectIamAdmin)
    • Service Usage Admin(roles/serviceusage.serviceUsageAdmin)
    • Service Account Admin(roles/iam.serviceAccountAdmin)
    • Service Account User(roles/iam.serviceAccountUser)
    • Pub/Sub Admin(roles/pubsub.admin)
    • Secret Manager Admin(roles/secretmanager.admin)
    • Cloud Build Editor(roles/cloudbuild.builds.editor)
    • Artifact Registry Administrator(roles/artifactregistry.admin)
    • Storage Admin(roles/storage.admin)
    • Cloud Run Admin(roles/run.admin)
    • Cloud Memorystore Redis Admin(roles/redis.admin)
    • Serverless VPC Access Admin(roles/vpcaccess.admin)
  2. UI コネクタと Cloud Pub/Sub インターセプタのイメージをビルドし、イメージ名をメモします。
    • UI Connector の場合は、./ui-connector フォルダで次のコマンドを実行します。
      $ gcloud builds submit --tag gcr.io/$GCP_PROJECT_ID/aa-integration-backend/ui-connector
    • Cloud Pub/Sub インターセプタの場合は、./cloud-pubsub-interceptor フォルダで次のコマンドを実行します。
      $ gcloud builds submit --tag gcr.io/$GCP_PROJECT_ID/aa-integration-backend/cloud-pubsub-interceptor
  3. Terraform の状態を保存する Cloud Storage バケットを作成し、次のコマンドを使用して /terraform/backend.tf のバックエンド バケット値を更新します。
    GCP_PROJECT_ID=$(gcloud config get-value project)
    # Create the Cloud storage bucket
    gcloud storage buckets create gs://${GCP_PROJECT_ID}-tfstate
    # Enable Object Versioning to keep the history of your deployments
    gcloud storage buckets update gs://${GCP_PROJECT_ID}-tfstate --versioning
  4. 必要な Terraform 変数 gcp_project_idui_connector_docker_imagecloud_pubsub_interceptor_docker_image の値をエクスポートします。例: export TF_VAR_gcp_project_id='you-gcp-project-id'。または、/terraform/variables.tf で直接値を入力することもできます。
  5. /ui-connector/auth.pyauth.check_auth() メソッドを変更して、認証方法をカスタマイズします。

Cloud Build を使用してこれらの手順を自動化する場合は、こちらの手順に沿って、ビルド構成ファイル ./terraform_cloudbuild.yaml を使用します。Cloud Build がサービスをデプロイできるようにするには、Cloud Build サービス アカウントにステップ 1 で説明した IAM ロールを付与する必要があります。

手動でのデプロイ

次の手順では、バックエンド モジュールを手動でデプロイする方法について説明します。

環境変数を設定する

デプロイのコマンドを簡素化するため、シェルで次の便利な環境変数を設定することをおすすめします。変数を設定するには、次のコマンド例を使用します。

$ export GCP_PROJECT_ID='aa-integration-service'

次の環境変数を設定します。

  • GCP_PROJECT_ID: 関連リソースをホストする Cloud Platform プロジェクトのプロジェクト ID。例: my-project
  • SERVICE_REGION: サービスと関連する Google Cloud リソースのロケーションまたはリージョン。プラットフォーム リソース。例: us-central1

管理者アカウントを設定する

サービス管理とランタイム ID には、別々の Google Cloud アカウントを使用することをおすすめします。サービス管理は主に Google アカウントを持つユーザーによって行われますが、ランタイム ID は サービス アカウントを使用して Cloud Run サービスに権限を付与し、必要なリソースへのアクセスを可能にします。

人間の管理者アカウントを準備する

プロジェクトで編集者またはオーナーの権限がすでに付与されているアカウントを使用する場合は、次のセクションに進んでください。

バックエンド インフラストラクチャを管理するには、管理者アカウントを作成し、次の Identity and Access Management(IAM)ロールを付与します。これらの権限はすべて、編集者とオーナーの基本ロールに含まれています。

  • roles/secretmanager.admin(Secret Manager 管理者): JWT の生成と検証のために Secret Manager に保存されているシークレットを管理します。
  • roles/run.admin(Cloud Run 管理者): Cloud Run サービスをデプロイして管理します。
  • roles/iam.serviceAccountUser(サービス アカウント ユーザー): Cloud Run ランタイム サービス アカウントに iam.serviceAccounts.actAs 権限を付与します。
  • roles/cloudbuild.builds.editor(Cloud Build 編集者): Cloud Build を使用して統合サービスの Docker イメージをビルドします。
  • Artifact Registry 管理者: 統合サービスのビルド済み Docker イメージを保存して管理します。
  • roles/pubsub.editor(Cloud Pub/Sub 編集者): Cloud Pub/Sub トピックとサブスクリプションを作成して管理します。
  • roles/redis.admin(Redis 管理者): Memorystore for Redis リソースを作成して管理します。

ユーザー アカウントに IAM ロールを付与するには、add-iam-policy-binding Google Cloud CLI コマンドを使用します。コマンドの例を示します。

$ gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
 --member='user:test-user@gmail.com' \
 --role='roles/pubsub.editor'

gcloud で人間の管理者アカウントを設定する

次の例では、$ADMIN_ACCOUNT を使用する管理者アカウント(myaccount@gmail.com など)に置き換えます。

$ gcloud config set account $ADMIN_ACCOUNT

サービス アカウントを設定する

デフォルトでは、Cloud Run サービスまたはジョブは、デフォルトの Compute Engine サービス アカウントとして実行されます。デフォルトのままにするのではなく、最小限の権限セットを持つユーザー管理サービス アカウントを割り当てることで、すべての Cloud Run サービスに専用 ID を付与することをおすすめします。デフォルトのサービス アカウントを保持する場合は、環境変数を設定するに進んでください。

Cloud Run ランタイムごとに 2 つのサービス アカウントを作成する

  1. サービス アカウントを作成するには、$CONNECTOR_SERVICE_ACCOUNT_ID$INTERCEPTOR_SERVICE_ACCOUNT_ID の値を置き換えて、次のコマンドを実行します。

    $ export CONNECTOR_SERVICE_ACCOUNT_ID='aa-ui-connector' && gcloud iam service-accounts create $CONNECTOR_SERVICE_ACCOUNT_ID \
    --description='Agent Assist integration - UI connector service account' \
    --display-name='Agent Assist integration - UI connector'
    $ export INTERCEPTOR_SERVICE_ACCOUNT_ID='aa-pubsub-interceptor' && gcloud iam service-accounts create $INTERCEPTOR_SERVICE_ACCOUNT_ID \
    --description='Agent Assist integration - Pubsub interceptor service account' \
    --display-name='Agent Assist integration - Pubsub interceptor'
  2. 次のサンプル コマンドを使用して、UI コネクタと Cloud Pub/Sub コネクタのサービス アカウントに次のロールを割り当てます。

    $ gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
    --member='serviceAccount:$CONNECTOR_SERVICE_ACCOUNT_ID@$GCP_PROJECT_ID.iam.gserviceaccount.com' \
    --role='roles/pubsub.editor'

UI コネクタのサービス アカウントに次の IAM ロールを付与します。

  • roles/redis.editor
  • roles/vpcaccess.user
  • roles/compute.viewer
  • roles/secretmanager.secretAccessor
  • roles/dialogflow.agentAssistClient

Cloud Pub/Sub コネクタ サービス アカウントに次のロールを付与します。

  • roles/redis.editor
  • roles/vpcaccess.user
  • roles/compute.viewer

環境変数を設定する

次の環境変数の値を、作成したサービス アカウントまたはプロジェクトの Compute Engine のデフォルトのサービス アカウントに設定します。

  1. CONNECTOR_SERVICE_ACCOUNT: UI コネクタ ランタイムのサービス アカウント。例: aa-ui-connector@my-project-id.iam.gserviceaccount.com
  2. INTERCEPTOR_SERVICE_ACCOUNT: Cloud Pub/Sub Interceptor ランタイムのサービス アカウント。例: aa-pubsub-interceptor@my-project-id.iam.gserviceaccount.com

ユーザー認証方法をカスタマイズする

コード リポジトリは、Genesys Cloud と Twilio のバックエンド ユーザーとフロントエンド モジュールのユーザーの両方をサポートしています。

  1. コード リポジトリ内で、ui_connector/auth.py ファイルを開きます。
  2. 環境変数 AUTH_OPTION を設定してサポートされている ID プロバイダを指定するか、auth.check_auth を使用して認証方法を実装します。

    デフォルトでは、AUTH_OPTION は空で、UI Connector サービスに JWT を登録できるユーザーはいません。サポートされる値:

    • Salesforce: Salesforce OpenID Connect を使用して認証トークンを検証します。必要な環境変数: SALESFORCE_ORGANIZATION_ID。
    • SalesforceLWC: oauth2/userinfo REST エンドポイントを使用して、Salesforce OAuth クライアント認証情報の認証トークンを検証します。必要な環境変数: SALESFORCE_ORGANIZATION_ID、SALESFORCE_DOMAIN。
    • GenesysCloud: Genesys SDK UsersAPI を使用して認証トークンを検証します。
    • Twilio: Twilio の認証トークンを検証します。必要な環境変数: TWILIO_FLEX_ENVIRONMENT。
    • Skip: 認証トークンの検証をスキップします。本番環境では使用しないでください。

    例:

    $ export AUTH_OPTION='Salesforce'

    トークンタイプごとに異なる検証方法が使用される場合があります。トークンの検証方法はユーザーが決定します。変更がない場合、auth.check_auth はすべてのリクエストに対して false を返します。

サービスにアクセスできるオリジンを制限するには、config.CORS_ALLOWED_ORIGINS 変数の値を変更します。デフォルト値の * を使用すると、任意のオリジンがサービスにアクセスできます。

JWT 秘密鍵を生成して保存する

UI コネクタ サービスが安全な認証トークンをクライアントに送信するには、JWT 秘密鍵を使用してトークンを暗号化する必要があります。キーの値には任意の文字列を使用できますが、一意で推測しにくいものにする必要があります。

このシークレット キーは Secret Manager に保存されます。

環境変数を設定する

  • JWT_SECRET_NAME: Secret Manager のシークレット鍵の名前。任意の名前を指定できます。推奨値: aa-integration-jwt-secret

キーを生成する

攻撃者に推測されないように、JWT 秘密鍵としてランダムなハッシュを生成することをおすすめします。これを行うには、python secrets を使用して、安全な乱数を生成します。

# generate_secret_key.py
import secrets
jwt_secret_key = secrets.token_bytes(16)
print(jwt_secret_key) # Output example: b'L\x9b\xd6i4\xc3\x1d\x95\xe3\xf78z\xdda\x97\xec'

キーを Secret Manager に保存する

次のコマンド例では、my_key を使用する予定のシークレット キーに置き換えます。

$ python generate_secret_key.py | gcloud secrets create $JWT_SECRET_NAME --data-file=- \
--replication-policy=user-managed --locations=$SERVICE_REGION

Memorystore for Redis を設定する

Redis を設定するには、次の環境変数が必要です。

  • VPC_CONNECTOR_NAME: Cloud Run サービスを Memorystore for Redis に接続するためのサーバーレス VPC アクセス コネクタの名前。推奨値: aa-integration-vpc
  • VPC_NETWORK: サーバーレス VPC アクセス コネクタを接続する VPC ネットワーク。 Google Cloud プロジェクトに VPC を設定しない場合、値は default にする必要があります。
  • VPC_SUBNET: Redis インスタンスがアタッチされている承認済み VPC ネットワークの名前。VPC ネットワーク設定をカスタマイズしていない場合、値は default にする必要があります。
  • REDIS_IP_RANGE: サーバーレス VPC アクセス コネクタ用に予約されていない内部 IP ネットワーク。未割り振りスペースの /28 が必要です。推奨値: 10.8.0.0/28(この値はほとんどの新しいプロジェクトで機能します)。
  • REDIS_INSTANCE_ID: Redis インスタンスの名前。推奨値: aa-integration-redis

Cloud Run サービスのリージョンに Redis インスタンスを作成する

次のコマンドを実行します。

$ gcloud redis instances create $REDIS_INSTANCE_ID --size=5 --region=$SERVICE_REGION

ダイレクト下り(外向き)またはサーバーレス VPC アクセスを使用すると、Cloud Run から Redis インスタンスに接続できます。

サーバーレス VPC アクセス コネクタを作成する {:#create-svpca-connector}(省略可)

お客様がダイレクト エグレスを選択した場合、これは現在省略可能です。サーバーレス VPC アクセスを選択した場合は、サーバーレス VPC アクセス コネクタを作成する必要があります。この手順の詳細については、Cloud Run チュートリアルをご覧ください。

プロジェクトで Serverless VPC Access API が有効になっていることを確認します。

$ gcloud services enable vpcaccess.googleapis.com

カスタム IP 範囲でサーバーレス VPC アクセス コネクタを作成します。

$ gcloud compute networks vpc-access connectors create $VPC_CONNECTOR_NAME \
  --network $VPC_NETWORK \
  --region $SERVICE_REGION \
  --range $REDIS_IP_RANGE

Redis ホストと Redis ポートを環境変数として保存する

  • Redis インスタンスの IP アドレスを環境変数 REDIS_HOST に設定します。
  • Redis インスタンスのポート番号を環境変数 REDIS_PORT に設定します。

UI コネクタ サービスをデプロイする

UI コネクタ サービスには、次の環境変数が必要です。

  • CONNECTOR_SERVICE_NAME: UI Connector の Cloud Run サービス名。推奨値: ui-connector
  • CONNECTOR_IMAGE_NAME: UI Connector サービスのイメージ名。CONNECTOR_SERVICE_NAME と同じにすることもできます。推奨値: ui-connector

Docker イメージをビルドする

/ui-connector フォルダで、次のコマンドを実行します。

$ gcloud builds submit --tag gcr.io/$GCP_PROJECT_ID/$CONNECTOR_IMAGE_NAME

UI コネクタを Cloud Run にデプロイする

/ui-connector フォルダで、次のコマンドを実行します。

  • Redis 接続に接続するためにダイレクト下り(外向き)を使用している場合。
$ gcloud run deploy $CONNECTOR_IMAGE_NAME \
--image gcr.io/$GCP_PROJECT_ID/$CONNECTOR_IMAGE_NAME \
--platform managed \
--service-account=$CONNECTOR_SERVICE_ACCOUNT_NAME \
--allow-unauthenticated \
--timeout 3600 \
--region $SERVICE_REGION \
--network $VPC_NETWORK \
--subnet $VPC_SUBNET \
--clear-vpc-connector \
--min-instances=1 \
--set-env-vars REDISHOST=$REDIS_HOST,REDISPORT=$REDIS_PORT,GCP_PROJECT_ID=$GCP_PROJECT_ID,AUTH_OPTION=$AUTH_OPTION \
--update-secrets=/secret/jwt_secret_key=${JWT_SECRET_NAME}:latest
  • 作成したサーバーレス VPC アクセス コネクタを Redis 接続に使用する場合。
$ gcloud run deploy $CONNECTOR_IMAGE_NAME \
--image gcr.io/$GCP_PROJECT_ID/$CONNECTOR_IMAGE_NAME \
--platform managed \
--service-account=$CONNECTOR_SERVICE_ACCOUNT_NAME \
--allow-unauthenticated \
--timeout 3600 \
--region $SERVICE_REGION \
--vpc-connector $VPC_CONNECTOR_NAME \
--clear-network \
--min-instances=1 \
--no-cpu-throttling \
--set-env-vars REDISHOST=$REDIS_HOST,REDISPORT=$REDIS_PORT,GCP_PROJECT_ID=$GCP_PROJECT_ID,AUTH_OPTION=$AUTH_OPTION \
--update-secrets=/secret/jwt_secret_key=${JWT_SECRET_NAME}:latest

デプロイされた UI Connector のサービス URL をメモします。これはクライアント(エージェント デスクトップ)で使用されます。

Cloud Pub/Sub インターセプタ サービスをデプロイする

Pub/Sub インターセプタ サービスには、次の環境変数が必要です。

  • INTERCEPTOR_SERVICE_NAME: Cloud Pub/Sub インターセプタの Cloud Run サービス名。推奨値: cloud-pubsub-interceptor
  • INTERCEPTOR_IMAGE_NAME: Cloud Pub/Sub インターセプタ サービスのイメージ名。INTERCEPTOR_SERVICE_NAME と同じ値を指定できます。推奨値: cloud-pubsub-interceptor
  • INTERCEPTOR_SERVICE_ACCOUNT_NAME: Cloud Pub/Sub インターセプタ ランタイムのサービス アカウント。

Docker イメージをビルドする

/cloud-pubsub-interceptor フォルダで、次のコマンドを実行します。

$ gcloud builds submit --tag gcr.io/$GCP_PROJECT_ID/$INTERCEPTOR_IMAGE_NAME

Pub/Sub インターセプタを Cloud Run にデプロイする

/cloud-pubsub-interceptor フォルダで、次のコマンドを実行します。

  • Redis 接続に接続するためにダイレクト下り(外向き)を使用している場合。
$ gcloud run deploy $INTERCEPTOR_SERVICE_NAME \
--image gcr.io/$GCP_PROJECT_ID/$INTERCEPTOR_IMAGE_NAME \
--platform managed \
--service-account=$INTERCEPTOR_SERVICE_ACCOUNT_NAME \
--region $SERVICE_REGION \
--network $VPC_NETWORK \
--subnet $VPC_SUBNET \
--clear-vpc-connector \
--ingress=internal \
--min-instances=1 \
--no-cpu-throttling \
# You can also add LOGGING_FILE here to specify the logging file path on Cloud Run.
--set-env-vars REDISHOST=$REDIS_HOST,REDISPORT=$REDIS_PORT
  • 作成したサーバーレス VPC アクセス コネクタを Redis 接続に使用する場合。
$ gcloud run deploy $INTERCEPTOR_SERVICE_NAME \
--image gcr.io/$GCP_PROJECT_ID/$INTERCEPTOR_IMAGE_NAME \
--platform managed \
--service-account=$INTERCEPTOR_SERVICE_ACCOUNT_NAME \
--region $SERVICE_REGION \
--vpc-connector $VPC_CONNECTOR_NAME \
--clear-network \
--ingress=internal \
--min-instances=1 \
# You can also add LOGGING_FILE here to specify the logging file path on Cloud Run.
--set-env-vars REDISHOST=$REDIS_HOST,REDISPORT=$REDIS_PORT

デプロイされた URL を保存する

デプロイされた URL を INTERCEPTOR_SERVICE_URL 環境変数として設定します。

Cloud Pub/Sub サブスクリプションを構成する

Cloud Pub/Sub サブスクリプションでは、次のものが使用されます。

  • トピック
  • 会話プロファイル
  • サービス アカウント
  • インターセプタ サービスに対するサービス アカウントの権限

Cloud Pub/Sub トピックを作成する

Dialogflow から必要なイベント通知の種類ごとに Cloud Pub/Sub トピックを作成します。使用可能なイベント通知のタイプは次のとおりです。

  • 新しい候補イベント: 新しいエージェント アシストの候補が利用可能になったときに送信されるイベント(顧客の発言に対する新しいスマート リプライの候補など)。
  • 新しいメッセージ イベント: エージェントまたはお客様から新しい発話が認識されるたびに送信されるイベント(お客様が Hi と発言した場合など)。
  • 新しい会話ライフサイクル イベント: 特定の会話ライフサイクルの変更(会話の開始時や完了時など)に対して送信されるイベント。
  • 新しい認識結果通知イベント: エージェントまたはお客様から中間文字起こしが認識されたときに送信されるイベント(例: お客様が Hi, how can I help you? と発言した場合、お客様の発言中に中間文字起こしが Hi how can になります)。

後でバックエンドをデプロイするために、トピック ID とトピック名をメモしておきます。

会話プロファイルを構成する

前の手順で作成した Cloud Pub/Sub トピックを使用して、会話プロファイルを構成します。

  • 新しい会話プロファイルを作成するときに、[Pub/Sub 通知] を選択し、[Pub/Sub 通知を有効にする] を選択します。有効にすると、有効にする通知の種類の横にあるチェックボックスをオンにして、通知に関連付けられた Cloud Pub/Sub トピックのトピック ID を入力できます。
  • 各トピックのメッセージ形式として JSON を選択します。

Pub/Sub サブスクリプション ID のサービス アカウントを作成する

次のコマンドを使用して、Pub/Sub サブスクリプション ID を表すサービス アカウントを作成します。

$ gcloud iam service-accounts create cloud-run-pubsub-invoker \
     --display-name "Cloud Run Pub/Sub Invoker"

インターセプタ サービスを呼び出す権限をサービス アカウントに付与する

次のコマンドを実行します。

$ gcloud run services add-iam-policy-binding $INTERCEPTOR_SERVICE_NAME \ 
  --member=serviceAccount:cloud-run-pubsub-invoker@$GCP_PROJECT_ID.iam.gserviceaccount.com \
   --role=roles/run.invoker

トピックの Cloud Pub/Sub サブスクリプションを作成する

作成したトピックごとに、対応する Cloud Pub/Sub サブスクリプションを作成する必要があります。

新しい候補イベント

your-new-suggestion-topic-id は、新しい提案用に構成した Cloud Pub/Sub トピックに置き換えます。

$ export TOPIC_ID='your-new-suggestion-topic-id' && gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_ID \
   --push-endpoint=$INTERCEPTOR_SERVICE_URL/human-agent-assistant-event \
   --push-auth-service-account=cloud-run-pubsub-invoker@$GCP_PROJECT_ID.iam.gserviceaccount.com
新しいメッセージ イベント

your-new-message-event-topic-id は、新しいメッセージ イベント用に構成した Cloud Pub/Sub トピックに置き換えます。

$ export TOPIC_ID='your-new-message-event-topic-id' && gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_ID \
   --push-endpoint=$INTERCEPTOR_SERVICE_URL/new-message-event \
   --push-auth-service-account=cloud-run-pubsub-invoker@$GCP_PROJECT_ID.iam.gserviceaccount.com
会話のライフサイクル イベント

your-conversation-lifecycle-event-topic は、新しい会話のライフサイクル イベント用に構成した Cloud Pub/Sub トピックに置き換えます。

$ export TOPIC_ID='your-conversation-lifecycle-event-topic' && gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_ID \
   --push-endpoint=$INTERCEPTOR_SERVICE_URL/conversation-lifecycle-event \
   --push-auth-service-account=cloud-run-pubsub-invoker@$GCP_PROJECT_ID.iam.gserviceaccount.com
新しい認識結果通知イベント
$ export TOPIC_ID='your-new-recognition-result-notification-event-topic' && gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_ID \
   --push-endpoint=$INTERCEPTOR_SERVICE_URL/new-recognition-result-notification-event \
   --push-auth-service-account=cloud-run-pubsub-invoker@$GCP_PROJECT_ID.iam.gserviceaccount.com