Cómo comenzar a usar las incorporaciones de vectores en Cloud SQL para PostgreSQL

1. Introducción

En este codelab, aprenderás a usar la integración de IA de Cloud SQL para PostgreSQL combinando la búsqueda vectorial con las incorporaciones de Vertex AI.

30b7c4dcdd8bb68f.png

Requisitos previos

  • Conocimientos básicos sobre Google Cloud y la consola
  • Habilidades básicas de la interfaz de línea de comandos y Cloud Shell

Qué aprenderás

  • Cómo implementar una instancia de Cloud SQL para PostgreSQL
  • Cómo crear una base de datos y habilitar la integración de IA de Cloud SQL
  • Cómo cargar datos en la base de datos
  • Cómo usar el modelo de incorporación de Vertex AI en Cloud SQL
  • Cómo enriquecer el resultado con el modelo generativo de Vertex AI
  • Cómo mejorar el rendimiento con el índice vectorial

Requisitos

  • Una cuenta de Google Cloud y un proyecto de Google Cloud
  • Un navegador web, como Chrome, que admita la consola de Google Cloud y Cloud Shell

2. Configuración y requisitos

Configuración del entorno de autoaprendizaje

  1. Accede a Google Cloud Console y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • El Nombre del proyecto es el nombre visible de los participantes de este proyecto. Es una cadena de caracteres que no se utiliza en las APIs de Google. Puedes actualizarla cuando quieras.
  • El ID del proyecto es único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). La consola de Cloud genera automáticamente una cadena única. Por lo general, no importa cuál sea. En la mayoría de los codelabs, deberás hacer referencia al ID de tu proyecto (suele identificarse como PROJECT_ID). Si no te gusta el ID que se generó, podrías generar otro aleatorio. También puedes probar uno propio y ver si está disponible. No se puede cambiar después de este paso y se usa el mismo durante todo el proyecto.
  • Recuerda que hay un tercer valor, un número de proyecto, que usan algunas APIs. Obtén más información sobre estos tres valores en la documentación.
  1. A continuación, deberás habilitar la facturación en la consola de Cloud para usar las APIs o los recursos de Cloud. Ejecutar este codelab no costará mucho, tal vez nada. Para cerrar recursos y evitar que se generen cobros más allá de este instructivo, puedes borrar los recursos que creaste o borrar el proyecto. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de $300.

Inicia Cloud Shell

Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.

En Google Cloud Console, haz clic en el ícono de Cloud Shell en la barra de herramientas en la parte superior derecha:

55efc1aaa7a4d3ad.png

El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:

7ffe5cbb04455448.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. 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. Todo tu trabajo en este codelab se puede hacer en un navegador. No es necesario que instales nada.

3. Antes de comenzar

Habilita la API

Resultado:

En Cloud Shell, asegúrate de que tu ID del proyecto esté configurado:

gcloud config set project [YOUR-PROJECT-ID]

Configura la variable de entorno PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

Habilita todos los servicios necesarios con el siguiente comando:

gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com

Resultado esperado

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

4. Cree una instancia de Cloud SQL

Crea una instancia de Cloud SQL con integración de bases de datos en Vertex AI.

Crea la contraseña de la base de datos

Define la contraseña para el usuario predeterminado de la base de datos. Puedes definir tu propia contraseña o usar una función aleatoria para generar una:

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

Anota el valor generado para la contraseña:

echo $CLOUDSQL_PASSWORD

Crea una instancia de Cloud SQL para PostgreSQL

En la sesión de Cloud Shell, ejecuta lo siguiente:

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

Después de crear la instancia, debemos establecer una contraseña para el usuario predeterminado en la instancia y verificar si podemos conectarnos con ella.

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

Ejecuta el comando y escribe tu contraseña en la indicación cuando esté todo listo para conectarse.

gcloud sql connect my-cloudsql-instance --user=postgres

Habilitar la integración en Vertex AI

Otorga los privilegios necesarios a la cuenta de servicio interna de Cloud SQL para poder usar la integración de Vertex AI.

