1. บทนำ
ใน Codelab นี้ คุณจะได้เชื่อมต่อโมเดล Jev ของ TypeSafe AI กับ AlloyDB AI โดยใช้ฟังก์ชัน AI ดั้งเดิมของ AlloyDB (ai.if, ai.analyze_sentiment และ ml_predict_row) ซึ่งจะช่วยให้คุณเรียกใช้การอนุมานแบบเป็นกลุ่มได้อย่างมีประสิทธิภาพโดยใช้โมเดล Jev โดยตรงกับข้อมูลการดำเนินงานใน AlloyDB โดยไม่ต้องย้ายข้อมูลหรือเขียนโค้ดฝั่งแอปพลิเคชันที่ซับซ้อน
สิ่งที่คุณจะทำ
- จัดสรร Private Service Access (PSA) และคลัสเตอร์ AlloyDB สำหรับ PostgreSQL รวมถึงอินสแตนซ์หลัก
- สร้างกฎไฟร์วอลล์ VPC ที่อนุญาต Cloud Shell และการเชื่อมต่อภายใน
- โหลดชุดข้อมูลตัวอย่างอีคอมเมิร์ซโดยใช้
gcloud alloydb clusters import - เปิดใช้ Google Secret Manager และส่วนขยาย
google_ml_integrationของ AlloyDB - จัดเก็บและให้สิทธิ์เข้าถึงคีย์ API ของ TypeSafe AI ใน Secret Manager
- สร้างฟังก์ชันการแปลงอินพุตและเอาต์พุต PL/pgSQL สำหรับไพรมิตีฟ
noul(บูลีน) และchoice(ความรู้สึก) ของ Jev - ลงทะเบียนปลายทางโมเดล
jev-modelที่กำหนดเองใน AlloyDB - เรียกใช้การค้นหาเชิงความหมายแบบสเกลาร์และแบบอาร์เรย์ (
ai.ifและai.analyze_sentiment) โดยตรงใน SQL - ค้นหารีวิวสินค้าจริงจากลูกค้าเพื่อการจัดประเภทความรู้สึกโดยใช้
ai.analyze_sentiment - (โบนัส) ลงทะเบียนปลายทางทั่วไป (
jev-systemone) และประเมินความหนักของความพึงพอใจของลูกค้าอย่างต่อเนื่องโดยใช้scorePrimitive ของ Jev
สิ่งที่คุณต้องมี
- เว็บเบราว์เซอร์ เช่น Chrome
- โปรเจ็กต์ Google Cloud ที่เปิดใช้การเรียกเก็บเงิน
- คีย์ API ของ TypeSafe AI (จาก TypeSafe AI)
2. ก่อนเริ่มต้น
เลือกโปรเจ็กต์ Google Cloud
ในคอนโซล Google Cloud ให้เลือกหรือสร้างโปรเจ็กต์ที่อยู่ในระบบคลาวด์ Google Cloud ที่ต้องการใช้
เริ่มต้น Cloud Shell
คลิกเปิดใช้งาน Cloud Shell ที่ด้านขวาบนของคอนโซล Google Cloud
ตรวจสอบว่าเซสชัน Cloud Shell ได้รับการตรวจสอบสิทธิ์แล้ว
gcloud auth list
ตั้งค่ารหัสโปรเจ็กต์และตัวแปรสภาพแวดล้อม
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"
เปิดใช้ Google Cloud APIs ที่จำเป็น
เรียกใช้คำสั่งนี้เพื่อเปิดใช้ Google Cloud Service API ที่จำเป็นทั้งหมด
gcloud services enable \
alloydb.googleapis.com \
servicenetworking.googleapis.com \
secretmanager.googleapis.com \
compute.googleapis.com
3. จัดสรรคลัสเตอร์และอินสแตนซ์หลักของ AlloyDB
ในขั้นตอนนี้ คุณจะจัดสรรช่วง IP ของการเข้าถึงบริการแบบส่วนตัวในเครือข่าย VPC, สร้างการ Peering แบบส่วนตัว และจัดสรรคลัสเตอร์ AlloyDB และอินสแตนซ์หลักที่มีสิทธิ์เข้าถึงอินเทอร์เน็ตขาออก
1. สร้างช่วง IP ของการเข้าถึงบริการส่วนตัว (PSA)
AlloyDB ต้องมีการจัดสรรช่วง IP ส่วนตัวในเครือข่าย Virtual Private Cloud (VPC) สมมติว่าคุณใช้defaultเครือข่าย VPC
สร้างการจัดสรรช่วง IP ส่วนตัว
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
สร้างการเชื่อมต่อการเพียร์ VPC ส่วนตัวโดยทำดังนี้
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
2. สร้างคลัสเตอร์ AlloyDB
สร้างรหัสผ่านฐานข้อมูลที่ปลอดภัยสำหรับpostgresผู้ใช้ที่เป็นผู้ดูแลระบบเริ่มต้น
export PGPASSWORD="$(openssl rand -hex 8)@1aA"
echo "Your generated AlloyDB postgres password is: $PGPASSWORD"
สร้างคลัสเตอร์ AlloyDB Free Trial
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
3. สร้างอินสแตนซ์หลักด้วย Flag AI และการเชื่อมต่อขาออก
AlloyDB จะเชื่อมต่อโดยตรงกับปลายทาง SaaS ที่ปลอดภัยของ TypeSafe AI (https://api.typesafe.ai/v1/systemone) ผ่าน HTTPS ขาออก ดังนั้นคุณต้องระบุ --outbound-public-ip นอกจากนี้ ให้กำหนดค่าแฟล็กฐานข้อมูล AlloyDB AI สำหรับสภาพแวดล้อมดังนี้
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. โหลดข้อมูลอีคอมเมิร์ซตัวอย่าง
หากต้องการทดสอบการค้นหาเชิงความหมายที่สมจริง ให้นำเข้าชุดข้อมูลอีคอมเมิร์ซตัวอย่างที่มีแคตตาล็อกผลิตภัณฑ์และรีวิวจากลูกค้าโดยตรงจาก 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. จัดเก็บคีย์ API ของ TypeSafe AI ใน Secret Manager
การจัดการปลายทางของโมเดลของ AlloyDB ผสานรวมกับ Google Secret Manager โดยกำเนิดเพื่อตรวจสอบสิทธิ์การเรียก API ภายนอกโดยไม่ต้องเปิดเผยข้อมูลเข้าสู่ระบบข้อความธรรมดาในโค้ดฐานข้อมูลหรือบันทึกการกำหนดค่า
1. สร้างข้อมูลลับ
ใน Cloud Shell ให้สร้างข้อมูลลับใหม่ชื่อ typesafe-jev-api-key:
gcloud secrets create typesafe-jev-api-key \
--replication-policy="automatic"
เพิ่มคีย์ TypeSafe AI API เป็นเวอร์ชันลับโดยทำดังนี้
echo -n "<YOUR_TYPESAFE_API_KEY>" | \
gcloud secrets versions add typesafe-jev-api-key --data-file=-
2. ให้สิทธิ์เข้าถึง AlloyDB Service Agent
AlloyDB ใช้ตัวแทนบริการของโปรเจ็กต์เพื่อดึงข้อมูลลับในระหว่างการดำเนินการค้นหา ค้นหาหมายเลขโปรเจ็กต์และให้บทบาท Secret Accessor โดยทำดังนี้
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"
คุณควรเห็นเอาต์พุตที่ยืนยันว่าตัวแทนบริการได้รับ roles/secretmanager.secretAccessor แล้ว
5. เชื่อมต่อกับ AlloyDB ผ่าน AlloyDB Studio และเริ่มต้นส่วนขยายฐานข้อมูล
หากต้องการโต้ตอบกับฐานข้อมูล AlloyDB โดยตรงจากเบราว์เซอร์โดยไม่ต้องกำหนดค่าเครื่องมือไคลเอ็นต์ในเครื่องหรือพร็อกซี ให้ใช้ AlloyDB Studio ในคอนโซล Google Cloud
1. เปิด AlloyDB Studio
- ใน คอนโซล Google Cloud ให้ไปที่ AlloyDB สำหรับ PostgreSQL > คลัสเตอร์
- คลิกคลัสเตอร์ (
my-alloydb-cluster) - คลิก AlloyDB Studio ในเมนูการนำทางด้านซ้าย
- ตรวจสอบสิทธิ์เข้าถึงฐานข้อมูล:
- ฐานข้อมูล:
postgres - ผู้ใช้:
postgres - รหัสผ่าน: ป้อน
$PGPASSWORDที่สร้างขึ้นระหว่างการสร้างคลัสเตอร์ (เช่น เรียกใช้echo $PGPASSWORDใน Cloud Shell เพื่อดู)
- ฐานข้อมูล:
- คลิกตรวจสอบสิทธิ์
ตอนนี้คุณอยู่ในโปรแกรมแก้ไขการค้นหา SQL แบบอินเทอร์แอกทีฟของ AlloyDB Studio แล้ว
2. เปิดใช้ส่วนขยายและฟีเจอร์ของฐานข้อมูล
ในเครื่องมือแก้ไขคำค้นหา AlloyDB Studio ให้วางและเรียกใช้คำสั่งต่อไปนี้เพื่อเปิดใช้ส่วนขยาย google_ml_integration และกำหนดค่าการตั้งค่ารันไทม์
-- 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';
คลิกเรียกใช้เพื่อดำเนินการกับคำค้นหา
3. ลงทะเบียนข้อมูลลับใน MEM ของ AlloyDB
บอก AlloyDB ว่าจะดูคีย์ 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. สร้างฟังก์ชันการเปลี่ยนรูปแบบ SQL
API ของ System One ของ TypeSafe AI ยอมรับ JSON ที่มีโครงสร้างพร้อมด้วย Primitive การให้เหตุผลที่แตกต่างกัน (noul สำหรับข้อจำกัดบูลีน choice สำหรับการแยกประเภทแบบหลายคลาส)
การจัดการปลายทางโมเดลของ AlloyDB ใช้ฟังก์ชันการแปลง 4 ฟังก์ชัน (อินพุตสเกลาร์ เอาต์พุตสเกลาร์ อินพุตแบบกลุ่ม เอาต์พุตแบบกลุ่ม) เพื่อเชื่อมโยงลายเซ็นฟังก์ชัน ai.* ของ PostgreSQL มาตรฐานกับรูปแบบ Jev REST API
1. การแปลงอินพุตสเกลาร์
เพิ่มฟังก์ชันต่อไปนี้เพื่อแปลงการเรียก ai.if และ ai.analyze_sentiment แถวเดียวเป็นเพย์โหลดคำขอ 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. การแปลงเอาต์พุตสเกลาร์
เพิ่มฟังก์ชันเพื่อคลายการตอบกลับ JSON ของ Jev กลับไปเป็นผลลัพธ์ PostgreSQL TEXT
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. การเปลี่ยนรูปแบบอินพุตแบบกลุ่ม
Jev สามารถประเมินคำถามหลายสิบคำถามพร้อมกันภายใน HTTP Round Trip เดียวโดยไม่มีการเสื่อมถอยเชิงกำเนิด
เพิ่มการแปลงอินพุตแบบกลุ่มเพื่อแปลงอาร์เรย์ prompts TEXT[] PostgreSQL เป็นคำถาม q_1 .. q_N Jev แบบขนาน
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. การแปลงเอาต์พุตแบบกลุ่ม
เพิ่มฟังก์ชันเพื่อดึงคำตอบตาม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. ลงทะเบียนปลายทางโมเดลที่กำหนดเองใน AlloyDB
ตอนนี้คุณจะเชื่อมโยงฟังก์ชันการเปลี่ยนรูปแบบ ข้อมูลเข้าสู่ระบบลับ และปลายทาง REST ของ TypeSafe AI เข้าด้วยกันเป็นโมเดลที่ลงทะเบียนชื่อ jev-model
1. ลงทะเบียน jev-model
ในเครื่องมือแก้ไขการค้นหาของ AlloyDB Studio ให้วางและเรียกใช้คำสั่งต่อไปนี้
-- 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. ยืนยันการลงทะเบียน
ค้นหามุมมองรีจิสทรีโมเดลเพื่อให้แน่ใจว่า jev-model ใช้งานได้และระบบรู้จัก
SELECT model_id, model_type, model_provider, model_auth_type
FROM google_ml.model_info_view
WHERE model_id = 'jev-model';
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
model_id | model_type | model_provider | model_auth_type ----------+------------+----------------+----------------- jev-model | llm | custom | secret_manager (1 row)
8. เรียกใช้การทดสอบการค้นหาเทียบกับ Jev
เมื่อลงทะเบียน jev-model แล้ว คุณจะดำเนินการเชิงความหมายได้โดยตรงภายในคำค้นหา PostgreSQL มาตรฐาน
1. ทดสอบการกรองบูลีนสเกลาร์ (ai.if)
ประเมินข้อความเดียวโดยใช้ 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;
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
is_suitable ------------- true (1 row)
2. ทดสอบการวิเคราะห์ความรู้สึกแบบสเกลาร์ (ai.analyze_sentiment)
ประเมินความคิดเห็นของลูกค้าเป็นป้ายกำกับหมวดหมู่ (positive, negative หรือ 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;
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
sentiment ----------- negative (1 row)
3. ทดสอบการกรองบูลีนแบบอาร์เรย์
ประเมินหลายรายการในคำค้นหาเดียวโดยส่งอาร์เรย์ของพรอมต์
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;
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
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. ทดสอบการค้นหาตารางด้วยการจัดกลุ่มอาร์เรย์
ตอนนี้ให้ค้นหาตาราง ecomm.products ที่โหลดไว้ก่อนหน้านี้ในระหว่างการจัดสรรคลัสเตอร์ โดยใช้ ai.if กับรายการเป็นกลุ่มเพื่อตรวจสอบว่าผลิตภัณฑ์ใดในแคตตาล็อกเป็นอุปกรณ์สำหรับสภาพอากาศหนาว
หากต้องการเรียกใช้การกรองเชิงความหมายที่มีปริมาณงานสูงในข้อมูลตาราง (เช่น 50 แถวต่อกลุ่ม) ให้ใช้row_number()ฟังก์ชันสร้างกรอบข้อมูลของ PostgreSQL เพื่อแบ่งแถวออกเป็นกลุ่ม
-- 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;
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
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. ค้นหารีวิวผลิตภัณฑ์ของลูกค้าเพื่อดูความรู้สึก
ตอนนี้คุณสามารถวิเคราะห์รีวิวของลูกค้าจากecomm.product_reviewsตารางโดยใช้ai.analyze_sentimentที่ขับเคลื่อนโดยchoiceดั้งเดิมของ 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;
คุณควรเห็นเอาต์พุตที่คล้ายกับตัวอย่างต่อไปนี้
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. โบนัส: การให้คะแนนความรู้สึกอย่างต่อเนื่องด้วย Jev score
แม้ว่าฟังก์ชัน AI ของ AlloyDB เช่น ai.analyze_sentiment จะแสดงกลุ่มหมวดหมู่ (positive, negative, neutral) แต่ไพรมิทีฟ score ของ TypeSafe AI จะประเมินความแตกต่างในเกณฑ์การให้คะแนนที่เรียงลำดับแล้ว และแสดงคะแนนแบบต่อเนื่องที่ถ่วงน้ำหนักตามความคาดหวังตั้งแต่ 0 ถึง 100
เนื่องจาก score จะแสดงผลข้อมูลเมตาที่เป็นตัวเลขแทนป้ายกำกับการจัดประเภทข้อความ คุณจึงลงทะเบียนปลายทางโมเดล generic ที่กำหนดเอง (jev-systemone) และเรียกใช้โดยใช้ google_ml.predict_row ได้
1. ลงทะเบียนปลายทางทั่วไป
ใน AlloyDB Studio ให้ลงทะเบียน jev-systemone ด้วย 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. เรียกใช้การประเมินแบบหลายงาน (คะแนนบูลีน + คะแนนต่อเนื่อง)
ประเมินทั้งการตรวจสอบบูลีนข้อบกพร่อง (noul) และความเข้มของความรู้สึกอย่างต่อเนื่อง (score) พร้อมกันในการเรียกใช้ 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;
คุณควรเห็นเอาต์พุตที่คล้ายกับ (ผลลัพธ์ของคุณอาจแตกต่างกันไป)
{
"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 ประเมินเป็น 11 / 100 ซึ่งแสดงให้เห็นอย่างถูกต้องว่าลูกค้าได้รับประสบการณ์ในเชิงลบเป็นส่วนใหญ่ แม้จะยอมรับว่าเนื้อผ้ามีความนุ่มก็ตาม
10. ล้างข้อมูล
หากไม่ต้องการให้มีการเรียกเก็บเงินอย่างต่อเนื่องสำหรับทรัพยากรที่สร้างขึ้นระหว่าง Codelab นี้ ให้ล้างข้อมูลลับและออบเจ็กต์ฐานข้อมูล แล้วลบคลัสเตอร์ AlloyDB
1. ลบทรัพยากร Secret Manager
ใน Cloud Shell ให้ลบข้อมูลลับที่สร้างขึ้นสำหรับคีย์ API ของ TypeSafe AI ดังนี้
gcloud secrets delete typesafe-jev-api-key --quiet
2. ลบอินสแตนซ์หลักและคลัสเตอร์ AlloyDB
ลบอินสแตนซ์หลักก่อน โดยทำดังนี้
gcloud alloydb instances delete $ADBINSTANCE \
--cluster=$ADBCLUSTER \
--region=$REGION \
--quiet
เมื่อการลบอินสแตนซ์เสร็จสมบูรณ์แล้ว ให้ลบคลัสเตอร์โดยทำดังนี้
gcloud alloydb clusters delete $ADBCLUSTER \
--region=$REGION \
--quiet
11. ขอแสดงความยินดี
ยินดีด้วย คุณได้จัดสรรคลัสเตอร์ AlloyDB ของ Google Cloud และผสานรวมกับ TypeSafe AI System One (Jev) เรียบร้อยแล้ว
สิ่งที่คุณได้เรียนรู้
- วิธีสร้างการเข้าถึงบริการส่วนตัว (PSA) และจัดสรรคลัสเตอร์ AlloyDB สำหรับ PostgreSQL และอินสแตนซ์หลัก
- วิธีเปิดใช้
--outbound-public-ipเพื่อให้ AlloyDB เข้าถึง API ของ SaaS ที่ใช้ HTTPS ภายนอกได้ - วิธีจัดเก็บข้อมูลเข้าสู่ระบบของผู้ให้บริการ AI บุคคลที่สามอย่างปลอดภัยใน Google Secret Manager และเชื่อมโยงข้อมูลดังกล่าวกับ AlloyDB
- วิธีเขียนฟังก์ชันการแปลง PL/pgSQL ที่เชื่อมฟังก์ชัน AI มาตรฐานของ PostgreSQL (
ai.ifและai.analyze_sentiment) กับ REST API ภายนอก - วิธีลงทะเบียนปลายทาง LLM ที่กำหนดเองใน AlloyDB โดยใช้
google_ml.create_model - วิธีเรียกใช้ทั้งคำค้นหา SQL เชิงความหมายแบบสเกลาร์และแบบเป็นกลุ่มที่มีปริมาณงานสูงใน PostgreSQL โดยตรง
- วิธีวิเคราะห์รีวิวผลิตภัณฑ์จริงของลูกค้าเพื่อดูความรู้สึกตามหมวดหมู่
- วิธีลงทะเบียนปลายทางโมเดลทั่วไปและประเมินคะแนนความพึงพอใจของลูกค้าอย่างต่อเนื่อง (
0..100) ผ่านgoogle_ml.predict_row
ขั้นตอนถัดไป
- ดูข้อมูลเพิ่มเติมเกี่ยวกับความสามารถของฟังก์ชัน AI ของ AlloyDB ได้ในเอกสารประกอบเกี่ยวกับ AI ของ AlloyDB
- อ่านข้อมูลอ้างอิง TypeSafe AI API เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับตรรกะข้อจำกัดของ Noul และการให้คะแนนความรู้สึก