Usar a Vertex AI para Pesquisa em PDFs (dados não estruturados) no Cloud Storage a partir de um serviço do Cloud Run

1. Introdução

Visão geral

A Vertex AI para Pesquisa e Conversação (antes conhecida como Generative AI App Builder) permite que os desenvolvedores aproveitem o poder dos modelos de fundação, da experiência em pesquisa e das tecnologias de IA de conversação do Google para criar aplicativos de IA generativa de nível empresarial. Este codelab se concentra no uso da Vertex AI para Pesquisa, em que é possível criar um app de pesquisa com a qualidade do Google usando seus próprios dados e incorporar uma barra de pesquisa nas páginas da Web ou no app.

O Cloud Run é uma plataforma de computação gerenciada para gerar contêineres diretamente na infraestrutura escalonável do Google. É possível implantar um código escrito em qualquer linguagem de programação no Cloud Run (que pode ser colocado em um contêiner) usando a opção de implantação baseada em origem.

Neste codelab, você vai criar um serviço do Cloud Run usando a implantação baseada em origem para recuperar resultados da pesquisa de conteúdo não estruturado em arquivos PDF em um bucket do Cloud Storage. Saiba mais sobre como ingerir conteúdo não estruturado.

O que você vai aprender

  • Como criar um app da Vertex AI para Pesquisa com dados não estruturados em PDFs ingeridos de um bucket do Cloud Storage
  • Como criar um endpoint HTTP usando a implantação baseada em origem no Cloud Run
  • Como criar uma conta de serviço seguindo o princípio de privilégio mínimo para o serviço do Cloud Run usar ao consultar o app Vertex AI para Pesquisa
  • Como invocar o serviço do Cloud Run para consultar o app da Vertex AI para Pesquisa

2. Configuração e requisitos

Pré-requisitos

Ativar o Cloud Shell

  1. No Console do Cloud, clique em Ativar o Cloud Shelld1264ca30785e435.png.

cb81e7c8e34bc8d.png

Se esta for a primeira vez que você inicia o Cloud Shell, uma tela intermediária vai aparecer com a descrição dele. Se isso acontecer, clique em Continuar.

d95252b003979716.png

Leva apenas alguns instantes para provisionar e se conectar ao Cloud Shell.

7833d5e1c5d18f54.png

Essa máquina virtual contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Neste codelab, quase todo o trabalho pode ser feito com um navegador.

Depois de se conectar ao Cloud Shell, você vai ver que sua conta já está autenticada e que o projeto está configurado com o ID do seu projeto.

  1. Execute o seguinte comando no Cloud Shell para confirmar se a conta está autenticada:
gcloud auth list

Resposta ao comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Execute o comando a seguir no Cloud Shell para confirmar se o comando gcloud sabe sobre seu projeto:
gcloud config list project

Resposta ao comando

[core]
project = <PROJECT_ID>

Se o projeto não estiver configurado, configure-o usando este comando:

gcloud config set project <PROJECT_ID>

Resposta ao comando

Updated property [core/project].

3. Ativar APIs

Antes de usar a Vertex AI para Pesquisa, é necessário ativar várias APIs.

Primeiro, este codelab exige o uso das APIs Vertex AI para Pesquisa e Conversação, BigQuery e Cloud Storage. Ative essas APIs aqui.

Em seguida, siga estas etapas para ativar a API Vertex AI para Pesquisa e Conversação:

  1. No console do Google Cloud, navegue até o console da Vertex AI para Pesquisa e Conversação.
  2. Leia e aceite os Termos de Serviço e clique em Continuar e ativar a API.

