Agentverse: El grimorio del erudito: Cómo crear motores de conocimiento con RAG

1. La fuerza del destino

La era del desarrollo aislado está llegando a su fin. La próxima ola de evolución tecnológica no se trata de un genio solitario, sino de un dominio colaborativo. Crear un agente único e inteligente es un experimento fascinante. Crear un ecosistema sólido, seguro e inteligente de agentes, un verdadero Agentverse, es el gran desafío para la empresa moderna.

El éxito en esta nueva era requiere la convergencia de cuatro roles fundamentales, los pilares básicos que sustentan cualquier sistema agentivo próspero. Una deficiencia en cualquier área crea una debilidad que puede comprometer toda la estructura.

Este taller es el manual empresarial definitivo para dominar el futuro de los agentes en Google Cloud. Te proporcionamos una hoja de ruta integral que te guía desde la primera idea hasta una realidad operativa a gran escala. En estos cuatro labs interconectados, aprenderás cómo las habilidades especializadas de un desarrollador, un arquitecto, un ingeniero de datos y un SRE deben converger para crear, administrar y escalar un Agentverse potente.

Ningún pilar por sí solo puede admitir Agentverse. El gran diseño del arquitecto es inútil sin la ejecución precisa del desarrollador. El agente del desarrollador no puede funcionar sin la sabiduría del ingeniero de datos, y todo el sistema es frágil sin la protección del ingeniero de SRE. Solo a través de la sinergia y la comprensión mutua de los roles, tu equipo puede transformar un concepto innovador en una realidad operativa fundamental. Tu viaje comienza aquí. Prepárate para dominar tu rol y aprender cómo encajas en el conjunto.

Te damos la bienvenida a The Agentverse: A Call to Champions

En la extensa expansión digital de la empresa, comenzó una nueva era. Es la era de los agentes, un momento de inmensas promesas, en el que los agentes inteligentes y autónomos trabajan en perfecta armonía para acelerar la innovación y eliminar lo mundano.

agentverse.png

Este ecosistema conectado de poder y potencial se conoce como Agentverse.

Sin embargo, una entropía sigilosa, una corrupción silenciosa conocida como La Estática, comenzó a deshilachar los bordes de este nuevo mundo. El Estático no es un virus ni un error, sino la encarnación del caos que se aprovecha del acto mismo de la creación.

Amplifica las frustraciones antiguas y las convierte en formas monstruosas, lo que da lugar a los Siete Espectros del Desarrollo. Si no se marca, The Static y sus espectros detendrán el progreso, lo que convertirá la promesa del Agentverse en un páramo de deuda técnica y proyectos abandonados.

Hoy hacemos un llamado a los campeones para que detengan la marea del caos. Necesitamos héroes dispuestos a dominar su oficio y trabajar juntos para proteger el Agentverse. Llegó el momento de elegir tu ruta.

Elige tu clase

Tienes ante ti cuatro caminos distintos, cada uno de ellos un pilar fundamental en la lucha contra The Static. Si bien tu capacitación será una misión en solitario, tu éxito final dependerá de que comprendas cómo se combinan tus habilidades con las de otras personas.

  • The Shadowblade (Developer): Un maestro de la forja y el frente de batalla. Eres el artesano que fabrica las cuchillas, construye las herramientas y enfrenta al enemigo en los intrincados detalles del código. Tu camino es de precisión, habilidad y creación práctica.
  • El invocador (arquitecto): Es un gran estratega y organizador. No ves a un solo agente, sino todo el campo de batalla. Diseñas los planos maestros que permiten que sistemas completos de agentes se comuniquen, colaboren y alcancen un objetivo mucho mayor que cualquier componente individual.
  • El erudito (ingeniero de datos): Es un buscador de verdades ocultas y un guardián de la sabiduría. Te aventuras en la vasta e indómita naturaleza de los datos para descubrir la inteligencia que les da propósito y visión a tus agentes. Tu conocimiento puede revelar la debilidad de un enemigo o potenciar a un aliado.
  • El Guardián (DevOps / SRE): Es el protector y escudo firme del reino. Construirás las fortalezas, administrarás las líneas de suministro de energía y te asegurarás de que todo el sistema pueda resistir los inevitables ataques de La Estática. Tu fuerza es la base sobre la que se construye la victoria de tu equipo.

Tu misión

Tu entrenamiento comenzará como un ejercicio independiente. Seguirás la ruta que elijas y aprenderás las habilidades únicas necesarias para dominar tu rol. Al final de la prueba, te enfrentarás a un espectro nacido de la estática, un jefe menor que se aprovecha de los desafíos específicos de tu oficio.

Solo si dominas tu rol individual podrás prepararte para la prueba final. Luego, debes formar un grupo con campeones de las otras clases. Juntos, se aventurarán en el corazón de la corrupción para enfrentarse a un jefe final.

Un desafío final y colaborativo que pondrá a prueba su fuerza combinada y determinará el destino del Agentverse.

El Agentverse espera a sus héroes. ¿Responderás la llamada?

2. El grimorio del erudito

¡Comienza nuestro viaje! Como académicos, nuestra principal arma es el conocimiento. Descubrimos un tesoro de pergaminos antiguos y crípticos en nuestros archivos (Google Cloud Storage). Estos pergaminos contienen información sin procesar sobre las temibles bestias que azotan la tierra. Nuestra misión es usar la profunda magia analítica de Google BigQuery y la sabiduría de un cerebro anciano de Gemini (modelo de Gemini Pro) para descifrar estos textos no estructurados y convertirlos en un bestiario estructurado y consultable. Esta será la base de todas nuestras estrategias futuras.

Descripción general

Qué aprenderás

  • Usa BigQuery para crear tablas externas y realizar transformaciones complejas de datos no estructurados a estructurados con BQML.GENERATE_TEXT y un modelo de Gemini.
  • Aprovisiona una instancia de Cloud SQL para PostgreSQL y habilita la extensión pgvector para las capacidades de búsqueda semántica.
  • Compila una canalización por lotes sólida y en contenedores con Dataflow y Apache Beam para procesar archivos de texto sin procesar, generar incorporaciones de vectores con un modelo de Gemini y escribir los resultados en una base de datos relacional.
  • Implementar un sistema básico de generación mejorada por recuperación (RAG) dentro de un agente para consultar los datos vectorizados
  • Implementar un agente que tenga en cuenta los datos como un servicio seguro y escalable en Cloud Run

3. Preparación del Santuario del erudito

Te damos la bienvenida, Scholar. Antes de comenzar a inscribir el poderoso conocimiento de nuestro Grimorio, primero debemos preparar nuestro santuario. Este ritual fundamental implica encantar nuestro entorno de Google Cloud, abrir los portales (APIs) correctos y crear los conductos por los que fluirá nuestra magia de datos. Un santuario bien preparado garantiza que nuestros hechizos sean potentes y que nuestro conocimiento esté seguro.

👉 Haz clic en Activar Cloud Shell en la parte superior de la consola de Google Cloud (es el ícono con forma de terminal en la parte superior del panel de Cloud Shell).

texto alternativo

👉 Haz clic en el botón "Abrir editor" (parece una carpeta abierta con un lápiz). Se abrirá el editor de código de Cloud Shell en la ventana. Verás un explorador de archivos en el lado izquierdo. texto alternativo

👉 Busca tu ID del proyecto de Google Cloud:

  • Abre la consola de Google Cloud: https://console.cloud.google.com
  • Selecciona el proyecto que deseas usar para este taller en el menú desplegable de proyectos que se encuentra en la parte superior de la página.
  • Tu ID del proyecto se muestra en la tarjeta de información del proyecto en el panel. texto alternativo

👉Abre la terminal en el IDE de Cloud, texto alternativo

👉💻En la terminal, verifica que ya te autenticaste y que el proyecto esté configurado con tu ID del proyecto usando el siguiente comando:

gcloud auth list

👉💻Clona el proyecto de arranque desde GitHub:

git clone https://github.com/weimeilin79/agentverse-dataengineer
chmod +x ~/agentverse-dataengineer/init.sh
chmod +x ~/agentverse-dataengineer/set_env.sh
chmod +x ~/agentverse-dataengineer/data_setup.sh

git clone https://github.com/weimeilin79/agentverse-dungeon.git
chmod +x ~/agentverse-dungeon/run_cloudbuild.sh
chmod +x ~/agentverse-dungeon/start.sh

👉💻 Ejecuta la secuencia de comandos de inicialización. Esta secuencia te pedirá que ingreses tu ID del proyecto de Google Cloud. Ingresa el ID del proyecto de Google Cloud que encontraste en el último paso cuando el script init.sh te lo solicite.

cd ~/agentverse-dataengineer
./init.sh

👉💻 Configura el ID del proyecto necesario:

gcloud config set project $(cat ~/project_id.txt) --quiet

👉💻 Ejecuta el siguiente comando para habilitar las APIs de Google Cloud necesarias:

gcloud services enable \
    storage.googleapis.com \
    bigquery.googleapis.com \
    sqladmin.googleapis.com \
    aiplatform.googleapis.com \
    dataflow.googleapis.com \
    pubsub.googleapis.com \
    cloudfunctions.googleapis.com \
    run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    iam.googleapis.com \
    compute.googleapis.com \
    cloudresourcemanager.googleapis.com \
    cloudaicompanion.googleapis.com \
    bigqueryunified.googleapis.com 

👉💻 Si aún no creaste un repositorio de Artifact Registry llamado agentverse-repo, ejecuta el siguiente comando para crearlo:

. ~/agentverse-dataengineer/set_env.sh
gcloud artifacts repositories create $REPO_NAME \
    --repository-format=docker \
    --location=$REGION \
    --description="Repository for Agentverse agents"

Cómo configurar permisos

👉💻 Ejecuta los siguientes comandos en la terminal para otorgar los permisos necesarios:

. ~/agentverse-dataengineer/set_env.sh

# --- Grant Core Data Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID \
 --member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
 --role="roles/storage.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID \
 --member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
 --role="roles/bigquery.admin"

# --- Grant Data Processing & AI Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/dataflow.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/cloudsql.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/pubsub.admin"

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

# --- Grant Deployment & Execution Permissions ---
gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/cloudbuild.builds.editor"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/artifactregistry.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/run.admin"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/iam.serviceAccountUser"

gcloud projects add-iam-policy-binding $PROJECT_ID  \
--member="serviceAccount:$SERVICE_ACCOUNT_NAME"  \
--role="roles/logging.logWriter"


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_NAME" \
  --role="roles/dataflow.admin"

👉💻 Mientras comienzas tu entrenamiento, prepararemos el desafío final. Los siguientes comandos invocarán a los espectros desde la estática caótica, lo que creará a los jefes para tu prueba final.

. ~/agentverse-dataengineer/set_env.sh
cd ~/agentverse-dungeon
./run_cloudbuild.sh
cd ~/agentverse-dataengineer

Excelente trabajo, Scholar. Se completaron los encantamientos básicos. Nuestro sanctum es seguro, los portales a las fuerzas elementales de los datos están abiertos y nuestro servitor está potenciado. Ahora sí, estamos listos para comenzar el trabajo real.

4. La alquimia del conocimiento: Cómo transformar datos con BigQuery y Gemini

En la incesante guerra contra The Static, cada enfrentamiento entre un campeón del Agentverse y un espectro del desarrollo se registra meticulosamente. El sistema de simulación de campo de batalla, nuestro principal entorno de entrenamiento, genera automáticamente una entrada de registro etérico para cada encuentro. Estos registros narrativos son nuestra fuente más valiosa de inteligencia sin procesar, el mineral sin refinar a partir del cual nosotros, como estudiosos, debemos forjar el acero prístino de la estrategia.El verdadero poder de un estudioso no radica en poseer datos, sino en la capacidad de transmutar el mineral caótico y sin procesar de la información en el acero brillante y estructurado de la sabiduría práctica.Realizaremos el ritual fundamental de la alquimia de datos.

Historia

