Utilizzo del modello Jev di TypeSafe AI con le funzioni AI di AlloyDB per query AI ad alta velocità

1. Introduzione

In questo codelab, collegherai il modello Jev di TypeSafe AI ad AlloyDB AI utilizzando le funzioni AI native di AlloyDB (ai.if, ai.analyze_sentiment e ml_predict_row). In questo modo, puoi eseguire un'inferenza batch efficiente utilizzando il modello Jev direttamente sui tuoi dati operativi in AlloyDB, senza spostare i dati o scrivere codice complesso lato applicazione.

In questo lab proverai a:

  • Esegui il provisioning di Private Service Access (PSA) e di un cluster e un'istanza primaria AlloyDB per PostgreSQL
  • Crea una regola firewall VPC che consenta la connettività interna e Cloud Shell
  • Caricare un set di dati di esempio di e-commerce utilizzando gcloud alloydb clusters import
  • Abilita Google Secret Manager e l'estensione google_ml_integration di AlloyDB
  • Archivia e concedi l'accesso alla chiave API TypeSafe AI in Secret Manager
  • Crea funzioni di trasformazione di input e output PL/pgSQL per le primitive noul (booleano) e choice (sentimento) di Jev
  • Registra l'endpoint del modello jev-model personalizzato in AlloyDB
  • Esegui query semantiche scalari e in batch di array (ai.if e ai.analyze_sentiment) direttamente in SQL
  • Esegui query sulle recensioni prodotto fornite da clienti reali per la classificazione del sentiment utilizzando ai.analyze_sentiment
  • (Bonus) Registra un endpoint generico (jev-systemone) e valuta l'intensità della soddisfazione continua dei clienti utilizzando la primitiva score di Jev

Che cosa ti serve

  • Un browser web come Chrome
  • Un progetto cloud Google Cloud con la fatturazione abilitata
  • Una chiave API TypeSafe AI (di TypeSafe AI)

2. Prima di iniziare

Seleziona il tuo progetto Google Cloud

Nella console Google Cloud, seleziona o crea il progetto cloud di Google Cloud che vuoi utilizzare.

Avvia Cloud Shell

Fai clic su Attiva Cloud Shell in alto a destra nella console Google Cloud.

Verifica che la sessione di Cloud Shell sia autenticata:

gcloud auth list

Imposta l'ID progetto e le variabili di ambiente:

export PROJECT_ID=$(gcloud config get-value project)
gcloud config set project $PROJECT_ID

export REGION="us-west4"
export ADBCLUSTER="my-alloydb-cluster"
export ADBINSTANCE="my-alloydb-primary"

Abilita le API Google Cloud richieste

Esegui questo comando per abilitare tutte le API dei servizi Google Cloud necessarie:

gcloud services enable \
  alloydb.googleapis.com \
  servicenetworking.googleapis.com \
  secretmanager.googleapis.com \
  compute.googleapis.com

3. Esegui il provisioning del cluster AlloyDB e dell'istanza principale

In questo passaggio, allocherai un intervallo IP di accesso privato ai servizi nella tua rete VPC, stabilirai il peering privato e eseguirai il provisioning del cluster AlloyDB e dell'istanza primaria con accesso a internet in uscita.

1. Crea intervallo IP di accesso privato ai servizi (PSA)

AlloyDB richiede l'allocazione di un intervallo di IP privati nella rete Virtual Private Cloud (VPC). Supponendo che tu stia utilizzando la rete VPC default:

Crea l'allocazione dell'intervallo IP privato:

gcloud compute addresses create psa-range \
    --global \
    --purpose=VPC_PEERING \
    --prefix-length=24 \
    --description="VPC private service access" \
    --network=default

Stabilisci la connessione di peering VPC privata:

gcloud services vpc-peerings connect \
    --service=servicenetworking.googleapis.com \
    --ranges=psa-range \
    --network=default

2. Crea il cluster AlloyDB

Genera una password sicura per il database per l'utente amministrativo iniziale postgres:

export PGPASSWORD="$(openssl rand -hex 8)@1aA"
echo "Your generated AlloyDB postgres password is: $PGPASSWORD"

Crea un cluster di prova senza costi aggiuntivi di AlloyDB:

gcloud alloydb clusters create $ADBCLUSTER \
    --password=$PGPASSWORD \
    --network=default \
    --region=$REGION 

3. Crea l'istanza principale con i flag AI e la connettività in uscita