4. Criar um app de pesquisa para dados não estruturados do Cloud Storage

  1. No console do Google Cloud, acesse a página Pesquisa e conversas. Clique em Novo app.
  2. No painel Selecionar tipo de app, escolha Pesquisa.
  3. Verifique se a opção Recursos corporativos está ativada para receber respostas extraídas literalmente dos seus documentos.
  4. Verifique se a opção Recursos avançados de LLM está ativada para receber o resumo da pesquisa.
  5. No campo Nome do app, insira um nome para seu app. O ID do app aparece abaixo do nome dele.
  6. Selecione global (Global) como o local do app e clique em Continuar.
  7. No painel Repositórios de dados, clique em Criar novo repositório de dados.
  8. No painel Selecionar uma fonte de dados, escolha Cloud Storage.
  9. No painel Importar dados do GCS, verifique se a opção Pasta está selecionada.
  10. No campo gs://, insira o seguinte valor: cloud-samples-data/gen-app-builder/search/stanford-cs-224. Esse bucket do Cloud Storage contém arquivos PDF de uma pasta do Cloud Storage disponível publicamente para fins de teste.
  11. Selecione Documentos não estruturados e clique em Continuar.
  12. No painel Configure seu repositório de dados, selecione global (Global) como o local do seu repositório de dados.
  13. Insira um nome para o repositório de dados. Você vai usar esse nome mais tarde neste codelab ao implantar o serviço do Cloud Run. Clique em Criar.
  14. No painel Repositórios de dados, selecione o novo repositório e clique em Criar.
  15. Na página Dados do repositório de dados, clique na guia Atividade para conferir o status da ingestão de dados. Importação concluída aparece na coluna "Status" quando o processo de importação é concluído.
  16. Clique na guia Documentos para conferir o número de documentos importados.
  17. No menu de navegação, clique em Visualizar para testar o app de pesquisa.
  18. Na barra de pesquisa, digite final lab due date e pressione Enter para consultar os resultados.

5. Criar o serviço do Cloud Run

Nesta seção, você vai criar um serviço do Cloud Run que aceita uma string de consulta para seus termos de pesquisa. Esse serviço vai usar as bibliotecas de cliente Python para a API Discovery Engine. Para outros ambientes de execução compatíveis, confira a lista aqui.

Criar o código-fonte da função

Primeiro, crie um diretório e acesse-o.

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

Em seguida, crie um arquivo requirements.txt com o seguinte conteúdo:

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

Em seguida, crie um arquivo de origem main.py com o seguinte conteúdo:

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)))

Configurar as variáveis de ambiente.

Neste código, você vai criar algumas variáveis de ambiente para melhorar a legibilidade dos comandos gcloud usados neste codelab.

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>

Crie uma conta de serviço

Este codelab mostra como criar uma conta de serviço para o serviço do Cloud Run usar no acesso à API Vertex AI para Pesquisa.

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'

Implantar o serviço do Cloud Run

Agora você pode usar uma implantação baseada em origem para criar contêineres automaticamente para seu serviço do 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

e salve o URL do Cloud Run como uma variável de ambiente para usar depois.

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

6. Chamar o serviço do Cloud Run

Agora você pode chamar o serviço do Cloud Run com uma string de consulta para perguntar 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"

Os resultados serão parecidos com este exemplo:

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

7. Parabéns!

Parabéns por concluir o codelab!

Recomendamos consultar a documentação sobre a Vertex AI para Pesquisa e o Cloud Run.

O que vimos

  • Como criar um app da Vertex AI para Pesquisa com dados não estruturados em PDFs ingeridos de um bucket do Cloud Storage
  • Como criar um endpoint HTTP usando a implantação baseada em origem no Cloud Run
  • Como criar uma conta de serviço seguindo o princípio de privilégio mínimo para o serviço do Cloud Run usar ao consultar o app Vertex AI para Pesquisa.
  • Como invocar o serviço do Cloud Run para consultar o app da Vertex AI para Pesquisa

8. Limpar

Para evitar cobranças acidentais, por exemplo, se essa Função do Cloud for invocada mais vezes do que sua alocação mensal de invocações da Função do Cloud no nível sem custo financeiro, exclua a Função do Cloud ou o projeto criado na etapa 2.

Para excluir a função do Cloud, acesse o console do Cloud Functions em https://console.cloud.google.com/functions/ e exclua a função imagen_vqa (ou $FUNCTION_NAME se você usou um nome diferente).

Se você quiser excluir todo o projeto, acesse https://console.cloud.google.com/cloud-resource-manager, selecione o projeto criado na Etapa 2 e escolha "Excluir". Se você excluir o projeto, vai precisar mudar de projeto no SDK Cloud. Para conferir a lista de todos os projetos disponíveis, execute gcloud projects list.