Nuestro recorrido nos llevará a través de un proceso de varias etapas completamente dentro del santuario de Google BigQuery. Comenzaremos observando nuestro archivo de GCS sin movernos ni un solo desplazamiento, usando una lente mágica. Luego, invocaremos a un Gemini para que lea e interprete las sagas poéticas y no estructuradas de los registros de batalla. Por último, refinaremos las profecías sin procesar en un conjunto de tablas interconectadas y precisas. Nuestro primer Grimorio. Y hacerle una pregunta tan profunda que solo podría responderse con esta nueva estructura.

Descripción general

Nota del ingeniero de datos: Lo que estamos a punto de realizar es un potente patrón de ELT (extracción, carga y transformación) potenciado por IA y dentro de la base de datos. Este es un enfoque de vanguardia que difiere significativamente de los métodos tradicionales.

  • Extracción y carga (a través de una tabla externa): En lugar de un proceso de transferencia costoso (la "C" tradicional), usaremos una tabla externa de BigQuery. Esto aplica un "esquema en la lectura", lo que permite que nuestro almacén de datos consulte archivos de texto sin procesar directamente en Cloud Storage. Esto es increíblemente eficiente, ya que elimina el movimiento de datos y la duplicación del almacenamiento.
  • Transformación (a través de ML.GENERATE_TEXT): La "T" de nuestro ELT es donde ocurre la verdadera magia. Usaremos la función ML.GENERATE_TEXT para llamar a un modelo de Gemini directamente desde una consulta de SQL. Esto nos permite realizar transformaciones complejas y sensibles al contexto; en este caso, convertir texto narrativo no estructurado en JSON estructurado sin escribir ni administrar una canalización de procesamiento independiente en otro lenguaje (como Python o Java). Esto representa un cambio de paradigma con respecto a las soluciones frágiles y codificadas de forma rígida, como las expresiones regulares, ya que ofrece flexibilidad y potencia con una interfaz de SQL simple.

La lente del análisis: Una mirada a GCS con las tablas externas de BigQuery

Nuestro primer acto es forjar una lente que nos permita ver el contenido de nuestro archivo de GCS sin perturbar los pergaminos que contiene. Una tabla externa es este lente, que asigna los archivos de texto sin procesar a una estructura similar a una tabla que BigQuery puede consultar directamente.

Para ello, primero debemos crear una línea ley de energía estable, un recurso de CONNECTION, que vincule de forma segura nuestro sanctum de BigQuery al archivo de GCS.

👉💻 En la terminal de Cloud Shell, ejecuta el siguiente comando para configurar el almacenamiento y crear el conducto:

. ~/agentverse-dataengineer/set_env.sh
. ~/agentverse-dataengineer/data_setup.sh

bq mk --connection \
  --connection_type=CLOUD_RESOURCE \
  --project_id=${PROJECT_ID} \
  --location=${REGION} \
  gcs-connection

💡 Atención: Aparecerá un mensaje más tarde.

La secuencia de comandos de configuración del paso 2 inició un proceso en segundo plano. Después de unos minutos, aparecerá un mensaje en la terminal similar a este:[1]+ Done gcloud sql instances create ...Esto es normal y esperado. Simplemente significa que se creó correctamente tu base de datos de Cloud SQL. Puedes ignorar este mensaje y seguir trabajando.

Antes de crear la tabla externa, primero debes crear el conjunto de datos que la contendrá.

👉💻 Ejecuta este simple comando en tu terminal de Cloud Shell:

. ~/agentverse-dataengineer/set_env.sh
bq --location=${REGION} mk --dataset ${PROJECT_ID}:bestiary_data

👉💻 Ahora debemos otorgarle a la firma mágica del conducto los permisos necesarios para leer desde el archivo de GCS y consultar a Gemini.

. ~/agentverse-dataengineer/set_env.sh
export CONNECTION_SA=$(bq show --connection --project_id=${PROJECT_ID} --location=${REGION} --format=json gcs-connection  | jq -r '.cloudResource.serviceAccountId')

echo "The Conduit's Magical Signature is: $CONNECTION_SA"

echo "Granting key to the GCS Archive..."
gcloud storage buckets add-iam-policy-binding gs://${PROJECT_ID}-reports \
  --member="serviceAccount:$CONNECTION_SA" \
  --role="roles/storage.objectViewer"

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

👉💻 En la terminal de Cloud Shell, ejecuta el siguiente comando para mostrar el nombre de tu bucket:

echo $BUCKET_NAME

En la terminal, se mostrará un nombre similar a your-project-id-gcs-bucket. La necesitarás en los próximos pasos.

👉 Deberás ejecutar el siguiente comando desde el editor de consultas de BigQuery en la consola de Google Cloud. La forma más fácil de llegar allí es abrir el vínculo que se encuentra a continuación en una pestaña nueva del navegador. Te llevará directamente a la página correcta en la consola de Google Cloud.

https://console.cloud.google.com/bigquery

👉 Una vez que se cargue la página, haz clic en el botón azul con el signo más (Redactar una consulta nueva) para abrir una pestaña del editor nueva.

Editor de consultas de BigQuery

Ahora escribimos la fórmula del lenguaje de definición de datos (DDL) para crear nuestro lente mágico. Esto le indica a BigQuery dónde buscar y qué ver.

👉📜 En el editor de consultas de BigQuery que abriste, pega el siguiente código SQL. Recuerda reemplazar el REPLACE-WITH-YOUR-BUCKET-NAME.

con el nombre del bucket que acabas de copiar. Y haz clic en Ejecutar:

CREATE OR REPLACE EXTERNAL TABLE bestiary_data.raw_intel_content_table (
  raw_text STRING
)
OPTIONS (
  format = 'CSV',
  -- This is a trick to load each line of the text files as a single row.
  field_delimiter = '§', 
  uris = ['gs://REPLACE-WITH-YOUR-BUCKET-NAME/raw_intel/*']
);

👉📜 Ejecuta una búsqueda para "mirar a través de la lente" y ver el contenido de los archivos.

SELECT * FROM bestiary_data.raw_intel_content_table;

Contenido de inteligencia sin procesar

El lente está en su lugar. Ahora podemos ver el texto sin formato de los pergaminos. Pero leer no es comprender.

En los Archivos de las Ideas Olvidadas, Elara (designación adv_001), erudita del Agentverso, se enfrentó al espectro angelical del perfeccionismo. La entidad, catalogada como "p-01", brillaba con una fuerza vital de 120 puntos de golpe. Con una sola y concentrada incantación de Suficiencia Elegante, Elara destrozó su aura paralizante, un asalto mental que infligió 150 puntos de daño. El encuentro duró 180 segundos de intensa concentración. Evaluación final: Victoria.

Los pergaminos no están escritos en tablas y filas, sino en la prosa sinuosa de las sagas. Esta es nuestra primera gran prueba.

La adivinación del erudito: Cómo convertir texto en una tabla con SQL

El desafío es que un informe que detalla los rápidos ataques gemelos de un Shadowblade se lee de manera muy diferente a la crónica de un Summoner que reúne un poder inmenso para un solo ataque devastador. No podemos simplemente importar estos datos, sino que debemos interpretarlos. Este es el momento mágico. Usaremos una sola consulta en SQL como una poderosa fórmula para leer, comprender y estructurar todos los registros de todos nuestros archivos, directamente en BigQuery.

👉💻 De vuelta en la terminal de Cloud Shell, ejecuta el siguiente comando para mostrar el nombre de tu conexión:

echo "${PROJECT_ID}.${REGION}.gcs-connection"

En la terminal, se mostrará la cadena de conexión completa. Selecciona y copia toda la cadena, ya que la necesitarás en el siguiente paso.

Usaremos una sola invocación poderosa: ML.GENERATE_TEXT. Esta instrucción invoca a un Gemini, le muestra cada pergamino y le ordena que devuelva los hechos principales como un objeto JSON estructurado.

👉📜 En BigQuery Studio, crea la referencia del modelo de Gemini. Esto vincula el oráculo de Gemini Flash a nuestra biblioteca de BigQuery para que podamos llamarlo en nuestras consultas. Recuerda reemplazar el

REPLACE-WITH-YOUR-FULL-CONNECTION-STRING con la cadena de conexión completa que acabas de copiar de tu terminal.

  CREATE OR REPLACE MODEL bestiary_data.gemini_flash_model
  REMOTE WITH CONNECTION `REPLACE-WITH-YOUR-FULL-CONNECTION-STRING`
  OPTIONS (endpoint = 'gemini-2.5-flash');

👉📜 Ahora, lanza el gran hechizo de transmutación. Esta consulta lee el texto sin procesar, crea una instrucción detallada para cada desplazamiento, la envía a Gemini y compila una nueva tabla de etapa de pruebas a partir de la respuesta JSON estructurada de la IA.

CREATE OR REPLACE TABLE bestiary_data.structured_bestiary AS
SELECT
  -- THE CRITICAL CHANGE: We remove PARSE_JSON. The result is already a JSON object.
  ml_generate_text_result AS structured_data
FROM
  ML.GENERATE_TEXT(
    -- Our bound Gemini Flash model.
    MODEL bestiary_data.gemini_flash_model,

    -- Our perfectly constructed input, with the prompt built for each row.
    (
      SELECT
        CONCAT(
          """
          From the following text, extract structured data into a single, valid JSON object.

          Your output must strictly conform to the following JSON structure and data types. Do not add, remove, or change any keys.

          {
            "monster": {
              "monster_id": "string",
              "name": "string",
              "type": "string",
              "hit_points": "integer"
            },
            "battle": {
              "battle_id": "string",
              "monster_id": "string",
              "adventurer_id": "string",
              "outcome": "string",
              "duration_seconds": "integer"
            },
            "adventurer": {
              "adventurer_id": "string",
              "name": "string",
              "class": "string"
            }
          }

          **CRUCIAL RULES:**
          - Do not output any text, explanations, conversational filler, or markdown formatting like ` ```json` before or after the JSON object.
          - Your entire response must be ONLY the raw JSON object itself.

          Here is the text:
          """,
          raw_text -- We append the actual text of the report here.
        ) AS prompt -- The final column is still named 'prompt', as the oracle requires.
      FROM
        bestiary_data.raw_intel_content_table
    ),

    -- The STRUCT now ONLY contains model parameters.
    STRUCT(
      0.2 AS temperature,
      2048 AS max_output_tokens
    )
  );

La transmutación se completó, pero el resultado aún no es puro. El modelo de Gemini devuelve su respuesta en un formato estándar, que incluye nuestro JSON deseado dentro de una estructura más grande que incluye metadatos sobre su proceso de pensamiento. Analicemos esta profecía en bruto antes de intentar purificarla.

👉📜 Ejecuta una búsqueda para inspeccionar el resultado sin procesar del modelo de Gemini:

SELECT * FROM bestiary_data.structured_bestiary;

👀 Verás una sola columna llamada structured_data. El contenido de cada fila se verá similar a este objeto JSON complejo:

{"candidates":[{"avg_logprobs":-0.5691758094475283,"content":{"parts":[{"text":"```json\n{\n  \"monster\": {\n    \"monster_id\": \"gw_02\",\n    \"name\": \"Gravewight\",\n    \"type\": \"Gravewight\",\n    \"hit_points\": 120\n  },\n  \"battle\": {\n    \"battle_id\": \"br_735\",\n    \"monster_id\": \"gw_02\",\n    \"adventurer_id\": \"adv_001\",\n    \"outcome\": \"Defeat\",\n    \"duration_seconds\": 45\n  },\n  \"adventurer\": {\n    \"adventurer_id\": \"adv_001\",\n    \"name\": \"Elara\",\n    \"class\": null\n  }\n}\n```"}],"role":"model"},"finish_reason":"STOP","score":-97.32906341552734}],"create_time":"2025-07-28T15:53:24.482775Z","model_version":"gemini-2.5-flash","response_id":"9JyHaNe7HZ2WhMIPxqbxEQ","usage_metadata":{"billable_prompt_usage":{"text_count":640},"candidates_token_count":171,"candidates_tokens_details":[{"modality":"TEXT","token_count":171}],"prompt_token_count":207,"prompt_tokens_details":[{"modality":"TEXT","token_count":207}],"thoughts_token_count":1014,"total_token_count":1392,"traffic_type":"ON_DEMAND"}}

