Wprowadzenie do wektorów dystrybucyjnych w Cloud SQL dla MySQL

Wprowadzenie do wektorów dystrybucyjnych w Cloud SQL dla MySQL

Informacje o tym ćwiczeniu (w Codelabs)

subjectOstatnia aktualizacja: kwi 22, 2025
account_circleAutorzy: Gleb Otochkin

1. Wprowadzenie

W tym laboratorium kodu dowiesz się, jak używać Cloud SQL do integracji z Vertex AI w MySQL, łącząc wyszukiwanie wektorów z wektorami dystrybucyjnymi Vertex AI.

30b7c4dcdd8bb68f.png

  • podstawowa znajomość konsoli Google Cloud;
  • podstawowe umiejętności w zakresie interfejsu wiersza poleceń i Cloud Shell;
  • Wdrażanie instancji Cloud SQL for MySQL
  • Jak utworzyć bazę danych i włączyć integrację z Cloud SQL AI
  • Wczytywanie danych do bazy danych
  • Jak używać modelu wektorów dystrybucyjnych Vertex AI w Cloud SQL
  • Jak wzbogacić wynik za pomocą modelu generatywnego Vertex AI
  • Jak zwiększyć wydajność dzięki indeksowi wektorowemu

Czego potrzebujesz

  • Konto Google Cloud i projekt Google Cloud
  • przeglądarka internetowa, np. Chrome, obsługująca konsolę Google Cloud i Cloud Shell;

2. Konfiguracja i wymagania

Konfiguracja środowiska w samodzielnym tempie

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

fbef9caa1602edd0.png

a99b7ace416376c4.png

5e3ff691252acf41.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, którego nie używają interfejsy API Google. Zawsze możesz ją zaktualizować.
  • Identyfikator projektu jest niepowtarzalny w ramach wszystkich projektów Google Cloud i nie można go zmienić (po ustawieniu). Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie ma znaczenia, jaki to ciąg. W większości laboratoriów z kodem musisz podać identyfikator projektu (zazwyczaj oznaczony jako PROJECT_ID). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować inny losowy. Możesz też spróbować użyć własnego adresu e-mail, aby sprawdzić, czy jest on dostępny. Po wykonaniu tego kroku nie można go zmienić. Pozostanie on na stałe w ramach projektu.
  • Informacyjnie: istnieje jeszcze 3 wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów i interfejsów API Cloud. Przejście przez ten samouczek nie będzie kosztowne, a być może nawet bezpłatne. Aby wyłączyć zasoby i uniknąć obciążenia opłatami po zakończeniu samouczka, możesz usunąć utworzone zasoby lub usunąć projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Uruchomienie Cloud Shell

Google Cloud można obsługiwać zdalnie z laptopa, ale w tym przypadku będziesz korzystać z Google Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.

W konsoli Google Cloud kliknij ikonę Cloud Shell na pasku narzędzi w prawym górnym rogu:

55efc1aaa7a4d3ad.png

Uzyskanie dostępu do środowiska i połączenie się z nim powinno zająć tylko kilka chwil. Po jego zakończeniu powinno wyświetlić się coś takiego:

7ffe5cbb04455448.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie poprawia wydajność sieci i uwierzytelnianie. Wszystkie zadania w tym CodeLab możesz wykonać w przeglądarce. Nie musisz niczego instalować.

3. Zanim zaczniesz

Włącz interfejs API

W Cloud Shell sprawdź, czy identyfikator projektu jest skonfigurowany:

gcloud config set project [YOUR-PROJECT-ID]

Ustaw zmienną środowiskową PROJECT_ID:

PROJECT_ID=$(gcloud config get-value project)

Włącz wszystkie niezbędne usługi:

gcloud services enable sqladmin.googleapis.com \
                       compute
.googleapis.com \
                       cloudresourcemanager
.googleapis.com \
                       servicenetworking
.googleapis.com \
                       aiplatform
.googleapis.com

Oczekiwany wynik

student@cloudshell:~ (test-project-001-402417)$ gcloud config set project test-project-001-402417
Updated property [core/project].
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project)
Your active configuration is: [cloudshell-14650]
student@cloudshell:~ (test-project-001-402417)$ 
student@cloudshell:~ (test-project-001-402417)$ gcloud services enable sqladmin.googleapis.com \
                       compute.googleapis.com \
                       cloudresourcemanager.googleapis.com \
                       servicenetworking.googleapis.com \
                       aiplatform.googleapis.com