AlloyDB si connette direttamente all'endpoint SaaS sicuro di TypeSafe AI (https://api.typesafe.ai/v1/systemone) tramite HTTPS in uscita. Pertanto, devi specificare --outbound-public-ip. Inoltre, configura i flag di database AlloyDB AI per l'ambiente:

gcloud alloydb instances create $ADBINSTANCE \
    --instance-type=PRIMARY \
    --cpu-count=2 \
    --region=$REGION \
    --cluster=$ADBCLUSTER \
    --outbound-public-ip \
    --ssl-mode=ALLOW_UNENCRYPTED_AND_ENCRYPTED \
    --database-flags=\
google_ml_integration.enable_model_support=on,\
google_ml_integration.enable_ai_query_engine=on,\
google_ml_integration.enable_ai_function_acceleration=on,\
google_ml_integration.enable_cost_optimized_ai_functions=on,\
parameterized_views.enabled=on,\
password.enforce_complexity=on,\
password.min_uppercase_letters=1,\
password.min_numerical_chars=1,\
password.min_pass_length=10

4. Carica dati e-commerce di esempio

Per testare query semantiche realistiche, importa un set di dati di e-commerce di esempio contenente cataloghi di prodotti e recensioni dei clienti direttamente da Cloud Storage:

gcloud alloydb clusters import $ADBCLUSTER \
    --region=$REGION \
    --project=$PROJECT_ID \
    --gcs-uri="gs://sample-data-and-media/ecomm-retail/ecom_generic.sql" \
    --sql \
    --database=postgres \
    --user=postgres

4. Archivia la chiave API TypeSafe AI in Secret Manager

La gestione degli endpoint del modello di AlloyDB si integra in modo nativo con Google Secret Manager per autenticare le chiamate API esterne senza esporre credenziali in testo normale nel codice del database o nei log di configurazione.

1. Crea il secret

In Cloud Shell, crea un nuovo secret denominato typesafe-jev-api-key:

gcloud secrets create typesafe-jev-api-key \
  --replication-policy="automatic"

Aggiungi la chiave API TypeSafe AI come versione del secret:

echo -n "<YOUR_TYPESAFE_API_KEY>" | \
  gcloud secrets versions add typesafe-jev-api-key --data-file=-

2. Concedi l'accesso all'agente di servizio AlloyDB

AlloyDB utilizza il service agent del progetto per recuperare i secret durante l'esecuzione delle query. Trova il numero del progetto e concedi il ruolo di accesso ai secret:

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
ALLOYDB_SA="service-${PROJECT_NUMBER}@gcp-sa-alloydb.iam.gserviceaccount.com"

gcloud secrets add-iam-policy-binding typesafe-jev-api-key \
  --member="serviceAccount:${ALLOYDB_SA}" \
  --role="roles/secretmanager.secretAccessor"

Dovresti visualizzare un output che conferma che il service agent ha ricevuto roles/secretmanager.secretAccessor.

5. Connettersi ad AlloyDB tramite AlloyDB Studio e inizializzare le estensioni del database

Per interagire con il database AlloyDB direttamente dal browser senza configurare strumenti client locali o tunnel proxy, utilizza AlloyDB Studio nella console Google Cloud.

1. Apri AlloyDB Studio

  1. Nella console Google Cloud, vai ad AlloyDB per PostgreSQL > Cluster.
  2. Fai clic sul tuo cluster (my-alloydb-cluster).
  3. Nel menu di navigazione a sinistra, fai clic su AlloyDB Studio.
  4. Esegui l'autenticazione al database:
    • Database: postgres
    • Utente: postgres
    • Password: inserisci $PGPASSWORD generato durante la creazione del cluster (ad es. esegui echo $PGPASSWORD in Cloud Shell per visualizzarlo).
  5. Fai clic su Authenticate (Autentica).

Ora ti trovi nell'editor di query SQL interattivo di AlloyDB Studio.

2. Abilita estensioni e flag di database

Nell'editor di query di AlloyDB Studio, incolla ed esegui le seguenti istruzioni per attivare l'estensione google_ml_integration e configurare le impostazioni di runtime:

-- Enable the AlloyDB AI integration extension
CREATE EXTENSION IF NOT EXISTS google_ml_integration;

-- Enable preview AI functions (ai.analyze_sentiment, ai.classify)
SET google_ml_integration.enable_preview_ai_functions = 'on';