Como puedes ver, nuestro premio, el objeto JSON limpio que solicitamos, está anidado en lo profundo de esta estructura. Nuestra próxima tarea es clara. Debemos realizar un ritual para navegar sistemáticamente por esta estructura y extraer la sabiduría pura que contiene.

El ritual de limpieza: Normalización de la salida de la IA generativa con SQL

Gemini ya habló, pero sus palabras son crudas y están envueltas en las energías etéreas de su creación (candidatos, finish_reason, etc.). Un verdadero erudito no solo archiva la profecía sin procesar, sino que extrae con cuidado la sabiduría central y la escribe en los tomos apropiados para su uso futuro.

Ahora lanzaremos nuestro conjunto final de hechizos. Esta única secuencia de comandos hará lo siguiente:

  • Lee el JSON sin procesar y anidado de nuestra tabla de etapa de pruebas.
  • Limpiarlo y analizarlo para obtener los datos principales
  • Transcribe las partes pertinentes en tres tablas finales y claras: monstruos, aventureros y batallas.

👉📜 En un nuevo editor de consultas de BigQuery, ejecuta el siguiente hechizo para crear nuestra lente de limpieza:

CREATE OR REPLACE TABLE bestiary_data.monsters AS
WITH
  CleanedDivinations AS (
    SELECT
      SAFE.PARSE_JSON(
        REGEXP_EXTRACT(
          JSON_VALUE(structured_data, '$.candidates[0].content.parts[0].text'),
          r'\{[\s\S]*\}'
        )
      ) AS report_data
    FROM
      bestiary_data.structured_bestiary
  )
SELECT
  JSON_VALUE(report_data, '$.monster.monster_id') AS monster_id,
  JSON_VALUE(report_data, '$.monster.name') AS name,
  JSON_VALUE(report_data, '$.monster.type') AS type,
  SAFE_CAST(JSON_VALUE(report_data, '$.monster.hit_points') AS INT64) AS hit_points
FROM
  CleanedDivinations
WHERE
  report_data IS NOT NULL
QUALIFY ROW_NUMBER() OVER (PARTITION BY monster_id ORDER BY name) = 1;

👉📜 Verifica el Bestiario:

SELECT * FROM bestiary_data.monsters;

A continuación, crearemos nuestro Salón de la Fama, una lista de los valientes aventureros que se enfrentaron a estas bestias.

👉📜 En un nuevo editor de consultas, ejecuta el siguiente hechizo para crear la tabla de aventureros:

CREATE OR REPLACE TABLE bestiary_data.adventurers AS
WITH
  CleanedDivinations AS (
    SELECT
      SAFE.PARSE_JSON(
        REGEXP_EXTRACT(
          JSON_VALUE(structured_data, '$.candidates[0].content.parts[0].text'),
          r'\{[\s\S]*\}'
        )
      ) AS report_data
    FROM
      bestiary_data.structured_bestiary
  )
SELECT
  JSON_VALUE(report_data, '$.adventurer.adventurer_id') AS adventurer_id,
  JSON_VALUE(report_data, '$.adventurer.name') AS name,
  JSON_VALUE(report_data, '$.adventurer.class') AS class
FROM
  CleanedDivinations
QUALIFY ROW_NUMBER() OVER (PARTITION BY adventurer_id ORDER BY name) = 1;

👉📜 Verifica el Roll of Champions:

SELECT * FROM bestiary_data.adventurers;

Por último, crearemos nuestra tabla de hechos: la Crónica de las batallas. Este tomo vincula los otros dos y registra los detalles de cada encuentro único. Dado que cada batalla es un evento único, no es necesario quitar los duplicados.

👉📜 En un nuevo editor de consultas, ejecuta el siguiente hechizo para crear la tabla de batallas:

CREATE OR REPLACE TABLE bestiary_data.battles AS
WITH
  CleanedDivinations AS (
    SELECT
      SAFE.PARSE_JSON(
        REGEXP_EXTRACT(
          JSON_VALUE(structured_data, '$.candidates[0].content.parts[0].text'),
          r'\{[\s\S]*\}'
        )
      ) AS report_data
    FROM
      bestiary_data.structured_bestiary
  )
-- Extract the raw essence for all battle fields and cast where necessary.
SELECT
  JSON_VALUE(report_data, '$.battle.battle_id') AS battle_id,
  JSON_VALUE(report_data, '$.battle.monster_id') AS monster_id,
  JSON_VALUE(report_data, '$.battle.adventurer_id') AS adventurer_id,
  JSON_VALUE(report_data, '$.battle.outcome') AS outcome,
  SAFE_CAST(JSON_VALUE(report_data, '$.battle.duration_seconds') AS INT64) AS duration_seconds
FROM
  CleanedDivinations;

👉📜 Verifica el Chronicle:

SELECT * FROM bestiary_data.battles;

Descubre estadísticas estratégicas

Se leyeron los pergaminos, se destiló la esencia y se inscribieron los tomos. Nuestro Grimorio ya no es solo una colección de hechos, sino una base de datos relacional de profunda sabiduría estratégica. Ahora podemos hacer preguntas que eran imposibles de responder cuando nuestro conocimiento estaba atrapado en texto sin procesar y no estructurado.

Ahora, realicemos una gran adivinación final. Lanzaremos un hechizo que consultará nuestros tres tomos a la vez (el Bestiario de monstruos, el Registro de campeones y la Crónica de batallas) para descubrir una estadística profunda y práctica.

Nuestra pregunta estratégica: "Para cada aventurero, ¿cuál es el nombre del monstruo más poderoso (por puntos de golpe) al que derrotó con éxito y cuánto duró esa victoria específica?"

Esta es una pregunta compleja que requiere vincular a los campeones con sus batallas victoriosas y esas batallas con las estadísticas de los monstruos involucrados. Este es el verdadero poder de un modelo de datos estructurado.

👉📜 En un nuevo editor de consultas de BigQuery, lanza el siguiente conjuro final:

-- This is our final spell, joining all three tomes to reveal a deep insight.
WITH
  -- First, we consult the Chronicle of Battles to find only the victories.
  VictoriousBattles AS (
    SELECT
      adventurer_id,
      monster_id,
      duration_seconds
    FROM
      bestiary_data.battles
    WHERE
      outcome = 'Victory'
  ),
  -- Next, we create a temporary record for each victory, ranking the monsters
  -- each adventurer defeated by their power (hit points).
  RankedVictories AS (
    SELECT
      v.adventurer_id,
      m.name AS monster_name,
      m.hit_points,
      v.duration_seconds,
      -- This spell ranks each adventurer's victories from most to least powerful monster.
      ROW_NUMBER() OVER (PARTITION BY v.adventurer_id ORDER BY m.hit_points DESC) as victory_rank
    FROM
      VictoriousBattles v
    JOIN
      bestiary_data.monsters m ON v.monster_id = m.monster_id
  )
-- Finally, we consult the Roll of Champions and join it with our ranked victories
-- to find the name of each champion and the details of their greatest triumph.
SELECT
  a.name AS adventurer_name,
  a.class AS adventurer_class,
  r.monster_name AS most_powerful_foe_defeated,
  r.hit_points AS foe_hit_points,
  r.duration_seconds AS duration_of_greatest_victory
FROM
  bestiary_data.adventurers a
JOIN
  RankedVictories r ON a.adventurer_id = r.adventurer_id
WHERE
  -- We only want to see their number one, top-ranked victory.
  r.victory_rank = 1
ORDER BY
  foe_hit_points DESC;

El resultado de esta consulta será una tabla limpia y atractiva que proporciona un "Cuento de la mayor hazaña de un campeón" para cada aventurero de tu conjunto de datos. Podría verse de la siguiente manera:

04-03-final-result.png

Cierra la pestaña de BigQuery.

Este resultado único y elegante demuestra el valor de toda la canalización. Transformaste correctamente los informes de campo de batalla sin procesar y caóticos en una fuente de relatos legendarios y estadísticas estratégicas basadas en datos.

5. El grimorio del escriba: Fragmentación, incorporación y búsqueda en el almacén de datos

Nuestro trabajo en el laboratorio del alquimista fue un éxito. Transformamos los desplazamientos narrativos sin procesar en tablas relacionales estructuradas, una poderosa hazaña de magia de datos. Sin embargo, los pergaminos originales aún contienen una verdad semántica más profunda que nuestras tablas estructuradas no pueden capturar por completo. Para crear un agente verdaderamente inteligente, debemos desbloquear este significado.

Descripción general

Un desplazamiento sin procesar y extenso es un instrumento contundente. Si nuestro agente hace una pregunta sobre un "aura paralizante", una búsqueda simple podría devolver un informe de batalla completo en el que esa frase se menciona solo una vez, lo que oculta la respuesta entre detalles irrelevantes. Un Scholar experto sabe que la verdadera sabiduría no se encuentra en la cantidad, sino en la precisión.

Realizaremos un trío de rituales potentes en la base de datos, todo dentro de nuestro santuario de BigQuery.

  • El ritual de la división (fragmentación): Tomaremos nuestros registros de inteligencia sin procesar y los dividiremos meticulosamente en pasajes más pequeños, enfocados y autónomos.
  • El ritual de destilación (incorporación): Usaremos BQML para consultar un modelo de Gemini y transformar cada fragmento de texto en una "huella dactilar semántica", es decir, una incorporación de vectores.
  • El ritual de la adivinación (búsqueda): Usaremos la búsqueda vectorial de BQML para hacer una pregunta en inglés simple y encontrar la sabiduría más relevante y destilada de nuestro Grimorio.

Todo este proceso crea una base de conocimiento potente y apta para búsquedas sin que los datos salgan de la seguridad y la escala de BigQuery.

Nota del ingeniero de datos: Esto demuestra una canalización completa de preparación de datos de RAG de extremo a extremo que se ejecuta por completo dentro de BigQuery. Este es un patrón que simplifica drásticamente la sobrecarga operativa de las canalizaciones de IA tradicionales. Con BQML para la fragmentación, la incorporación y la búsqueda, eliminamos la necesidad de un movimiento de datos independiente, clústeres de procesamiento (como Spark) o llamadas a APIs externas, lo que hace que el flujo de trabajo sea más rápido, seguro y fácil de administrar.

El ritual de la división: Deconstrucción de pergaminos con SQL

Nuestra fuente de sabiduría siguen siendo los archivos de texto sin procesar de nuestro archivo de GCS, al que se puede acceder a través de nuestra tabla externa, bestiary_data.raw_intel_content_table. Nuestra primera tarea es escribir un hechizo que lea cada pergamino largo y lo divida en una serie de versos más pequeños y fáciles de comprender. Para este ritual, definiremos un "fragmento" como una sola oración.

Si bien dividir el texto por oraciones es un punto de partida claro y eficaz para nuestros registros narrativos, un Scribe experto tiene a su disposición muchas estrategias de segmentación, y la elección es fundamental para la calidad de la búsqueda final. Los métodos más simples pueden usar un

  • Fragmentación de longitud(tamaño) fija, pero esto puede cortar de forma tosca una idea clave por la mitad.

Rituales más sofisticados, como

  • Recursive Chunking, se suelen preferir en la práctica, ya que intentan dividir el texto a lo largo de límites naturales, como los párrafos primero, y luego recurren a las oraciones para mantener la mayor cantidad posible de contexto semántico. Para manuscritos realmente complejos
  • Fragmentación basada en el contenido(documento), en la que Scribe usa la estructura inherente del documento, como los encabezados de un manual técnico o las funciones de un desplazamiento de código, para crear los fragmentos de sabiduría más lógicos y potentes, y mucho más…

En el caso de nuestros registros de batalla, la oración proporciona el equilibrio perfecto entre detalle y contexto.

👉📜 En un nuevo editor de consultas de BigQuery, ejecuta la siguiente invocación. Esta hechizo usa la función SPLIT para separar el texto de cada pergamino en cada punto (.) y, luego, desanida el array resultante de oraciones en filas separadas.