Operation "operations/acat.p2-4470404856-1f44ebd8-894e-4356-bea7-b84165a57442" finished successfully.

4. Tworzenie instancji Cloud SQL

Utwórz instancję Cloud SQL z integracją bazy danych z Vertex AI.

Utwórz hasło do bazy danych

Określ hasło domyślnego użytkownika bazy danych. Możesz zdefiniować własne hasło lub wygenerować je za pomocą funkcji losowania:

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

Zanotuj wygenerowaną wartość hasła:

echo $CLOUDSQL_PASSWORD

Tworzenie instancji Cloud SQL for MySQL

Podczas tworzenia instancji można włączyć flagę cloudsql_vector. Obsługa wektorów jest obecnie dostępna w MySQL 8.0 R20241208.01_00 lub nowszej.

W sesji Cloud Shell wykonaj te czynności:

gcloud sql instances create my-cloudsql-instance \
--database-version=MYSQL_8_4 \
--tier=db-custom-2-8192 \
--region=us-central1 \
--enable-google-ml-integration \
--edition=ENTERPRISE \
--root-password=$CLOUDSQL_PASSWORD

Możemy sprawdzić połączenie z Cloud Shell.

gcloud sql connect my-cloudsql-instance --user=root

Uruchom polecenie i wpisz hasło w oknie dialogowym, gdy będzie gotowe do połączenia.

Oczekiwany wynik:

$gcloud sql connect my-cloudsql-instance --user=root
Allowlisting your IP for incoming connection for 5 minutes...done.                                                                                                                           
Connecting to database with SQL user [root].Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 71
Server version: 8.4.4-google (Google)

Copyright (c) 2000, 2025, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

Włącz integrację z Vertex AI

Przyznaj niezbędne uprawnienia wewnętrznemu kontu usługi cloud sql, aby móc korzystać z integracji z Vertex AI.

Znajdź adres e-mail wewnętrznego konta usługi Cloud SQL i wyeksportuj go jako zmienną.

SERVICE_ACCOUNT_EMAIL=$(gcloud sql instances describe my-cloudsql-instance --format="value(serviceAccountEmailAddress)")
echo $SERVICE_ACCOUNT_EMAIL

Przyznaj dostęp do Vertex AI kontu usługi Cloud SQL:

gcloud projects add-iam-policy-binding $PROJECT_ID \
 
--member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
 
--role="roles/aiplatform.user"

Więcej informacji o tworzeniu i konfigurowaniu instancji znajdziesz tutaj w dokumentacji Cloud SQL.

5. Przygotuj bazę danych

Teraz musimy utworzyć bazę danych i włączyć obsługę wektorów.

Utwórz bazę danych

Utwórz bazę danych o nazwie quickstart_db. Aby to zrobić, możesz użyć różnych opcji, takich jak klienci baz danych w wierszu poleceń, np. mysql dla mySQL, SDK lub Cloud SQL Studio. Do utworzenia bazy danych użyjemy pakietu SDK (gcloud).

W Cloud Shell wykonaj polecenie tworzenia bazy danych.

gcloud sql databases create quickstart_db --instance=my-cloudsql-instance

6. Wczytaj dane

Teraz musimy utworzyć obiekty w bazie danych i załadować dane. Użyjemy fikcyjnych danych ze sklepu z talerzami perkusyjnymi. Dane są dostępne w formacie SQL (schemat) i CSV (dane).

Cloud Shell będzie naszym głównym środowiskiem do łączenia się z bazą danych, tworzenia wszystkich obiektów i wczytywania danych.

Najpierw musimy dodać publiczny adres IP Cloud Shell do listy autoryzowanych sieci instancji Cloud SQL. W Cloud Shell wykonaj te czynności:

gcloud sql instances patch my-cloudsql-instance --authorized-networks=$(curl ifconfig.me)

Jeśli sesja została utracona, zresetowana lub pracujesz z innego narzędzia, ponownie wyeksportuj zmienną CLOUDSQL_PASSWORD:

export CLOUDSQL_PASSWORD=...your password defined for the instance...

Teraz możemy utworzyć w bazie danych wszystkie wymagane obiekty. W tym celu użyjemy narzędzia mysql MySQL w połączeniu z narzędziem curl, które pobiera dane ze źródła publicznego.

W Cloud Shell wykonaj te czynności:

export INSTANCE_IP=$(gcloud sql instances describe my-cloudsql-instance --format="value(ipAddresses.ipAddress)")
curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_mysql_schema.sql | mysql --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db

Co dokładnie zrobiliśmy w poprzednim poleceniu? Połączyliśmy się z naszą bazą danych i wykonaliśmy pobrany kod SQL, który utworzył tabele, indeksy i sekwencje.

Kolejnym krokiem jest wczytanie danych z tabeli cymbal_products. Używamy tych samych narzędzi curl i mysql.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_products.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_products FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

Następnie kontynuujemy z cymbal_stores.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_stores.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_stores FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

Uzupełnij go o dane z kolumny cymbal_inventory, która zawiera liczbę każdego produktu w każdym sklepie.

curl -LJ https://raw.githubusercontent.com/GoogleCloudPlatform/devrel-demos/main/infrastructure/cymbal-store-embeddings/cymbal_inventory.csv | mysql --enable-local-infile --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db -e "LOAD DATA LOCAL INFILE '/dev/stdin'  INTO TABLE cymbal_inventory FIELDS TERMINATED BY ','  OPTIONALLY ENCLOSED BY '\"'  LINES TERMINATED BY '\n'  IGNORE 1 LINES;"

Jeśli masz własne przykładowe dane i pliki CSV zgodne z narzędziem importu Cloud SQL dostępnym w Cloud Console, możesz z niego skorzystać zamiast opisanego powyżej podejścia.

7. Tworzenie wektorów

Następnym krokiem jest utworzenie wektorów osadzonych dla opisów produktów za pomocą modelu textembedding-005 z Google Vertex AI i zapisanie ich w nowej kolumnie w tabeli cymbal_products.

Aby przechowywać dane wektorów, musimy włączyć funkcję wektorów w naszej instancji Cloud SQL. Wykonaj w Cloud Shell:

gcloud sql instances patch my-cloudsql-instance \
--database-flags=cloudsql_vector=on

Połącz się z bazą danych:

mysql --host=$INSTANCE_IP --user=root --password=$CLOUDSQL_PASSWORD quickstart_db

Utwórz też kolumnę wirtualną embedding w tabeli cymbal_products za pomocą funkcji embedding.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) using varbinary;
UPDATE cymbal_products SET embedding = mysql.ml_embedding('text-embedding-005', product_description);

Generowanie wektorów zastępczych dla 2000 wierszy zwykle zajmuje mniej niż 5 minut, ale czasami może potrwać nieco dłużej, a często jest znacznie szybsze.

8. Uruchom wyszukiwanie podobieństw

Teraz możemy wykonać wyszukiwanie z użyciem wyszukiwania podobieństwa na podstawie wartości wektorowych obliczonych dla opisów oraz wartości wektorowej wygenerowanej dla naszego żądania przy użyciu tego samego modelu wstawiania.

Zapytanie SQL można wykonać w tym samym interfejsie wiersza poleceń lub alternatywnie w Cloud SQL Studio. Wszelkimi złożonymi zapytaniami z wieloma wierszami lepiej zarządzać w Cloud SQL Studio.

Tworzenie konta użytkownika

Potrzebujemy nowego użytkownika, który będzie mógł korzystać z Cloud SQL Studio. Utworzymy wbudowany typ użytkownika student z tym samym hasłem, którego użyliśmy w przypadku użytkownika root.

W Cloud Shell wykonaj te czynności:

gcloud sql users create student  --instance=my-cloudsql-instance --password=$CLOUDSQL_PASSWORD --host=%

Uruchamianie Cloud SQL Studio

W konsoli kliknij wcześniej utworzoną instancję Cloud SQL.

667b658dbf98eb0b.png

Gdy otworzysz panel po prawej stronie, zobaczysz Cloud SQL Studio. Kliknij go.

a879e8ac914a8ce9.png

Otworzy się okno, w którym możesz podać nazwę bazy danych i swoje dane logowania:

  • Baza danych: quickstart_db
  • Użytkownik: student
  • Hasło: zapisane hasło użytkownika

Kliknij przycisk „AUTORYZUJ”.

36e603684733d18.png

Otworzy się kolejne okno, w którym po prawej stronie kliknij kartę „Editor” (Edytor), aby otworzyć Edytor SQL.

d803b7b6a798094f.png

Możemy teraz uruchomić zapytania.

Uruchom zapytanie