Obtén el correo electrónico de la cuenta de servicio interna de Cloud SQL y expórtalo como una variable.

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

Otorga acceso a Vertex AI a la cuenta de servicio de Cloud SQL:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

Obtén más información sobre la creación y configuración de instancias en la documentación de Cloud SQL aquí.

5. Prepara la base de datos

Ahora, debemos crear una base de datos y habilitar la compatibilidad con vectores.

Crear base de datos

Crea una base de datos con el nombre quickstart_db .Para ello, tenemos diferentes opciones, como clientes de bases de datos de línea de comandos, como psql para PostgreSQL, el SDK o Cloud SQL Studio. Usaremos el SDK (gcloud) para crear bases de datos y conectarnos a la instancia.

En Cloud Shell, ejecuta el comando para crear la base de datos

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

Habilita las extensiones

Para poder trabajar con Vertex AI y vectores, debemos habilitar dos extensiones en la base de datos que creamos.

En Cloud Shell, ejecuta el comando para conectarte a la base de datos creada (deberás proporcionar tu contraseña).

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Luego, después de establecer una conexión correcta, en la sesión de SQL, debes ejecutar dos comandos:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;

Sal de la sesión de SQL:

exit;

6. Cargar datos

Ahora, debemos crear objetos en la base de datos y cargar datos. Usaremos datos ficticios de la tienda de Cymbal. Los datos están disponibles en el bucket público de Google Storage en formato CSV.

Primero, debemos crear todos los objetos necesarios en nuestra base de datos. Para ello, usaremos los comandos gcloud sql connect y gcloud storage que ya conoces para descargar e importar los objetos del esquema a nuestra base de datos.

En Cloud Shell, ejecuta el siguiente comando y proporciona la contraseña que anotaste cuando creaste la instancia:

gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

¿Qué hicimos exactamente en el comando anterior? Nos conectamos a nuestra base de datos y ejecutamos el código SQL descargado, que creó tablas, índices y secuencias.

El siguiente paso es cargar los datos y, para ello, debemos descargar los archivos CSV de Google Cloud Storage.

gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv .

Luego, debemos conectarnos a la base de datos.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Además, importamos datos de nuestros archivos CSV.

\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header

Sal de la sesión de SQL:

exit;

Si tienes tus propios datos y tus archivos CSV son compatibles con la herramienta de importación de Cloud SQL disponible en la consola de Cloud, puedes usarla en lugar del enfoque de línea de comandos.

7. Crea incorporaciones

El siguiente paso es crear incorporaciones para nuestras descripciones de productos con el modelo textembedding-004 de Google Vertex AI y almacenarlas como datos vectoriales.

Conéctate a la base de datos:

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Y crea una columna virtual incorporada en nuestra tabla cymbal_products con la función de incorporación.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;

Puede tardar un poco, pero para 900 a 1,000 filas, no debería tardar más de 5 minutos y, por lo general, es mucho más rápido.

8. Ejecuta la búsqueda de similitud

Ahora podemos ejecutar nuestra búsqueda con la búsqueda de similitud basada en los valores de vectores calculados para las descripciones y el valor de vector que obtenemos para nuestra solicitud.

La consulta SQL se puede ejecutar desde la misma interfaz de línea de comandos con gcloud sql connect o, como alternativa, desde Cloud SQL Studio. Es mejor administrar cualquier consulta compleja y de varias filas en Cloud SQL Studio.

Inicia Cloud SQL Studio

En la consola, haz clic en la instancia de Cloud SQL que creamos antes.

b8d4844da1114a0b.png

Cuando se abre en el panel derecho, podemos ver Cloud SQL Studio. Haz clic en ella.

ce3f27dc21367f2e.png

Se abrirá un diálogo en el que deberás proporcionar el nombre de la base de datos y tus credenciales:

  • Base de datos: quickstart_db
  • Usuario: postgres
  • Contraseña: La contraseña que anotaste para el usuario principal de la base de datos

Haz clic en el botón “AUTHENTICATE”.