-- Disable async batching for the session to use custom transform functions directly
SET google_ml_integration.enable_async_operation = 'off';

Fai clic su Esegui per eseguire la query.

3. Registra il secret in AlloyDB MEM

Indica ad AlloyDB dove trovare la chiave API TypeSafe AI:

CALL google_ml.create_sm_secret(
    secret_id => 'jev_api_key',
    secret_path => 'projects/<YOUR_PROJECT_ID>/secrets/typesafe-jev-api-key/versions/latest'
);

6. Crea funzioni di trasformazione SQL

L'API System One di TypeSafe AI accetta JSON strutturato con primitive di ragionamento distinte (noul per i vincoli booleani, choice per la classificazione multiclasse).

La gestione degli endpoint del modello di AlloyDB utilizza quattro funzioni di trasformazione (input scalare, output scalare, input batch, output batch) per collegare le firme delle funzioni ai.* PostgreSQL standard al formato dell'API REST Jev.

1. Trasformazione di input scalare

Aggiungi la seguente funzione per convertire le chiamate ai.if e ai.analyze_sentiment a una sola riga in payload di richieste Jev:

CREATE OR REPLACE FUNCTION public.jev_model_input_transform(
    model_id VARCHAR(100),
    input_text TEXT,
    generation_config JSON,
    system_instruction TEXT
) RETURNS JSON
LANGUAGE plpgsql IMMUTABLE AS $$
DECLARE
    full_instruction TEXT;
    enum_json JSON;
    criteria_obj JSONB := '{}'::JSONB;
    elem TEXT;
    q_obj JSON;
BEGIN
    -- Combine optional system instructions with the input prompt
    IF system_instruction IS NOT NULL AND length(trim(system_instruction)) > 0 THEN
        full_instruction := system_instruction || E'\n\n' || input_text;
    ELSE
        full_instruction := input_text;
    END IF;

    -- Inspect generation_config to determine whether caller expects a multi-class choice or boolean
    enum_json := COALESCE(
        generation_config->'generationConfig'->'responseSchema'->'enum',
        generation_config->'responseSchema'->'enum'
    );

    IF enum_json IS NOT NULL AND json_typeof(enum_json) = 'array' THEN
        -- Multi-class classification (ai.analyze_sentiment) -> Jev choice primitive
        FOR elem IN SELECT json_array_elements_text(enum_json) LOOP
            criteria_obj := criteria_obj || jsonb_build_object(elem, 'Category: ' || elem);
        END LOOP;
        q_obj := json_build_object(
            'type', 'choice',
            'instructions', full_instruction,
            'criteria', criteria_obj::JSON
        );
    ELSE
        -- Boolean filtering (ai.if) -> Jev noul primitive
        q_obj := json_build_object(
            'type', 'noul',
            'instructions', full_instruction
        );
    END IF;

    RETURN json_build_object(
        'model', 'jev-latest',
        'state', COALESCE(generation_config->>'state', 'Evaluate the question accurately based on the provided text.'),
        'questions', json_build_object('q_1', q_obj)
    );
END;
$$;

2. Trasformazione dell'output scalare

Aggiungi la funzione per decomprimere la risposta JSON di Jev in un risultato TEXT PostgreSQL:

CREATE OR REPLACE FUNCTION public.jev_model_output_transform(
    model_id VARCHAR(100),
    response_json JSON
) RETURNS TEXT
LANGUAGE plpgsql IMMUTABLE AS $$
DECLARE
    q_ans JSON := response_json->'answers'->'q_1';
    ans_type TEXT := q_ans->>'type';
BEGIN
    IF ans_type = 'choice' THEN
        RETURN q_ans->>'choice';
    ELSIF ans_type = 'noul' THEN
        -- Convert probability score (0.00 to 1.00) to boolean text
        RETURN CASE WHEN (q_ans->>'noul')::FLOAT >= 0.50 THEN 'true' ELSE 'false' END;
    ELSE
        RAISE EXCEPTION 'Unexpected Jev response payload: %', response_json::TEXT;
    END IF;
END;
$$;

3. Trasformazione di input batch

Jev può valutare decine di domande contemporaneamente all'interno di un singolo round trip HTTP senza degradazione generativa.

Aggiungi la trasformazione di input batch per convertire gli array prompts TEXT[] di PostgreSQL in domande Jev parallele q_1 .. q_N:

