将后端模块与您的系统集成

后端模块提供了一种基础架构,用于处理大量与功能相关的消息并与客服人员桌面界面进行交互。本教程将引导您完成将后端模块与代理系统集成的过程。

如需详细了解后台模块的概念和结构,请参阅后台模块基础知识文档。

前提条件

  1. 如果您尚未配置,请安装 Google Cloud CLI
  2. 为需要从 Dialogflow 收到的每种事件通知创建 Cloud Pub/Sub 主题。记下主题 ID 和主题名称,以备后续后端部署使用。
  3. 使用 Agent Assist 控制台和 Pub/Sub 主题配置对话配置文件

自动部署

部署可以通过 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. 为界面连接器和 Cloud Pub/Sub 拦截器构建映像,并记下映像名称。
    • 对于界面连接器,请在 ./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. 创建一个 Cloud Storage 存储桶来存储 Terraform 状态,并使用以下命令更新 /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.py 中的 auth.check_auth() 方法来自定义身份验证方法。

如果您想使用 Cloud Build 自动执行这些步骤,请按照此说明操作,并使用 build 配置文件 ./terraform_cloudbuild.yaml。如需允许 Cloud Build 部署服务,您需要向 Cloud Build 服务账号授予第 1 步中列出的 IAM 角色。

手动部署

以下步骤介绍了如何手动部署后端模块。

设置环境变量

为了简化部署命令,我们建议您在 shell 中设置以下有用的环境变量。您可以使用以下示例命令设置变量:

$ export GCP_PROJECT_ID='aa-integration-service'

设置以下环境变量:

  • GCP_PROJECT_ID:托管相关资源的 Cloud Platform 项目的 ID。示例:my-project
  • SERVICE_REGION:服务和相关 Google Cloud 资源的位置或区域。 平台资源。示例:us-central1

设置管理员账号

我们建议您使用单独的 Google Cloud 账号进行服务管理和运行时身份验证。服务管理主要由拥有 Google 账号的人员执行,而运行时身份则使用服务账号向 Cloud Run 服务授予权限,以实现对必要资源的访问。

准备人工管理账号

如果您计划使用已在项目中拥有编辑者或所有者权限的账号,则可以跳到下一部分

如需管理后端基础架构,请设置管理员账号并向其授予以下 Identity and Access Management (IAM) 角色。Editor 和 Owner 基本角色中包含这些角色的所有权限。

  • roles/secretmanager.admin (Secret Manager Admin):管理存储在 Secret Manager 中的用于 JWT 生成和验证的密文。
  • roles/run.admin(Cloud Run Admin):部署和管理 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 Editor):创建和管理 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 服务分配一个用户代管式服务账号,并授予一组最低必需权限,而不是使用默认服务账号,从而为该服务提供专用身份。如果您打算保留默认服务账号,可以跳过此步骤,直接设置环境变量

为每个 Cloud Run 运行时创建两个服务账号

  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. 使用以下示例命令将以下角色分配给界面连接器和服务账号和 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'

向界面连接器服务账号授予以下 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:界面连接器运行时的服务账号。 示例:aa-ui-connector@my-project-id.iam.gserviceaccount.com
  2. INTERCEPTOR_SERVICE_ACCOUNT:Cloud Pub/Sub 拦截器运行时的服务账号。示例:aa-pubsub-interceptor@my-project-id.iam.gserviceaccount.com

自定义用户身份验证方法

代码库同时支持后端用户以及 Genesys Cloud 和 Twilio 的前端模块用户。

  1. 在代码库中,打开 ui_connector/auth.py 文件。
  2. 通过设置环境变量 AUTH_OPTION 指定受支持的身份提供商,或使用 auth.check_auth 实现身份验证方法。

    默认情况下,AUTH_OPTION 为空,不允许任何用户向界面连接器服务注册 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 密钥

为了让界面连接器服务将安全身份验证令牌发送回客户端,它必须使用 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

部署界面连接器服务

对于界面连接器服务,您需要以下环境变量:

  • CONNECTOR_SERVICE_NAME:界面连接器的 Cloud Run 服务名称。 建议值:ui-connector
  • CONNECTOR_IMAGE_NAME:界面连接器服务的映像名称。它可以与 CONNECTOR_SERVICE_NAME 相同。建议值:ui-connector

构建 Docker 映像

/ui-connector 文件夹下,运行以下命令:

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

将界面连接器部署到 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

记下已部署的界面连接器的服务网址,该网址将供客户端(客服人员桌面)使用。

部署 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

保存已部署的网址

将已部署的网址设置为 INTERCEPTOR_SERVICE_URL 环境变量。

配置 Cloud Pub/Sub 订阅

Cloud Pub/Sub 订阅使用以下内容:

  • 主题
  • 对话资料
  • 服务账号
  • 拦截器服务的服务账号权限

创建 Cloud Pub/Sub 主题

为需要从 Dialogflow 收到的每种事件通知创建 Cloud Pub/Sub 主题。可用的事件通知类型包括:

  • 新的建议事件:当有新的 Agent Assist 建议可用时发送的事件(例如,针对客户话语的新智能回复建议)。
  • 新消息事件:每当识别出客服人员或客户的新话语(例如,客户说“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 订阅身份创建服务账号

使用以下命令创建一个表示 Pub/Sub 订阅身份的服务账号:

$ 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