通过 Cloud Run 服务对 Cloud Storage 中的 PDF(非结构化数据)使用 Vertex AI Search

1. 简介

概览

借助 Vertex AI Search and Conversation(以前称为 Generative AI App Builder),开发者可以充分利用 Google 的基础模型、搜索专业知识和对话式 AI 技术来创建企业级生成式 AI 应用。本 Codelab 重点介绍如何使用 Vertex AI Search,您可以基于自己的数据构建 Google 品质的搜索应用,并在网页或应用中嵌入搜索栏。

Cloud Run 是一个托管式计算平台,可让您直接在 Google 可伸缩的基础架构之上运行容器。您可以使用基于源代码的部署选项,在 Cloud Run 上部署使用任何编程语言编写的代码(能够放入容器中)。

在此 Codelab 中,您将使用基于源代码的部署创建一个 Cloud Run 服务,以检索 Cloud Storage 存储分区中 PDF 文件内非结构化内容的搜索结果。您可以点击此处详细了解如何提取非结构化内容。

学习内容

  • 如何为从 Cloud Storage 存储分区注入的 PDF 格式的非结构化数据创建 Vertex AI Search 应用
  • 如何在 Cloud Run 中使用基于源代码的部署创建 HTTP 端点
  • 如何根据最小权限原则创建服务账号,供 Cloud Run 服务用于查询 Vertex AI Search 应用
  • 如何调用 Cloud Run 服务来查询 Vertex AI Search 应用

2. 设置和要求

前提条件

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud Shelld1264ca30785e435.png

cb81e7c8e34bc8d.png

如果您是第一次启动 Cloud Shell,系统会显示一个介绍其功能的过渡页面。如果您看到了过渡页面,请点击继续

d95252b003979716.png

预配和连接到 Cloud Shell 只需花几分钟时间。

7833d5e1c5d18f54.png

这个虚拟机已加载了所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器即可完成本 Codelab 中的大部分工作。

连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID。

  1. 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list

命令输出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project

命令输出

[core]
project = <PROJECT_ID>

如果不是上述结果,您可以使用以下命令进行设置:

gcloud config set project <PROJECT_ID>

命令输出

Updated property [core/project].

3. 启用 API

在开始使用 Vertex AI Search 之前,您需要启用多个 API。

首先,此 Codelab 需要使用 Vertex AI Search and Conversation、BigQuery、Cloud Storage API。您可以在此处启用这些 API

其次,请按以下步骤启用 Vertex AI Search and Conversation API:

  1. 在 Google Cloud 控制台中,前往 Vertex AI Search and Conversation 控制台
  2. 阅读并同意服务条款,然后点击“继续”并激活 API。

4. 为 Cloud Storage 中的非结构化数据创建搜索应用

  1. 在 Google Cloud 控制台中,前往 Search & Conversation 页面。点击新建应用
  2. 选择应用类型窗格中,选择搜索
  3. 确保企业功能启用,以便接收从您的文档中逐字提取的回答。
  4. 确保高级 LLM 功能选项处于启用状态,以便接收搜索摘要。
  5. 应用名称字段中,输入应用的名称。应用 ID 显示在应用名称下方。
  6. 选择 global (Global) 作为应用的位置,然后点击继续
  7. 数据存储区窗格中,点击创建新的数据存储区
  8. 选择数据源窗格中,选择 Cloud Storage
  9. 从 GCS 导入数据窗格中,确保已选择文件夹
  10. gs:// 字段中,输入以下值:cloud-samples-data/gen-app-builder/search/stanford-cs-224 此 Cloud Storage 存储分区包含来自公开提供的 Cloud Storage 文件夹的 PDF 文件,仅用于测试目的。
  11. 选择非结构化文档,然后点击继续
  12. 配置数据存储区窗格中,选择全球作为数据存储区的位置。
  13. 为数据存储区输入一个名称。在本 Codelab 的后面部分部署 Cloud Run 服务时,您将用到此名称。点击创建
  14. 数据存储区窗格中,选择新的数据存储区,然后点击创建
  15. 在数据存储区的数据页面上,点击活动标签页以查看数据注入的状态。导入过程完成后,“状态”列中会显示导入已完成
  16. 点击文档标签页以查看导入的文档数量。
  17. 在导航菜单中,点击预览以测试搜索应用。
  18. 在搜索栏中,输入 final lab due date,然后按 Enter 键以查看结果。