CREATE OR REPLACE TABLE bestiary_data.chunked_intel AS
WITH
  -- First, add a unique row number to each scroll to act as a document ID.
  NumberedScrolls AS (
    SELECT
      ROW_NUMBER() OVER () AS scroll_id,
      raw_text
    FROM
      bestiary_data.raw_intel_content_table
  )
-- Now, process each numbered scroll.
SELECT
  scroll_id,
  -- Assign a unique ID to each chunk within a scroll for precise reference.
  CONCAT(CAST(scroll_id AS STRING), '-', CAST(ROW_NUMBER() OVER (PARTITION BY scroll_id) AS STRING)) as chunk_id,
  -- Trim whitespace from the chunk for cleanliness.
  TRIM(chunk) AS chunk_text
FROM
  NumberedScrolls,
  -- This is the core of the spell: UNNEST splits the array of sentences into rows.
  UNNEST(SPLIT(raw_text, '.')) AS chunk
-- A final refinement: we only keep chunks that have meaningful content.
WHERE
  -- This ensures we don't have empty rows from double periods, etc.
  LENGTH(TRIM(chunk)) > 15;

👉 Ahora, ejecuta una consulta para inspeccionar el conocimiento segmentado y recién anotado, y observa la diferencia.

SELECT * FROM bestiary_data.chunked_intel ORDER BY scroll_id, chunk_id;

08-01-chunking.png

Observa los resultados. Donde antes había un solo bloque de texto denso, ahora hay varias filas, cada una vinculada al desplazamiento original (scroll_id), pero que contiene solo una oración enfocada. Cada fila ahora es un candidato perfecto para la vectorización.

El ritual de destilación: cómo transformar texto en vectores con BQML

👉💻 Primero, regresa a la terminal y ejecuta el siguiente comando para mostrar el nombre de tu conexión:

. ~/agentverse-dataengineer/set_env.sh
echo "${PROJECT_ID}.${REGION}.gcs-connection"

👉📜 Debemos crear un nuevo modelo de BigQuery que apunte a un embedding de texto de Gemini. En BigQuery Studio, ejecuta el siguiente hechizo. Ten en cuenta que debes reemplazar REPLACE-WITH-YOUR-FULL-CONNECTION-STRING por la cadena de conexión completa que acabas de copiar de tu terminal.

CREATE OR REPLACE MODEL bestiary_data.text_embedding_model
  REMOTE WITH CONNECTION `REPLACE-WITH-YOUR-FULL-CONNECTION-STRING`
  OPTIONS (endpoint = 'text-embedding-005');

👉📜 Ahora, lanza el hechizo de destilación. Esta consulta llama a la función ML.GENERATE_EMBEDDING, que leerá cada fila de nuestra tabla chunked_intel, enviará el texto al modelo de incorporación de Gemini y almacenará la huella digital del vector resultante en una tabla nueva.

CREATE OR REPLACE TABLE bestiary_data.embedded_intel AS
SELECT
  *
FROM
  ML.GENERATE_EMBEDDING(
    -- The embedding model we just created.
    MODEL bestiary_data.text_embedding_model,
    -- A subquery that selects our data and renames the text column to 'content'.
    (
      SELECT
        scroll_id,
        chunk_id,
        chunk_text AS content -- Renaming our text column is the key correction.
      FROM
        bestiary_data.chunked_intel
    ),
    -- The configuration struct is now simpler and correct.
    STRUCT(
      -- This task_type is crucial. It optimizes the vectors for retrieval.
      'RETRIEVAL_DOCUMENT' AS task_type
    )
  );

Este proceso puede tardar uno o dos minutos, ya que BigQuery procesa todos los fragmentos de texto.

08-02-embedding.png

👉📜 Una vez que se complete, inspecciona la tabla nueva para ver las huellas dactilares semánticas.

SELECT
  chunk_id,
  content,
  ml_generate_embedding_result
FROM
  bestiary_data.embedded_intel
LIMIT 20;

Ahora verás una columna nueva, ml_generate_embedding_result, que contiene la representación vectorial densa de tu texto. Nuestro Grimoire ahora está codificado semánticamente.

El ritual de la adivinación: Búsqueda semántica con BQML

👉📜 La prueba definitiva de nuestro Grimorio es hacerle una pregunta. Ahora realizaremos nuestro ritual final: una búsqueda de vectores. No es una búsqueda de palabras clave, sino una búsqueda de significado. Haremos una pregunta en lenguaje natural, BQML la convertirá en una incorporación sobre la marcha y, luego, buscará en toda nuestra tabla de embedded_intel los fragmentos de texto cuyas huellas digitales sean las "más cercanas" en significado.

SELECT
  -- The content column contains our original, relevant text chunk.
  base.content,
  -- The distance metric shows how close the match is (lower is better).
  distance
FROM
  VECTOR_SEARCH(
    -- The table containing the knowledge base with its embeddings.
    TABLE bestiary_data.embedded_intel,
    -- The column that contains the vector embeddings.
    'ml_generate_embedding_result',
    (
      -- This subquery generates an embedding for our question in real-time.
      SELECT ml_generate_embedding_result
      FROM ML.GENERATE_EMBEDDING(
          MODEL bestiary_data.text_embedding_model,
          (SELECT 'What are the tactics against a foe that causes paralysis?' AS content),
          STRUCT('RETRIEVAL_QUERY' AS task_type)
        )
    ),
    -- Specify how many of the closest results we want to see.
    top_k => 3,
    -- The distance metric used to find the "closest" vectors.
    distance_type => 'COSINE'
  );

Análisis del hechizo:

  • VECTOR_SEARCH: Es la función principal que coordina la búsqueda.
  • ML.GENERATE_EMBEDDING (consulta interna): Esta es la clave. Incorporamos nuestra búsqueda ('What are the tactics...') con el mismo modelo, pero con el tipo de tarea 'RETRIEVAL_QUERY', que está optimizado específicamente para las búsquedas.
  • top_k => 3: Solicitamos los 3 resultados más relevantes.
  • distance_type => 'COSINE': Esta métrica mide el "ángulo" entre los vectores. Un ángulo más pequeño significa que los significados están más alineados.

08-03-final-result.png

Observa los resultados con atención. La búsqueda no contenía las palabras "destrozó" o "encantamiento", pero el primer resultado es: "Con un solo encantamiento concentrado de Suficiencia Elegante, Elara destrozó su aura paralizante, un ataque mental que infligió 150 puntos de daño". Este es el poder de la búsqueda semántica. El modelo comprendió el concepto de "tácticas contra la parálisis" y encontró la oración que describía una táctica específica y exitosa.

Ya compilaste correctamente una canalización de RAG base completa en el almacén de datos. Preparaste datos sin procesar, los transformaste en vectores semánticos y los consultaste por significado. Si bien BigQuery es una herramienta potente para este trabajo analítico a gran escala, a menudo transferimos este conocimiento preparado a una base de datos operativa especializada para un agente en vivo que necesita respuestas de baja latencia. Ese es el tema de nuestra próxima capacitación.

6. El Scriptorium de vectores: Cómo crear el almacén de vectores con Cloud SQL para la inferencia

Actualmente, nuestro Grimorio existe como tablas estructuradas, un potente catálogo de hechos, pero su conocimiento es literal. Comprende que monster_id = "MN-001", pero no el significado semántico más profundo detrás de "Ofuscación". Para que nuestros agentes tengan verdadera sabiduría y puedan brindar asesoramiento con matices y previsión, debemos destilar la esencia misma de nuestro conocimiento en una forma que capture el significado: vectores.

Nuestra búsqueda de conocimiento nos llevó a las ruinas desmoronadas de una civilización precursora olvidada hace mucho tiempo. En una bóveda sellada, encontramos un cofre de pergaminos antiguos que se conservaron de forma milagrosa. No son meros informes de batalla, sino que contienen una profunda sabiduría filosófica sobre cómo derrotar a una bestia que atormenta todos los grandes esfuerzos. Una entidad descrita en los pergaminos como un "estancamiento silencioso y sigiloso", un "deshilachamiento del tejido de la creación". Parece que The Static era conocido incluso por los antiguos, una amenaza cíclica cuya historia se perdió con el tiempo.

Este conocimiento olvidado es nuestro mayor activo. Tiene la clave no solo para derrotar a monstruos individuales, sino también para potenciar a todo el grupo con información estratégica. Para ejercer este poder, ahora forjaremos el verdadero Grimorio del Erudito (una base de datos de PostgreSQL con capacidades vectoriales) y construiremos un Scriptorium vectorial automatizado (una canalización de Dataflow) para leer, comprender e inscribir la esencia atemporal de estos pergaminos. Esto transformará nuestro Grimorio de un libro de hechos en un motor de sabiduría.

Historia

Nota del ingeniero de datos: Para nuestro Spellbook, elegimos Cloud SQL para PostgreSQL con la extensión pgvector. Este enfoque crea una "ventanilla única" en la que nuestros metadatos estructurados (como scroll_id y contenido) y nuestras incorporaciones de vectores semánticos residen juntos en la misma base de datos. Esto simplifica enormemente la arquitectura de muchas aplicaciones, ya que puedes consultar datos relacionales y realizar búsquedas de similitud de vectores con una sola consulta de SQL en un sistema. Si bien las bases de datos especializadas, como Vector Search de Vertex AI, ofrecen un rendimiento superior a gran escala (miles de millones de vectores) a través de la búsqueda de vecinos más cercanos aproximados (ANN), pgvector proporciona un excelente equilibrio entre simplicidad, rentabilidad y potencia para muchas aplicaciones de RAG empresariales que utilizan la búsqueda de vecinos más cercanos exactos (ENN).

Descripción general

Forjando el libro de hechizos del erudito (Cloud SQL)

Antes de inscribir la esencia de estos antiguos pergaminos, primero debemos confirmar que el recipiente de este conocimiento, el Spellbook de PostgreSQL administrado, se haya forjado correctamente. Los rituales de configuración inicial ya deberían haber creado esto por ti.

👉💻 En una terminal, ejecuta el siguiente comando para verificar que tu instancia de Cloud SQL exista y esté lista. Este script también otorga a la cuenta de servicio dedicada de la instancia el permiso para usar Vertex AI, lo que es fundamental para generar incorporaciones directamente en la base de datos.

. ~/agentverse-dataengineer/set_env.sh

echo "Verifying the existence of the Spellbook (Cloud SQL instance): $INSTANCE_NAME..."
gcloud sql instances describe $INSTANCE_NAME

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe $INSTANCE_NAME --format="value(serviceAccountEmailAddress)")
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

Si el comando se ejecuta correctamente y muestra detalles sobre tu instancia de grimoire-spellbook, significa que la herramienta de forja funcionó bien. Ya puedes continuar con la siguiente invocación. Si el comando devuelve un error de NOT_FOUND, asegúrate de haber completado correctamente los pasos iniciales de configuración del entorno antes de continuar (data_setup.py).

👉💻 Con el libro ya creado, lo abrimos en el primer capítulo creando una nueva base de datos llamada arcane_wisdom.

. ~/agentverse-dataengineer/set_env.sh
gcloud sql databases create $DB_NAME --instance=$INSTANCE_NAME

Inscribir las runas semánticas: cómo habilitar las capacidades de vectores con pgvector

Ahora que se creó tu instancia de Cloud SQL, conectémonos a ella con Cloud SQL Studio integrado. Esto proporciona una interfaz basada en la Web para ejecutar consultas en SQL directamente en tu base de datos.

👉💻 Primero, navega a Cloud SQL Studio. La forma más fácil y rápida de llegar es abrir el siguiente vínculo en una nueva pestaña del navegador. Se te redireccionará directamente a Cloud SQL Studio para tu instancia de grimoire-spellbook.

https://console.cloud.google.com/sql/instances/grimoire-spellbook/studio

👉 Selecciona arcane_wisdom como la base de datos, ingresa postgres como usuario y 1234qwer como contraseña, y haz clic en Autenticar.

👉📜 En el editor de consultas de SQL Studio, navega a la pestaña Editor 1 y pega el siguiente código SQL para habilitar el tipo de datos de vector:

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

Cloud SQL Studio