CREATE OR REPLACE FUNCTION public.jev_model_batch_input_transform(
    model_id VARCHAR(100),
    prompts TEXT[],
    generation_config JSON,
    system_instructions JSON
) RETURNS JSON
LANGUAGE plpgsql IMMUTABLE AS $$
DECLARE
    questions_obj JSONB := '{}'::JSONB;
    enum_json JSON;
    criteria_obj JSONB := '{}'::JSONB;
    elem TEXT;
    is_choice BOOLEAN := FALSE;
    i INT;
BEGIN
    enum_json := COALESCE(
        generation_config->'generationConfig'->'responseSchema'->'items'->'enum',
        generation_config->'generationConfig'->'responseSchema'->'enum',
        generation_config->'responseSchema'->'items'->'enum',
        generation_config->'responseSchema'->'enum'
    );

    IF enum_json IS NOT NULL AND json_typeof(enum_json) = 'array' THEN
        IF NOT (enum_json::JSONB = '["true", "false"]'::JSONB OR enum_json::JSONB = '["false", "true"]'::JSONB) THEN
            is_choice := TRUE;
            FOR elem IN SELECT json_array_elements_text(enum_json) LOOP
                criteria_obj := criteria_obj || jsonb_build_object(elem, 'Category: ' || elem);
            END LOOP;
        END IF;
    END IF;

    -- Construct parallel questions for every prompt in the array
    FOR i IN 1 .. COALESCE(array_length(prompts, 1), 0) LOOP
        IF is_choice THEN
            questions_obj := questions_obj || jsonb_build_object(
                'q_' || i::TEXT,
                jsonb_build_object(
                    'type', 'choice',
                    'instructions', prompts[i],
                    'criteria', criteria_obj
                )
            );
        ELSE
            questions_obj := questions_obj || jsonb_build_object(
                'q_' || i::TEXT,
                jsonb_build_object(
                    'type', 'noul',
                    'instructions', prompts[i]
                )
            );
        END IF;
    END LOOP;

    RETURN json_build_object(
        'model', 'jev-latest',
        'state', COALESCE(generation_config->>'state', 'Evaluate each question independently based on the record data.'),
        'questions', questions_obj::JSON
    );
END;
$$;

4. Trasformazione dell'output batch

Aggiungi la funzione per estrarre le risposte nell'ordine corretto dell'indice dell'array 1..N:

CREATE OR REPLACE FUNCTION public.jev_model_batch_output_transform(
    model_id VARCHAR(100),
    response JSON
) RETURNS TEXT[]
LANGUAGE plpgsql IMMUTABLE AS $$
DECLARE
    results TEXT[] := ARRAY[]::TEXT[];
    answers JSON := response->'answers';
    i INT := 1;
    q_ans JSON;
    ans_type TEXT;
BEGIN
    LOOP
        q_ans := answers->('q_' || i::TEXT);
        EXIT WHEN q_ans IS NULL;
        ans_type := q_ans->>'type';
        IF ans_type = 'choice' THEN
            results := array_append(results, q_ans->>'choice');
        ELSE
            results := array_append(results, CASE WHEN (q_ans->>'noul')::FLOAT >= 0.50 THEN 'true' ELSE 'false' END);
        END IF;
        i := i + 1;
    END LOOP;
    RETURN results;
END;
$$;

7. Registra l'endpoint del modello personalizzato in AlloyDB

Ora devi associare le funzioni di trasformazione, le credenziali segrete e l'endpoint REST di TypeSafe AI in un modello registrato denominato jev-model.

1. Registra jev-model

Nell'editor di query di AlloyDB Studio, incolla ed esegui:

-- Drop previous registration if updating
DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM google_ml.model_info_view WHERE model_id = 'jev-model') THEN
        CALL google_ml.drop_model('jev-model');
    END IF;
END $$;

-- Register custom LLM endpoint
CALL google_ml.create_model(
    model_id => 'jev-model',
    model_request_url => 'https://api.typesafe.ai/v1/systemone',
    model_provider => 'custom',
    model_type => 'llm',
    model_qualified_name => 'jev-latest',
    model_auth_type => 'secret_manager',
    model_auth_id => 'jev_api_key',
    model_in_transform_fn => 'jev_model_input_transform',
    model_out_transform_fn => 'jev_model_output_transform',
    model_batch_in_transform_fn => 'jev_model_batch_input_transform',
    model_batch_out_transform_fn => 'jev_model_batch_output_transform'
);