5. 创建 Cloud Run 服务

在本部分中,您将创建一个 Cloud Run 服务,该服务接受搜索字词的查询字符串。此服务将使用 Discovery Engine API 的 Python 客户端库。如需查看其他受支持的运行时,请点击此处查看列表

创建函数的源代码

首先,创建一个目录,然后通过 cd 命令进入该目录。

mkdir docs-search-service-python && cd $_

然后,创建一个包含以下内容的 requirements.txt 文件:

blinker==1.6.3
cachetools==5.3.1
certifi==2023.7.22
charset-normalizer==3.3.0
click==8.1.7
Flask==3.0.0
google-api-core==2.12.0
google-auth==2.23.3
google-cloud-discoveryengine==0.11.2
googleapis-common-protos==1.61.0
grpcio==1.59.0
grpcio-status==1.59.0
idna==3.4
importlib-metadata==6.8.0
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
numpy==1.26.1
proto-plus==1.22.3
protobuf==4.24.4
pyasn1==0.5.0
pyasn1-modules==0.3.0
requests==2.31.0
rsa==4.9
urllib3==2.0.7
Werkzeug==3.0.1
zipp==3.17.0

接下来,创建一个包含以下内容的 main.py 源文件:

from typing import List
import json
import os
from flask import Flask
from flask import request

app = Flask(__name__)

from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine_v1 as discoveryengine

project_id = os.environ.get('PROJECT_ID')
location = "global"  # Values: "global", "us", "eu"
data_store_id = os.environ.get('SEARCH_ENGINE_ID')

print(project_id)
print(data_store_id)

@app.route("/")
def search_storage():

    search_query = request.args.get("searchQuery")

    result = search_sample(project_id, location, data_store_id, search_query)
    return result

def search_sample(
    project_id: str,
    location: str,
    data_store_id: str,
    search_query: str,
) -> str:
    #  For more information, refer to:
    # https://cloud.google.com/generative-ai-app-builder/docs/locations#specify_a_multi-region_for_your_data_store
    client_options = (
        ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
        if location != "global"
        else None
    )

    # Create a client
    client = discoveryengine.SearchServiceClient(client_options=client_options)

    # The full resource name of the search engine serving config
    # e.g. projects/{project_id}/locations/{location}/dataStores/{data_store_id}/servingConfigs/{serving_config_id}
    serving_config = client.serving_config_path(
        project=project_id,
        location=location,
        data_store=data_store_id,
        serving_config="default_config",
    )

    # Optional: Configuration options for search
    # Refer to the `ContentSearchSpec` reference for all supported fields:
    # https://cloud.google.com/python/docs/reference/discoveryengine/latest/google.cloud.discoveryengine_v1.types.SearchRequest.ContentSearchSpec
    content_search_spec = discoveryengine.SearchRequest.ContentSearchSpec(
        # For information about snippets, refer to:
        # https://cloud.google.com/generative-ai-app-builder/docs/snippets
        snippet_spec=discoveryengine.SearchRequest.ContentSearchSpec.SnippetSpec(
            return_snippet=True
        ),
        # For information about search summaries, refer to:
        # https://cloud.google.com/generative-ai-app-builder/docs/get-search-summaries
        summary_spec=discoveryengine.SearchRequest.ContentSearchSpec.SummarySpec(
            summary_result_count=5,
            include_citations=True,
            ignore_adversarial_query=True,
            ignore_non_summary_seeking_query=True,
        ),
    )


    # Refer to the `SearchRequest` reference for all supported fields:
    # https://cloud.google.com/python/docs/reference/discoveryengine/latest/google.cloud.discoveryengine_v1.types.SearchRequest
    request = discoveryengine.SearchRequest(
        serving_config=serving_config,
        query=search_query,
        page_size=10,
        content_search_spec=content_search_spec,
        query_expansion_spec=discoveryengine.SearchRequest.QueryExpansionSpec(
            condition=discoveryengine.SearchRequest.QueryExpansionSpec.Condition.AUTO,
        ),
        spell_correction_spec=discoveryengine.SearchRequest.SpellCorrectionSpec(
            mode=discoveryengine.SearchRequest.SpellCorrectionSpec.Mode.AUTO
        ),
    )

    response = client.search(request)

    return response.summary.summary_text

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

