1. はじめに
この Codelab では、AlloyDB のネイティブ AI 関数(ai.if、ai.analyze_sentiment、ml_predict_row)を使用して、TypeSafe AI の Jev モデルを AlloyDB AI に接続します。これにより、データを移動したり、複雑なアプリケーション側のコードを記述したりすることなく、AlloyDB の運用データで Jev モデルを使用して効率的なバッチ推論を直接実行できます。
演習内容
- プライベート サービス アクセス(PSA)、AlloyDB for PostgreSQL クラスタ、プライマリ インスタンスをプロビジョニングする
- Cloud Shell と内部接続を許可する VPC ファイアウォール ルールを作成する
gcloud alloydb clusters importを使用して e コマースのサンプル データセットを読み込む- Google Secret Manager と AlloyDB の
google_ml_integration拡張機能を有効にする - Secret Manager で TypeSafe AI API キーを保存してアクセス権を付与する
- Jev の
noul(ブール値)プリミティブとchoice(感情)プリミティブの PL/pgSQL 入力変換関数と出力変換関数を作成する - AlloyDB にカスタム
jev-modelモデル エンドポイントを登録する - SQL でスカラーおよび配列バッチのセマンティック クエリ(
ai.ifとai.analyze_sentiment)を直接実行する ai.analyze_sentimentを使用して、実際の購入者による商品レビューの感情分類をクエリする- (ボーナス)汎用エンドポイント(
jev-systemone)を登録し、Jev のscoreプリミティブを使用して顧客満足度の継続的な強度を評価する
必要なもの
- ウェブブラウザ(Chrome など)
- 課金を有効にした Google Cloud プロジェクト
- TypeSafe AI API キー(TypeSafe AI から取得)
2. 始める前に
Google Cloud プロジェクトを選択する
Google Cloud コンソールで、使用する Google Cloud クラウド プロジェクトを選択または作成します。
Cloud Shell の起動
Google Cloud コンソールの右上にある [Cloud Shell をアクティブにする] をクリックします。
Cloud Shell セッションが認証されていることを確認します。
gcloud auth list
プロジェクト ID と環境変数を設定します。
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 サービス API を有効にします。
gcloud services enable \
alloydb.googleapis.com \
servicenetworking.googleapis.com \
secretmanager.googleapis.com \
compute.googleapis.com
3. AlloyDB クラスタとプライマリ インスタンスをプロビジョニングする
この手順では、VPC ネットワークにプライベート サービス アクセスの IP 範囲を割り当て、プライベート ピアリングを確立し、アウトバウンド インターネット アクセスを使用して AlloyDB クラスタとプライマリ インスタンスをプロビジョニングします。
1. プライベート サービス アクセス(PSA)IP 範囲を作成する
AlloyDB には、Virtual Private Cloud(VPC)ネットワークでのプライベート IP 範囲の割り当てが必要です。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 無料トライアル クラスタを作成します。
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
3. AI フラグとアウトバウンド接続を使用してプライマリ インスタンスを作成する
AlloyDB は、アウトバウンド HTTPS 経由で TypeSafe AI の安全な SaaS エンドポイント(https://api.typesafe.ai/v1/systemone)に直接接続します。したがって、--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. サンプル e コマース データを読み込む
現実的なセマンティック クエリをテストするには、商品カタログと顧客レビューを含むサンプル e コマース データセットを 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. TypeSafe AI API キーを Secret Manager に保存する
AlloyDB のモデル エンドポイント管理は Google Secret Manager とネイティブに統合されており、データベース コードや構成ログでプレーンテキストの認証情報を公開することなく、外部 API 呼び出しを認証します。
1. Secret を作成する
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 サービス エージェントへのアクセス権を付与する
AlloyDB は、クエリの実行中にプロジェクト サービス エージェントを使用してシークレットを取得します。プロジェクト番号を確認し、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"
サービス エージェントが roles/secretmanager.secretAccessor を受け取ったことを確認する出力が表示されます。
5. AlloyDB Studio を介して AlloyDB に接続し、データベース拡張機能を初期化する
ローカル クライアント ツールやプロキシ トンネルを構成せずに、ブラウザから AlloyDB データベースを直接操作するには、Google Cloud コンソールの AlloyDB Studio を使用します。
1. AlloyDB Studio を開く
- Google Cloud コンソールで、[AlloyDB for PostgreSQL] > [クラスタ] に移動します。
- クラスタ(
my-alloydb-cluster)をクリックします。 - 左側のナビゲーション メニューで [AlloyDB Studio] をクリックします。
- データベースに対して認証します。
- データベース:
postgres - ユーザー:
postgres - パスワード: クラスタの作成時に生成された
$PGPASSWORDを入力します(例: Cloud Shell でecho $PGPASSWORDを実行して表示します)。
- データベース:
- [認証] をクリックします。
AlloyDB Studio のインタラクティブ SQL クエリエディタが表示されます。
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. AlloyDB MEM に Secret を登録する
TypeSafe AI API キーの場所を AlloyDB に伝えます。
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 変換関数を作成する
TypeSafe AI の System One API は、個別の推論プリミティブ(ブール値制約の場合は noul、マルチクラス分類の場合は choice)を含む構造化 JSON を受け入れます。
AlloyDB のモデル エンドポイント管理は、4 つの変換関数(スカラー入力、スカラー出力、バッチ入力、バッチ出力)を使用して、標準の PostgreSQL ai.* 関数シグネチャを 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. スカラー出力変換
Jev の JSON レスポンスを 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 ラウンドトリップ内で数十の質問を同時に評価できます。
バッチ入力変換を追加して、PostgreSQL の prompts TEXT[] 配列を並列 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 にカスタムモデル エンドポイントを登録する
次に、変換関数、シークレット認証情報、TypeSafe AI REST エンドポイントを 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. 配列バッチ処理されたブール値フィルタリングをテストする
プロンプトの配列を渡して、1 つのクエリで複数のアイテムを評価します。
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 行など)を実行するには、PostgreSQL の row_number() ウィンドウ関数を使用して行をバッチにチャンクします。
-- 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. 感情に関する顧客の商品レビューをクエリする
次に、Jev の choice プリミティブでサポートされている ai.analyze_sentiment を使用して、ecomm.product_reviews テーブルの購入者レビューを分析します。
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 スコアによる継続的な感情スコアリング
AlloyDB の ai.analyze_sentiment などの AI 関数はカテゴリ バケット(positive、negative、neutral)を返しますが、TypeSafe AI の score プリミティブは順序付けられたルーブリック全体でニュアンスを評価し、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. マルチタスク評価(ブール値 + 連続スコア)を実行する
単一の HTTP 呼び出しで、欠陥ブール値チェック(noul)と継続的な感情の強さ(score)の両方を同時に評価します。
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. クリーンアップ
この Coelab で作成したリソースの継続的な料金が発生しないようにするには、シークレットとデータベース オブジェクトをクリーンアップし、AlloyDB クラスタを削除します。
1. Secret Manager リソースを削除する
Cloud Shell で、TypeSafe AI API キー用に作成したシークレットを削除します。
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. 完了
おめでとうございます!Google Cloud AlloyDB クラスタを正常にプロビジョニングし、TypeSafe AI System One(Jev)と統合しました。
学習した内容
- プライベート サービス アクセス(PSA)を確立し、AlloyDB for PostgreSQL クラスタとプライマリ インスタンスをプロビジョニングする方法。
- AlloyDB が外部 HTTPS SaaS API にアクセスできるように
--outbound-public-ipを有効にする方法。 - サードパーティの AI プロバイダの認証情報を Google Secret Manager に安全に保存し、AlloyDB にバインドする方法。
- 標準の PostgreSQL AI 関数(
ai.ifとai.analyze_sentiment)を外部 REST API にブリッジする PL/pgSQL 変換関数を作成する方法。 google_ml.create_modelを使用して AlloyDB にカスタム LLM エンドポイントを登録する方法。- スカラーと高スループットのバッチ セマンティック SQL クエリの両方を PostgreSQL で直接実行する方法。
- 実際の顧客の商品レビューを分析して、カテゴリ別の感情を把握する方法。
- 汎用モデル エンドポイントを登録し、
google_ml.predict_rowを介して継続的な顧客満足度スコア(0..100)を評価する方法。
次のステップ
- AlloyDB AI 関数の機能の詳細については、AlloyDB AI のドキュメントをご覧ください。
- Noul 制約ロジックと感情スコアリングの詳細については、TypeSafe AI API リファレンスをご覧ください。