2. Verifica registrazione

Esegui una query sulla visualizzazione del registro dei modelli per assicurarti che jev-model sia attivo e riconosciuto:

SELECT model_id, model_type, model_provider, model_auth_type 
FROM google_ml.model_info_view 
WHERE model_id = 'jev-model';

Dovresti visualizzare un output simile al seguente:

 model_id | model_type | model_provider | model_auth_type 
----------+------------+----------------+-----------------
 jev-model  | llm        | custom         | secret_manager
(1 row)

8. Esegui query di test su Jev

Ora che jev-model è registrato, puoi eseguire operazioni semantiche direttamente all'interno delle query PostgreSQL standard.

1. Test Scalar Boolean Filtering (ai.if)

Valuta una singola istruzione di testo utilizzando ai.if:

SELECT ai.if(
    prompt => 'Is the product "North Face Waterproof Gore-Tex Hiking Jacket ($249)" suitable for rainy outdoor conditions?',
    model_id => 'jev-model'
) AS is_suitable;

Dovresti visualizzare un output simile al seguente:

 is_suitable 
-------------
 true
(1 row)

2. Test Scalar Sentiment Analysis (ai.analyze_sentiment)

Valuta il feedback dei clienti in un'etichetta categorica (positive, negative o neutral):

SET google_ml_integration.enable_preview_ai_functions = 'on';
SELECT ai.analyze_sentiment(
    input => 'The stitching on this jacket tore on the second day and the zipper jammed completely.',
    model_id => 'jev-model'
) AS sentiment;

Dovresti visualizzare un output simile al seguente:

 sentiment 
-----------
 negative
(1 row)

3. Testa il filtro booleano in batch di array

Valuta più elementi in un'unica query passando un array di prompt:

SET google_ml_integration.enable_async_operation = 'off';
SELECT unnest(prompts) AS product_prompt,
       unnest(ai.if(prompts => prompts, model_id => 'jev-model')) AS is_cold_weather
FROM (
    SELECT ARRAY[
        'Is "Arctic Expedition Down Parka (-30F)" cold-weather winter outerwear?',
        'Is "Men''s Boardshorts Beach Swim Trunk" cold-weather winter outerwear?',
        'Is "Merino Wool Thermal Base Layer" cold-weather winter outerwear?'
    ] AS prompts
) b;

Dovresti visualizzare un output simile al seguente:

                             product_prompt                              | is_cold_weather 
-------------------------------------------------------------------------+-----------------
 Is "Arctic Expedition Down Parka (-30F)" cold-weather winter outerwear? | true
 Is "Men's Boardshorts Beach Swim Trunk" cold-weather winter outerwear?  | false
 Is "Merino Wool Thermal Base Layer" cold-weather winter outerwear?      | false
(3 rows)

4. Testare le query sulle tabelle con il batch di array

Ora esegui una query sulla tabella ecomm.products caricata in precedenza durante il provisioning del cluster, utilizzando ai.if su un batch di elementi per verificare quali prodotti del catalogo sono attrezzature per il freddo.

Per eseguire il filtro semantico ad alto throughput sui dati delle tabelle (ad es. 50 righe per batch), utilizza la funzione finestra row_number() di PostgreSQL per dividere le righe in batch:

-- Evaluate a 50-row batch of real catalog items from ecomm.products
WITH numbered AS (
    SELECT 
        id, 
        name, 
        category,
        product_description,
        ((row_number() OVER (ORDER BY id) - 1) / 50) AS batch_id
    FROM ecomm.products
    ORDER BY id DESC
    LIMIT 50
),
batched AS (
    SELECT 
        batch_id,
        array_agg(id ORDER BY id) AS ids,
        array_agg(name ORDER BY id) AS names,
        array_agg(category ORDER BY id) AS categories,
        array_agg(product_description ORDER BY id) AS descs,
        ai.if(
            prompts => array_agg('Is "' || name || '" designed for cold weather winter outerwear?' ORDER BY id),
            model_id => 'jev-model'
        ) AS decisions
    FROM numbered
    GROUP BY batch_id
),
unrolled AS (
    SELECT 
        b.batch_id,
        u.id,
        u.name,
        u.category,
        u.product_description,
        u.decision AS cold_weather_gear
    FROM batched b
    CROSS JOIN LATERAL unnest(b.ids, b.names, b.categories, b.descs, b.decisions) 
      AS u(id, name, category, product_description, decision)
)
SELECT id, name, category, product_description, cold_weather_gear
FROM unrolled
WHERE cold_weather_gear = TRUE
LIMIT 5;