Wykonaj zapytanie, aby uzyskać listę dostępnych produktów najbardziej pasujących do żądań klienta. Żądanie, które przekażemy Vertex AI, aby uzyskać wartość wektora, brzmi mniej więcej tak: „Jakie drzewa owocowe dobrze rosną w tym miejscu?”

Oto zapytanie, które możesz uruchomić, aby wybrać 5 pierwszych elementów najbardziej pasujących do Twojego zapytania za pomocą funkcji cosine_distance:

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cosine_distance(cp.embedding ,@query_vector) as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 5;

Skopiuj i wklej zapytanie do edytora Cloud SQL Studio i kliknij przycisk „Uruchom” lub wklej zapytanie w sesji wiersza poleceń, łącząc się z bazą danych quickstart_db.

dffc70835901cf03.png

Oto lista wybranych produktów pasujących do zapytania.

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set (0.13 sec)

Wykonywanie zapytania z użyciem funkcji cosine_distance zajęło 0,13 sek.

Teraz wykonujemy to samo zapytanie, ale z wyszukiwaniem KNN przy użyciu funkcji approx_distance. Jeśli nie mamy indeksu ANN dla naszych wektorów, automatycznie przechodzimy do wyszukiwania dokładnego:

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 5;

Oto lista produktów zwróconych przez zapytanie.

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set, 1 warning (0.12 sec)

Wykonanie zapytania zajęło tylko 0,12 sekundy. Otrzymaliśmy te same wyniki co w przypadku funkcji cosine_distance.

9. Poprawianie odpowiedzi LLM za pomocą odzyskanych danych

Możemy ulepszyć odpowiedź generatywnej AI LLM dla aplikacji klienta, korzystając z wyników wykonanego zapytania, i przygotować znaczące dane wyjściowe, używając dostarczonych wyników zapytania jako części promptu dla generatywnego modelu językowego Vertex AI.

Aby to zrobić, musimy wygenerować dane w formacie JSON na podstawie wyników wyszukiwania wektorów, a potem użyć wygenerowanego ciągu JSON jako uzupełnienia promptu dla modelu LLM w Vertex AI, aby uzyskać sensowne dane wyjściowe. Najpierw generujemy plik JSON, potem testujemy go w Vertex AI Studio, a na końcu włączamy go w wyrażeniu SQL, które można wykorzystać w aplikacji.

Generowanie danych wyjściowych w formacie JSON

Zmień zapytanie, aby generować dane wyjściowe w formacie JSON i zwracać tylko 1 wiersz, który ma być przekazany do Vertex AI.

