Usar Vertex AI Search en PDF (datos no estructurados) en Cloud Storage desde un servicio de Cloud Run

1. Introducción

Descripción general

Vertex AI Search and Conversation (antes conocido como Generative AI App Builder) permite que los desarrolladores aprovechen el poder de los modelos de base, la experiencia de búsqueda y las tecnologías de IA conversacional de Google para crear aplicaciones de IA generativa de nivel empresarial. Este codelab se enfoca en el uso de Vertex AI Search, donde puedes crear una app de búsqueda con la calidad de Google con tus propios datos y, además, incorporar una barra de búsqueda en tus páginas web o app.

Cloud Run es una plataforma de computación administrada que te permite ejecutar contenedores directamente sobre la infraestructura escalable de Google. Puedes implementar código escrito en cualquier lenguaje de programación en Cloud Run (que se pueda colocar dentro de un contenedor) con la opción de implementación basada en código fuente.

En este codelab, crearás un servicio de Cloud Run con la implementación basada en código fuente para recuperar resultados de búsqueda de contenido no estructurado en archivos PDF en un bucket de Cloud Storage. Puedes obtener más información para transferir contenido no estructurado aquí.

Qué aprenderás

  • Cómo crear una app de Vertex AI Search para datos no estructurados como archivos PDF transferidos desde un bucket de Cloud Storage
  • Cómo crear un extremo HTTP con la implementación basada en código fuente en Cloud Run
  • Cómo crear una cuenta de servicio siguiendo el principio de privilegio mínimo para que el servicio de Cloud Run la use para consultar la app de Vertex AI Search
  • Cómo invocar el servicio de Cloud Run para consultar la app de Vertex AI Search

2. Configuración y requisitos

Requisitos previos

Activar Cloud Shell

  1. En la consola de Cloud, haz clic en Activar Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Si es la primera vez que inicias Cloud Shell, aparecerá una pantalla intermedia en la que se describirá qué es. Si apareció una pantalla intermedia, haz clic en Continuar.

d95252b003979716.png

El aprovisionamiento y la conexión a Cloud Shell solo tomará unos minutos.

7833d5e1c5d18f54.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo necesarias. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Gran parte de tu trabajo en este codelab, si no todo, se puede hacer con un navegador.

Una vez que te conectes a Cloud Shell, deberías ver que ya te autenticaste y que el proyecto ya se configuró con el ID de tu proyecto.

  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que tienes la autenticación:
gcloud auth list

Resultado del comando

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. En Cloud Shell, ejecuta el siguiente comando para confirmar que el comando gcloud conoce tu proyecto:
gcloud config list project

Resultado del comando

[core]
project = <PROJECT_ID>

De lo contrario, puede configurarlo con este comando:

gcloud config set project <PROJECT_ID>

Resultado del comando

Updated property [core/project].

3. Habilita las APIs

Antes de comenzar a usar Vertex AI Search, deberás habilitar varias APIs.

En primer lugar, este codelab requiere el uso de las APIs de Vertex AI Search and Conversation, BigQuery y Cloud Storage. Puedes habilitar esas APIs aquí.

En segundo lugar, sigue estos pasos para habilitar la API de Vertex AI Search and Conversation:

  1. En la consola de Google Cloud, ve a la consola de Vertex AI Search and Conversation.
  2. Lee y acepta las Condiciones del Servicio y, luego, haz clic en Continuar y activar la API (Continue and activate the API).