Dovresti visualizzare un output simile al seguente:

  id   |                                 name                                 |  category   |                                                product_description                                                 | cold_weather_gear 
-------+----------------------------------------------------------------------+-------------+--------------------------------------------------------------------------------------------------------------------+-------------------
 29071 | Winter Striped Beanie with Pom                                       | Accessories | Brave the chill in style with the SoleStyle Winter Striped Beanie! This cozy beanie adds a pop of personality...  | true
 29077 | Knit Collegiate Rugby Stripe Winter Scarf & Beanie Hat Set           | Accessories | Stay cozy and show off your sporty side with our Knit Collegiate Rugby Stripe Scarf & Beanie Set...               | true
 29083 | Junction Finds Men's Muscle Wool Blend Trapper Hat                   | Accessories | Brave the elements in style with the Junction Finds Trapper Hat! This wool-blend hat will keep you warm...        | true
 29086 | Mens Soft Thermal Insulated Wrist Length Leather Gloves - Black      | Accessories | Brave the chill in style with these supple leather gloves from Gavel Goods! Lined with a soft, thermal knit...    | true
 29090 | Long Beanie-Red W16S24E                                              | Accessories | Stay cozy and stylish all season long with this vibrant red beanie from Enchant! This isn't just any hat...       | true
(5 rows)

5. Query Customer Product Reviews for Sentiment

Ora analizza le recensioni dei clienti dalla tabella ecomm.product_reviews utilizzando ai.analyze_sentiment supportato dalla primitiva choice di Jev:

SET google_ml_integration.enable_preview_ai_functions = 'on'
SELECT 
    r.id,
    p.name AS product_name,
    r.rating AS customer_star_rating,
    substring(r.review_text FROM 1 FOR 70) || '...' AS review_snippet,
    ai.analyze_sentiment(
        input => r.review_text,
        model_id => 'jev-model'
    ) AS detected_sentiment
FROM ecomm.product_reviews r
JOIN ecomm.products p ON r.product_id = p.id
ORDER BY r.id
LIMIT 5;

Dovresti visualizzare un output simile al seguente:

 id |                  product_name                  | customer_star_rating |                             review_snippet                              | detected_sentiment 
----+------------------------------------------------+----------------------+-------------------------------------------------------------------------+--------------------
  1 | Hugs & Kisses Juniors Peplum Skirt             |                    1 | This skirt was poorly made and the fabric felt extremely cheap for for...| negative
  2 | Bonkers Larry Full Length Pull on Pants        |                    1 | These pants are way too expensive for the terrible quality you get. Th...| negative
  3 | Gifts and Garb Brah Bra Extenders              |                    3 | These extenders are okay but nothing special. They do add a bit of ext...| neutral
  4 | Auto Forge Men's Tall Duck Traditional Coat    |                    1 | This coat is terribly stiff and heavy, making it very uncomfortable to...| negative
  5 | Weaver's Way Men's Shetland Zip Neck Sweater   |                    2 | This sweater is just okay and not really worth the high price tag. The...| negative
(5 rows)

9. Bonus: punteggio di sentiment continuo con il punteggio Jev

Mentre le funzioni AI di AlloyDB come ai.analyze_sentiment restituiscono bucket categorici (positive, negative, neutral), la primitiva score di TypeSafe AI valuta le sfumature in base a una rubrica ordinata e restituisce una valutazione continua ponderata in base alle aspettative da 0 a 100.

Poiché score restituisce metadati numerici anziché un'etichetta di classificazione del testo, puoi registrare un endpoint del modello generic personalizzato (jev-systemone) e richiamarlo utilizzando google_ml.predict_row.

1. Registra l'endpoint generico

In AlloyDB Studio, registra jev-systemone con model_type => 'generic':

DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM google_ml.model_info_view WHERE model_id = 'jev-systemone') THEN
        CALL google_ml.drop_model('jev-systemone');
    END IF;
EXCEPTION WHEN OTHERS THEN
    NULL;
END $$;

CALL google_ml.create_model(
    model_id => 'jev-systemone',
    model_request_url => 'https://api.typesafe.ai/v1/systemone',
    model_provider => 'custom',
    model_type => 'generic',
    model_qualified_name => 'jev-latest',
    model_auth_type => 'secret_manager',
    model_auth_id => 'jev_api_key'
);

