使用事件异步调用智能体 AI 应用

1. 简介

概览

本实验演示了如何使用 Eventarc 和 Pub/Sub 服务安全地实现对部署在 Cloud Run 上的 ADK 代理的事件驱动型调用。在大多数情况下,代理由用户或其他代理直接调用。不过,当代理集成到基于事件的现有工作流中时,直接调用需要更改现有软件。根据事件触发代理调用,可将代理纳入现有工作流,而无需更改工作流。

您将执行的操作

在本实验中,您将创建一个 ZooKeeper 智能体应用,该应用具有 AI 智能体,并使用多种工具来提供有关虚构动物园中动物的信息。

Zoo-Keeper 插图

您将以服务的形式将 ZooKeeper 应用部署到 Cloud Run,后者是一个全托管式无服务器计算平台,可在 Google 的基础设施上运行无状态容器。然后,您将设置一个 Eventarc 触发器,该触发器将调用服务端点来异步处理发布到 Pub/Sub 主题的消息。您将确保部署遵循最佳实践,包括使用指定的 IAM 服务账号、授予最低权限的访问权限,以及仅向 Eventarc 公开 ZooKeeper 应用的端点,从而最大限度地减少潜在的攻击面。您将在 Cloud Shell 和 Cloud 控制台的帮助下完成此操作。您将使用 ADK 和 Python 版 Cloud SDK 库。如需检查行为,您将使用 gcloud CLI。

学习内容

  • 将 ADK 代理部署到 Google Cloud Run。
  • 将 Eventarc 触发器与在 Google Cloud Run 上运行的 ADK 代理集成。
  • 借助 Google Cloud IAM,遵循最小权限原则来保护您的部署和与 Eventarc 的集成。
  • 向 Pub/Sub 发布消息以及从 Pub/Sub 拉取消息。
  • 最大限度地减少部署到 Google Cloud Run 的应用的公开曝光。

所需条件

  • Chrome 网络浏览器†
  • 个人 Google 账号 ‡
  • 与有效结算账号相关联的 Google Cloud 项目

请注意,您的账号必须具有对项目的 IAM 访问权限,以便您预配资源并配置对这些资源的 IAM 访问权限。

† 使用其他浏览器的用户体验可能与实验中所述的不同。

‡ 使用公司或学校账号可能无法执行实验中描述的某些操作。

2. 环境设置

为确保实验室的开发环境功能齐全,您将使用 Google Cloud Shell,其中预安装了所有必需的工具。按照说明设置环境。

如果您没有 Google 账号,请创建 Google 账号。

设置说明

  1. 使用您的 Google 账号登录 Google Cloud 控制台。
  2. 👉 打开顶部导航栏中的项目选择器(可能会显示“选择项目”或现有项目名称),或按 Ctrl+O 键盘快捷键,然后选择现有项目或创建新项目。创建新项目需要几秒钟时间。等待项目准备就绪,然后使用项目选择器选择该项目。
  1. 👉 点击 Google Cloud 控制台顶部的 Cloud Shell 图标。(以红色矩形标记):Cloud Shell 按钮
    如果系统要求您授权,请在弹出式对话框中点击 **授权**,以批准 Cloud Shell 使用您账号的凭据。
    授权对话框
  2. 👉💻 确保 gcloud CLI 已配置为使用您选择(或创建)的项目。运行以下命令以检查配置的项目 ID:
    gcloud config get-value project
    
    您应该会看到类似于以下内容的输出:
    Your active configuration is: [cloudshell-19597]
    [PROJECT_ID]
    
    ,其中 [PROJECT_ID] 是您选择或创建的项目 ID。👉💻 如果您看到其他值,请运行以下命令,将您的项目 ID 配置为 gcloud CLI 命令的默认项目 ID:
    gcloud config set project [YOUR_PROJECT_ID]
    
    例如,如果您的项目 ID 为 lab-project-id-example-123,则命令应为:
    gcloud config set project lab-project-id-example-123
    
    🤔💻 如果您不记得项目 ID,请使用以下命令列出您有权访问的所有项目 ID(从最近的项目开始):
    gcloud projects list \
        --format='value(projectId)' \
        --sort-by='~createTime'
    
  1. 👉💻 在环境变量中设置用于预配资源的位置以及项目 ID 和编号:
    export LOCATION="us-central1"
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
    
  2. 👉💻 启用本实验所需的 Google API。
    gcloud services enable \
        aiplatform.googleapis.com \
        eventarc.googleapis.com \
        run.googleapis.com \
        artifactregistry.googleapis.com \
        cloudbuild.googleapis.com \
        pubsub.googleapis.com
    
    请耐心等待,此命令可能需要几分钟时间。成功执行该命令后,您应该会看到类似于以下内容的消息:
    Operation "operations/ab12345c-6e7f-8ghi-jkl9-m0e1d23456f7" finished successfully.
    