设置环境变量

在此代码中,您将创建几个环境变量,以提高此 Codelab 中使用的 gcloud 命令的可读性。

PROJECT_ID=$(gcloud config get-value project)

SERVICE_NAME="search-storage-pdfs-python"
SERVICE_REGION="us-central1"

# update with your data store name
SEARCH_ENGINE_ID=<your-data-store-name>

创建服务账号

此 Codelab 展示了如何为 Cloud Run 服务创建一个服务账号,以便该服务使用此账号访问 Vertex AI Search API。

SERVICE_ACCOUNT="cloud-run-vertex-ai-search"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run Vertex AI Search service account"

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role='roles/discoveryengine.editor'

部署 Cloud Run 服务

现在,您可以使用基于源代码的部署来自动容器化 Cloud Run 服务。

gcloud run deploy $SERVICE_NAME \
--region=$SERVICE_REGION \
--source=. \
--service-account $SERVICE_ACCOUNT \
--update-env-vars SEARCH_ENGINE_ID=$SEARCH_ENGINE_ID,PROJECT_ID=$PROJECT_ID \
--no-allow-unauthenticated

然后,您可以将 Cloud Run 网址保存为环境变量以供日后使用。

ENDPOINT_URL="$(gcloud run services describe $SERVICE_NAME --region=$SERVICE_REGION --format='value(status.url)')"

6. 调用 Cloud Run 服务

您现在可以使用查询字符串调用 Cloud Run 服务,以询问 What is the final lab due date?

curl -H "Authorization: bearer $(gcloud auth print-identity-token)" "$ENDPOINT_URL?searchQuery=what+is+the+final+lab+due+date"

您的结果应类似于以下示例输出:

The final lab is due on Tuesday, March 21 at 4:30 PM [1].

7. 恭喜!

恭喜您完成此 Codelab!

建议您查看有关 Vertex AI SearchCloud Run 的文档。

所学内容

  • 如何为从 Cloud Storage 存储分区注入的 PDF 格式的非结构化数据创建 Vertex AI Search 应用
  • 如何在 Cloud Run 中使用基于源代码的部署创建 HTTP 端点
  • 如何创建服务账号,遵循最小权限原则,供 Cloud Run 服务用于查询 Vertex AI Search 应用。
  • 如何调用 Cloud Run 服务来查询 Vertex AI Search 应用

8. 清理

为避免产生意外费用(例如,如果此 Cloud Functions 函数被意外调用多次,超过了免费层级中每月 Cloud Functions 函数调用次数的分配额度),您可以删除该 Cloud Functions 函数,也可以删除您在第 2 步中创建的项目。

如需删除 Cloud Functions 函数,请前往 Cloud Functions Cloud 控制台 (https://console.cloud.google.com/functions/),然后删除 imagen_vqa 函数(如果您使用了其他名称,请删除 $FUNCTION_NAME)。

如果您选择删除整个项目,可以前往 https://console.cloud.google.com/cloud-resource-manager,选择您在第 2 步中创建的项目,然后选择“删除”。如果您删除项目,则需要在 Cloud SDK 中更改项目。您可以运行 gcloud projects list 查看所有可用项目的列表。