2. Eseguire una valutazione multi-task (booleana + punteggio continuo)

Valuta contemporaneamente un controllo booleano dei difetti (noul) e l'intensità del sentimento continuo (score) in una singola chiamata HTTP:

SELECT jsonb_pretty(google_ml.predict_row(
    model_id => 'jev-systemone',
    request_body => json_build_object(
        'model', 'jev-latest',
        'state', 'Review for North Face Parka: "The zipper broke on day 3 and customer service refused an exchange, though the fabric itself is very soft."',
        'questions', json_build_object(
            'has_defect', json_build_object(
                'type', 'noul',
                'instructions', 'Does this review report a physical product defect or failure?'
            ),
            'satisfaction_score', json_build_object(
                'type', 'score',
                'instructions', 'Rate the customer sentiment and satisfaction on a 1-5 scale.',
                'criteria', json_build_array(
                    '1: Extremely dissatisfied / defect failure',
                    '2: Dissatisfied',
                    '3: Mixed or neutral',
                    '4: Satisfied',
                    '5: Delighted'
                )
            )
        )
    )
)::jsonb) AS jev_analysis;

Dovresti visualizzare un output simile al seguente (i risultati potrebbero variare):

{
  "model": "jev-1.13.0",
  "usage": {
    "input_tokens": 388,
    "output_tokens": 39
  },
  "answers": {
    "has_defect": {
      "noul": 0.98,
      "type": "noul"
    },
    "satisfaction_score": {
      "type": "score",
      "score": 0.11,
      "legend": {
        "0": "1: Extremely dissatisfied / defect failure",
        "1": "2: Dissatisfied",
        "2": "3: Mixed or neutral",
        "3": "4: Satisfied",
        "4": "5: Delighted"
      },
      "confidence": 0.91,
      "probabilities": {
        "0": 0.9,
        "1": 0.08,
        "2": 0.02,
        "3": 0.0,
        "4": 0.0
      }
    }
  }
}

Nota che satisfaction_score è stato valutato come 11 / 100, il che riflette con precisione il fatto che il cliente ha avuto un'esperienza per lo più negativa, nonostante abbia riconosciuto che il tessuto era morbido.

10. Esegui la pulizia

Per evitare addebiti continui per le risorse create durante questo codelab, libera spazio per il secret e gli oggetti di database ed elimina il cluster AlloyDB.

1. Elimina le risorse di Secret Manager

In Cloud Shell, elimina il secret creato per la chiave API TypeSafe AI:

gcloud secrets delete typesafe-jev-api-key --quiet

2. Elimina l'istanza principale e il cluster AlloyDB

Elimina prima l'istanza principale:

gcloud alloydb instances delete $ADBINSTANCE \
  --cluster=$ADBCLUSTER \
  --region=$REGION \
  --quiet

Al termine dell'eliminazione dell'istanza, elimina il cluster:

gcloud alloydb clusters delete $ADBCLUSTER \
  --region=$REGION \
  --quiet

11. Complimenti

Complimenti! Hai eseguito il provisioning di un cluster Google Cloud AlloyDB e lo hai integrato con TypeSafe AI System One (Jev).

Che cosa hai imparato

  • Come stabilire l'accesso privato ai servizi (PSA) e il provisioning di un cluster AlloyDB per PostgreSQL e dell'istanza principale.
  • Come attivare --outbound-public-ip in modo che AlloyDB possa raggiungere le API SaaS HTTPS esterne.
  • Come archiviare in modo sicuro le credenziali del fornitore di AI di terze parti in Google Secret Manager e associarle ad AlloyDB.
  • Come scrivere funzioni di trasformazione PL/pgSQL che collegano le funzioni di AI standard di PostgreSQL (ai.if e ai.analyze_sentiment) alle API REST esterne.
  • Come registrare gli endpoint LLM personalizzati in AlloyDB utilizzando google_ml.create_model.
  • Come eseguire query SQL semantiche sia scalari che batch ad alto rendimento direttamente in PostgreSQL.
  • Come analizzare le recensioni prodotto reali dei clienti per il sentiment categorico.
  • Come registrare un endpoint del modello generico e valutare i punteggi di soddisfazione dei clienti continui (0..100) tramite google_ml.predict_row.

Passaggi successivi

Documenti di riferimento