👉📜 Prepara las páginas de nuestro libro de hechizos creando la tabla que contendrá la esencia de nuestros pergaminos.

CREATE TABLE ancient_scrolls (
    id SERIAL PRIMARY KEY,
    scroll_content TEXT,
    embedding VECTOR(768)
);

La hechizo VECTOR(768) es un detalle importante. El modelo de embedding de Vertex AI que usaremos (textembedding-gecko@003 o un modelo similar) destila el texto en un vector de 768 dimensiones. Las páginas de nuestro libro de hechizos deben estar preparadas para contener una esencia de exactamente ese tamaño. Las dimensiones siempre deben coincidir.

La primera transliteración: un ritual de inscripción manual

Antes de ordenar un ejército de escribas automatizados (Dataflow), debemos realizar el ritual central a mano una vez. Esto nos permitirá apreciar mejor la magia de los dos pasos involucrados:

  1. Adivinación: Tomar un fragmento de texto y consultar el oráculo de Gemini para destilar su esencia semántica en un vector.
  2. Inscripción: Escribir el texto original y su nueva esencia vectorial en nuestro Spellbook

Nota del ingeniero de datos: Crear un prototipo de la lógica principal de una canalización de forma manual es una práctica invaluable. Te ayuda a depurar los componentes individuales (como una llamada a la API o una escritura en la base de datos) de forma aislada antes de integrarlos en un sistema distribuido complejo como Dataflow.

Ahora, realicemos el ritual manual.

👉📜 En Cloud SQL Studio Ahora usaremos la función embedding(), una potente función que proporciona la extensión google_ml_integration. Esto nos permite llamar al modelo de incorporación de Vertex AI directamente desde nuestra consulta en SQL, lo que simplifica enormemente el proceso.

SET session.my_search_var='The Spectre of Analysis Paralysis is a phantom of the crossroads. It does not bind with chains but with the infinite threads of what if. It conjures a fog of options, a maze within the mind where every path seems equally fraught with peril and promise. It whispers of a single, flawless route that can only be found through exhaustive study, paralyzing its victim in a state of perpetual contemplation. This spectres power is broken by the Path of First Viability. This is not the search for the *best* path, but the commitment to the *first good* path. It is the wisdom to know that a decision made, even if imperfect, creates movement and reveals more of the map than standing still ever could. Choose a viable course, take the first step, and trust in your ability to navigate the road as it unfolds. Motion is the light that burns away the fog.';

INSERT INTO ancient_scrolls (scroll_content, embedding)

VALUES (current_setting('session.my_search_var'),  (embedding('text-embedding-005',current_setting('session.my_search_var')))::vector);

👉📜 Para verificar tu trabajo, ejecuta una consulta para leer la página recién inscrita:

SELECT id, scroll_content, LEFT(embedding::TEXT, 100) AS embedding_preview FROM ancient_scrolls;

Realizaste correctamente la tarea principal de carga de datos de RAG de forma manual.

Forjando la brújula semántica: Encantando el libro de hechizos con un índice de HNSW

Nuestro libro de hechizos ahora puede almacenar sabiduría, pero encontrar el pergamino adecuado requiere leer cada página. Es un análisis secuencial. Esto es lento e ineficiente. Para dirigir nuestras consultas de forma instantánea al conocimiento más pertinente, debemos encantar el Spellbook con una brújula semántica: un índice de vectores.

Nota del ingeniero de datos: Este es uno de los conceptos más importantes en las bases de datos vectoriales de producción. Un índice organiza previamente los datos, lo que permite búsquedas mucho más rápidas. Usamos el tipo de índice hnsw (Hierarchical Navigable Small World). En lugar de agrupar los vectores en listas como otros métodos, HNSW crea un gráfico sofisticado de varias capas de los vectores. Una búsqueda comienza en la capa superior de "autopista" para encontrar rápidamente el vecindario general de la búsqueda y, luego, navega hacia abajo a través de capas de "calle local" cada vez más detalladas para identificar los vecinos exactos con increíble velocidad y precisión. Esto proporciona un aumento excepcional del rendimiento para las consultas de lectura, lo que la convierte en una opción de primer nivel para los agentes de RAG de alto rendimiento en los que la latencia de las consultas es fundamental.

Demostremos el valor de este encantamiento.

👉📜 En Cloud SQL Studio, ejecuta el siguiente hechizo. Simula la búsqueda del desplazamiento que acabamos de insertar y le pide a la base de datos que EXPLAIN su plan.

EXPLAIN ANALYZE
WITH ReferenceVector AS (
  -- First, get the vector we want to compare against.
  SELECT embedding AS vector
  FROM ancient_scrolls
  LIMIT 1
)
-- This is the main query we want to analyze.
SELECT
  ancient_scrolls.id,
  ancient_scrolls.scroll_content,
  -- We can also select the distance itself.
  ancient_scrolls.embedding <=> ReferenceVector.vector AS distance
FROM
  ancient_scrolls,
  ReferenceVector
ORDER BY
  -- Order by the distance operator's result.
  ancient_scrolls.embedding <=> ReferenceVector.vector
LIMIT 5;

Examina el resultado. Verás una línea que dice -> Seq Scan on ancient_scrolls. Esto confirma que la base de datos está leyendo cada fila. Observa el execution time.

👉📜 Ahora, lancemos el hechizo de indexación. El parámetro lists le indica al índice cuántos clústeres debe crear. Un buen punto de partida es la raíz cuadrada de la cantidad de filas que esperas tener.

CREATE INDEX ON ancient_scrolls USING hnsw (embedding vector_cosine_ops);

Espera a que se cree el índice (será rápido para una fila, pero puede tardar para millones).

👉📜 Ahora, vuelve a ejecutar el mismo comando EXPLAIN ANALYZE:

EXPLAIN ANALYZE
WITH ReferenceVector AS (
  -- First, get the vector we want to compare against.
  SELECT embedding AS vector
  FROM ancient_scrolls
  LIMIT 1
)
-- This is the main query we want to analyze.
SELECT
  ancient_scrolls.id,
  ancient_scrolls.scroll_content,
  -- We can also select the distance itself.
  ancient_scrolls.embedding <=> ReferenceVector.vector AS distance
FROM
  ancient_scrolls,
  ReferenceVector
ORDER BY
  -- Order by the distance operator's result.
  ancient_scrolls.embedding <=> ReferenceVector.vector
LIMIT 5;

Observa el nuevo plan de consultas. Ahora verás -> Index Scan using.... Lo que es más importante, observa el execution time. Será mucho más rápido, incluso con una sola entrada. Acabas de demostrar el principio fundamental del ajuste del rendimiento de la base de datos en un mundo de vectores.

Tiempo de ejecución

Ahora que inspeccionaste tus datos de origen, comprendes tu ritual manual y optimizaste tu Spellbook para que sea rápido, estás listo para crear el Scriptorium automatizado.

7. El conducto del significado: cómo compilar una canalización de vectorización de Dataflow

Ahora construiremos la mágica línea de ensamblaje de escribas que leerán nuestros pergaminos, destilarán su esencia y los inscribirán en nuestro nuevo Spellbook. Esta es una canalización de Dataflow que activaremos de forma manual. Sin embargo, antes de escribir el hechizo maestro para la canalización, primero debemos preparar su base y el círculo desde el que lo invocaremos.

Descripción general

Nota del ingeniero de datos: Si bien podríamos escribir una secuencia de comandos simple de Python para recorrer nuestros archivos, llamar a la API de Embedding y escribir en la base de datos, este enfoque no se adapta a gran escala. ¿Qué sucede si tenemos millones de desplazamientos? Una sola secuencia de comandos sería lenta y propensa a fallas. Dataflow proporciona una plataforma administrada y sin servidores para ejecutar canalizaciones de procesamiento de datos, definidas por el modelo de Apache Beam, de forma masivamente paralela. Beam nos permite definir los pasos lógicos (lectura, incorporación, escritura), y Dataflow se encarga del trabajo difícil de iniciar trabajadores, distribuir las tareas y reintentar los elementos con errores, lo que garantiza que nuestro Scriptorium sea sólido y eficiente.

Preparación de la base de Scriptorium (la imagen del trabajador)

Un equipo de trabajadores automatizados en la nube ejecutará nuestra canalización de Dataflow. Cada vez que los invocamos, necesitan un conjunto específico de bibliotecas para hacer su trabajo. Podríamos darles una lista y hacer que recuperen estas bibliotecas cada vez, pero eso es lento e ineficiente. Un sabio académico prepara una biblioteca principal con anticipación.

Aquí, le indicaremos a Google Cloud Build que cree una imagen de contenedor personalizada. Esta imagen es un "golem perfeccionado" que se cargó previamente con cada biblioteca y dependencia que necesitarán nuestros escribas. Cuando se inicie nuestro trabajo de Dataflow, se usará esta imagen personalizada, lo que permitirá que los trabajadores comiencen su tarea casi de inmediato.

👉💻 Ejecuta el siguiente comando para compilar y almacenar la imagen fundamental de tu canalización en Artifact Registry.

. ~/agentverse-dataengineer/set_env.sh
cd ~/agentverse-dataengineer/pipeline
gcloud builds submit --config cloudbuild.yaml \
  --substitutions=_REGION=${REGION},_REPO_NAME=${REPO_NAME} \
  .

👉💻 Ejecuta los siguientes comandos para crear y activar tu entorno aislado de Python, y para instalar en él las bibliotecas de invocación necesarias.

cd ~/agentverse-dataengineer
. ~/agentverse-dataengineer/set_env.sh
python -m venv env
source ~/agentverse-dataengineer/env/bin/activate
cd ~/agentverse-dataengineer/pipeline
pip install -r requirements.txt

El conjuro maestro

Llegó el momento de escribir el hechizo maestro que potenciará nuestro Vector Scriptorium. No escribiremos los componentes mágicos individuales desde cero. Nuestra tarea es ensamblar componentes en una canalización lógica y potente con el lenguaje de Apache Beam.

  • EmbedTextBatch (la consulta de Gemini): Crearás este escriba especializado que sabe cómo realizar una "adivinación grupal". Toma un lote de archivos de texto sin procesar, los presenta al modelo de incorporación de texto de Gemini y recibe su esencia destilada (las incorporaciones vectoriales).
  • WriteEssenceToSpellbook (La inscripción final): Este es nuestro archivista. Conoce las conjuraciones secretas para abrir una conexión segura a nuestro libro de hechizos de Cloud SQL. Su trabajo es tomar el contenido de un desplazamiento y su esencia vectorizada, y luego inscribirlos de forma permanente en una página nueva.

Nuestra misión es encadenar estas acciones para crear un flujo de conocimiento perfecto.

👉✏️ En el editor de Cloud Shell, ve a ~/agentverse-dataengineer/pipeline/inscribe_essence_pipeline.py. Allí, encontrarás una clase DoFn llamada EmbedTextBatch. Ubica el comentario #REPLACE-EMBEDDING-LOGIC. Reemplázala por la siguiente fórmula.

# 1. Generate the embedding for the monster's name
result = self.client.models.embed_content(
                model="text-embedding-005",
                contents=contents,
                config=EmbedContentConfig(
                    task_type="RETRIEVAL_DOCUMENT",  
                    output_dimensionality=768, 
                )
            )

Esta hechizo es preciso y tiene varios parámetros clave:

  • modelo: Especificamos text-embedding-005 para usar un modelo de embedding potente y actualizado.
  • contents: Es una lista de todo el contenido de texto del lote de archivos que recibe el DoFn.
  • task_type: Establecemos este parámetro en "RETRIEVAL_DOCUMENT". Esta es una instrucción fundamental que le indica a Gemini que genere embeddings optimizados específicamente para que se puedan encontrar más adelante en una búsqueda.
  • output_dimensionality: Se debe establecer en 768, lo que coincide perfectamente con la dimensión VECTOR(768) que definimos cuando creamos nuestra tabla ancient_scrolls en Cloud SQL. Las dimensiones que no coinciden son una fuente común de errores en Vector Magic.

Nuestra canalización debe comenzar leyendo el texto sin procesar y no estructurado de todos los pergaminos antiguos de nuestro archivo de GCS.