Oto przykład zapytania z wykorzystaniem wyszukiwania w sieci neuronowej:

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
WITH trees as (
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id as product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        (approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine')) ASC
LIMIT 1)
SELECT json_arrayagg(json_object('product_name',product_name,'description',description,'sale_price',sale_price,'zip_code',zip_code,'product_id',product_id)) FROM trees;

A tutaj dane wyjściowe w formacie JSON:

[{"zip_code": 93230, "product_id": "23e41a71d63d8bbc9bdfa1d118cfddc5", "sale_price": 100.00, "description": "Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo", "product_name": "Malus Domestica"}]

Uruchamianie promptu w Vertex AI Studio

Wygenerowany plik JSON możemy użyć jako część promptu do modelu tekstowego generatywnej AI w Vertex AI Studio.

Otwórz prompt Vertex AI Studio w konsoli Google Cloud.

411ffb9d164ac140.png

Możesz otrzymać prośbę o włączenie dodatkowych interfejsów API, ale możesz ją zignorować. Do ukończenia laboratorium nie potrzebujemy żadnych dodatkowych interfejsów API.

Oto prompt, którego użyjemy:

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
[place your JSON here]
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

A tak wygląda kod, gdy zastąpimy placeholder JSON odpowiedzią na zapytanie:

You are a friendly advisor helping to find a product based on the customer's needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","description":"some description","sale_price":10,"zip_code": 10234, "produt_id": "02056727942aeb714dc9a2313654e1b0"}
Here is the list of products:
{"zip_code": 93230, "product_id": "23e41a71d63d8bbc9bdfa1d118cfddc5", "sale_price": 100.00, "description": "Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo", "product_name": "Malus Domestica"}
The customer asked "What tree is growing the best here?"
You should give information about the product, price and some supplemental information.
Do not ask any additional questions and assume location based on the zip code provided in the list of products.

Oto wynik, gdy uruchomimy prompt z wartościami JSON i modelem gemini-2.0-flash:

9839af512686130d.png

Odpowiedź, którą otrzymaliśmy od modelu w tym przykładzie, jest zgodna z wynikami wyszukiwania semantycznego i najlepiej pasującym produktem dostępnym w wymienionym kodzie pocztowym.

Uruchamianie prompta w PSQL

Możemy też użyć integracji Cloud SQL AI z Vertex AI, aby uzyskać podobną odpowiedź od modelu generatywnego, używając SQL bezpośrednio w bazie danych.

Teraz możemy użyć wygenerowanego w zapytaniu podrzędnym kodu JSON, aby podać go jako część promptu dla generatywnego modelu tekstowego AI za pomocą kodu SQL.

W sesji mysql lub Cloud SQL Studio do bazy danych uruchom zapytanie

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
WITH trees AS (
SELECT
        cp.product_name,
        cp.product_description AS description,
        cp.sale_price,
        cs.zip_code,
        cp.uniq_id AS product_id
FROM
        cymbal_products cp
JOIN cymbal_inventory ci ON
        ci.uniq_id = cp.uniq_id
JOIN cymbal_stores cs ON
        cs.store_id = ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
         (approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine')) ASC
LIMIT 1),
prompt AS (
SELECT
       CONCAT( 'You are a friendly advisor helping to find a product based on the customer''s needs.
Based on the client request we have loaded a list of products closely related to search.
The list in JSON format with list of values like {"product_name":"name","product_description":"some description","sale_price":10}
Here is the list of products:', json_arrayagg(json_object('product_name',trees.product_name,'description',trees.description,'sale_price',trees.sale_price,'zip_code',trees.zip_code,'product_id',trees.product_id)) , 'The customer asked "What kind of fruit trees grow well here?"
You should give information about the product, price and some supplemental information') AS prompt_text
FROM
        trees),
response AS (
SELECT
       mysql.ML_PREDICT_ROW('publishers/google/models/gemini-2.0-flash-001:generateContent',
        json_object('contents',
        json_object('role',
        'user',
        'parts',
        json_array(
        json_object('text',
        prompt_text))))) AS resp
FROM
        prompt)
SELECT
JSON_EXTRACT(resp, '$.candidates[0].content.parts[0].text')
FROM
        response;

Oto przykładowe dane wyjściowe. Dane wyjściowe mogą się różnić w zależności od wersji modelu i parametrów:

"Okay, I see you're looking for fruit trees that grow well in your area. Based on the available product, the **Malus Domestica** (Apple Tree) is a great option to consider!\n\n* **Product:** Malus Domestica (Apple Tree)\n* **Description:** This classic apple tree grows to about 30 feet tall and provides beautiful seasonal color with green leaves in summer and fiery colors in the fall. It's known for its strength and provides good shade. Most importantly, it produces delicious apples!\n* **Price:** \\$100.00\n* **Growing Zones:** This particular apple tree is well-suited for USDA zones 4-8. Since your zip code is 93230, you are likely in USDA zone 9a or 9b. While this specific tree is rated for zones 4-8, with proper care and variety selection, apple trees can still thrive in slightly warmer climates. You may need to provide extra care during heat waves.\n\n**Recommendation:** I would recommend investigating varieties of Malus Domestica suited to slightly warmer climates or contacting a local nursery/arborist to verify if it is a good fit for your local climate conditions.\n"

Dane wyjściowe są podawane w formacie Markdown.

10. Tworzenie indeksu najbliższych sąsiadów

Nasz zbiór danych jest stosunkowo mały, a czas odpowiedzi zależy głównie od interakcji z modelami AI. Jednak gdy masz miliony wektorów, wyszukiwanie wektorów może zająć znaczną część czasu odpowiedzi i wygenerować duże obciążenie systemu. Aby to poprawić, możemy utworzyć indeks na podstawie naszych wektorów.

Tworzenie indeksu ScANN

W naszym teście użyjemy indeksu ScANN.

Aby utworzyć indeks kolumny wektorów dystrybucyjnych, musimy zdefiniować miarę odległości dla tej kolumny. Szczegółowe informacje o parametrach znajdziesz w dokumentacji.

CREATE VECTOR INDEX cymbal_products_embedding_idx ON cymbal_products(embedding) USING SCANN DISTANCE_MEASURE=COSINE;

Porównaj odpowiedź

Teraz możemy ponownie uruchomić zapytanie w ramach wyszukiwania wektorowego i sprawdzić wyniki.

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 5;

Oczekiwany wynik:

+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| product_name    | description                                                                      | sale_price | zip_code | distance            |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
| Malus Domestica | Malus Domestica, the classic apple tree, brings beauty and delicious fruit to yo |     100.00 |    93230 | 0.37740096545831603 |
| Cerasus         | Cerasus: A beautiful cherry tree that brings delicious fruit and vibrant color t |      75.00 |    93230 |   0.405704177142419 |
| Persica         | Persica: Enjoy homegrown, delicious peaches with this beautiful peach tree. Reac |     150.00 |    93230 | 0.41031799106722877 |
| Meyer Lemon     | Grow your own juicy Meyer Lemons with this semi-dwarf tree, California's favorit |      34.00 |    93230 | 0.42823360959352186 |
| Acer            | Acer, the classic maple. Known for vibrant fall foliage in reds, oranges, and ye |     100.00 |    93230 | 0.42953897057301615 |
+-----------------+----------------------------------------------------------------------------------+------------+----------+---------------------+
5 rows in set (0.08 sec)

Widzimy, że czas wykonania był tylko nieznacznie różny, ale jest to oczekiwane w przypadku tak małego zbioru danych. Powinna być znacznie bardziej zauważalna w przypadku dużych zbiorów danych zawierających miliony wektorów.

Możemy też sprawdzić plan wykonania za pomocą polecenia EXPLAIN:

SELECT mysql.ML_EMBEDDING('text-embedding-005','What kind of fruit trees grow well here?') into @query_vector;
EXPLAIN ANALYZE SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        approx_distance(cp.embedding ,@query_vector, 'distance_measure=cosine') as distance
FROM
        cymbal_products cp
JOIN cymbal_inventory ci on
        ci.uniq_id=cp.uniq_id
JOIN cymbal_stores cs on
        cs.store_id=ci.store_id
        AND ci.inventory>0
        AND cs.store_id = 1583
ORDER BY
        distance ASC
LIMIT 5;

Plan wykonania (fragment):

...
-> Nested loop inner join  (cost=443 rows=5) (actual time=1.14..1.18 rows=5 loops=1)
                                -> Vector index scan on cp  (cost=441 rows=5) (actual time=1.1..1.1 rows=5 loops=1)
                                -> Single-row index lookup on cp using PRIMARY (uniq_id=cp.uniq_id)  (cost=0.25 rows=1) (actual time=0.0152..0.0152 rows=1 loops=5)

...

Widzimy, że używa on skanowania indeksu wektorów w przypadku kolumny cp (aliasu dla tabeli cymbal_products).

Aby sprawdzić, jak działa wyszukiwanie semantyczne w MySQL, możesz eksperymentować z własnymi danymi lub testować różne zapytania.

11. Czyszczenie środowiska

Usuń instancję Cloud SQL

Po zakończeniu ćwiczenia usuń instancję Cloud SQL

Jeśli nastąpiło rozłączenie i utracono wszystkie poprzednie ustawienia, w Cloud Shell określ zmienne projektu i środowiska:

export INSTANCE_NAME=my-cloudsql-instance
export PROJECT_ID=$(gcloud config get-value project)

Usuń instancję:

gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID

Oczekiwane dane wyjściowe konsoli:

student@cloudshell:~$ gcloud sql instances delete $INSTANCE_NAME --project=$PROJECT_ID
All of the instance data will be lost when the instance is deleted.

Do you want to continue (Y/n)?  y

Deleting Cloud SQL instance...done.                                                                                                                
Deleted [https://sandbox.googleapis.com/v1beta4/projects/test-project-001-402417/instances/my-cloudsql-instance].

12. Gratulacje

Gratulujemy ukończenia ćwiczenia.

Omówione zagadnienia

  • Wdrażanie instancji Cloud SQL for MySQL
  • Jak utworzyć bazę danych i włączyć integrację z Cloud SQL AI
  • Wczytywanie danych do bazy danych
  • Jak używać modelu wektorów dystrybucyjnych Vertex AI w Cloud SQL
  • Jak wzbogacić wynik za pomocą modelu generatywnego Vertex AI
  • Jak zwiększyć wydajność dzięki indeksowi wektorowemu

Wypróbuj podobne CodeLab dla AlloyDB lub CodeLab dla Cloud SQL for PostgreSQL.

13. Ankieta

Dane wyjściowe:

Jak będziesz korzystać z tego samouczka?