3. 部署 ZooKeeper 演示应用

以下步骤将预配和配置资源,包括部署智能体 AI 应用。

设置 Pub/Sub 资源

您将创建两个 Pub/Sub 主题。一个将由第三方服务用于向您的智能体 AI 应用发送事件。另一个用于发布事件处理结果。

  1. 👉💻 创建用于触发智能体 AI 应用的 Pub/Sub 主题:
    gcloud pubsub topics create invoke_agent
    export INVOKE_TOPIC_ID=$(gcloud pubsub topics describe invoke_agent --format="value(name)")
    
  2. 👉💻 创建一个 Pub/Sub 主题,供应用发布其响应:
    gcloud pubsub topics create agent_responses
    export RESPONSE_TOPIC_ID=$(gcloud pubsub topics describe agent_responses --format="value(name)")
    gcloud pubsub subscriptions create agent_responses \
        --topic=agent_responses
    
    这些命令还会为创建的 Pub/Sub 主题创建订阅。当您运行演示版时,系统会使用该订阅来显示结果。

设置服务账号和项目级层 IAM 政策

您将创建两个服务账号,以根据最小权限原则将 Cloud Run 服务和 Eventarc 触发器的访问权限范围限制为最低限度。Cloud Run 服务需要以下权限:写入日志和轨迹、在 Google Vertex AI 上调用 Gemini LLM,以及将结果发布到 Pub/Sub 主题。Eventarc 触发器的最低访问权限需要具备调用 Cloud Run ZooKeeper 服务和访问 Pub/Sub 以读取已发布事件的权限。这些说明将引导您向触发器的服务账号授予模拟 Pub/Sub 系统服务所需的权限。创建 Eventarc 触发器资源后,您将运行以下命令来授予 roles/run.invoker 角色,以使触发器的服务账号能够调用 Cloud Run 服务。

  1. 👉💻 为 Cloud Run 服务创建服务账号:
    gcloud iam service-accounts create zookeeper-cloudrun-sa
    export ZOOKEEPER_SA="zookeeper-cloudrun-sa@${PROJECT_ID}.iam.gserviceaccount.com"
    
  2. 👉💻 向服务账号授予在 Vertex AI 上写入日志和轨迹以及使用 Gemini 模型的权限:
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
         --member="serviceAccount:${ZOOKEEPER_SA}" \
         --role="roles/logging.logWriter" \
         --condition=None
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/cloudtrace.agent" \
        --condition=None
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/aiplatform.user" \
        --condition=None
    
  3. 👉💻 向服务账号授予向“agent_responses”主题发布消息的权限:
    gcloud pubsub topics add-iam-policy-binding agent_responses \
        --member="serviceAccount:${ZOOKEEPER_SA}" \
        --role="roles/pubsub.publisher"
    
  4. 👉💻 为 Eventarc 触发器创建服务账号:
    gcloud iam service-accounts create zookeeper-trigger-sa
    export TRIGGER_SA="zookeeper-trigger-sa@${PROJECT_ID}.iam.gserviceaccount.com"
    
  5. 👉💻 向 Pub/Sub 系统服务账号授予权限,以发出经过身份验证的推送请求:
    gcloud iam service-accounts add-iam-policy-binding "${TRIGGER_SA}" \
           --member="serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com" \
        --role="roles/iam.serviceAccountTokenCreator"
    
    如果项目是 2021 年 4 月 8 日之后创建的,则此命令是可选的。

将 ZooKeeper 应用部署到 Cloud Run

