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

Com a Vertex AI para Pesquisa e Conversação (antes conhecida como Generative AI App Builder), os desenvolvedores podem aproveitar 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. O foco deste codelab é o uso da Vertex AI para Pesquisa, em que é possível criar um app de pesquisa com a qualidade do Google com base nos seus próprios dados e incorporar uma barra de pesquisa nas suas páginas da Web ou apps.

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

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

O que você vai aprender

  • Como criar um app Vertex AI para Pesquisa para dados não estruturados, como PDFs ingeridos de um bucket do Cloud Storage.
  • Como criar um endpoint HTTP usando uma implantação baseada na 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 para consultar o app Vertex AI para Pesquisa
  • Como invocar o serviço do Cloud Run para consultar o app 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 você estiver iniciando o Cloud Shell pela primeira vez, verá uma tela intermediária com a descrição dele. Se aparecer uma tela intermediária, clique em Continuar.

d95252b003979716.png

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

7833d5e1c5d18f54.png

Essa máquina virtual tem 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. Grande parte do trabalho neste codelab, se não todo, pode ser feito em um navegador.

Depois de se conectar ao Cloud Shell, você verá sua autenticação e o projeto estará 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 seguinte comando no Cloud Shell para confirmar que 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 começar a usar a Vertex AI para Pesquisa, você precisa ativar várias APIs.

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

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

  1. No console do Google Cloud, acesse o Console da Vertex AI para Pesquisa e Conversação.
  2. Leia e concorde com os Termos de Serviço, clique em "Continuar" e ative a API.

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

  1. No console do Google Cloud, acesse Pesquisar e Página Conversa. Clique em Novo aplicativo.
  2. No painel Selecionar tipo de app, escolha Pesquisa.
  3. Verifique se os Recursos empresariais estão ativados para receber respostas extraídas literalmente dos seus documentos.
  4. Verifique se a opção Recursos avançados do LLM está ativada para receber o resumo da pesquisa.
  5. No campo Nome do app, insira um nome para ele. O ID do app aparece abaixo do nome do app.
  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 Configurar seu repositório de dados, selecione Global (Global) como o local do repositório de dados.
  13. Insira um nome para o repositório de dados. Você vai usar esse nome mais adiante 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 de dados e clique em Criar.
  15. Na página Dados do repositório de dados, clique na guia Atividade para ver o status da ingestão de dados. A mensagem 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 os termos de pesquisa. Este serviço usará as bibliotecas de cliente Python para a API Discovery Engine. Para outros ambientes de execução compatíveis, consulte a lista aqui.

Criar o código-fonte para a função

Primeiro, crie um diretório e use cd nele.

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 para acessar a 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 é possível usar uma implantação baseada na origem para conteinerizar automaticamente 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 salvar 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 é possível chamar seu serviço do Cloud Run com uma string de consulta para pedir 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 o exemplo de saída abaixo:

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 Vertex AI para Pesquisa para dados não estruturados, como PDFs ingeridos de um bucket do Cloud Storage.
  • Como criar um endpoint HTTP usando uma implantação baseada na 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 para consultar o app Vertex AI para Pesquisa.
  • Como invocar o serviço do Cloud Run para consultar o app 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ção de 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 caso você tenha usado um nome diferente).

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