使用事件异步调用智能体 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 和 Cloud SDK 库(适用于 Python)。如需检查行为,您将使用 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 文件夹下的文件,即可查看 agentic 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. 总结

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

清理

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

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

方法 1:关停项目

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

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

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

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

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

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

详细了解如何关停项目

后续步骤