您将从 GitHub 下载演示应用的相应代码。并将代码部署到 Cloud Run。

  1. 👉💻 下载智能体 AI 应用:
    mkdir zoo-keeper-lab && cd zoo-keeper-lab
    git init
    git remote add origin https://github.com/GoogleCloudPlatform/devrel-demos
    git config set core.sparseCheckout true
    echo "ai-ml/agent-labs/adk_invoke_with_pubsub/" >> .git/info/sparse-checkout
    git pull origin main --depth 1
    cd ai-ml/agent-labs/adk_invoke_with_pubsub/
    
    这些命令使用演示版应用文件夹的 Git 稀疏检出,以缩短下载时间。
  2. 👉💻 将智能体 AI 应用部署到 Cloud Run:
    gcloud run deploy zookeeper-agent \
        --region="${LOCATION}" \
        --source="." \
        --no-allow-unauthenticated \
        --quiet \
        --service-account="${ZOOKEEPER_SA}" \
        --set-env-vars="REPLY_TOPIC_ID=${RESPONSE_TOPIC_ID}"
    

配置 Eventarc 触发器

准备好所有资源(Pub/Sub 主题、IAM 服务账号和 Cloud Run 服务)后,就可以设置 Eventarc 触发器资源了。您将创建 Eventarc 触发器资源,并向触发器的服务账号授予调用 Cloud Run 服务的权限。

  1. 👉💻 创建 Eventarc 触发器:
    gcloud eventarc triggers create invoke-agent \
        --location="${LOCATION}" \
        --destination-run-service="zookeeper-agent" \
        --destination-run-path="/zookeeper" \
        --destination-run-region="${LOCATION}" \
        --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
        --transport-topic="${INVOKE_TOPIC_ID}" \
        --service-account="${TRIGGER_SA}"
    
  2. 👉💻 向触发器的服务账号授予调用 Cloud Run 服务的权限:
    gcloud run services add-iam-policy-binding zookeeper-agent \
        --region="${LOCATION}" \
        --member="serviceAccount:${TRIGGER_SA}" \
        --role="roles/run.invoker"
    

4. 查看解决方案的运作方式

现在,查看您刚刚部署的内容。下图反映了所有资源以及它们如何相互交互。您将使用 gcloud CLI 将消息发布到“invoke_agent”主题。这将模拟第三方服务记录到通讯服务中的事件,以调用智能体 AI 应用。

解决方案图

部署遵循最小权限原则,因此非常安全。Cloud Run 服务强制执行身份验证(请参阅上一部分中第 9 步的 --no-allow-unauthenticated 实参)。只有具有 roles/run.invoker 或类似权限的身份才能调用该服务。此角色仅授予 Eventarc 触发器的服务账号。同样,对“invoke_agent”主题的访问权限也已最小化,以禁止未经授权的事件发布。仍然可以直接调用 ZooKeeper 代理,绕过向 Pub/Sub 主题发布消息的步骤。请参阅第 6 部分,了解如何隐藏应用的端点,使其无法公开访问。

运行工作流

您将通过向 ZooKeeper 发布自然语言问题来模拟外部事件。

👉💻 使用以下命令将消息发布到 Pub/Sub 主题:

gcloud pubsub topics publish invoke_agent \
    --message='{"user_id": "important_app", "prompt": "How many animals are in the zoo?"}'

实际上,活动信息的可读性可能较差。为了处理该事件,智能体 AI 应用需要获得有关事件格式、数据以及智能体应如何处理事件信息的详细说明。

您可以检查代理是否已收到事件、处理请求并将响应发布到“agent_responses”主题。如需读取响应,您将使用“agent_responses”订阅(在此 Codelab 中,主题和订阅的 ID 相同,用于接收响应)。

👉💻 使用以下命令从 Pub/Sub 订阅中读取代理的响应:

gcloud pubsub subscriptions pull agent_responses --auto-ack

输出将打印一个表格,其中包含消息元数据和载荷(包含“动物园中有 33 个物种”这一答案)。--auto-ack 标志会在拉取消息后自动确认消息,因此不会再次传送消息。

运作方式