2591c8bbc93e4e97.png

Se abrirá la siguiente ventana en la que deberás hacer clic en la pestaña "Editor" del lado derecho para abrir el editor de SQL.

74307cb101a3ba9d.png

Ahora tenemos todo listo para ejecutar nuestras consultas.

Ejecutar consulta

Ejecuta una consulta para obtener una lista de los productos disponibles más relacionados con la solicitud de un cliente. La solicitud que pasaremos a Vertex AI para obtener el valor del vector suena como "¿Qué tipo de árboles frutales crecen bien aquí?".

Esta es la consulta que puedes ejecutar para elegir los primeros 10 elementos más adecuados para nuestra solicitud:

SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 10;

Copia y pega la consulta en el editor de Cloud SQL Studio y presiona el botón "RUN" o pégala en la sesión de línea de comandos que se conecta a la base de datos quickstart_db.

cd07549522fd04c9.png

Esta es una lista de los productos elegidos que coinciden con la búsqueda.

product_name       |                                   description                                    | sale_price | zip_code |      distance       
-------------------------+----------------------------------------------------------------------------------+------------+----------+---------------------
 Cherry Tree             | This is a beautiful cherry tree that will produce delicious cherries. It is an d |      75.00 |    93230 | 0.43922018972266397
 Meyer Lemon Tree        | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by  |         34 |    93230 |  0.4685112926118228
 Toyon                   | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e |      10.00 |    93230 |  0.4835677149651668
 California Lilac        | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d |       5.00 |    93230 |  0.4947204525907498
 California Peppertree   | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e |      25.00 |    93230 |  0.5054166905547247
 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d |     100.00 |    93230 |  0.5084219510932597
 California Sycamore     | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is  |     300.00 |    93230 |  0.5140519790508755
 Coast Live Oak          | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev |     500.00 |    93230 |  0.5143126438081371
 Fremont Cottonwood      | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i |     200.00 |    93230 |  0.5174774727252058
 Madrone                 | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an |      50.00 |    93230 |  0.5227400803389093
(10 rows)

9. Mejora la respuesta del LLM con datos recuperados

Podemos mejorar la respuesta del LLM de IA generativa a una aplicación cliente con el resultado de la consulta ejecutada y preparar un resultado significativo con los resultados de la consulta proporcionados como parte de la instrucción a un modelo de lenguaje de base generativa de Vertex AI.

Para lograrlo, debemos generar un JSON con nuestros resultados de la búsqueda vectorial y, luego, usar ese JSON generado como complemento de una instrucción para un modelo de LLM en Vertex AI para crear un resultado significativo. En el primer paso, generamos el JSON, luego lo probamos en Vertex AI Studio y, en el último paso, lo incorporamos a una sentencia SQL que se puede usar en una aplicación.

Genera un resultado en formato JSON

Modifica la consulta para generar el resultado en formato JSON y mostrar solo una fila para pasarla a Vertex AI.

Cloud SQL para PostgreSQL

Este es el ejemplo de la consulta:

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Y este es el JSON esperado en el resultado:

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Ejecuta la instrucción en Vertex AI Studio

Podemos usar el JSON generado para proporcionarlo como parte de la instrucción al modelo de texto de IA generativa en Vertex AI Studio.

Abre el chat de Vertex AI Studio en la consola de Cloud.

449b5959fa0e93bd.png

Es posible que se te solicite que habilites APIs adicionales, pero puedes ignorar la solicitud. No necesitamos ninguna API adicional para terminar el lab.

Esta es la consigna que usaremos:

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

Y así se ve cuando reemplazamos el marcador de posición JSON por la respuesta de la consulta:

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

Este es el resultado cuando ejecutamos la instrucción con nuestros valores JSON y usamos el modelo gemini-2.0-flash:

2c5145ebc04daae1.png

A continuación, se muestra la respuesta que obtuvimos del modelo en este ejemplo. Ten en cuenta que tu respuesta puede ser diferente debido a los cambios en el modelo y los parámetros con el tiempo:

“Bien, según la lista de productos disponibles, el mejor árbol que tenemos y que podría crecer bien en tu área es el cerezo.

Tiene un precio de USD 75.00.

Si bien no tengo detalles específicos sobre las condiciones de crecimiento en tu código postal exacto (93230), se sabe que los cerezos prosperan en áreas con climas moderados y suelos bien drenados. Por lo general, requieren un período de frío invernal para producir frutos, así que tenlo en cuenta. Sin embargo, pueden ser un complemento maravilloso para un jardín, ya que proporcionan belleza y deliciosas cerezas cuando las condiciones son las adecuadas”.

Ejecuta el mensaje en PSQL

También podemos usar la integración de IA de Cloud SQL con Vertex AI para obtener una respuesta similar de un modelo generativo con SQL directamente en la base de datos. Sin embargo, para usar el modelo gemini-2.0-flash-exp, primero debemos registrarlo.

Ejecutar en Cloud SQL para PostgreSQL

Actualiza la extensión a la versión 1.4.2 o una posterior (si la versión actual es anterior). Conéctate a la base de datos quickstart_db desde gcloud sql connect como se mostró antes (o usa Cloud SQL Studio) y ejecuta lo siguiente:

SELECT extversion from pg_extension where extname='google_ml_integration';

Si el valor que se muestra es inferior a 1.4.2, ejecuta lo siguiente:

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';

Luego, debemos establecer la marca de base de datos google_ml_integration.enable_model_support en "on". Para ello, puedes usar la interfaz de la consola web o ejecutar el siguiente comando de gcloud.

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

El comando tarda entre 1 y 3 minutos en ejecutarse en segundo plano. Luego, puedes verificar la nueva marca en la sesión de psql o usar Cloud SQL Studio para conectarte a la base de datos quickstart_db.

show google_ml_integration.enable_model_support;

El resultado esperado de la sesión de psql es “on”:

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Luego, debemos registrar dos modelos. El primero es el modelo text-embedding-004 que ya se usó. Debe estar registrado porque habilitamos las capacidades de registro de modelos.

Para registrar el modelo ejecutado en psql o Cloud SQL Studio, usa el siguiente código:

CALL
  google_ml.create_model(
    model_id => 'text-embedding-004',
    model_provider => 'google',
    model_qualified_name => 'text-embedding-004',
    model_type => 'text_embedding',
    model_auth_type => 'cloudsql_service_agent_iam',
    model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
    model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');

El siguiente modelo que debemos registrar es gemini-2.0-flash-001, que se usará para generar el resultado fácil de usar.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.0-flash-001',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_service_agent_iam');

Puedes verificar la lista de modelos registrados en cualquier momento seleccionando información de google_ml.model_info_view.

select model_id,model_type from google_ml.model_info_view;

Este es un resultado de muestra

quickstart_db=> select model_id,model_type from google_ml.model_info_view;
               model_id               |   model_type   
--------------------------------------+----------------
 textembedding-gecko                  | text_embedding
 textembedding-gecko@001              | text_embedding
 gemini-1.5-pro:streamGenerateContent | generic
 gemini-1.5-pro:generateContent       | generic
 gemini-1.0-pro:generateContent       | generic
 text-embedding-004                   | text_embedding
 gemini-2.0-flash-001                 | generic

Ahora podemos usar el JSON generado en una subconsulta para proporcionarlo como parte de la instrucción al modelo de texto de IA generativa con SQL.

En la sesión de psql o Cloud SQL Studio a la base de datos, ejecuta la consulta.

WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci ON
        ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
        cs.store_id = ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> google_ml.embedding('text-embedding-004',
        'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
        'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:' || json_agg(trees) || 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information' AS prompt_text
FROM
        trees),
