Yüksek Hızlı Yapay Zeka Sorguları İçin TypeSafe AI'ın Jev Modelini AlloyDB AI İşlevleriyle Kullanma

1. Giriş

Bu codelab'de, AlloyDB'nin yerel yapay zeka işlevlerini (ai.if, ai.analyze_sentiment ve ml_predict_row) kullanarak TypeSafe AI'ın Jev modelini AlloyDB AI'a bağlayacaksınız. Bu sayede, verilerinizi taşımadan veya karmaşık uygulama tarafı kodu yazmadan Jev modelini kullanarak doğrudan AlloyDB'deki operasyonel verileriniz üzerinde verimli toplu çıkarım çalıştırabilirsiniz.

Yapacaklarınız

  • Özel hizmet erişimi (PSA) ve AlloyDB for PostgreSQL kümesi ile birincil örnek sağlama
  • Cloud Shell'e ve dahili bağlantıya izin veren bir VPC güvenlik duvarı kuralı oluşturun.
  • gcloud alloydb clusters import kullanarak bir e-ticaret örnek veri kümesi yükleyin.
  • Google Secret Manager'ı ve AlloyDB'nin google_ml_integration uzantısını etkinleştirme
  • TypeSafe AI API anahtarınızı Secret Manager'da saklama ve erişim izni verme
  • Jev'in noul (boolean) ve choice (sentiment) temel öğeleri için PL/pgSQL giriş ve çıkış dönüştürme işlevleri oluşturun
  • AlloyDB'de özel jev-model model uç noktasını kaydetme
  • Doğrudan SQL'de skaler ve dizi toplu semantik sorgular (ai.if ve ai.analyze_sentiment) çalıştırma
  • ai.analyze_sentiment kullanarak duyarlılık sınıflandırması için gerçek müşteri ürün yorumlarını sorgulama
  • (Bonus) Genel bir uç nokta kaydedin (jev-systemone) ve Jev'in score temel öğesini kullanarak sürekli müşteri memnuniyeti yoğunluğunu değerlendirin.