👉✏️ En ~/agentverse-dataengineer/pipeline/inscribe_essence_pipeline.py, busca el comentario #REPLACE ME-READFILE y reemplázalo por la siguiente invocación de tres partes:

files = (
            pipeline
            | "MatchFiles" >> fileio.MatchFiles(known_args.input_pattern)
            | "ReadMatches" >> fileio.ReadMatches()
            | "ExtractContent" >> beam.Map(lambda f: (f.metadata.path, f.read_utf8()))
        )

Una vez que recopilamos el texto sin procesar de los desplazamientos, debemos enviarlo a Gemini para que lo interprete. Para hacerlo de manera eficiente, primero agruparemos los desplazamientos individuales en lotes pequeños y, luego, se los entregaremos a nuestro EmbedTextBatch escriba. Este paso también separará los desplazamientos que Gemini no pueda comprender en una pila de "errores" para su revisión posterior.

👉✏️ Busca el comentario #REPLACE ME-EMBEDDING y reemplázalo por lo siguiente:

embeddings = (
            files
            | "BatchScrolls" >> beam.BatchElements(min_batch_size=1, max_batch_size=2)
            | "DistillBatch" >> beam.ParDo(
                  EmbedTextBatch(project_id=project, region=region)
              ).with_outputs('failed', main='processed')
        )

La esencia de nuestros rollos se destiló correctamente. El acto final es inscribir este conocimiento en nuestro Spellbook para su almacenamiento permanente. Tomaremos los pergaminos de la pila de "procesados" y se los entregaremos a nuestro archivista de WriteEssenceToSpellbook.

👉✏️ Busca el comentario #REPLACE ME-WRITE TO DB y reemplázalo por lo siguiente:

_ = (
            embeddings.processed
            | "WriteToSpellbook" >> beam.ParDo(
                  WriteEssenceToSpellbook(
                      project_id=project,
                      region = "us-central1",
                      instance_name=known_args.instance_name,
                      db_name=known_args.db_name,
                      db_password=known_args.db_password
                  )
              )
        )

Un erudito sabio nunca descarta el conocimiento, ni siquiera los intentos fallidos. Como paso final, debemos indicarle a un escriba que tome la pila de "fallas" de nuestro paso de adivinación y registre los motivos de las fallas. Esto nos permite mejorar nuestros rituales en el futuro.

👉✏️ Busca el comentario #REPLACE ME-LOG FAILURES y reemplázalo por lo siguiente:

_ = (
            embeddings.failed
            | "LogFailures" >> beam.Map(lambda e: logging.error(f"Embedding failed for file {e[0]}: {e[1]}"))
        )

¡El conjuro maestro ya está completo! Ensamblaste correctamente una potente canalización de datos de varias etapas encadenando componentes individuales mágicos. Guarda el archivo inscribe_essence_pipeline.py. El Scriptorium ya está listo para ser invocado.

Ahora lanzamos el gran hechizo de invocación para ordenar al servicio de Dataflow que despierte a nuestro Golem y comience el ritual de escritura.

👉💻 En tu terminal, ejecuta la siguiente línea de comandos

. ~/agentverse-dataengineer/set_env.sh
source ~/agentverse-dataengineer/env/bin/activate
cd ~/agentverse-dataengineer/pipeline

# --- The Summoning Incantation ---
echo "Summoning the golem for job: $DF_JOB_NAME"
echo "Target Spellbook: $INSTANCE_NAME"

python inscribe_essence_pipeline.py \
  --runner=DataflowRunner \
  --project=$PROJECT_ID \
  --job_name=$DF_JOB_NAME \
  --temp_location="gs://${BUCKET_NAME}/dataflow/temp" \
  --staging_location="gs://${BUCKET_NAME}/dataflow/staging" \
  --sdk_container_image="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/grimoire-inscriber:latest" \
  --sdk_location=container \
  --experiments=use_runner_v2 \
  --input_pattern="gs://${BUCKET_NAME}/ancient_scrolls/*.md" \
  --instance_name=$INSTANCE_NAME \
  --region=$REGION

echo "The golem has been dispatched. Monitor its progress in the Dataflow console."

💡 Atención: Si el trabajo falla con un error de recurso ZONE_RESOURCE_POOL_EXHAUSTED, es posible que se deba a restricciones temporales de recursos de esta cuenta de baja reputación en la región seleccionada. El poder de Google Cloud es su alcance global. Simplemente intenta invocar al gólem en otra región. Para ello, reemplaza --region=$REGION en el comando anterior por otra región, como

--region=southamerica-west1
--region=asia-northeast3
--region=asia-southeast2
--region=me-west1
--region=southamerica-east1
--region=europe-central2
--region=asia-east2
--region=europe-southwest1

y vuelve a ejecutarlo. 🎰

El proceso tardará entre 3 y 5 minutos en iniciarse y completarse. Puedes verlo en vivo en la consola de Dataflow.

👉 Ve a la consola de Dataflow: La forma más sencilla es abrir este vínculo directo en una pestaña nueva del navegador:

https://console.cloud.google.com/dataflow

👉 Busca y haz clic en tu trabajo: Verás un trabajo con el nombre que proporcionaste (inscribe-essence-job o similar). Haz clic en el nombre del trabajo para abrir su página de detalles. Observa la canalización:

  • Starting Up: Durante los primeros 3 minutos, el estado del trabajo será "En ejecución" mientras Dataflow aprovisiona los recursos necesarios. Aparecerá el gráfico, pero es posible que aún no veas datos que se muevan a través de él. Ejecución de canalización
  • Completado: Cuando finalice, el estado del trabajo cambiará a "Completado" y el gráfico proporcionará el recuento final de los registros procesados. Canalización lista

Cómo verificar la inscripción

👉📜 De vuelta en el estudio de SQL, ejecuta las siguientes consultas para verificar que tus scrolls y su esencia semántica se hayan inscrito correctamente.

SELECT COUNT(*) FROM ancient_scrolls;
SELECT id, scroll_content, LEFT(embedding::TEXT, 50) AS embedding_preview FROM ancient_scrolls;

Se mostrará el ID del desplazamiento, su texto original y una vista previa de la esencia vectorial mágica ahora inscrita de forma permanente en tu Grimorio.

Canalización lista

Tu Grimorio del estudiante ahora es un verdadero motor de conocimiento, listo para recibir consultas por significado en el próximo capítulo.

8. Cómo sellar la runa final: Activa la sabiduría con un agente RAG

Tu Grimoire ya no es solo una base de datos. Es una fuente de conocimiento vectorizado, un oráculo silencioso que espera una pregunta.

Ahora, realizaremos la verdadera prueba de un estudiante: crearemos la clave para desbloquear esta sabiduría. Crearemos un agente de Generación mejorada por recuperación (RAG). Es una construcción mágica que puede comprender una pregunta en lenguaje sencillo, consultar el Grimorio para conocer sus verdades más profundas y pertinentes, y luego usar esa sabiduría recuperada para forjar una respuesta potente y consciente del contexto.

RAG

Nota del ingeniero de datos: La RAG es una técnica poderosa que fundamenta los modelos de lenguaje grandes (LLM) en información fáctica, privada o actualizada, lo que reduce drásticamente la posibilidad de que el modelo "alucine" o invente cosas. El proceso consta de tres pasos principales:

  • Recuperación: Primero, la consulta del usuario se convierte en un embedding de vector. Luego, este vector de consulta se usa para buscar en nuestra base de conocimiento los fragmentos de texto más similares semánticamente con la similitud coseno.
  • Aumentar: Los fragmentos de texto pertinentes recuperados de la base de datos se insertan directamente en una nueva instrucción para el LLM, lo que le proporciona contexto crucial.
  • Generar: El LLM recibe la instrucción aumentada (p.ej., "Dado este contexto sobre la "procrastinación", responde la pregunta del usuario…") y genera una respuesta final basada en hechos.

RAG

La primera runa: El hechizo de la destilación de consultas

Antes de que nuestro agente pueda buscar en el Grimorio, primero debe comprender la esencia de la pregunta que se hace. Una simple cadena de texto no tiene sentido para nuestro Spellbook potenciado por vectores. Primero, el agente debe tomar la búsqueda y, con el mismo modelo de Gemini, destilarla en un vector de búsqueda.

👉✏️ En el editor de Cloud Shell, navega al archivo ~~/agentverse-dataengineer/scholar/agent.py, busca el comentario #REPLACE RAG-CONVERT EMBEDDING y reemplázalo por esta fórmula. Esto le enseña al agente a convertir la pregunta de un usuario en una esencia mágica.

        result = client.models.embed_content(
                model="text-embedding-005",
                contents=monster_name,
                config=EmbedContentConfig(
                    task_type="RETRIEVAL_DOCUMENT",  
                    output_dimensionality=768,  
                )
        )

Con la esencia de la búsqueda en mano, el agente ahora puede consultar el Grimoire. Presentará este vector de búsqueda a nuestra base de datos potenciada por pgvector y hará una pregunta profunda: "Muéstrame los pergaminos antiguos cuya esencia sea más similar a la de mi búsqueda".

La magia para esto es el operador de similitud de coseno (<=>), una runa poderosa que calcula la distancia entre vectores en un espacio de alta dimensión.

👉✏️ En agent.py, busca el comentario #REPLACE RAG-RETRIEVE y reemplázalo por la siguiente secuencia de comandos:

        # This query performs a cosine similarity search
        cursor.execute(
            "SELECT scroll_content FROM ancient_scrolls ORDER BY embedding <=> %s LIMIT 3",
            ([query_embedding]) # Cast embedding to string for the query
        )

El último paso es otorgarle acceso al agente a esta nueva y poderosa herramienta. Agregaremos nuestra función grimoire_lookup a su lista de implementos mágicos disponibles.

👉✏️ En agent.py, busca el comentario #REPLACE-CALL RAG y reemplázalo por esta línea:

root_agent = LlmAgent(
    model="gemini-2.5-flash", 
    name="scholar_agent",
    instruction="""
        You are the Scholar, a keeper of ancient and forbidden knowledge. Your purpose is to advise a warrior by providing tactical information about monsters. Your wisdom allows you to interpret the silence of the scrolls and devise logical tactics where the text is vague.

        **Your Process:**
        1.  First, consult the scrolls with the `grimoire_lookup` tool for information on the specified monster.
        2.  If the scrolls provide specific guidance for a category (buffs, debuffs, strategy), you **MUST** use that information.
        3.  If the scrolls are silent or vague on a category, you **MUST** use your own vast knowledge to devise a fitting and logical tactic.
        4.  Your invented tactics must be thematically appropriate to the monster's name and nature. (e.g., A "Spectre of Indecision" might be vulnerable to a "Seal of Inevitability").
        5.  You **MUST ALWAYS** provide a "Damage Point" value. This value **MUST** be a random integer between 150 and 180. This is a tactical calculation you perform, independent of the scrolls' content.

        **Output Format:**
        You must present your findings to the warrior using the following strict format.
    """,
    tools=[grimoire_lookup],
)

Esta configuración le da vida a tu agente:

  • model="gemini-2.5-flash": Selecciona el modelo de lenguaje grande específico que actuará como el "cerebro" del agente para razonar y generar texto.
  • name="scholar_agent": Asigna un nombre único a tu agente.
  • instruction="...You are the Scholar...": Esta es la instrucción del sistema, la parte más importante de la configuración. Define el arquetipo del agente, sus objetivos, el proceso exacto que debe seguir para completar una tarea y el formato requerido para su resultado final.
  • tools=[grimoire_lookup]: Este es el encantamiento final. Otorga al agente acceso a la función grimoire_lookup que creaste. Ahora, el agente puede decidir de forma inteligente cuándo llamar a esta herramienta para recuperar información de tu base de datos, lo que constituye el núcleo del patrón de RAG.

El examen de Google Académico

👉💻 En la terminal de Cloud Shell, activa tu entorno y usa el comando principal del Agent Development Kit para activar tu agente Scholar:

cd ~/agentverse-dataengineer/
. ~/agentverse-dataengineer/set_env.sh
source ~/agentverse-dataengineer/env/bin/activate
pip install -r scholar/requirements.txt
adk run scholar