response AS (
SELECT
        json_array_elements(google_ml.predict_row( model_id =>'gemini-2.0-flash-001',
        request_body => json_build_object('contents',
        json_build_object('role',
        'user',
        'parts',
        json_build_object('text',
        prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
        prompt)
SELECT
        string_agg(resp::text,
        ' ')
FROM
        response;

Este es el resultado esperado. El resultado puede ser diferente según la versión y los parámetros del modelo:

"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""

10. Crea un índice de vecino más cercano

Nuestro conjunto de datos es bastante pequeño y el tiempo de respuesta depende principalmente de las interacciones con los modelos de IA. Sin embargo, cuando tienes millones de vectores, la búsqueda de vectores puede ocupar una parte significativa de nuestro tiempo de respuesta y generar una carga alta en el sistema. Para mejorarlo, podemos crear un índice sobre nuestros vectores.

Cómo crear un índice de HNSW

Probaremos el tipo de índice HNSW para nuestra prueba. HNSW significa mundo pequeño navegable jerárquico y representa un índice de gráfico de varias capas.

Para compilar el índice de nuestra columna de incorporación, debemos definir nuestra columna de incorporación, la función de distancia y, de manera opcional, parámetros como m o ef_constructions. Puedes obtener información detallada sobre los parámetros en la documentación.

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

Resultado esperado:

quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
CREATE INDEX
quickstart_db=>

Comparar respuesta

Ahora podemos ejecutar la consulta de búsqueda vectorial en el modo EXPLAIN y verificar si se usó el índice.

EXPLAIN (analyze) 
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Resultado esperado:

 Aggregate  (cost=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1)
   ->  Subquery Scan on trees  (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1)
         ->  Limit  (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1)
               ->  Nested Loop  (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1)
                     ->  Nested Loop  (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1)
                           ->  Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp  (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1)
                                 Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,...
<redacted>
...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604
]'::vector)
                           ->  Index Scan using product_inventory_pkey on cymbal_inventory ci  (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3)
                                 Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text))
                                 Filter: (inventory > 0)
                                 Rows Removed by Filter: 1
                     ->  Materialize  (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1)
                           ->  Index Scan using product_stores_pkey on cymbal_stores cs  (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1)
                                 Index Cond: (store_id = 1583)
 Planning Time: 112.398 ms
 Execution Time: 1.221 ms

En el resultado, podemos ver claramente que la consulta usaba "Index Scan using cymbal_products_embeddings_hnsw".

Y si ejecutamos la consulta sin explicar:

WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Resultado esperado:

[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]

Podemos ver que el resultado es el mismo y muestra el mismo árbol de cerezo que estaba en la parte superior de nuestra búsqueda sin índice. Según los parámetros y el tipo de índice, es posible que el resultado sea ligeramente diferente. Durante mis pruebas, la consulta indexada mostró resultados en 131.301 ms en comparación con 167.631 ms sin ningún índice, pero estábamos trabajando con un conjunto de datos muy pequeño y la diferencia sería más sustancial en un conjunto de datos más grande.

Puedes probar diferentes índices disponibles para los vectores y más labs y ejemplos con la integración de cadenas de idiomas disponibles en la documentación.

11. Limpia el entorno

Borra la instancia de Cloud SQL.

Cuando termines el lab, destruye la instancia de Cloud SQL

En Cloud Shell, define el proyecto y las variables de entorno si te desconectaste y se perdieron todos los parámetros de configuración anteriores:

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

Borra la instancia:

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

Resultado esperado en la consola:

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. Felicitaciones

Felicitaciones por completar el codelab.

Temas abordados

  • Cómo implementar una instancia de Cloud SQL para PostgreSQL
  • Cómo crear una base de datos y habilitar la integración de IA de Cloud SQL
  • Cómo cargar datos en la base de datos
  • Cómo usar el modelo de incorporación de Vertex AI en Cloud SQL
  • Cómo enriquecer el resultado con el modelo generativo de Vertex AI
  • Cómo mejorar el rendimiento con el índice vectorial

Prueba un codelab similar para AlloyDB con el índice ScaNN en lugar de HNSW.

13. Encuesta

Resultado:

¿Cómo usarás este instructivo?

Solo lo leeré Lo leeré y completaré los ejercicios