打开 Cloud Shell 编辑器,然后查看 ~/zoo-keeper-lab 文件夹下的文件,即可查看智能体 AI 应用的源代码。您还可以在 GitHub 上查看源代码。

  • main.py 实现了一个基本的 FastAPI Web 应用,其中包含一个处理 Eventarc 事件的处理程序。
  • processor.py 会解析事件的消息,以检索用户 ID 和请求。然后,它会在 ADK 运行程序中创建一个新会话,并调用 Zookeeper 代理来处理请求。代理的响应会发布到“agent_responses”Pub/Sub 主题。
  • 子文件夹 zookeeper_agent 包含 ADK 代理的源代码。您可以从应用的根文件夹运行命令 adk run zookeeper_agent,以使用 ADK CLI 与智能体互动。

问题排查操作说明

如果上述任何命令失败,请仔细阅读错误消息。如果向 Cloud Run 的部署失败,第一步是确定失败发生在流程的哪个阶段。

  • 如果“gcloud run deploy...”命令的输出报告 build 失败,请查看输出中的 build 日志网址,并在单独的窗口中打开该网址。
  • 如果输出显示“服务启动失败”或类似内容,则表示服务已部署,但执行失败,健康检查未通过。在这种情况下,请打开日志浏览器,或参阅下段中的 gcloud CLI 命令。读取日志以查找失败的根本原因。

如果您向 Pub/Sub 发布了消息,但代理未响应或响应看起来很奇怪,该怎么办?

👉💻 使用以下命令读取最近一次执行发布的应用日志:

gcloud logging read \
    'resource.type = "cloud_run_revision" AND \
     resource.labels.service_name = "zookeeper-agent" AND \
     resource.labels.location = "us-central1"'

日志会跟踪执行情况并报告错误,例如消息载荷不正确或无法解析、来自 Gemini 模型的响应无效、环境设置无效以及其他可能的问题。

5. 强化部署安全性

您部署的 Cloud Run 服务公开了一个可供互联网上的任何人调用的公共端点。虽然端点受到保护,可防止未经授权的调用,并且会严格验证请求的结构,但它仍然会留下此攻击途径,从而导致拒绝服务攻击和拒绝钱包攻击。由于当前设计中服务的唯一调用路径是通过 Eventarc 触发器,因此服务无需向互联网公开其端点。

👉💻 通过将对服务的调用限制为仅来自有限的来源集合(包括 Eventarc 触发器)来关闭此攻击途径:

gcloud run services update zookeeper-agent --region=${LOCATION} --ingress=internal

现在,如果您尝试从本地机器调用服务的网址,将会收到“404 找不到网页”错误。

👉💻 使用 curl 向服务端点发送请求:

URL=$(gcloud run services describe zookeeper-agent --region=${LOCATION} --format='value(status.url)')
curl -X POST -d '{}' "${URL}/zookeeper"

您将看到类似于以下内容的输出:

<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>404 Page not found</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Page not found</h1>
<h2>The requested URL was not found on this server.</h2>
<h2></h2>
</body></html>

更改后,除非您从同一项目中的 VPC、您的修订版本配置为向其发送流量的共享 VPC 网络或属于 VPC Service Controls 边界的主机进行调用,否则无法再通过调用 Cloud Run 服务端点直接调用 ZooKeeper。

6. 总结

恭喜!您已成功设置环境,以异步方式调用由传入事件触发的智能体 AI 应用。

清理

请注意,保留您预配的资源可能会导致您的结算账号产生费用。如果您不打算使用此环境进行更多实验,并且为了避免产生即将到来的费用,建议您删除在此 Codelab 期间创建的资源。

您可以通过以下两种方法实现此目的:

方法 1:关停项目

关闭(删除)项目会释放项目的所有资源和数据,并解除结算账号的关联。使用此方法可避免因本 Codelab 中使用的任何资源或数据而产生进一步的费用。使用以下命令关闭项目:

gcloud projects delete $(gcloud config get-value project) --quiet

方法 2:删除项目中的资源

删除 Cloud Run 服务可避免因使用无服务器平台而产生更多费用。请注意,此方法不会完全移除 Codelab 期间生成的所有数据,例如 Cloud Build 和应用日志、容器映像等。运行以下命令可删除服务:

gcloud run services delete zookeeper-agent --region=${LOCATION}

Eventarc 触发器定义和 Pub/Sub 主题不会产生管理费用(如需了解详情,请参阅 Eventarc 价格和 Pub/Sub 价格)。

详细了解如何关停项目。

后续步骤