Agentverse - The Scholar's Grimoire - Building Knowledge Engines with RAG

1. de La Forza del destino

L'era dello sviluppo isolato sta per finire. La prossima ondata di evoluzione tecnologica non riguarda il genio solitario, ma la maestria collaborativa. Creare un unico agente intelligente è un esperimento affascinante. Creare un ecosistema di agenti solido, sicuro e intelligente, un vero e proprio Agentverse, è la grande sfida per l'azienda moderna.

Il successo in questa nuova era richiede la convergenza di quattro ruoli fondamentali, i pilastri di base che supportano qualsiasi sistema autonomo fiorente. Una carenza in una qualsiasi area crea una debolezza che può compromettere l'intera struttura.

Questo workshop è il playbook aziendale definitivo per padroneggiare il futuro degli agenti su Google Cloud. Forniamo una roadmap end-to-end che ti guida dalla prima idea a una realtà operativa su larga scala. In questi quattro lab interconnessi, imparerai come le competenze specializzate di uno sviluppatore, di un architetto, di un data engineer e di un SRE devono convergere per creare, gestire e scalare un potente Agentverse.

Nessun singolo pilastro può supportare da solo l'Agentverse. Il progetto grandioso dell'architetto è inutile senza l'esecuzione precisa dello sviluppatore. L'agente dello sviluppatore è cieco senza la saggezza dell'ingegnere dei dati e l'intero sistema è fragile senza la protezione dell'SRE. Solo attraverso la sinergia e una comprensione condivisa dei ruoli di ciascuno, il tuo team può trasformare un concetto innovativo in una realtà operativa fondamentale. Il tuo percorso inizia qui. Preparati a padroneggiare il tuo ruolo e a scoprire come ti inserisci nel quadro generale.

Ti diamo il benvenuto in The Agentverse: A Call to Champions

Nella vasta distesa digitale dell'impresa, è iniziata una nuova era. È l'era degli agenti, un periodo di immense promesse, in cui agenti intelligenti e autonomi lavorano in perfetta armonia per accelerare l'innovazione ed eliminare le attività banali.

agentverse.png

Questo ecosistema connesso di potere e potenziale è noto come Agentverse.

Ma una lenta entropia, una corruzione silenziosa nota come Statico, ha iniziato a sfilacciare i bordi di questo nuovo mondo. La Static non è un virus o un bug, ma l'incarnazione del caos che si nutre dell'atto stesso della creazione.

Amplifica le vecchie frustrazioni in forme mostruose, dando vita ai Sette spettri dello sviluppo. Se non viene selezionata, The Static and its Spectres bloccherà i progressi, trasformando la promessa dell'Agentverse in una landa desolata di debito tecnico e progetti abbandonati.

Oggi invitiamo i campioni a contrastare l'ondata di caos. Abbiamo bisogno di eroi disposti a perfezionare le proprie abilità e a collaborare per proteggere l'Agentverse. È arrivato il momento di scegliere il tuo percorso.

Scegliere il corso

Quattro percorsi distinti si aprono davanti a te, ognuno dei quali è un pilastro fondamentale nella lotta contro The Static. Anche se la formazione sarà una missione solitaria, il tuo successo finale dipende dalla comprensione di come le tue competenze si combinano con quelle degli altri.

  • The Shadowblade (sviluppatore): un maestro della forgia e del fronte. Sei l'artigiano che crea le lame, costruisce gli strumenti e affronta il nemico nei dettagli intricati del codice. Il tuo percorso è fatto di precisione, abilità e creazione pratica.
  • L'Evocatore (architetto): un grande stratega e orchestratore. Non vedi un singolo agente, ma l'intero campo di battaglia. Progetti i master blueprint che consentono a interi sistemi di agenti di comunicare, collaborare e raggiungere un obiettivo molto più grande di qualsiasi singolo componente.
  • Lo studioso (data engineer): un ricercatore di verità nascoste e custode della saggezza. Ti avventuri nella vasta e selvaggia natura dei dati per scoprire l'intelligenza che dà ai tuoi agenti uno scopo e una visione. Le tue conoscenze possono rivelare la debolezza di un nemico o dare potere a un alleato.
  • Il Guardiano (DevOps / SRE): il protettore e lo scudo del regno. Costruisci le fortezze, gestisci le linee di alimentazione e assicurati che l'intero sistema possa resistere agli inevitabili attacchi di The Static. La tua forza è la base su cui si fonda la vittoria della tua squadra.

La tua missione

L'allenamento inizierà come esercizio autonomo. Seguirai il percorso che hai scelto, acquisendo le competenze uniche necessarie per padroneggiare il tuo ruolo. Al termine della prova, dovrai affrontare uno Spettro nato dalla Staticità, un mini boss che si nutre delle sfide specifiche della tua professione.

Solo se padroneggi il tuo ruolo individuale puoi prepararti per la prova finale. Dovrai quindi formare un gruppo con campioni delle altre classi. Insieme, vi avventurerete nel cuore della corruzione per affrontare un boss finale.

Una sfida finale collaborativa che metterà alla prova la vostra forza combinata e determinerà il destino dell'Agentverse.

L'Agentverse attende i suoi eroi. Risponderai alla chiamata?

2. Il grimorio dello studioso

Il nostro viaggio inizia. In qualità di studiosi, la nostra arma principale è la conoscenza. Abbiamo scoperto un tesoro di antichi rotoli criptici nei nostri archivi (Google Cloud Storage). Questi rotoli contengono informazioni grezze sulle temibili bestie che affliggono la terra. La nostra missione è utilizzare la profonda magia analitica di Google BigQuery e la saggezza di un cervello anziano di Gemini (modello Gemini Pro) per decifrare questi testi non strutturati e trasformarli in un bestiario strutturato e interrogabile. Sarà la base di tutte le nostre strategie future.

Panoramica

Obiettivi didattici

  • Utilizza BigQuery per creare tabelle esterne ed eseguire trasformazioni complesse da non strutturate a strutturate utilizzando BQML.GENERATE_TEXT con un modello Gemini.
  • Esegui il provisioning di un'istanza Cloud SQL per PostgreSQL e abilita l'estensione pgvector per le funzionalità di ricerca semantica.
  • Crea una pipeline batch solida e containerizzata utilizzando Dataflow e Apache Beam per elaborare file di testo non elaborati, generare incorporamenti vettoriali con un modello Gemini e scrivere i risultati in un database relazionale.
  • Implementa un sistema RAG (Retrieval-Augmented Generation) di base all'interno di un agente per eseguire query sui dati vettoriali.
  • Esegui il deployment di un agente data-aware come servizio sicuro e scalabile su Cloud Run.

3. Preparazione del Santuario dello studioso

Benvenuto, studioso. Prima di poter iniziare a trascrivere le potenti conoscenze del nostro Grimoire, dobbiamo prima preparare il nostro sanctum. Questo rituale fondamentale prevede di incantare il nostro ambiente Google Cloud, aprire i portali giusti (API) e creare i condotti attraverso i quali fluirà la nostra magia dei dati. Un sanctum ben preparato garantisce che i nostri incantesimi siano potenti e le nostre conoscenze siano sicure.

