1. Введение
В этом практическом занятии вы подключите модель Jev из TypeSafe AI к AlloyDB AI, используя собственные функции искусственного интеллекта AlloyDB ( ai.if , ai.analyze_sentiment и ml_predict_row ). Это позволит вам эффективно выполнять пакетный вывод с использованием модели Jev непосредственно на ваших оперативных данных в AlloyDB, без перемещения данных или написания сложного кода на стороне приложения.
Что вы будете делать
- Предоставление доступа к частным сервисам (PSA) и кластера AlloyDB для PostgreSQL, а также основного экземпляра.
- Создайте правило брандмауэра VPC, разрешающее подключение к Cloudshell и внутренним сетям.
- Загрузите пример набора данных для электронной коммерции с помощью
gcloud alloydb clusters import - Включите Google Secret Manager и расширение
google_ml_integrationот AlloyDB. - Сохраните и предоставьте доступ к вашему ключу API TypeSafe AI в Secret Manager.
- Создайте функции преобразования входных и выходных данных PL/pgSQL для примитивов Jev's
noul(логическое значение) иchoice(эмоциональное состояние). - Зарегистрируйте пользовательскую конечную точку модели
jev-modelв AlloyDB. - Выполняйте семантические запросы (
ai.ifиai.analyze_sentiment) как для скалярных значений, так и для массивов непосредственно в SQL. - Для классификации тональности отзывов реальных покупателей используйте
ai.analyze_sentiment - (Бонус) Зарегистрируйте универсальную конечную точку (
jev-systemone) и оцените непрерывную интенсивность удовлетворенности клиентов, используя примитивscoreJev.
Что вам понадобится
- Веб-браузер, например 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"
Включите необходимые API Google Cloud.
Выполните эту команду, чтобы включить все необходимые API-интерфейсы сервисов Google Cloud:
gcloud services enable \
alloydb.googleapis.com \
servicenetworking.googleapis.com \
secretmanager.googleapis.com \
compute.googleapis.com
3. Подготовка кластера AlloyDB и основного экземпляра.
На этом этапе вы выделите диапазон IP-адресов для доступа к частным сервисам в вашей сети VPC, настроите частное пиринговое соединение и обеспечите кластеру AlloyDB и основному экземпляру исходящий доступ в Интернет.
1. Создайте диапазон IP-адресов для доступа к частным службам (PSA).
Для работы AlloyDB требуется выделение диапазона частных IP-адресов в вашей виртуальной частной сети (VPC). Предположим, вы используете сеть VPC default :
Создайте выделенный диапазон частных 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. Создайте основной экземпляр с флагами ИИ и исходящим подключением.
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"
Добавьте свой ключ API TypeSafe AI в качестве секретной версии:
echo -n "<YOUR_TYPESAFE_API_KEY>" | \
gcloud secrets versions add typesafe-jev-api-key --data-file=-
2. Предоставьте доступ к агенту службы AlloyDB.
AlloyDB использует свой агент службы проектов для получения секретов во время выполнения запросов. Найдите номер своего проекта и предоставьте ему роль доступа к секретам:
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 for 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. Зарегистрируйте секретный ключ в памяти 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 с различными примитивами логического вывода ( noul для булевых ограничений, choice для многоклассовой классификации).
В системе управления конечными точками модели AlloyDB используются четыре функции преобразования (скалярный ввод, скалярный вывод, пакетный ввод, пакетный вывод) для сопоставления стандартных сигнатур функций PostgreSQL ai.* с форматом REST API Jev.
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-ответа Джева обратно в 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. Пакетное преобразование входных данных
Jev может одновременно обрабатывать десятки вопросов в рамках одного HTTP-запроса без снижения производительности из-за проблем с генеративным преобразованием.
Добавьте преобразование пакетного ввода для преобразования массивов 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 Джева:
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 возвращают категориальные категории ( 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. Проведите многозадачную оценку (логическая + непрерывная оценка).
Одновременно в одном 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. Уборка
Чтобы избежать постоянных расходов на ресурсы, созданные в ходе этого практического занятия, очистите секретные и баз данных объекты, а также удалите кластер AlloyDB.
1. Удалите ресурсы менеджера секретов.
В 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. Поздравляем!
Поздравляем! Вы успешно развернули кластер Google Cloud AlloyDB и интегрировали его с TypeSafe AI System One ( Jev ).
Что вы узнали
- Как настроить частный доступ к сервису (PSA) и подготовить кластер AlloyDB для PostgreSQL, а также основной экземпляр.
- Как включить
--outbound-public-ip, чтобы AlloyDB мог получать доступ к внешним HTTPS-API SaaS-сервисов. - Как безопасно хранить учетные данные сторонних поставщиков ИИ в Google Secret Manager и привязать их к AlloyDB.
- Как писать функции преобразования PL/pgSQL, которые связывают стандартные функции искусственного интеллекта PostgreSQL (
ai.ifиai.analyze_sentiment) с внешними REST API. - Как зарегистрировать пользовательские конечные точки LLM в AlloyDB с помощью
google_ml.create_model. - Как выполнять как скалярные, так и высокопроизводительные пакетные семантические SQL-запросы непосредственно в PostgreSQL.
- Как анализировать реальные отзывы покупателей о товарах для определения тональности текста.
- Как зарегистрировать универсальную конечную точку модели и оценить непрерывные показатели удовлетворенности клиентов (
0..100) с помощьюgoogle_ml.predict_row.
Следующие шаги
- Подробнее о возможностях функций AlloyDB AI можно узнать в документации AlloyDB AI .
- Ознакомьтесь со справочником по API TypeSafe AI, чтобы узнать больше о логике ограничений Noul и оценке настроения.