İhtiyacınız olanlar

  • Chrome gibi bir web tarayıcısı
  • Faturalandırmanın etkin olduğu bir Google Cloud projesi
  • TypeSafe AI API anahtarı (TypeSafe AI'dan alınır)

2. Başlamadan önce

Google Cloud projenizi seçin

Google Cloud Console'da kullanmak istediğiniz Google Cloud projesini seçin veya oluşturun.

Cloud Shell'i Başlatma

Google Cloud Console'un sağ üst kısmındaki Activate Cloud Shell'i (Cloud Shell'i etkinleştir) tıklayın.

Cloud Shell oturumunuzun kimliğinin doğrulandığını onaylayın:

gcloud auth list

Proje kimliğinizi ve ortam değişkenlerinizi ayarlayın:

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"

Gerekli Google Cloud API'lerini etkinleştirme

Gerekli tüm Google Cloud hizmeti API'lerini etkinleştirmek için bu komutu çalıştırın:

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

3. AlloyDB kümesini ve birincil örneğini sağlama

Bu adımda, VPC ağınızda bir Private Service Access IP aralığı ayıracak, özel eşleme oluşturacak ve AlloyDB kümenizi ve birincil örneğinizi giden internet erişimiyle sağlayacaksınız.

1. Özel hizmet erişimi (PSA) IP aralığı oluşturma

AlloyDB için Sanal Özel Bulut (VPC) ağınızda özel bir IP adresi aralığı ayrılması gerekir. default VPC ağını kullandığınızı varsayarsak:

Özel IP aralığı ayırma işlemi oluşturun:

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

Özel VPC eşleme bağlantısını oluşturun:

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

2. AlloyDB kümesini oluşturun

İlk postgres yönetici kullanıcısı için güvenli bir veritabanı şifresi oluşturun:

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

AlloyDB ücretsiz deneme kümesi oluşturun:

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

3. Yapay zeka işaretleri ve giden bağlantı ile birincil örneği oluşturma

AlloyDB, giden HTTPS üzerinden TypeSafe AI'ın güvenli SaaS uç noktasına (https://api.typesafe.ai/v1/systemone) doğrudan bağlanır. Bu nedenle, --outbound-public-ip değerini belirtmeniz gerekir. Ayrıca, ortam için AlloyDB AI veritabanı işaretlerini yapılandırın:

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. Örnek e-ticaret verilerini yükleme

Gerçekçi semantik sorguları test etmek için ürün katalogları ve müşteri yorumları içeren örnek bir e-ticaret veri kümesini doğrudan Cloud Storage'dan içe aktarın:

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. TypeSafe AI API anahtarını Secret Manager'da saklama

AlloyDB'nin Model Endpoint Management özelliği, veritabanı kodunda veya yapılandırma günlüklerinde düz metin kimlik bilgilerini göstermeden harici API çağrılarını kimlik doğrulamak için Google Secret Manager ile yerel olarak entegre olur.

1. Gizli anahtarı oluşturma

Cloud Shell'de typesafe-jev-api-key adlı yeni bir gizli dizi oluşturun:

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

TypeSafe AI API anahtarınızı gizli sürüm olarak ekleyin:

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

2. AlloyDB hizmet aracısına erişim izni verme

AlloyDB, sorgu yürütme sırasında sırları almak için proje hizmeti aracısını kullanır. Proje numaranızı bulun ve Secret Accessor rolünü verin:

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"

Hizmet aracısının roles/secretmanager.secretAccessor aldığını onaylayan bir çıktı görürsünüz.

5. AlloyDB Studio aracılığıyla AlloyDB'ye bağlanma ve veritabanı uzantılarını başlatma

Yerel istemci araçlarını veya proxy tünellerini yapılandırmadan doğrudan tarayıcınızdan AlloyDB veritabanınızla etkileşim kurmak için Google Cloud Console'da AlloyDB Studio'yu kullanın.

1. AlloyDB Studio'yu açma

  1. Google Cloud Console'da AlloyDB for PostgreSQL > Clusters'a (Kümeler) gidin.
  2. Kümenizi (my-alloydb-cluster) tıklayın.
  3. Sol gezinme menüsünde AlloyDB Studio'yu tıklayın.
  4. Veritabanında kimlik doğrulama:
    • Veritabanı: postgres
    • Kullanıcı: postgres
    • Şifre: Küme oluşturma sırasında oluşturulan $PGPASSWORD değerini girin (ör. görüntülemek için Cloud Shell'de echo $PGPASSWORD komutunu çalıştırın).
  5. Kimlik doğrula'yı tıklayın.

Artık AlloyDB Studio'nun etkileşimli SQL sorgu düzenleyicisindesiniz.

2. Veritabanı uzantılarını ve işaretlerini etkinleştirme

AlloyDB Studio sorgu düzenleyicisinde, google_ml_integration uzantısını etkinleştirmek ve çalışma zamanı ayarlarını yapılandırmak için aşağıdaki ifadeleri yapıştırıp çalıştırın:

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

Sorguyu yürütmek için Çalıştır'ı tıklayın.

3. Gizli anahtarı AlloyDB MEM'e kaydetme

AlloyDB'ye TypeSafe AI API anahtarınızı nerede bulacağını söyleyin:

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. SQL Dönüşüm İşlevleri Oluşturma

TypeSafe AI'ın System One API'si, farklı akıl yürütme öğeleriyle (boolean kısıtlamalar için noul, çok sınıflı sınıflandırma için choice) yapılandırılmış JSON'u kabul eder.

AlloyDB'nin Model Endpoint Management özelliği, standart PostgreSQL ai.* işlev imzalarını Jev REST API biçimine bağlamak için dört dönüştürme işlevi (skaler giriş, skaler çıkış, toplu giriş, toplu çıkış) kullanır.

1. Skaler Giriş Dönüşümü

Tek satırlık ai.if ve ai.analyze_sentiment çağrılarını Jev istek yüklerine dönüştürmek için aşağıdaki işlevi ekleyin:

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. Skaler Çıkış Dönüşümü

Jev'in JSON yanıtını tekrar PostgreSQL TEXT sonucuna açacak işlevi ekleyin:

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. Toplu Giriş Dönüşümü

Jev, üretkenlikte düşüş olmadan tek bir HTTP gidiş dönüşü içinde aynı anda düzinelerce soruyu değerlendirebilir.

PostgreSQL prompts TEXT[] dizilerini paralel q_1 .. q_N Jev sorularına dönüştürmek için toplu giriş dönüşümünü ekleyin:

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. Toplu Çıkış Dönüşümü

Yanıtları uygun 1..N dizi dizininde ayıklamak için işlevi ekleyin:

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. Özel Model Uç Noktasını AlloyDB'ye Kaydetme

Şimdi dönüştürme işlevlerini, gizli kimlik bilgisini ve TypeSafe AI REST uç noktasını jev-model adlı kayıtlı bir modelde birleştireceksiniz.

1. jev-model kartını kaydetme

AlloyDB Studio sorgu düzenleyicisinde aşağıdakileri yapıştırıp çalıştırın:

-- 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. Kaydı doğrulama

jev-model öğesinin etkin ve tanınmış olduğundan emin olmak için model kayıt görünümünü sorgulayın:

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

Şuna benzer bir çıkış alırsınız:

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

8. Jev'e Karşı Test Sorguları Çalıştırma

jev-model kaydedildikten sonra artık standart PostgreSQL sorgularında doğrudan anlamsal işlemler yürütebilirsiniz.

1. Test Scalar Boolean Filtering (ai.if)

ai.if kullanarak tek bir metin ifadesini değerlendirin:

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;

Şuna benzer bir çıkış alırsınız:

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

2. Test Scalar Sentiment Analysis (ai.analyze_sentiment)

Müşteri geri bildirimlerini kategorik bir etikete (positive, negative veya neutral) dönüştürün:

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;

Şuna benzer bir çıkış alırsınız:

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

3. Test Array-Batched Boolean Filtering

Bir istem dizisi ileterek tek bir sorguda birden fazla öğeyi değerlendirin:

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;

Şuna benzer bir çıkış alırsınız:

                             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. Dizi gruplama ile tablo sorgularını test etme

Şimdi, küme sağlama sırasında daha önce yüklenen ecomm.products tablosunu sorgulayın. Katalogdaki ürünlerden hangilerinin soğuk hava ekipmanı olduğunu kontrol etmek için bir grup öğede ai.if kullanın.

Tablo verileri üzerinde yüksek işleme hızlı semantik filtreleme (ör. toplu iş başına 50 satır) çalıştırmak için satırları toplu işler halinde bölmek üzere PostgreSQL'in row_number() pencere işlevini kullanın:

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

Şuna benzer bir çıkış alırsınız:

  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. Duyarlılık için Müşteri Ürün Yorumlarını Sorgulama

Şimdi, Jev'in choice temel öğesiyle desteklenen ai.analyze_sentiment kullanarak ecomm.product_reviews tablosundaki müşteri yorumlarını analiz edin:

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;

Şuna benzer bir çıkış alırsınız:

 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: Jev score ile sürekli duyarlılık puanı

AlloyDB'nin ai.analyze_sentiment gibi yapay zeka işlevleri kategorik gruplar (positive, negative, neutral) döndürürken TypeSafe AI'ın score öğesi, sıralı bir puan anahtarındaki nüansları değerlendirir ve 0 ile 100 arasında sürekli, beklenti ağırlıklı bir puan döndürür.

score, metin sınıflandırma etiketi yerine sayısal meta veriler döndürdüğünden özel bir generic model uç noktası (jev-systemone) kaydedebilir ve google_ml.predict_row kullanarak bunu çağırabilirsiniz.

1. Genel Uç Noktayı Kaydetme

AlloyDB Studio'da jev-systemone öğesini model_type => 'generic' ile kaydedin:

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. Çok Görevli Değerlendirme (Boolean + Sürekli Puan) Çalıştırma

Tek bir HTTP çağrısında hem kusurla ilgili boolean kontrolünü (noul) hem de sürekli duygu yoğunluğunu (score) aynı anda değerlendirin:

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;

Aşağıdakine benzer bir çıkış almanız gerekir (sonuçlarınız farklı olabilir):

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

satisfaction_score ifadesinin 11 / 100 olarak değerlendirildiğini ve müşterinin kumaşın yumuşak olduğunu kabul etmesine rağmen çoğunlukla olumsuz bir deneyim yaşadığını doğru şekilde yansıttığını fark edin.

10. Temizleme

Bu codelab sırasında oluşturulan kaynaklar için sürekli olarak ücretlendirilmemek amacıyla gizli ve veritabanı nesnelerini temizleyin ve AlloyDB kümesini silin.

1. Secret Manager kaynaklarını silme

Cloud Shell'de, TypeSafe AI API anahtarı için oluşturulan gizli anahtarı silin:

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

2. AlloyDB birincil örneğini ve kümesini silme

Önce birincil örneği silin:

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

Örnek silme işlemi tamamlandıktan sonra kümeyi silin:

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

11. Tebrikler

Tebrikler! Google Cloud AlloyDB kümesini başarıyla sağladınız ve TypeSafe AI System One ile entegre ettiniz (Jev).

Öğrendikleriniz

  • Private Service Access (PSA) oluşturma ve AlloyDB for PostgreSQL kümesi ile birincil örnek sağlama.
  • AlloyDB'nin harici HTTPS SaaS API'lerine ulaşabilmesi için --outbound-public-ip nasıl etkinleştirilir?
  • Üçüncü taraf yapay zeka sağlayıcı kimlik bilgilerini Google Secret Manager'da güvenli bir şekilde saklama ve AlloyDB'ye bağlama
  • Standart PostgreSQL yapay zeka işlevlerini (ai.if ve ai.analyze_sentiment) harici REST API'lerine bağlayan PL/pgSQL dönüştürme işlevleri yazma.
  • google_ml.create_model kullanarak AlloyDB'de özel LLM uç noktalarını kaydetme
  • Hem skaler hem de yüksek işleme hızlı toplu semantik SQL sorgularını doğrudan PostgreSQL'de yürütme
  • Gerçek müşteri ürün yorumlarını kategorik duygu açısından analiz etme
  • Genel bir model uç noktasını kaydetme ve google_ml.predict_row aracılığıyla sürekli müşteri memnuniyeti puanlarını (0..100) değerlendirme

Sonraki adımlar

Referans belgeleri