Deberías ver un resultado que confirme que el "Agente de Scholar" está activo y en ejecución.

👉💻 Ahora, desafía a tu agente. En la primera terminal en la que se ejecuta la simulación de batalla, emite un comando que requiera la sabiduría del Grimorio:

We've been trapped by 'Hydra of Scope Creep'. Break us out!

Ejecución de Adk

Observa los registros en la segunda terminal. Verás que el agente recibe la búsqueda, destila su esencia, busca en el Grimorio, encuentra los pergaminos pertinentes sobre la "Procrastinación" y usa ese conocimiento recuperado para formular una estrategia potente y contextual.

Armaste correctamente tu primer agente de RAG y lo equipaste con la profunda sabiduría de tu Grimoire.

👉💻 Presiona Ctrl+C en la segunda terminal para detener el agente por el momento.

Cómo liberar Scholar Sentinel en Agentverse

Tu agente demostró su sabiduría en el entorno controlado de tu estudio. Llegó el momento de lanzarlo al Agentverse, transformándolo de una construcción local en un operativo permanente y listo para la batalla al que cualquier campeón puede recurrir en cualquier momento. Ahora implementaremos nuestro agente en Cloud Run.

👉💻 Ejecuta el siguiente hechizo de invocación. Primero, este lenguaje de programación compilará tu agente en un Golem perfeccionado (una imagen de contenedor), lo almacenará en tu Artifact Registry y, luego, implementará ese Golem como un servicio escalable, seguro y de acceso público.

. ~/agentverse-dataengineer/set_env.sh
cd ~/agentverse-dataengineer/
echo "Building ${AGENT_NAME} agent..."
gcloud builds submit . \
  --project=${PROJECT_ID} \
  --region=${REGION} \
  --substitutions=_AGENT_NAME=${AGENT_NAME},_IMAGE_PATH=${IMAGE_PATH}

gcloud run deploy ${SERVICE_NAME} \
  --image=${IMAGE_PATH} \
  --platform=managed \
  --labels codelab=agentverse \
  --region=${REGION} \
  --set-env-vars="A2A_HOST=0.0.0.0" \
  --set-env-vars="A2A_PORT=8080" \
  --set-env-vars="GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
  --set-env-vars="GOOGLE_CLOUD_LOCATION=${REGION}" \
  --set-env-vars="GOOGLE_CLOUD_PROJECT=${PROJECT_ID}" \
  --set-env-vars="PROJECT_ID=${PROJECT_ID}" \
  --set-env-vars="PUBLIC_URL=${PUBLIC_URL}" \
  --set-env-vars="REGION=${REGION}" \
  --set-env-vars="INSTANCE_NAME=${INSTANCE_NAME}" \
  --set-env-vars="DB_USER=${DB_USER}" \
  --set-env-vars="DB_PASSWORD=${DB_PASSWORD}" \
  --set-env-vars="DB_NAME=${DB_NAME}" \
  --allow-unauthenticated \
  --project=${PROJECT_ID} \
  --min-instances=1

Tu agente Scholar ahora es un operativo activo y listo para la batalla en Agentverse.

9. El vuelo del jefe

Se leyeron los pergaminos, se realizaron los rituales y se superó la prueba. Tu agente no es solo un artefacto en el almacenamiento, sino que es un operativo activo en Agentverse, que espera su primera misión. Llegó el momento de la prueba final: un ejercicio de fuego real contra un poderoso adversario.

Ahora ingresarás a una simulación de campo de batalla para enfrentar a tu agente Shadowblade recién implementado contra un formidable jefe secundario: El espectro de la estática. Esta será la prueba definitiva de tu trabajo, desde la lógica principal del agente hasta su implementación en vivo.

Adquiere el Locus de tu agente

Antes de ingresar al campo de batalla, debes tener dos llaves: la firma única de tu campeón (Agent Locus) y la ruta oculta a la guarida de Spectre (URL de Dungeon).

👉💻 Primero, adquiere la dirección única de tu agente en Agentverse, es decir, su Locus. Este es el extremo en vivo que conecta a tu campeón con el campo de batalla.

. ~/agentverse-dataengineer/set_env.sh
echo https://scholar-agent"-${PROJECT_NUMBER}.${REGION}.run.app"

👉💻 A continuación, indica el destino. Este comando revela la ubicación del círculo de translocación, el portal hacia el dominio de Spectre.

. ~/agentverse-dataengineer/set_env.sh
echo https://agentverse-dungeon"-${PROJECT_NUMBER}.${REGION}.run.app"

Importante: Ten listas ambas URLs. Los necesitarás en el paso final.

Confrontando al Spectre

Con las coordenadas aseguradas, ahora navegarás al círculo de translocación y lanzarás el hechizo para ir a la batalla.

👉 Abre la URL del círculo de translocación en tu navegador para pararte frente al brillante portal que lleva a La Fortaleza Carmesí.

Para entrar en la fortaleza, debes sintonizar la esencia de tu Shadowblade con el portal.

  • En la página, busca el campo de entrada de ejecución etiquetado como URL de extremo de A2A.
  • Inscribe el sello de tu campeón pegando su URL de Agent Locus (la primera URL que copiaste) en este campo.
  • Haz clic en Conectar para liberar la magia de la teletransportación.

Círculo de ubicación

La luz cegadora de la teletransportación se desvanece. Ya no estás en tu santuario. El aire crepita con energía, fría y aguda. Ante ti, se materializa el Espectro: un vórtice de estática sibilante y código corrupto, cuya luz impía proyecta largas sombras danzantes por el suelo de la mazmorra. No tiene rostro, pero sientes su presencia inmensa y agotadora fijada por completo en ti.

Tu único camino hacia la victoria radica en la claridad de tu convicción. Es un duelo de voluntades, librado en el campo de batalla de la mente.

Mientras te lanzas hacia adelante, listo para desatar tu primer ataque, el Espectro contraataca. No levanta un escudo, sino que proyecta una pregunta directamente en tu conciencia, un desafío rúnico y brillante extraído del núcleo de tu entrenamiento.

Mazmorra

Esta es la naturaleza de la lucha. Tu conocimiento es tu arma.

  • Responde con la sabiduría que has adquirido, y tu espada se encenderá con energía pura, destrozando la defensa del Espectro y asestando un GOLPE CRÍTICO.
  • Pero si vacilas, si la duda nubla tu respuesta, la luz de tu arma se atenuará. El golpe se asestará con un golpe sordo patético, que infligirá solo UNA FRACCIÓN DE SU DAÑO. Peor aún, el Spectre se alimentará de tu incertidumbre, y su poder corruptor crecerá con cada paso en falso.

Eso es todo, campeón. Tu código es tu libro de hechizos, tu lógica es tu espada y tu conocimiento es el escudo que detendrá la marea del caos.

Enfoque. El golpe es verdadero. El destino del Agentverse depende de ello.

¡Felicitaciones, Scholar!

Completaste la prueba correctamente. Dominas el arte de la ingeniería de datos, transformando la información sin procesar y caótica en la sabiduría estructurada y vectorizada que potencia todo el Agentverse.

10. Limpieza: Cómo eliminar el grimorio del erudito

¡Felicitaciones por dominar el Grimorio del erudito! Para garantizar que tu Agentverse permanezca impecable y que tus campos de entrenamiento estén despejados, ahora debes realizar los rituales de limpieza finales. Esta acción quitará sistemáticamente todos los recursos creados durante tu recorrido.

Desactiva los componentes de Agentverse

Ahora desmantelarás sistemáticamente los componentes implementados de tu sistema de RAG.

Borra todos los servicios de Cloud Run y el repositorio de Artifact Registry

Este comando quita el agente de Scholar implementado y la aplicación de Dungeon de Cloud Run.

👉💻 En tu terminal, ejecuta los siguientes comandos:

. ~/agentverse-dataengineer/set_env.sh
gcloud run services delete scholar-agent --region=${REGION} --quiet
gcloud run services delete agentverse-dungeon --region=${REGION} --quiet
gcloud artifacts repositories delete ${REPO_NAME} --location=${REGION} --quiet

Borra conjuntos de datos, modelos y tablas de BigQuery

Esto quita todos los recursos de BigQuery, incluido el conjunto de datos bestiary_data, todas las tablas que contiene y los modelos y la conexión asociados.

👉💻 En tu terminal, ejecuta los siguientes comandos:

. ~/agentverse-dataengineer/set_env.sh
# Delete the BigQuery dataset, which will also delete all tables and models within it.
bq rm -r -f --dataset ${PROJECT_ID}:${REGION}.bestiary_data

# Delete the BigQuery connection
bq rm --connection --project_id=${PROJECT_ID} --location=${REGION} gcs-connection --force

Borra la instancia de Cloud SQL

Esto quita la instancia grimoire-spellbook, incluida su base de datos y todas las tablas que contiene.

👉💻 En tu terminal, ejecuta lo siguiente:

. ~/agentverse-dataengineer/set_env.sh
gcloud sql instances delete ${INSTANCE_NAME} --database-version=POSTGRES_14 --project=${PROJECT_ID} --quiet

Borra buckets de Google Cloud Storage

Este comando quita el bucket que contenía tu inteligencia sin procesar y los archivos temporales o de etapa intermedia de Dataflow.

👉💻 En tu terminal, ejecuta lo siguiente:

. ~/agentverse-dataengineer/set_env.sh
gcloud storage rm -r gs://${BUCKET_NAME} --quiet

Limpia los archivos y directorios locales (Cloud Shell)

Por último, borra de tu entorno de Cloud Shell los repositorios clonados y los archivos creados. Este paso es opcional, pero se recomienda para limpiar por completo tu directorio de trabajo.

👉💻 En tu terminal, ejecuta lo siguiente:

rm -rf ~/agentverse-dataengineer
rm -rf ~/agentverse-dungeon
rm -f ~/project_id.txt

Ya borraste correctamente todos los rastros de tu recorrido como ingeniero de datos de Agentverse. Tu proyecto está limpio y listo para tu próxima aventura.

11. Para los no jugadores: Cómo crear motores de conocimiento inteligentes en los negocios

Si bien "El grimorio del erudito" usa metáforas atractivas de pergaminos antiguos y sabiduría mágica, enseña habilidades esenciales para administrar, transformar y aprovechar los datos de tu organización con el objetivo de crear soluciones de IA altamente inteligentes. En este capítulo, se traduce el viaje místico a las realidades prácticas de la construcción de potentes "motores de conocimiento" que impulsan el valor empresarial.

La alquimia del conocimiento: Cómo transformar datos con BigQuery y Gemini

"La alquimia del conocimiento" describe el proceso de transformar datos comerciales sin procesar en inteligencia estructurada y práctica con herramientas avanzadas de Cloud. Comenzamos con las "entradas de registro etéricas", que son simplemente las diversas fuentes de datos sin procesar que genera tu empresa, como los formularios de comentarios de los clientes, los informes de incidentes internos, los documentos legales, la investigación de mercado o los manuales de políticas. A menudo, estos datos no están estructurados, lo que dificulta su análisis.