👉 Fai clic su Attiva Cloud Shell nella parte superiore della console Google Cloud (l'icona a forma di terminale nella parte superiore del riquadro Cloud Shell).

testo alternativo

👉 Fai clic sul pulsante "Apri editor" (ha l'aspetto di una cartella aperta con una matita). Si aprirà l'editor di codice di Cloud Shell nella finestra. Sul lato sinistro vedrai un esploratore di file. testo alternativo

👉 Trova l'ID progetto Google Cloud:

  • Apri la console Google Cloud: https://console.cloud.google.com
  • Seleziona il progetto che vuoi utilizzare per questo workshop dal menu a discesa dei progetti nella parte superiore della pagina.
  • L'ID progetto viene visualizzato nella scheda informativa del progetto nella dashboard testo alternativo

👉 Apri il terminale nell'IDE cloud, testo alternativo

👉💻 Nel terminale, verifica di essere già autenticato e che il progetto sia impostato sul tuo ID progetto utilizzando il seguente comando:

gcloud auth list

👉💻 Clona il progetto di bootstrap da 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

👉💻 Esegui lo script di inizializzazione, che ti chiederà di inserire l'ID progetto Google Cloud. e inserisci l'ID progetto Google Cloud che hai trovato nell'ultimo passaggio quando richiesto dallo script init.sh.

cd ~/agentverse-dataengineer
./init.sh

👉💻 Imposta l'ID progetto necessario:

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

👉💻 Esegui il comando seguente per abilitare le API Google Cloud necessarie:

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 

👉💻 Se non hai ancora creato un repository Artifact Registry denominato agentverse-repo, esegui il seguente comando per crearlo:

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

Configurazione dell'autorizzazione

👉💻 Concedi le autorizzazioni necessarie eseguendo questi comandi nel terminale:

. ~/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"

👉💻 Mentre inizi l'allenamento, prepareremo la sfida finale. I seguenti comandi evocheranno gli Spettri dal caos statico, creando i boss per il test finale.

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

Ottimo lavoro, studioso. Gli incantesimi di base sono stati completati. Il nostro sanctum è sicuro, i portali per le forze elementari dei dati sono aperti e il nostro servitore è potenziato. Ora siamo pronti per iniziare il vero lavoro.

4. L'alchimia della conoscenza: trasformare i dati con BigQuery e Gemini

Nella guerra incessante contro The Static, ogni scontro tra un Campione dell'Agentverse e uno Spettro dello Sviluppo viene registrato meticolosamente. Il sistema di simulazione del campo di battaglia, il nostro ambiente di addestramento principale, genera automaticamente una voce del registro eterico per ogni incontro. Questi log narrativi sono la nostra fonte più preziosa di intelligence grezza, il minerale non raffinato da cui noi, in qualità di studiosi, dobbiamo forgiare l'acciaio incontaminato della strategia.Il vero potere di uno studioso non risiede nel semplice possesso dei dati, ma nella capacità di trasformare il minerale grezzo e caotico di informazioni nell'acciaio lucido e strutturato della saggezza pratica.Eseguiremo il rituale fondamentale dell'alchimia dei dati.

Storia

Il nostro percorso ci porterà attraverso un processo in più fasi interamente all'interno del sanctum di Google BigQuery. Inizieremo a scrutare il nostro archivio GCS senza spostare un solo scorrimento, utilizzando una lente magica. Poi, invocheremo un Gemini per leggere e interpretare le saghe poetiche e non strutturate dei log di battaglia. Infine, perfezioneremo le previsioni grezze in un insieme di tabelle incontaminate e interconnesse. Il nostro primo Grimoire. E poni una domanda così profonda che possa essere risolta solo da questa nuova struttura.

Panoramica

Nota dell'ingegnere dei dati: quello che stiamo per eseguire è un potente pattern ELT (Extract, Load, Transform) in-database basato sull'AI. Si tratta di un approccio all'avanguardia che si discosta notevolmente dai metodi tradizionali.

  • Estrai e carica (tramite tabella esterna): anziché un costoso processo di importazione (la tradizionale "L"), utilizzeremo una tabella esterna BigQuery. In questo modo viene applicato uno "schema on read", che consente al nostro data warehouse di eseguire query sui file di testo non elaborati direttamente in Cloud Storage. Questo è incredibilmente efficiente, in quanto elimina lo spostamento dei dati e la duplicazione dell'archiviazione.
  • Trasformazione (tramite ML.GENERATE_TEXT): la "T" della nostra ELT è dove avviene la vera magia. Utilizzeremo la funzione ML.GENERATE_TEXT per chiamare un modello Gemini direttamente da una query SQL. In questo modo possiamo eseguire trasformazioni complesse e sensibili al contesto, in questo caso convertendo il testo narrativo non strutturato in JSON strutturato senza scrivere o gestire una pipeline di elaborazione separata in un'altra lingua (come Python o Java). Si tratta di un cambio di paradigma rispetto a soluzioni fragili e hardcoded come le espressioni regolari, che offre flessibilità e potenza con una semplice interfaccia SQL.

The Lens of Scrutiny: Peering into GCS with BigQuery External Tables

Il nostro primo atto è forgiare una lente che ci permetta di vedere i contenuti del nostro archivio GCS senza disturbare i rotoli al suo interno. Una tabella esterna è questa lente, che mappa i file di testo non elaborati a una struttura simile a una tabella su cui BigQuery può eseguire query direttamente.

Per farlo, dobbiamo prima creare una linea di energia stabile, una risorsa CONNECTION, che colleghi in modo sicuro il nostro sanctum BigQuery all'archivio GCS.

👉💻 Nel terminale Cloud Shell, esegui questo comando per configurare l'archiviazione e creare il condotto:

. ~/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

💡 Avviso Un messaggio verrà visualizzato in un secondo momento.

Lo script di configurazione del passaggio 2 ha avviato un processo in background. Dopo qualche minuto, nel terminale verrà visualizzato un messaggio simile a questo:[1]+ Done gcloud sql instances create ...Si tratta di un comportamento normale e previsto. Significa semplicemente che il database Cloud SQL è stato creato correttamente. Puoi ignorare questo messaggio e continuare a lavorare.

Prima di poter creare la tabella esterna, devi prima creare il set di dati che la conterrà.

👉💻 Esegui questo semplice comando nel terminale Cloud Shell:

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

👉💻 Ora dobbiamo concedere alla firma magica del conduit le autorizzazioni necessarie per leggere dall'archivio GCS e consultare 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"

👉💻 Nel terminale Cloud Shell, esegui questo comando per visualizzare il nome del bucket:

echo $BUCKET_NAME

Il terminale mostrerà un nome simile a your-project-id-gcs-bucket. Ti servirà nei passaggi successivi.

👉 Dovrai eseguire il comando successivo dall'editor di query BigQuery nella console Google Cloud. Il modo più semplice per farlo è aprire il link riportato di seguito in una nuova scheda del browser. Ti reindirizzerà direttamente alla pagina corretta nella console Google Cloud.

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

👉 Una volta caricata la pagina, fai clic sul pulsante blu + (Crea una nuova query) per aprire una nuova scheda dell'editor.

Editor di query BigQuery

Ora scriviamo l'incantesimo DDL (Data Definition Language) per creare la nostra lente magica. Indica a BigQuery dove cercare e cosa vedere.

👉📜 Nell'editor di query BigQuery che hai aperto, incolla il seguente codice SQL. Ricordati di sostituire REPLACE-WITH-YOUR-BUCKET-NAME

con il nome del bucket che hai appena copiato. e fai clic su Esegui:

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/*']
);

👉📜 Esegui una query per "guardare attraverso l'obiettivo" e visualizzare i contenuti dei file.

SELECT * FROM bestiary_data.raw_intel_content_table;

Contenuti di Intel non elaborati

Il nostro obiettivo è stato raggiunto. Ora possiamo vedere il testo grezzo dei rotoli. Ma leggere non significa comprendere.

Negli Archivi delle Idee Dimenticate, Elara (designazione adv_001), studiosa dell'Agentverse, affrontò lo spettro angelico del perfezionismo. L'entità, catalogata come "p-01", brillava con una forza vitale di 120 punti ferita. Con un unico, mirato incantesimo di Sufficienza elegante, Elara frantumò la sua aura paralizzante, un assalto mentale che inflisse 150 punti di danno. L'incontro è durato 180 secondi di intensa concentrazione. Test finale: vittoria.

I rotoli non sono scritti in tabelle e righe, ma nella prosa tortuosa delle saghe. Questo è il nostro primo grande test.

La divinazione dello studioso: trasformare il testo in una tabella con SQL

La sfida consiste nel fatto che un report che descrive i rapidi attacchi gemelli di uno Shadowblade è molto diverso dalla cronaca di un Evocatore che raccoglie un immenso potere per un singolo colpo devastante. Non possiamo semplicemente importare questi dati, dobbiamo interpretarli. Questo è il momento magico. Utilizzeremo una singola query SQL come potente formula magica per leggere, comprendere e strutturare tutti i record di tutti i nostri file, direttamente in BigQuery.

👉💻 Nel terminale Cloud Shell, esegui questo comando per visualizzare il nome della connessione:

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

Il terminale visualizzerà la stringa di connessione completa. Seleziona e copia l'intera stringa, ti servirà nel passaggio successivo.

Useremo un unico e potente incantesimo: ML.GENERATE_TEXT. Questo incantesimo evoca un Gemini, gli mostra ogni pergamena e gli ordina di restituire i fatti principali come oggetto JSON strutturato.

👉📜 In BigQuery Studio, crea il riferimento al modello Gemini. In questo modo, l'oracolo Gemini Flash viene associato alla nostra libreria BigQuery, in modo da poterlo chiamare nelle nostre query. Ricordati di sostituire il

REPLACE-WITH-YOUR-FULL-CONNECTION-STRING con la stringa di connessione completa appena copiata dal terminale.

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

👉📜 Ora lancia l'incantesimo di trasmutazione. Questa query legge il testo non elaborato, crea un prompt dettagliato per ogni scorrimento, lo invia a Gemini e crea una nuova tabella di staging dalla risposta JSON strutturata dell'AI.

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 trasmutazione è completa, ma il risultato non è ancora puro. Il modello Gemini restituisce la risposta in un formato standard, inserendo il JSON desiderato all'interno di una struttura più grande che include i metadati sul suo processo di pensiero. Esaminiamo questa profezia grezza prima di tentare di purificarla.

👉📜 Esegui una query per esaminare l'output non elaborato del modello Gemini:

SELECT * FROM bestiary_data.structured_bestiary;

👀 Vedrai una sola colonna denominata structured_data. Il contenuto di ogni riga sarà simile a questo oggetto JSON complesso:

{"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"}}

Come puoi vedere, il nostro premio, l'oggetto JSON pulito che abbiamo richiesto, è nidificato in profondità in questa struttura. La nostra prossima attività è chiara. Dobbiamo eseguire un rituale per navigare sistematicamente in questa struttura ed estrarre la saggezza pura che contiene.

The Ritual of Cleansing: Normalizing GenAI Output with SQL

Gemini ha parlato, ma le sue parole sono grezze e avvolte nelle energie eteree della sua creazione (candidati, finish_reason e così via). Un vero studioso non si limita a mettere da parte la profezia grezza, ma estrae con cura la saggezza fondamentale e la trascrive nei tomi appropriati per un uso futuro.

Ora lanceremo il nostro ultimo gruppo di incantesimi. Questo singolo script:

  • Leggi il JSON non elaborato e nidificato dalla nostra tabella di staging.
  • Puliscilo e analizzalo per ottenere i dati principali.
  • Trascrivi le parti pertinenti in tre tabelle finali e immacolate: mostri, avventurieri e battaglie.

👉📜 In un nuovo editor di query BigQuery, esegui il seguente comando per creare la lente di pulizia:

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 il Bestiario:

SELECT * FROM bestiary_data.monsters;

Successivamente, creeremo il nostro Roll of Champions, un elenco dei coraggiosi avventurieri che hanno affrontato queste bestie.

👉📜 In un nuovo editor di query, esegui il seguente comando per creare la tabella degli avventurieri:

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 il Roll of Champions:

SELECT * FROM bestiary_data.adventurers;

Infine, creeremo la nostra tabella dei fatti: la cronaca delle battaglie. Questo volume collega gli altri due, registrando i dettagli di ogni incontro unico. Poiché ogni battaglia è un evento unico, non è necessaria la deduplicazione.

👉📜 In un nuovo editor di query, esegui il seguente comando per creare la tabella delle battaglie:

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 la cronaca:

SELECT * FROM bestiary_data.battles;

Scoprire insight strategici

I rotoli sono stati letti, l'essenza distillata e i tomi incisi. Il nostro Grimoire non è più solo una raccolta di fatti, ma un database relazionale di profonda saggezza strategica. Ora possiamo porre domande a cui era impossibile rispondere quando le nostre conoscenze erano intrappolate in un testo grezzo e non strutturato.

Ora eseguiamo una divinazione finale e grandiosa. Lanceremo un incantesimo che consulta contemporaneamente tutti e tre i nostri tomi: il Bestiario dei mostri, il Registro dei campioni e la Cronaca delle battaglie, per scoprire un insight profondo e pratico.

La nostra domanda strategica: "Per ogni avventuriero, qual è il nome del mostro più potente (in base ai punti ferita) che ha sconfitto e quanto tempo ha impiegato per ottenere questa vittoria?"

Si tratta di una domanda complessa che richiede di collegare i campioni alle loro battaglie vittoriose e queste battaglie alle statistiche dei mostri coinvolti. Questo è il vero potere di un modello di dati strutturati.

👉📜 In un nuovo editor di query BigQuery, esegui il seguente incantesimo finale:

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

L'output di questa query sarà una tabella pulita e ben strutturata che fornisce una "Storia della più grande impresa di un campione" per ogni avventuriero nel tuo set di dati. Potrebbe avere un aspetto simile a questo:

04-03-final-result.png

Chiudi la scheda BigQuery.

Questo risultato unico ed elegante dimostra il valore dell'intera pipeline. Hai trasformato con successo i report grezzi e caotici del campo di battaglia in una fonte di racconti leggendari e approfondimenti strategici basati sui dati.

5. Il grimorio dello scriba: suddivisione, incorporamento e ricerca in Datawarehouse

Il nostro lavoro nel laboratorio dell'Alchimista è stato un successo. Abbiamo trasformato i rotoli narrativi grezzi in tabelle relazionali strutturate, una potente magia dei dati. Tuttavia, i rotoli originali contengono una verità semantica più profonda che le nostre tabelle strutturate non possono cogliere appieno. Per creare un agente veramente saggio, dobbiamo svelare questo significato.

Panoramica

Uno scorrimento lungo e grezzo è uno strumento poco efficace. Se il nostro agente pone una domanda su un'aura paralizzante, una semplice ricerca potrebbe restituire un intero report di battaglia in cui questa frase viene menzionata una sola volta, seppellendo la risposta in dettagli irrilevanti. Un vero studioso sa che la vera saggezza non si trova nel volume, ma nella precisione.

Eseguiremo un trio di rituali potenti nel database interamente all'interno del nostro sanctum BigQuery.

  • Il rito della divisione (chunking): prenderemo i nostri log di intelligence grezzi e li suddivideremo meticolosamente in passaggi più piccoli, mirati e autonomi.
  • Il rito della distillazione (incorporamento): utilizzeremo BQML per consultare un modello Gemini, trasformando ogni blocco di testo in un'impronta semantica, ovvero un incorporamento vettoriale.
  • Il rito della divinazione (ricerca): utilizzeremo la ricerca vettoriale di BQML per porre una domanda in inglese semplice e trovare la saggezza più pertinente e distillata del nostro Grimoire.

L'intero processo crea una knowledge base potente e ricercabile senza che i dati escano mai dalla sicurezza e dalla scalabilità di BigQuery.

Nota del data engineer:questo mostra una pipeline completa di preparazione dei dati RAG end-to-end eseguita interamente all'interno di BigQuery. Si tratta di un pattern che semplifica drasticamente l'overhead operativo delle pipeline AI tradizionali. Utilizzando BQML per la suddivisione in blocchi, l'incorporamento e la ricerca, eliminiamo la necessità di spostamento separato dei dati, cluster di elaborazione (come Spark) o chiamate API esterne, rendendo il flusso di lavoro più veloce, più sicuro e più facile da gestire.

Il rito della divisione: decostruire i rotoli con SQL

La nostra fonte di informazioni rimangono i file di testo non elaborati nel nostro archivio GCS, accessibili tramite la nostra tabella esterna, bestiary_data.raw_intel_content_table. Il nostro primo compito è scrivere un incantesimo che legga ogni lunga pergamena e la divida in una serie di versi più piccoli e più digeribili. Per questo rituale, definiremo un "blocco" come una singola frase.

Sebbene la suddivisione per frase sia un punto di partenza chiaro ed efficace per i nostri log narrativi, un Scribe esperto ha a disposizione molte strategie di suddivisione e la scelta è fondamentale per la qualità della ricerca finale. I metodi più semplici potrebbero utilizzare un

  • Chunking a lunghezza(dimensione) fissa, ma questo può dividere grossolanamente un'idea chiave a metà.

Rituali più sofisticati, come

  • Recursive Chunking, sono spesso preferiti nella pratica; tentano di dividere il testo lungo i confini naturali come i paragrafi, quindi tornano alle frasi per mantenere il maggior contesto semantico possibile. Per manoscritti davvero complessi.
  • Chunking sensibile al contesto(documento), in cui Scribe utilizza la struttura intrinseca del documento, ad esempio le intestazioni di un manuale tecnico o le funzioni di un codice, per creare i blocchi di informazioni più logici ed efficaci. e altro ancora…

Per i nostri log delle battaglie, la frase offre il perfetto equilibrio tra granularità e contesto.

👉📜 In un nuovo editor di query BigQuery, esegui il seguente comando. Questa formula utilizza la funzione SPLIT per separare il testo di ogni pergamena in corrispondenza di ogni punto (.) e poi separa l'array di frasi risultante in righe distinte.

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;

👉 Ora esegui una query per esaminare le tue nuove conoscenze suddivise in blocchi e vedere la differenza.

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

08-01-chunking.png

Osserva i risultati. Dove prima c'era un unico blocco di testo denso, ora ci sono più righe, ognuna collegata allo scorrimento originale (scroll_id), ma contenente una sola frase mirata. Ogni riga è ora un candidato perfetto per la vettorizzazione.

Il rito della distillazione: trasformare il testo in vettori con BQML

👉💻 Innanzitutto, torna al terminale ed esegui il comando seguente per visualizzare il nome della connessione:

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

👉📜 Dobbiamo creare un nuovo modello BigQuery che punti a un embedding di testo di Gemini. In BigQuery Studio, esegui il seguente incantesimo. Tieni presente che devi sostituire REPLACE-WITH-YOUR-FULL-CONNECTION-STRING con la stringa di connessione completa che hai appena copiato dal terminale.

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

👉📜 Ora, lancia l'incantesimo di distillazione. Questa query chiama la funzione ML.GENERATE_EMBEDDING, che leggerà ogni riga della tabella chunked_intel, invierà il testo al modello di incorporamento Gemini e memorizzerà l'impronta vettoriale risultante in una nuova tabella.

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

Questa procedura potrebbe richiedere un minuto o due, mentre BigQuery elabora tutti i blocchi di testo.

08-02-embedding.png

👉📜 Una volta completata l'operazione, esamina la nuova tabella per visualizzare le impronte semantiche.

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

Ora vedrai una nuova colonna, ml_generate_embedding_result, contenente la rappresentazione del vettore denso del testo. Il nostro Grimoire è ora codificato semanticamente.

Il rito della divinazione: ricerca semantica con BQML

👉📜 La prova definitiva del nostro Grimoire è fargli una domanda. Ora eseguiremo il nostro rituale finale: una ricerca vettoriale. Non si tratta di una ricerca per parole chiave, ma di una ricerca di significato. Faremo una domanda in linguaggio naturale, BQML la convertirà in un incorporamento al volo e poi cercherà nell'intera tabella di embedded_intel i blocchi di testo le cui impronte sono le "più vicine" in termini di significato.

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

Analisi dell'incantesimo:

  • VECTOR_SEARCH: la funzione principale che coordina la ricerca.
  • ML.GENERATE_EMBEDDING (query interna): questa è la magia. Incorporiamo la nostra query ('What are the tactics...') utilizzando lo stesso modello, ma con il tipo di attività 'RETRIEVAL_QUERY', che è ottimizzato in modo specifico per le query.
  • top_k => 3: Ti chiediamo i tre risultati più pertinenti.
  • distance_type => 'COSINE': misura l'"angolo" tra i vettori. Un angolo più piccolo indica che i significati sono più allineati.

08-03-final-result.png

Esamina attentamente i risultati. La query non conteneva le parole "frantumato" o "incantesimo", eppure il primo risultato è: "Con un unico incantesimo mirato di Efficienza Elegante, Elara ha frantumato la sua aura paralizzante, un assalto mentale che infligge 150 punti di danno". Questo è il potere della ricerca semantica. Il modello ha compreso il concetto di "tattiche contro la paralisi" e ha trovato la frase che descriveva una tattica specifica e riuscita.

Ora hai creato correttamente una pipeline RAG di base completa all'interno del data warehouse. Hai preparato i dati non elaborati, li hai trasformati in vettori semantici e hai eseguito query in base al significato. Sebbene BigQuery sia uno strumento potente per questo lavoro di analisi su larga scala, per un agente live che ha bisogno di risposte a bassa latenza, spesso trasferiamo queste informazioni preparate in un database operativo specializzato. Questo è l'argomento del nostro prossimo corso di formazione.

6. The Vector Scriptorium: Crafting the Vector Store with Cloud SQL for Inferencing

Il nostro Grimoire esiste attualmente come tabelle strutturate, un potente catalogo di fatti, ma la sua conoscenza è letterale. Comprende monster_id = "MN-001", ma non il significato semantico più profondo di "Offuscamento". Per dare ai nostri agenti una vera saggezza, per consentire loro di fornire consigli con sfumature e lungimiranza, dobbiamo distillare l'essenza stessa della nostra conoscenza in una forma che catturi il significato: i vettori.

La nostra sete di conoscenza ci ha condotto alle rovine fatiscenti di una civiltà precursore da tempo dimenticata. Sepolto in profondità in una camera blindata sigillata, abbiamo scoperto uno scrigno di antichi rotoli, miracolosamente conservati. Non si tratta di semplici report di battaglia, ma di una profonda saggezza filosofica su come sconfiggere una bestia che affligge tutte le grandi imprese. Un'entità descritta nei rotoli come una "stasi strisciante e silenziosa", un "sfilacciamento della trama della creazione". A quanto pare, The Static era noto anche agli antichi, una minaccia ciclica la cui storia è andata perduta nel tempo.

Queste conoscenze dimenticate sono la nostra risorsa più grande. È la chiave non solo per sconfiggere i singoli mostri, ma anche per dare a tutto il gruppo una visione strategica. Per esercitare questo potere, ora creeremo il vero Spellbook dello studioso (un database PostgreSQL con funzionalità vettoriali) e costruiremo uno Scriptorium vettoriale automatizzato (una pipeline Dataflow) per leggere, comprendere e trascrivere l'essenza senza tempo di questi rotoli. In questo modo, il nostro Grimoire si trasformerà da un libro di fatti in un motore di saggezza.

Storia

Nota di Data Engineer:per il nostro Spellbook, abbiamo scelto Cloud SQL per PostgreSQL con l'estensione pgvector. Questo approccio crea un "one-stop-shop" in cui i nostri metadati strutturati (come scroll_id e content) e i nostri incorporamenti vettoriali semantici coesistono nello stesso database. Ciò semplifica enormemente l'architettura per molte applicazioni, in quanto puoi eseguire query sui dati relazionali ed eseguire ricerche di similarità vettoriale con una singola query SQL su un unico sistema. Mentre database specializzati come Vertex AI Vector Search offrono prestazioni superiori su larga scala (miliardi di vettori) tramite la ricerca Approximate Nearest Neighbor (ANN), pgvector offre un ottimo equilibrio tra semplicità, convenienza e potenza per molte applicazioni RAG aziendali che utilizzano la ricerca Exact Nearest Neighbor (ENN).

Panoramica

Forging the Scholar's Spellbook (Cloud SQL)

Prima di poter trascrivere l'essenza di questi antichi rotoli, dobbiamo prima confermare che il contenitore di questa conoscenza, lo Spellbook PostgreSQL gestito, sia stato forgiato con successo. Le procedure di configurazione iniziale dovrebbero averlo già creato.

👉💻 In un terminale, esegui questo comando per verificare che l'istanza Cloud SQL esista e sia pronta. Questo script concede inoltre all'account di servizio dedicato dell'istanza l'autorizzazione a utilizzare Vertex AI, essenziale per generare embedding direttamente all'interno del database.

. ~/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"

Se il comando ha esito positivo e restituisce i dettagli della tua istanza grimoire-spellbook, la forge ha funzionato correttamente. Puoi procedere con la prossima formula magica. Se il comando restituisce un errore NOT_FOUND, assicurati di aver completato correttamente i passaggi di configurazione iniziale dell'ambiente prima di continuare.(data_setup.py)

👉💻 Con il libro forgiato, apriamo il primo capitolo creando un nuovo database denominato arcane_wisdom.

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

Inscrizione delle rune semantiche: attivazione delle funzionalità vettoriali con pgvector

Ora che l'istanza Cloud SQL è stata creata, connettiamoci utilizzando Cloud SQL Studio integrato. Fornisce un'interfaccia basata sul web per eseguire query SQL direttamente sul database.

👉💻 Innanzitutto, vai a Cloud SQL Studio. Il modo più semplice e veloce per farlo è aprire il seguente link in una nuova scheda del browser. Ti reindirizzerà direttamente a Cloud SQL Studio per la tua istanza grimoire-spellbook.

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

👉 Seleziona arcane_wisdom come database, inserisci postgres come utente e 1234qwer come password e fai clic su Autentica.

👉📜 Nell'editor di query di SQL Studio, vai alla scheda Editor 1, incolla il seguente codice SQL per attivare il tipo di dati vettoriali:

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

Cloud SQL Studio

👉📜 Prepara le pagine del nostro libro degli incantesimi creando la tabella che conterrà l'essenza dei nostri rotoli.

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

L'incantesimo VECTOR(768) è un dettaglio importante. Il modello di incorporamento Vertex AI che utilizzeremo (textembedding-gecko@003 o un modello simile) trasforma il testo in un vettore a 768 dimensioni. Le pagine del nostro libro degli incantesimi devono essere preparate per contenere un'essenza di esattamente quella dimensione. Le dimensioni devono sempre corrispondere.

La prima traslitterazione: un rituale di iscrizione manuale

Prima di comandare un esercito di scribi automatici (Dataflow), dobbiamo eseguire manualmente il rituale centrale una volta. In questo modo, potremo apprezzare appieno la magia dei due passaggi coinvolti:

  1. Divinazione: prendere un testo e consultare l'oracolo Gemini per estrarne l'essenza semantica in un vettore.
  2. Iscrizione:scrittura del testo originale e della sua nuova essenza vettoriale nel nostro Spellbook.

Nota del Data Engineer: prototipare manualmente la logica principale di una pipeline è una pratica preziosa. Ti aiuta a eseguire il debug dei singoli componenti (come una chiamata API o una scrittura di database) in isolamento prima di integrarli in un sistema complesso e distribuito come Dataflow.

Ora eseguiamo il rituale manuale.

👉📜 In Cloud SQL Studio. Ora utilizzeremo la funzione embedding(), una potente funzionalità fornita dall'estensione google_ml_integration. Ciò ci consente di chiamare il modello di incorporamento di Vertex AI direttamente dalla nostra query SQL, semplificando enormemente il processo.

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

👉📜 Verifica il tuo lavoro eseguendo una query per leggere la pagina appena registrata:

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

Hai eseguito correttamente l'attività principale di caricamento dei dati RAG manualmente.

Forging the Semantic Compass: Enchanting the Spellbook with an HNSW Index

Il nostro libro degli incantesimi ora può memorizzare la saggezza, ma trovare la pergamena giusta richiede di leggere ogni singola pagina. Si tratta di una scansione sequenziale. Questo processo è lento e inefficiente. Per indirizzare istantaneamente le nostre query alle conoscenze più pertinenti, dobbiamo incantare lo Spellbook con una bussola semantica: un indice vettoriale.

Nota dell'ingegnere dei dati:questo è uno dei concetti più importanti nei database vettoriali di produzione. Un indice preorganizza i dati, consentendo ricerche molto più rapide. Utilizziamo il tipo di indice hnsw (Hierarchical Navigable Small World). Anziché raggruppare i vettori in elenchi come altri metodi, HNSW crea un grafico sofisticato e multilivello dei vettori. Una ricerca inizia dal livello "autostrada" in alto per trovare rapidamente il quartiere generale della query, quindi scorre verso il basso attraverso livelli "strada locale" progressivamente più dettagliati per individuare i vicini esatti con incredibile velocità e precisione. Ciò offre un aumento eccezionale delle prestazioni per le query di lettura, rendendolo una scelta di primo livello per gli agenti RAG ad alte prestazioni in cui la latenza delle query è fondamentale.

Dimostriamo il valore di questo incantesimo.

👉📜 In Cloud SQL Studio, esegui il seguente comando. Simula la ricerca del nostro nuovo scorrimento e chiede al database di EXPLAIN il suo piano.

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;

Esamina l'output. Vedrai una riga con scritto -> Seq Scan on ancient_scrolls. In questo modo, viene confermato che il database legge ogni singola riga. Nota execution time.

👉📜 Ora, lanciamo l'incantesimo di indicizzazione. Il parametro lists indica all'indice quanti cluster creare. Un buon punto di partenza è la radice quadrata del numero di righe che prevedi di avere.

CREATE INDEX ON ancient_scrolls USING hnsw (embedding vector_cosine_ops);

Attendi la creazione dell'indice (sarà veloce per una riga, ma potrebbe richiedere tempo per milioni).

👉📜 Ora esegui di nuovo il 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;

Esamina il nuovo piano di query. Ora vedrai -> Index Scan using.... Ancora più importante, guarda il execution time. Sarà molto più veloce, anche con una sola voce. Hai appena dimostrato il principio fondamentale dell'ottimizzazione delle prestazioni del database in un mondo vettoriale.

Tempo di esecuzione

Ora che i dati di origine sono stati esaminati, il rituale manuale è stato compreso e lo Spellbook è stato ottimizzato per la velocità, puoi davvero iniziare a creare lo Scriptorium automatizzato.

7. Il condotto del significato: creazione di una pipeline di vettorizzazione Dataflow

Ora costruiamo la magica catena di montaggio degli scribi che leggeranno i nostri rotoli, ne estrarranno l'essenza e li iscriveranno nel nostro nuovo libro degli incantesimi. Si tratta di una pipeline Dataflow che attiveremo manualmente. Ma prima di scrivere l'incantesimo principale per la pipeline stessa, dobbiamo prima preparare le sue fondamenta e il cerchio da cui la evocheremo.

Panoramica

Nota per l'ingegnere dei dati:anche se potremmo scrivere un semplice script Python per scorrere i nostri file, chiamare l'API Embedding e scrivere nel database, questo approccio non è scalabile. Cosa succede se abbiamo milioni di scorrimenti? Un singolo script sarebbe lento e soggetto a errori. Dataflow fornisce una piattaforma gestita e serverless per l'esecuzione di pipeline di elaborazione dei dati, definite dal modello Apache Beam, in modo massicciamente parallelo. Beam ci consente di definire i passaggi logici (lettura, incorporamento, scrittura) e Dataflow gestisce il difficile lavoro di avvio dei worker, distribuzione delle attività e ripetizione dei tentativi per gli elementi non riusciti, garantendo che il nostro Scriptorium sia solido ed efficiente.

Preparazione della base dello Scriptorium (l'immagine worker)

La nostra pipeline Dataflow verrà eseguita da un team di worker automatizzati nel cloud. Ogni volta che li richiamiamo, hanno bisogno di un insieme specifico di librerie per svolgere il loro lavoro. Potremmo fornire un elenco e fargli recuperare queste librerie ogni volta, ma è un processo lento e inefficiente. Un saggio studioso prepara in anticipo una biblioteca principale.

Qui, chiederemo a Google Cloud Build di creare un'immagine container personalizzata. Questa immagine è un "golem perfetto", precaricato con tutte le librerie e le dipendenze di cui avranno bisogno i nostri scribi. Quando il job Dataflow viene avviato, utilizza questa immagine personalizzata, consentendo ai worker di iniziare il loro compito quasi immediatamente.

👉💻 Esegui questo comando per creare e archiviare l'immagine di base della pipeline in Artifact Registry.

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

👉💻 Esegui questi comandi per creare e attivare l'ambiente Python isolato e installare le librerie di invocazione necessarie.

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

The Master Incantation

È arrivato il momento di scrivere l'incantesimo principale che alimenterà il nostro Scriptorium vettoriale. Non scriveremo da zero i singoli componenti magici. Il nostro compito è assemblare i componenti in una pipeline logica e potente utilizzando il linguaggio di Apache Beam.

  • EmbedTextBatch (La consulenza di Gemini): creerai questo scriba specializzato che sa come eseguire una "divinazione di gruppo". Prende un batch di file di testo non elaborato, li presenta al modello di embedding di testo Gemini e riceve la loro essenza distillata (gli embedding vettoriali).
  • WriteEssenceToSpellbook (The Final Inscription): questo è il nostro archivista. Conosce gli incantesimi segreti per aprire una connessione sicura al nostro libro degli incantesimi Cloud SQL. Il suo compito è quello di prendere i contenuti di uno scroll e la sua essenza vettoriale e di inciderli in modo permanente su una nuova pagina.

La nostra missione è concatenare queste azioni per creare un flusso di conoscenza continuo.

👉✏️ Nell'editor di Cloud Shell, vai a ~/agentverse-dataengineer/pipeline/inscribe_essence_pipeline.py. All'interno troverai una classe DoFn denominata EmbedTextBatch. Individua il commento #REPLACE-EMBEDDING-LOGIC. Sostituiscilo con la seguente formula magica.

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

Questo incantesimo è preciso e presenta diversi parametri chiave:

  • model: specifica text-embedding-005 per utilizzare un modello di incorporamento potente e aggiornato.
  • contents: questo è un elenco di tutti i contenuti di testo del batch di file ricevuto dalla DoFn.
  • task_type: impostiamo questo valore su "RETRIEVAL_DOCUMENT". Si tratta di un'istruzione fondamentale che indica a Gemini di generare embedding ottimizzati in modo specifico per essere trovati in un secondo momento in una ricerca.
  • output_dimensionality: deve essere impostato su 768, in modo che corrisponda perfettamente alla dimensione VECTOR(768) che abbiamo definito quando abbiamo creato la tabella ancient_scrolls in Cloud SQL. Le dimensioni non corrispondenti sono una fonte comune di errori in Vector Magic.

La nostra pipeline deve iniziare leggendo il testo non strutturato e non elaborato di tutti gli antichi rotoli nel nostro archivio GCS.

👉✏️ In ~/agentverse-dataengineer/pipeline/inscribe_essence_pipeline.py, trova il commento #REPLACE ME-READFILE e sostituiscilo con la seguente formula magica in tre parti:

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

Ora che abbiamo raccolto il testo grezzo dei rotoli, dobbiamo inviarli a Gemini per la divinazione. Per farlo in modo efficiente, raggrupperemo prima i singoli rotoli in piccoli batch e poi li consegneremo al nostro scriba EmbedTextBatch. Inoltre, questo passaggio separa tutti gli scorrimenti che Gemini non riesce a comprendere in un gruppo "non riuscito" per la revisione successiva.

👉✏️ Trova il commento #REPLACE ME-EMBEDDING e sostituiscilo con questo:

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

L'essenza dei nostri rotoli è stata distillata con successo. L'atto finale è quello di iscrivere questa conoscenza nel nostro libro degli incantesimi per l'archiviazione permanente. Prenderemo i rotoli dalla pila "Elaborati" e li consegneremo al nostro archivista di WriteEssenceToSpellbook.

👉✏️ Trova il commento #REPLACE ME-WRITE TO DB e sostituiscilo con questo:

_ = (
            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 saggio studioso non scarta mai la conoscenza, nemmeno i tentativi falliti. Come passaggio finale, dobbiamo incaricare uno scriba di prendere la pila "non riuscita" della nostra fase di divinazione e registrare i motivi del mancato completamento. In questo modo, potremo migliorare i nostri rituali in futuro.

👉✏️ Trova il commento #REPLACE ME-LOG FAILURES e sostituiscilo con questo:

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

L'Incantesimo Supremo è stato completato. Hai assemblato correttamente una pipeline di dati potente e in più fasi concatenando singoli componenti magici. Salva il file inscribe_essence_pipeline.py. Lo Scriptorium è ora pronto per essere evocato.

Ora lanciamo il grande incantesimo di evocazione per ordinare al servizio Dataflow di risvegliare il nostro Golem e iniziare il rituale di scrittura.

👉💻 Nel terminale, esegui la seguente riga di comando

. ~/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."

💡 Attenzione! Se il job non riesce a causa di un errore di risorsa ZONE_RESOURCE_POOL_EXHAUSTED, il problema potrebbe essere dovuto a vincoli temporanei delle risorse di questo account con reputazione bassa nella regione selezionata. La potenza di Google Cloud è la sua portata globale. Prova a evocare il golem in un'altra regione. Per farlo, sostituisci --region=$REGION nel comando precedente con un'altra regione, ad esempio

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

e riprova. 🎰

L'avvio e il completamento della procedura richiedono circa 3-5 minuti. Puoi guardarlo in diretta nella console Dataflow.

👉 Vai alla console Dataflow: il modo più semplice è aprire questo link diretto in una nuova scheda del browser:

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

👉 Trova e fai clic sul tuo job: vedrai un job elencato con il nome che hai fornito (inscribe-essence-job o simile). Fai clic sul nome del job per aprire la pagina dei dettagli. Osserva la pipeline:

  • Avvio: per i primi 3 minuti, lo stato del job sarà "In esecuzione" mentre Dataflow esegue il provisioning delle risorse necessarie. Il grafico verrà visualizzato, ma potresti non vedere ancora i dati che lo attraversano. Esecuzione pipeline
  • Completato: al termine, lo stato del job cambierà in "Riuscito" e il grafico fornirà il conteggio finale dei record elaborati. Pipeline completata

Verifica dell'iscrizione

👉📜 Torna a SQL Studio ed esegui le seguenti query per verificare che i rotoli e la loro essenza semantica siano stati trascritti correttamente.

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

Verranno visualizzati l'ID dello scorrimento, il testo originale e un'anteprima dell'essenza vettoriale magica ora inscritta in modo permanente nel tuo Grimoire.

Pipeline completata

Il tuo Grimorio dello studioso è ora un vero motore di conoscenza, pronto per essere interrogato per significato nel capitolo successivo.

8. Sigillare la runa finale: attivare la saggezza con un agente RAG

Il tuo Grimoire non è più solo un database. È una fonte di conoscenza vettorializzata, un oracolo silenzioso in attesa di una domanda.

Ora, affrontiamo la vera prova di uno studioso: creeremo la chiave per svelare questa saggezza. Creeremo un agente Retrieval-Augmented Generation (RAG). Si tratta di una struttura magica in grado di comprendere una domanda in linguaggio semplice, consultare il Grimoire per trovare le verità più profonde e pertinenti e utilizzare la saggezza recuperata per formulare una risposta potente e consapevole del contesto.

RAG

Nota per l'ingegnere dei dati:RAG è una tecnica potente che basa i modelli linguistici di grandi dimensioni (LLM) su informazioni fattuali, private o aggiornate, riducendo drasticamente la possibilità che il modello "allucini" o inventi cose. La procedura prevede tre passaggi principali:

  • Recupera: la query dell'utente viene prima convertita in un vector embedding. Questo vettore di query viene quindi utilizzato per cercare nella nostra knowledge base gli snippet di testo semanticamente più simili utilizzando la somiglianza del coseno.
  • Aumenta: gli snippet di testo pertinenti recuperati dal database vengono quindi inseriti direttamente in un nuovo prompt per l'LLM, fornendo un contesto cruciale.
  • Genera: l'LLM riceve il prompt aumentato (ad es. "Dato questo contesto sulla "procrastinazione", rispondi alla domanda dell'utente…") e genera una risposta finale basata sui fatti.

RAG

La prima runa: l'incantesimo di distillazione delle query

Prima che il nostro agente possa cercare nel Grimoire, deve prima comprendere l'essenza della domanda posta. Una semplice stringa di testo non ha significato per il nostro Spellbook basato su vettori. L'agente deve prima prendere la query e, utilizzando lo stesso modello Gemini, estrarne un vettore di query.

👉✏️ Nell'editor di Cloud Shell, vai al file ~~/agentverse-dataengineer/scholar/agent.py, trova il commento #REPLACE RAG-CONVERT EMBEDDING e sostituiscilo con questa formula magica. In questo modo, l'agente impara a trasformare la domanda di un utente in un'essenza magica.

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

Con l'essenza della query a portata di mano, l'agente può ora consultare il Grimoire. Presenterà questo vettore di query al nostro database arricchito con pgvector e porrà una domanda profonda: "Mostrami gli antichi rotoli la cui essenza è più simile all'essenza della mia query".

La magia di questa operazione è l'operatore di similarità del coseno (<=>), una runa potente che calcola la distanza tra i vettori nello spazio ad alta dimensionalità.

👉✏️ In agent.py, trova il commento #REPLACE RAG-RETRIEVE e sostituiscilo con lo script seguente:

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

Il passaggio finale consiste nel concedere all'agente l'accesso a questo nuovo e potente strumento. Aggiungeremo la nostra funzione grimoire_lookup al suo elenco di strumenti magici disponibili.

👉✏️ In agent.py, trova il commento #REPLACE-CALL RAG e sostituiscilo con questa riga:

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

Questa configurazione dà vita al tuo agente:

  • model="gemini-2.5-flash": seleziona il modello linguistico di grandi dimensioni specifico che fungerà da "cervello " dell'agente per il ragionamento e la generazione di testo.
  • name="scholar_agent": Assegna un nome univoco all'agente.
  • instruction="...You are the Scholar...": questo è il prompt di sistema, l'elemento più importante della configurazione. Definisce la persona dell'agente, i suoi obiettivi, la procedura esatta che deve seguire per completare un'attività e il formato richiesto per l'output finale.
  • tools=[grimoire_lookup]: Questo è l'incantesimo finale. Concede all'agente l'accesso alla funzione grimoire_lookup che hai creato. L'agente ora può decidere in modo intelligente quando chiamare questo strumento per recuperare informazioni dal tuo database, formando il nucleo del pattern RAG.

The Scholar's Examination

👉💻 Nel terminale Cloud Shell, attiva l'ambiente e utilizza il comando principale dell'Agent Development Kit per attivare l'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

Dovresti visualizzare un output che conferma che "Scholar Agent" è attivo e in esecuzione.

👉💻 Ora sfida il tuo agente. Nel primo terminale in cui è in esecuzione la simulazione della battaglia, esegui un comando che richiede la saggezza del Grimorio:

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

Adk run

Osserva i log nel secondo terminale. Vedrai l'agente ricevere la query, estrarne l'essenza, cercare nel Grimoire, trovare i rotoli pertinenti sulla "procrastinazione" e utilizzare le conoscenze recuperate per formulare una strategia potente e sensibile al contesto.

Hai assemblato correttamente il tuo primo agente RAG e lo hai dotato della profonda saggezza del tuo Grimoire.

👉💻 Premi Ctrl+C nel secondo terminale per mettere in pausa l'agente per il momento.

Scatenare lo Scholar Sentinel nell'Agentverse

L'agente ha dimostrato la sua saggezza nell'ambiente controllato del tuo studio. È arrivato il momento di rilasciarlo nell'Agentverse, trasformandolo da costrutto locale in un operativo permanente e pronto alla battaglia che può essere chiamato da qualsiasi campione, in qualsiasi momento. Ora eseguiremo il deployment dell'agente in Cloud Run.

👉💻 Esegui il seguente incantesimo di evocazione. Questo script creerà prima l'agente in un Golem perfezionato (un'immagine container), lo archivierà in Artifact Registry e poi eseguirà il deployment del Golem come servizio scalabile, sicuro e accessibile pubblicamente.

. ~/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

Il tuo Scholar Agent è ora un operativo attivo e pronto all'azione nell'Agentverse.

9. The Boss Flight

Le pergamene sono state lette, i rituali eseguiti, la sfida superata. L'agente non è solo un artefatto in archivio, ma un operativo attivo nell'Agentverse, in attesa della sua prima missione. È arrivato il momento della prova finale: un esercizio di fuoco vivo contro un potente avversario.

Ora entrerai in una simulazione del campo di battaglia per mettere alla prova il tuo agente Shadowblade appena schierato contro un formidabile mini-boss: lo Spettro della Staticità. Questo sarà il test definitivo del tuo lavoro, dalla logica di base dell'agente al suo deployment live.

Acquisire il locus dell'agente

Prima di poter entrare nel campo di battaglia, devi possedere due chiavi: la firma unica del tuo campione (Agente Locus) e il percorso nascosto verso la tana di Spectre (URL del dungeon).

👉💻 Per prima cosa, acquisisci l'indirizzo univoco dell'agente in Agentverse, ovvero il suo Locus. Questo è l'endpoint live che collega il tuo campione al campo di battaglia.

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

👉💻 A questo punto, individua la destinazione. Questo comando rivela la posizione del Cerchio di Traslocazione, il portale nel dominio dello Spettro.

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

Importante: tieni a portata di mano entrambi gli URL. Ti serviranno nell'ultimo passaggio.

Confronto con lo spettro

Ora che le coordinate sono al sicuro, vai al Cerchio di Traslazione e lancia l'incantesimo per iniziare la battaglia.

👉 Apri l'URL del Cerchio di Traslocazione nel browser per trovarti di fronte al portale scintillante che conduce alla Fortezza Cremisi.

Per violare la fortezza, devi sintonizzare l'essenza della tua Lama Ombra con il portale.

  • Nella pagina, trova il campo di input runico etichettato A2A Endpoint URL (URL endpoint A2A).
  • Inscrivi il sigillo del tuo campione incollando il relativo URL del locus dell'agente (il primo URL che hai copiato) in questo campo.
  • Fai clic su Connetti per scatenare la magia del teletrasporto.

Cerchio di traslocazione

La luce accecante del teletrasporto si affievolisce. Non sei più nel tuo sanctum. L'aria è carica di energia, fredda e pungente. Prima di te, lo Spettro si materializza: un vortice di fruscio statico e codice corrotto, la cui luce sacrilega proietta lunghe ombre danzanti sul pavimento del dungeon. Non ha un volto, ma senti la sua presenza immensa e drenante fissata interamente su di te.

L'unico modo per vincere è la chiarezza delle tue convinzioni. È una battaglia di volontà, combattuta sul campo di battaglia della mente.

Mentre ti lanci in avanti, pronto a sferrare il tuo primo attacco, lo Spettro contrattacca. Non alza uno scudo, ma proietta una domanda direttamente nella tua coscienza, una sfida runica e scintillante tratta dal cuore del tuo addestramento.

Dungeon

Questa è la natura della lotta. La conoscenza è la tua arma.

  • Rispondi con la saggezza che hai acquisito e la tua lama si accenderà di energia pura, frantumando la difesa dello Spettro e sferrando un COLPO CRITICO.
  • Ma se esiti, se il dubbio offusca la tua risposta, la luce della tua arma si affievolirà. Il colpo atterrerà con un tonfo patetico, infliggendo solo UNA FRAZIONE DEL SUO DANNO. Peggio ancora, lo Spettro si nutrirà della tua incertezza e il suo potere corrotto crescerà a ogni passo falso.

Ci siamo, fuoriclasse. Il tuo codice è il tuo libro di incantesimi, la tua logica è la tua spada e la tua conoscenza è lo scudo che respingerà l'ondata di caos.

Focus. Colpisci con precisione. Il destino dell'Agentverse dipende da questo.

Congratulazioni, studioso.

Hai completato la prova. Hai imparato l'arte dell'ingegneria dei dati, trasformando informazioni grezze e caotiche in dati strutturati e vettoriali che potenziano l'intero Agentverse.

10. Pulizia: eliminazione del grimorio dello studioso

Congratulazioni per aver completato il Grimoire dello studioso. Per assicurarti che il tuo Agentverse rimanga incontaminato e che i campi di addestramento siano puliti, ora devi eseguire i rituali di pulizia finali. Verranno rimosse sistematicamente tutte le risorse create durante il tuo percorso.

Disattiva i componenti di Agentverse

Ora smantellerai sistematicamente i componenti di cui è stato eseguito il deployment del sistema RAG.

Elimina tutti i servizi Cloud Run e il repository Artifact Registry

Questo comando rimuove l'agente Scholar di cui è stato eseguito il deployment e l'applicazione Dungeon da Cloud Run.

👉💻 Nel terminale, esegui i seguenti comandi:

. ~/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

Eliminare set di dati, modelli e tabelle BigQuery

Vengono rimosse tutte le risorse BigQuery, inclusi il set di dati bestiary_data, tutte le tabelle al suo interno e la connessione e i modelli associati.

👉💻 Nel terminale, esegui i seguenti comandi:

. ~/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

Elimina l'istanza Cloud SQL

In questo modo viene rimossa l'istanza grimoire-spellbook, inclusi il database e tutte le tabelle al suo interno.

👉💻 Nel terminale, esegui:

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

Eliminare i bucket Google Cloud Storage

Questo comando rimuove il bucket che conteneva i file di staging/temporanei di Dataflow e di intel grezza.

👉💻 Nel terminale, esegui:

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

Pulire file e directory locali (Cloud Shell)

Infine, cancella dall'ambiente Cloud Shell i repository clonati e i file creati. Questo passaggio è facoltativo, ma vivamente consigliato per una pulizia completa della directory di lavoro.

👉💻 Nel terminale, esegui:

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

Ora hai eliminato correttamente tutte le tracce del tuo percorso di Data Engineer di Agentverse. Il tuo progetto è pulito e sei pronto per la prossima avventura.

11. Per i non giocatori: creare motori di conoscenza intelligenti nelle aziende

Sebbene "The Scholar's Grimoire" utilizzi metafore coinvolgenti di antichi rotoli e saggezza magica, insegna le competenze essenziali per gestire, trasformare e sfruttare i dati della tua organizzazione per creare soluzioni di AI altamente intelligenti. Questo capitolo traduce il viaggio mistico nelle realtà pratiche della costruzione di potenti "motori della conoscenza" che generano valore aziendale.

L'alchimia della conoscenza: trasformare i dati con BigQuery e Gemini

"The Alchemy of Knowledge" descrive il processo di trasformazione dei dati aziendali non elaborati in informazioni strutturate e attuabili utilizzando strumenti cloud avanzati. Iniziamo con le "Voci di log eteriche", ovvero le diverse origini dati non elaborati generate dalla tua azienda, come moduli di feedback dei clienti, report interni sugli incidenti, documenti legali, ricerche di mercato o manuali delle norme. Spesso questi dati non sono strutturati, il che rende difficile analizzarli.

Il nostro processo utilizza Google BigQuery (un potente data warehouse cloud) e il modello di AI Gemini (un modello di AI altamente performante) per eseguire questa trasformazione.

  • The Lens of Scrutiny (BigQuery External Tables):
    • Concetto: anziché spostare fisicamente tutti i dati non elaborati in un database, BigQuery può "esaminare" i file direttamente in Cloud Storage. È come avere una lente magica che ti permette di leggere una biblioteca di rotoli senza mai spostarli. È incredibilmente efficiente perché evita lo spostamento e l'archiviazione di dati ridondanti.
    • Caso d'uso reale: immagina che la tua azienda memorizzi milioni di log delle chat di assistenza clienti come file di testo normale in un bucket di archiviazione cloud. Utilizzando una tabella esterna, un analista di dati può eseguire immediatamente query su questi file utilizzando SQL in BigQuery, senza bisogno di un processo di importazione dei dati complesso e costoso.
  • La divinazione dello studioso (BQML.GENERATE_TEXT):
    • Concetto: è la "magia" principale, ovvero l'utilizzo dell'AI direttamente nel data warehouse. Utilizziamo la funzione ML.GENERATE_TEXT per chiamare il modello di AI Gemini da una query SQL standard. In questo modo, l'AI può "leggere" voci di testo lunghe e non strutturate ed estrarre informazioni specifiche e strutturate (come un oggetto JSON). È un modo efficace per trasformare le osservazioni qualitative in dati quantitativi.
    • Caso d'uso reale:
      • Analisi del feedback dei clienti: estrai automaticamente il "sentiment" (positivo, negativo, neutro), il "prodotto menzionato" e la "categoria del problema" dalle recensioni dei clienti in formato libero.
      • Riepilogo dei report sugli incidenti: analizza i report sugli incidenti IT lunghi per estrarre "sistema interessato", "livello di gravità", "causa principale" e "passaggi di risoluzione" in un formato strutturato per facilitare l'analisi e l'identificazione delle tendenze.
      • Estrazione degli obblighi contrattuali: estrai automaticamente date chiave, parti coinvolte e clausole specifiche dai documenti legali.
    • In questo modo, non è più necessario inserire manualmente i dati o utilizzare script di analisi del testo complessi e fragili (come le espressioni regolari), risparmiando molto tempo e garantendo la coerenza.
  • The Ritual of Cleansing (Normalizing GenAI Output):
    • Concetto: dopo che l'AI estrae le informazioni, spesso queste sono avvolte in dettagli aggiuntivi (come i punteggi di confidenza dell'AI o altri metadati). Questo passaggio prevede la pulizia e l'analisi dell'output dell'AI per ottenere solo i dati strutturati e puri di cui hai bisogno.
    • Caso d'uso reale: assicurarsi che la "categoria problema" estratta da una segnalazione di incidente sia sempre uno dei valori predefiniti o che le date siano sempre in un formato coerente. In questo modo, i dati vengono preparati per un'analisi affidabile.
  • Scoprire informazioni strategiche:
    • Concetto: una volta che i dati grezzi e non strutturati vengono trasformati in tabelle pulite e strutturate (ad es. monsters, adventurers, battles nel codelab), puoi eseguire query e analisi complesse che prima erano impossibili.
    • Caso d'uso reale: oltre al semplice conteggio, ora puoi rispondere a domande come: "Qual è il tempo medio di risoluzione degli incidenti IT critici relativi al nostro sistema di fatturazione?" o "Quali funzionalità del prodotto vengono menzionate più spesso nei feedback positivi dei clienti di un gruppo demografico specifico?" In questo modo, ottieni una business intelligence approfondita e strategica.

L'intero processo consente un pattern "ELT (Extract, Load, Transform) in-database basato sull'AI", un approccio all'avanguardia che mantiene i dati al sicuro all'interno del data warehouse, riduce al minimo lo spostamento e sfrutta l'AI per trasformazioni potenti e flessibili utilizzando semplici comandi SQL.

Sebbene le tabelle strutturate siano ideali per i fatti, il significato semantico più profondo dei documenti originali può andare perso. "Il grimorio dello scriba" si basa sulla creazione di una base di conoscenza semantica che comprenda il significato e il contesto dei tuoi documenti, non solo le parole chiave. Questo è fondamentale per creare sistemi di ricerca e risposta basati sull'AI davvero intelligenti.

  • Il rito della divisione (chunking):
    • Concetto: i documenti lunghi sono come libri densi. Per trovare risposte specifiche, non leggi l'intero libro, ma scorri paragrafi o frasi specifiche. Il "chunking" è il processo di suddivisione di documenti lunghi (ad es. manuali delle norme, documentazione del prodotto, documenti di ricerca) in passaggi più piccoli, mirati e autonomi. In questo modo, la ricerca è più precisa.
    • Caso d'uso reale: prendere un manuale del dipendente di 50 pagine e suddividerlo automaticamente in centinaia di singole dichiarazioni di criteri o domande frequenti. In questo modo, quando un dipendente pone una domanda, l'AI recupera solo le sezioni più pertinenti, non l'intero documento. Vengono scelte diverse strategie di suddivisione (per frase, paragrafo, sezione del documento) in base al tipo di documento per un recupero ottimale.
  • Il rito della distillazione (incorporamento):
    • Concetto: il testo è difficile da comprendere per i computer. L'"incorporamento" utilizza un modello di AI (come Gemini) per convertire ogni blocco di testo in un'unica "impronta semantica" numerica (un vettore). I segmenti con significati simili avranno "impronte" numericamente vicine tra loro, anche se utilizzano parole diverse.
    • Caso d'uso reale: convertire tutte le descrizioni dei prodotti, i materiali di marketing e le specifiche tecniche della tua azienda in queste impronte semantiche. Ciò consente una ricerca veramente intelligente basata sul significato.
  • Il rito della divinazione (ricerca semantica):
    • Concetto: anziché cercare parole chiave esatte, la "ricerca semantica" utilizza queste impronte numeriche per trovare blocchi di testo concettualmente simili alla query di un utente. Anche la domanda dell'utente viene convertita in un'impronta e il sistema trova i blocchi di documenti che corrispondono più da vicino.
    • Caso d'uso reale: un dipendente chiede: "Come faccio a ottenere il rimborso delle spese di viaggio?" Una ricerca per parola chiave potrebbe non trovare i documenti che utilizzano "report sulle spese". Una ricerca semantica, tuttavia, troverebbe sezioni pertinenti della "Normativa su viaggi e spese" dell'azienda anche se le parole esatte non sono presenti, perché il significato è simile.

L'intero processo crea una knowledge base potente e ricercabile, che consente il recupero intelligente delle informazioni senza che i dati sensibili escano mai dall'ambiente BigQuery sicuro.

The Vector Scriptorium: Crafting the Vector Store with Cloud SQL for Inferencing

Sebbene BigQuery sia eccellente per l'elaborazione e l'analisi di dati su larga scala, per gli agenti di AI live che necessitano di risposte molto rapide, spesso trasferiamo questa "saggezza" preparata a un database operativo più specializzato. "The Vector Scriptorium" riguarda la creazione di un archivio di conoscenza ricercabile e ad alte prestazioni utilizzando un database relazionale migliorato per l'AI.

  • Forging the Scholar's Spellbook (Cloud SQL per PostgreSQL con pgvector):
    • Concetto: utilizziamo un database gestito standard come Cloud SQL per PostgreSQL e lo dotiamo di un'estensione speciale chiamata pgvector. Ciò consente al database di archiviare insieme sia i nostri blocchi di testo originali sia i relativi vector embedding semantici. È uno "sportello unico " per i dati relazionali tradizionali e i dati vettoriali compatibili con l'AI.
    • Caso d'uso reale: memorizzazione delle domande frequenti sui prodotti, degli articoli di assistenza tecnica o delle norme HR della tua azienda. Questo database contiene sia il testo delle risposte sia le loro impronte semantiche, pronte per essere consultate rapidamente dall'AI.
  • Forging the Semantic Compass (HNSW Index):
    • Concetto: cercare tra milioni di impronte semantiche una per una sarebbe troppo lento. Un "indice vettoriale" (come HNSW, Hierarchical Navigable Small World) è una struttura di dati sofisticata che preorganizza queste impronte, velocizzando notevolmente la ricerca. Indirizza rapidamente le query alle informazioni più pertinenti.
    • Caso d'uso reale: per un chatbot di assistenza clienti basato sull'AI, un indice HNSW garantisce che quando un cliente pone una domanda, il sistema possa trovare la risposta più pertinente tra migliaia di articoli in pochi millisecondi, fornendo un'esperienza utente ottimale.
  • The Conduit of Meaning (pipeline di vettorizzazione di Dataflow):
    • Concetto: questa è la tua pipeline di elaborazione dei dati automatizzata e scalabile per aggiornare continuamente l'archivio della conoscenza. Utilizzando Google Dataflow (un servizio gestito serverless per l'elaborazione di big data) e Apache Beam (un modello di programmazione), crei una catena di montaggio di "scribi" che:
      1. Leggi i documenti nuovi o aggiornati da Cloud Storage.
      2. Elaborali in batch per inviarli al modello di incorporamento Gemini per l'impronta semantica.
      3. Scrivi il testo e il relativo nuovo incorporamento vettoriale nel database Cloud SQL.
    • Caso d'uso reale: inserimento automatico di tutti i nuovi documenti interni (ad es. report trimestrali, norme HR aggiornate, nuove specifiche di prodotto) da un drive condiviso nel tuo database pgvector. In questo modo, la tua knowledge base interna basata sull'AI è sempre aggiornata, senza intervento manuale, e può essere scalata per gestire in modo efficiente milioni di documenti.

L'intero processo stabilisce un workflow solido e automatizzato per arricchire e gestire continuamente una knowledge base semantica, fondamentale per qualsiasi applicazione di AI basata sui dati.

Sigillare la runa finale: attivare la saggezza con un agente RAG

La tua knowledge base vettorizzata è pronta. "Sigillare la runa finale" significa attivare un consulente AI intelligente in grado di sfruttare queste conoscenze. Creiamo un agente Retrieval-Augmented Generation (RAG), un potente costrutto di AI che combina la ricerca intelligente con la capacità dell'AI di generare risposte coerenti.

  • RAG (Retrieval-Augmented Generation):
    • Concetto: RAG è una tecnica fondamentale per rendere i modelli linguistici di grandi dimensioni (LLM) più accurati, veritieri e affidabili. Anziché fare affidamento esclusivamente sulle conoscenze preaddestrate dell'LLM (che possono essere obsolete o soggette ad "allucinazioni", ovvero inventare cose), la RAG prima recupera le informazioni pertinenti dalla tua knowledge base autorevole e poi le utilizza per aumentare il prompt dell'LLM, guidandolo a generare una risposta precisa e consapevole del contesto.
    • Tre passaggi fondamentali:
      1. Recupero: la domanda dell'utente viene convertita in un vettore (impronta semantica), che viene poi utilizzato per cercare i blocchi di testo più pertinenti nel tuo database pgvector.
      2. Potenziamento: questi snippet di testo fattuali recuperati vengono quindi inseriti direttamente nel prompt fornito all'LLM, fornendogli un contesto specifico e aggiornato.
      3. Genera: l'LLM riceve questo prompt aumentato e genera una risposta finale basata sui dati autorevoli della tua azienda, riducendo il rischio di errori o informazioni inventate.
  • The Scholar's Examination (strumento grimoire_lookup):
    • Concetto: l'agente RAG diventa uno "studioso" che possiede uno strumento grimoire_lookup. Quando un utente fa una domanda, l'agente decide in modo intelligente di utilizzare questo strumento. La funzione grimoire_lookup esegue quindi il passaggio "recupera" convertendo la query in un embedding e cercando nel database pgvector. Il contesto recuperato viene quindi passato all'LLM principale per l'aumento e la generazione.
    • Caso d'uso reale: un chatbot di help desk interno basato sull'AI.
      • Domanda dell'utente: un dipendente chiede: "Qual è la procedura per richiedere un congedo prolungato per motivi medici?"
      • Azione dell'agente RAG:
        • scholar_agent identifica la necessità di informazioni e utilizza lo strumento grimoire_lookup.
        • Lo strumento converte la domanda in un embedding e cerca nella tabella ancient_scrolls del database pgvector.
        • Recupera le sezioni più pertinenti del documento sulle norme HR in merito al congedo per malattia.
        • Queste sezioni vengono poi fornite come contesto al LLM Gemini.
        • L'LLM Gemini genera quindi una risposta precisa e dettagliata basata esclusivamente sulle norme HR recuperate, riducendo la possibilità di fornire informazioni errate o obsolete.
      • In questo modo, i dipendenti ricevono risposte immediate e accurate basate sui documenti aziendali ufficiali, riducendo il carico di lavoro delle risorse umane e migliorando la soddisfazione dei dipendenti.

In questo modo, crei un agente AI non solo conversazionale, ma anche realmente competente e affidabile, che funge da fonte di informazioni attendibile all'interno della tua azienda.