4. Crea una app de búsqueda de datos no estructurados desde Cloud Storage

  1. En la consola de Google Cloud, ve a la página Search & Conversation. Haz clic en Nueva aplicación.
  2. En el panel Selecciona el tipo de app, selecciona Búsqueda.
  3. Asegúrate de que la opción Funciones empresariales esté habilitada para recibir respuestas que se extraen textualmente de tus documentos.
  4. Asegúrate de que la opción Funciones avanzadas de LLM esté habilitada para recibir el resumen de la búsqueda.
  5. En el campo Nombre de la app, ingresa un nombre para ella. El ID de la app aparece debajo del nombre de la app.
  6. Selecciona global (Global) como la ubicación de tu app y, luego, haz clic en Continuar.
  7. En el panel Almacenes de datos, haz clic en Crear almacén de datos nuevo.
  8. En el panel Selecciona una fuente de datos, elige Cloud Storage.
  9. En el panel Importar datos de GCS, asegúrate de que esté seleccionada la opción Carpeta.
  10. En el campo gs://, ingresa el siguiente valor: cloud-samples-data/gen-app-builder/search/stanford-cs-224. Este bucket de Cloud Storage contiene archivos PDF de una carpeta de Cloud Storage disponible públicamente para fines de prueba.
  11. Selecciona Documentos no estructurados y, luego, haz clic en Continuar.
  12. En el panel Configura tu almacén de datos, selecciona global (Global) como la ubicación de tu almacén de datos.
  13. Ingresa un nombre para tu almacén de datos. Usarás este nombre más adelante en este codelab cuando implementes tu servicio de Cloud Run. Haz clic en Crear.
  14. En el panel Almacenes de datos, selecciona el almacén de datos nuevo y haz clic en Crear.
  15. En la página Datos de tu almacén de datos, haz clic en la pestaña Actividad para ver el estado de tu transferencia de datos. Se mostrará Importación completada en la columna Estado cuando se complete el proceso de importación.
  16. Haz clic en la pestaña Documentos para ver la cantidad de documentos importados.
  17. En el menú de navegación, haz clic en Vista previa para probar la app de búsqueda.
  18. En la barra de búsqueda, ingresa final lab due date y, luego, presiona Intro para ver los resultados.

5. Crea el servicio de Cloud Run

En esta sección, crearás un servicio de Cloud Run que acepte una cadena de consulta para tus términos de búsqueda. Este servicio usará las bibliotecas cliente de Python para la API de Discovery Engine. Para obtener otros entornos de ejecución compatibles, puedes ver la lista aquí.

Crea el código fuente de la función

Primero, crea un directorio y ábrelo con el comando cd.

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

Luego, crea un archivo requirements.txt con el siguiente contenido:

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

A continuación, crea un archivo fuente main.py con el siguiente contenido:

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

Configura variables de entorno

En este código, crearás algunas variables de entorno para mejorar la legibilidad de los comandos gcloud que se usan en este 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>

Crea una cuenta de servicio

En este codelab, se muestra cómo crear una cuenta de servicio para que el servicio de Cloud Run la use para acceder a la API de Vertex AI Search.

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'

Implementa el servicio de Cloud Run

Ahora puedes usar una implementación basada en código fuente para contener automáticamente tu servicio de 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

Luego, puedes guardar la URL de Cloud Run como una variable de entorno para usarla más adelante.

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

6. Llama al servicio de Cloud Run

Ahora puedes llamar a tu servicio de Cloud Run con una cadena de consulta para preguntar 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"

Los resultados deberían ser similares al siguiente ejemplo:

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

7. ¡Felicitaciones!

Felicitaciones por completar el codelab.

Te recomendamos que revises la documentación sobre Vertex AI Search y Cloud Run.

Temas abordados

  • Cómo crear una app de Vertex AI Search para datos no estructurados como archivos PDF transferidos desde un bucket de Cloud Storage
  • Cómo crear un extremo HTTP con la implementación basada en código fuente en Cloud Run
  • Cómo crear una cuenta de servicio siguiendo el principio de privilegio mínimo para que el servicio de Cloud Run la use para consultar la app de Vertex AI Search
  • Cómo invocar el servicio de Cloud Run para consultar la app de Vertex AI Search

8. Limpia

Para evitar cargos involuntarios (por ejemplo, si esta Cloud Function se invoca de forma involuntaria más veces que tu asignación mensual de invocación de Cloud Functions en el nivel gratuito), puedes borrar la Cloud Function o el proyecto que creaste en el paso 2.

Para borrar la Cloud Function, ve a la consola de Cloud Functions en https://console.cloud.google.com/functions/ y borra la función imagen_vqa (o $FUNCTION_NAME en caso de que hayas usado un nombre diferente).

Si eliges borrar todo el proyecto, puedes ir a https://console.cloud.google.com/cloud-resource-manager, seleccionar el proyecto que creaste en el paso 2 y elegir Borrar. Si borras el proyecto, deberás cambiar los proyectos en el SDK de Cloud. Para ver la lista de todos los proyectos disponibles, ejecuta gcloud projects list.