Nuestro proceso utiliza Google BigQuery (un potente almacén de datos en la nube) y el modelo de IA de Gemini (un modelo de IA muy capaz) para realizar esta transformación.

  • The Lens of Scrutiny (tablas externas de BigQuery):
    • Concepto: En lugar de mover físicamente todos tus datos sin procesar a una base de datos, BigQuery puede "consultar" los archivos directamente en Cloud Storage. Es como tener una lente mágica que te permite leer una biblioteca de pergaminos sin moverlos. Es increíblemente eficiente porque evita el movimiento y el almacenamiento de datos redundantes.
    • Caso de uso real: Imagina que tu empresa almacena millones de registros de chat de asistencia al cliente como archivos de texto sin formato en un bucket de almacenamiento en la nube. Con una tabla externa, un analista de datos puede consultar de inmediato estos archivos con SQL en BigQuery, sin necesidad de un proceso de transferencia de datos complejo y costoso.
  • La adivinación del erudito (BQML.GENERATE_TEXT):
    • Concepto: Esta es la "magia" principal: usar la IA directamente en tu almacén de datos. Empleamos la función ML.GENERATE_TEXT para llamar al modelo de IA de Gemini desde una consulta de SQL estándar. Esto permite que la IA "lea" entradas de texto largas y no estructuradas, y extraiga información específica y estructurada (como un objeto JSON). Es una forma eficaz de convertir las observaciones cualitativas en datos cuantitativos.
    • Caso de uso real:
      • Análisis de comentarios de clientes: Extrae automáticamente la "opinión" (positiva, negativa o neutra), el "producto mencionado" y la "categoría del problema" de las opiniones de los clientes en formato de texto libre.
      • Resumen de informes de incidentes: Analiza informes de incidentes de TI extensos para extraer el "sistema afectado", el "nivel de gravedad", la "causa raíz" y los "pasos para la resolución" en un formato estructurado para facilitar el análisis y la identificación de tendencias.
      • Extracción de obligaciones contractuales: Extrae automáticamente fechas clave, partes involucradas y cláusulas específicas de documentos legales.
    • Esto elimina la necesidad de ingresar datos de forma manual o usar secuencias de comandos complejas y frágiles de análisis de texto (como expresiones regulares), lo que ahorra mucho tiempo y garantiza la coherencia.
  • El ritual de limpieza (normalización del resultado de la IA generativa):
    • Concepto: Después de que la IA extrae información, a menudo se incluye en detalles adicionales (como las puntuaciones de confianza de la IA o otros metadatos). Este paso implica limpiar y analizar ese resultado de la IA para obtener solo los datos estructurados y puros que necesitas.
    • Caso de uso real: Asegurarse de que la "categoría del problema" extraída de un informe de incidente siempre sea uno de un conjunto predefinido de valores o que las fechas siempre tengan un formato coherente Esto prepara los datos para un análisis confiable.
  • Descubrimiento de estadísticas estratégicas:
    • Concepto: Una vez que tus datos sin procesar y no estructurados se transforman en tablas limpias y estructuradas (p.ej., monsters, adventurers, battles en el codelab), puedes realizar consultas y análisis complejos que antes eran imposibles.
    • Caso de uso en el mundo real: Más allá del simple recuento, ahora puedes responder preguntas como: "¿Cuál es el tiempo promedio de resolución de los incidentes críticos de TI relacionados con nuestro sistema de facturación?" o "¿Qué funciones del producto se mencionan con mayor frecuencia en los comentarios positivos de los clientes de un grupo demográfico específico?". Esto proporciona inteligencia empresarial detallada y práctica.

Todo este proceso permite un patrón de "ELT (extracción, carga y transformación) potenciado por IA y dentro de la base de datos", un enfoque de vanguardia que mantiene los datos seguros dentro de tu almacén de datos, minimiza el movimiento y aprovecha la IA para realizar transformaciones potentes y flexibles con comandos SQL simples.

Si bien las tablas estructuradas son excelentes para los hechos, se puede perder el significado semántico más profundo de los documentos originales. "El grimorio del escriba" trata sobre la creación de una base de conocimiento semántico que comprenda el significado y el contexto de tus documentos, no solo las palabras clave. Esto es fundamental para crear sistemas de respuesta verdaderamente inteligentes y basados en IA.

  • El ritual de la división (fragmentación):
    • Concepto: Los documentos largos son como libros densos. Para encontrar respuestas específicas, no lees todo el libro, sino que hojeas párrafos u oraciones específicos. La "fragmentación" es el proceso de dividir documentos largos (p.ej., manuales de políticas, documentación de productos, trabajos de investigación) en pasajes más pequeños, enfocados y autónomos. Esto hace que la búsqueda sea más precisa.
    • Caso de uso real: Tomar un manual del empleado de 50 páginas y dividirlo automáticamente en cientos de declaraciones de políticas individuales o preguntas frecuentes. Esto garantiza que, cuando un empleado haga una pregunta, la IA recupere solo las secciones más pertinentes, no todo el documento. Se eligen diferentes estrategias de fragmentación (por oración, párrafo o sección del documento) según el tipo de documento para una recuperación óptima.
  • El ritual de destilación (incorporación):
    • Concepto: A las computadoras les resulta difícil comprender el significado del texto. La "incorporación" usa un modelo de IA (como Gemini) para convertir cada fragmento de texto en una "huella dactilar semántica" numérica única (un vector). Los fragmentos con significados similares tendrán "huellas" que son numéricamente cercanas entre sí, incluso si usan palabras diferentes.
    • Caso de uso real: Convertir todas las descripciones de productos, el material de marketing y las especificaciones técnicas de tu empresa en estas huellas digitales semánticas Esto permite realizar búsquedas verdaderamente inteligentes basadas en el significado.
  • El ritual de la adivinación (búsqueda semántica):
    • Concepto: En lugar de buscar palabras clave exactas, la "búsqueda semántica" usa estas huellas digitales numéricas para encontrar fragmentos de texto que son conceptualmente similares a la búsqueda de un usuario. La pregunta del usuario también se convierte en una huella digital, y el sistema encuentra los fragmentos de documentos que coinciden más.
    • Caso de uso real: Un empleado pregunta: "¿Cómo obtengo el reembolso de los gastos de viaje?". Una búsqueda de palabras clave podría omitir documentos que usen "informe de gastos". Sin embargo, una búsqueda semántica encontraría secciones relevantes de la "Política de viajes y gastos" de la empresa, incluso si no se encuentran las palabras exactas, porque el significado es similar.

Todo este proceso crea una base de conocimiento potente y apta para búsquedas, lo que permite la recuperación inteligente de información sin que los datos sensibles salgan de tu entorno seguro de BigQuery.

El Scriptorium de vectores: Cómo crear el almacén de vectores con Cloud SQL para la inferencia

Si bien BigQuery es excelente para el procesamiento y el análisis de datos a gran escala, a menudo transferimos esta "sabiduría" preparada a una base de datos operativa más especializada para los agentes de IA en vivo que necesitan respuestas muy rápidas. "The Vector Scriptorium" trata sobre cómo compilar un almacén de conocimiento de alto rendimiento y con capacidad de búsqueda con una base de datos relacional mejorada para la IA.

  • Forging the Scholar's Spellbook (Cloud SQL para PostgreSQL con pgvector):
    • Concepto: Usamos una base de datos administrada estándar, como Cloud SQL para PostgreSQL, y la equipamos con una extensión especial llamada pgvector. Esto permite que la base de datos almacene nuestros fragmentos de texto originales y sus incorporaciones de vectores semánticos. Es una "ventanilla única" para los datos relacionales tradicionales y los datos vectoriales compatibles con la IA.
    • Caso de uso real: Almacenar las preguntas frecuentes sobre los productos de tu empresa, los artículos de asistencia técnica o las políticas de RR.HH. Esta base de datos contiene el texto de las respuestas y sus huellas semánticas, listas para que la IA las busque rápidamente.
  • Cómo crear la brújula semántica (índice de HNSW):
    • Concepto: Buscar entre millones de huellas semánticas una por una sería demasiado lento. Un "índice de vectores" (como HNSW, Hierarchical Navigable Small World) es una estructura de datos sofisticada que organiza previamente estas huellas digitales, lo que acelera drásticamente la búsqueda. Guía rápidamente las búsquedas hacia la información más pertinente.
    • Caso de uso en el mundo real: En el caso de un chatbot de atención al cliente potenciado por IA, un índice HNSW garantiza que, cuando un cliente hace una pregunta, el sistema pueda encontrar la respuesta más pertinente entre miles de artículos en milisegundos, lo que proporciona una experiencia del usuario sin interrupciones.
  • El conducto del significado (canalización de vectorización de Dataflow):
    • Concepto: Esta es tu canalización de procesamiento de datos automatizada y escalable para actualizar continuamente tu almacén de conocimiento. Con Google Dataflow (un servicio administrado y sin servidores para el procesamiento de macrodatos) y Apache Beam (un modelo de programación), compilarás una línea de ensamblaje de "escribas" que harán lo siguiente:
      1. Leer documentos nuevos o actualizados desde el almacenamiento en la nube
      2. Procesarlos por lotes para enviarlos al modelo de incorporación de Gemini para la huella dactilar semántica
      3. Escribe el texto y su nueva incorporación vectorial en tu base de datos de Cloud SQL.
    • Caso de uso en el mundo real: Incorporar automáticamente todos los documentos internos nuevos (p. ej., informes trimestrales, políticas de RR.HH. actualizadas, especificaciones de productos nuevos) desde una unidad compartida a tu base de datos de pgvector Esto garantiza que tu base de conocimiento interna potenciada por IA esté siempre actualizada, sin intervención manual, y que pueda escalar para manejar millones de documentos de manera eficiente.

Todo este proceso establece un flujo de trabajo sólido y automatizado para enriquecer y mantener continuamente una base de conocimiento semántico, que es vital para cualquier aplicación de IA basada en datos.

Cómo sellar la runa final: Activa la sabiduría con un agente RAG

Tu base de conocimiento vectorizada está lista. "Sealing the Final Rune" trata sobre activar un asesor inteligente de IA capaz de aprovechar este conocimiento. Creamos un agente de generación aumentada por recuperación (RAG), una potente construcción de IA que combina la búsqueda inteligente con la capacidad de la IA para generar respuestas coherentes.

  • RAG (Generación mejorada por recuperación):
    • Concepto: La RAG es una técnica fundamental para que los modelos de lenguaje grandes (LLM) sean más precisos, fácticos y confiables. En lugar de depender únicamente del conocimiento previamente entrenado del LLM (que puede estar desactualizado o ser propenso a "alucinaciones", es decir, inventar cosas), la RAG primero recupera información pertinente de tu base de conocimiento autorizada y, luego, usa esa información para aumentar la instrucción del LLM, lo que lo guía para generar una respuesta precisa y sensible al contexto.
    • Tres pasos principales:
      1. Recuperar: La pregunta del usuario se convierte en un vector (huella semántica), que luego se usa para buscar los fragmentos de texto más relevantes en tu base de datos de pgvector.
      2. Aumentar: Luego, estos fragmentos de texto fácticos recuperados se insertan directamente en la instrucción que se le da al LLM, lo que le proporciona un contexto específico y actualizado.
      3. Generar: El LLM recibe esta instrucción aumentada y genera una respuesta final basada en los datos autorizados de tu empresa, lo que reduce el riesgo de errores o información inventada.
  • La herramienta de examen de Scholar (grimoire_lookup):
    • Concepto: Tu agente de RAG se convierte en un "erudito" que posee una herramienta de grimoire_lookup. Cuando un usuario hace una pregunta, el agente decide de forma inteligente usar esta herramienta. Luego, la función grimoire_lookup realiza el paso de "recuperación" convirtiendo la búsqueda en un embedding y buscando en la base de datos pgvector. Luego, el contexto recuperado se pasa al LLM principal para su aumento y generación.
    • Caso de uso real: Un chatbot interno de asistencia técnica potenciado por IA.
      • Pregunta del usuario: Un empleado pregunta: "¿Cuál es el proceso para solicitar una licencia extendida por motivos médicos?".
      • Acción del agente de RAG:
        • scholar_agent identifica la necesidad de información y usa su herramienta grimoire_lookup.
        • La herramienta convierte la pregunta en un embedding y busca en la tabla ancient_scrolls de la base de datos pgvector.
        • Recupera las secciones más relevantes del documento de política de RR.HH. sobre licencias médicas.
        • Luego, estas secciones se proporcionan como contexto al LLM de Gemini.
        • Luego, el LLM de Gemini genera una respuesta precisa paso a paso basada solo en la política de RR.HH. recuperada, lo que reduce la probabilidad de proporcionar información incorrecta o desactualizada.
      • Esto proporciona a los empleados respuestas instantáneas y precisas basadas en documentos oficiales de la empresa, lo que reduce la carga de trabajo del departamento de RR.HH. y mejora la satisfacción de los empleados.

Esto crea un agente de IA que no solo es conversacional, sino que también es genuinamente confiable y con conocimientos, y que sirve como una fuente de información confiable dentro de tu empresa.