1. Wprowadzenie
W tym laboratorium z kodami dowiesz się, jak używać Cloud SQL do integracji z Vertex AI, łącząc wyszukiwanie wektorowe z wektorami dystrybucyjnymi Vertex AI.
Wymagania wstępne
- podstawowa znajomość konsoli Google Cloud;
- podstawowe umiejętności w zakresie interfejsu wiersza poleceń i Cloud Shell;
Czego się nauczysz
- Wdrażanie instancji Cloud SQL for PostgreSQL
- 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
- 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ć.
- 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 trzeba podać identyfikator projektu (zwykle 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.
- 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 ćwiczeniu 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:
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:
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
Dane wyjściowe:
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.
Tworzenie hasła 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 PostgreSQL
W sesji Cloud Shell wykonaj te czynności:
gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_16 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on
Po utworzeniu instancji musimy ustawić hasło dla domyślnego użytkownika w instancji i sprawdzić, czy możemy się połączyć z hasłem.
gcloud sql users set-password postgres \
--instance=my-cloudsql-instance \
--password=$CLOUDSQL_PASSWORD
Uruchom polecenie i wpisz hasło w oknie dialogowym, gdy będzie gotowe do połączenia.
gcloud sql connect my-cloudsql-instance --user=postgres
Włącz integrację z Vertex AI
Przyznaj niezbędne uprawnienia wewnętrznemu kontu usługi cloud sql, aby móc korzystać z integracji 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 na linii poleceń, np. psql dla PostgreSQL, SDK lub Cloud SQL Studio. Do tworzenia baz danych i łączenia się z instancją użyjemy pakietu SDK (gcloud).
W Cloud Shell wykonaj polecenie tworzenia bazy danych.
gcloud sql databases create quickstart_db --instance=my-cloudsql-instance
Włączanie rozszerzeń
Aby móc pracować z Vertex AI i wektorami, musimy włączyć 2 rozszerzenia w naszej utworzonej bazie danych.
W Cloud Shell uruchom polecenie, aby nawiązać połączenie z utworzoną bazą danych (musisz podać hasło).
gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres
Następnie, po nawiązaniu połączenia, w sesji SQL musisz uruchomić 2 polecenia:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector CASCADE;
Zakończ sesję SQL:
exit;
6. Wczytaj dane
Teraz musimy utworzyć obiekty w bazie danych i wczytać dane. Użyjemy fikcyjnych danych ze sklepu Cymbal. Dane są dostępne w publicznym zasobniku Google Storage w formacie CSV.
Najpierw musimy utworzyć w bazie danych wszystkie wymagane obiekty. W tym celu użyjemy znanych już poleceń gcloud sql connect i gcloud storage, aby pobrać i zaimportować obiekty schematu do naszej bazy danych.
W Cloud Shell wykonaj polecenie i podaj hasło zanotowane podczas tworzenia instancji:
gcloud storage cat gs://cloud-training/gcc/gcc-tech-004/cymbal_demo_schema.sql |gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres
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.
Następnym krokiem jest załadowanie danych. Aby to zrobić, musimy pobrać pliki CSV z Google Cloud Storage.
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_products.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_inventory.csv .
gcloud storage cp gs://cloud-training/gcc/gcc-tech-004/cymbal_stores.csv .
Następnie musimy połączyć się z bazą danych.
gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres
Możesz też importować dane z plików CSV.
\copy cymbal_products from 'cymbal_products.csv' csv header
\copy cymbal_inventory from 'cymbal_inventory.csv' csv header
\copy cymbal_stores from 'cymbal_stores.csv' csv header
Zakończ sesję SQL:
exit;
Jeśli masz własne dane i pliki CSV są zgodne z narzędziem do importowania do Cloud SQL dostępnym w Cloud Console, możesz z niego skorzystać zamiast wiersza poleceń.
7. Tworzenie wektorów
Następnym krokiem jest utworzenie wektorów dystrybucyjnych dla opisów produktów za pomocą modelu textembedding-004 z Vertex AI od Google i zapisanie ich jako danych wektorowych.
Połącz się z bazą danych:
gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres
Utwórz też kolumnę wirtualną embedding w tabeli cymbal_products za pomocą funkcji embedding.
ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-004',product_description)) STORED;
Może to zająć trochę czasu, ale w przypadku 900–1000 wierszy nie powinno zająć to więcej niż 5 minut, a zwykle jest znacznie szybciej.
8. Uruchamianie wyszukiwania podobieństwa
Teraz możemy wykonać wyszukiwanie z użyciem wyszukiwania podobieństwa na podstawie wartości wektorowych obliczonych dla opisów i wartości wektorowej uzyskanej dla naszej prośby.
Zapytanie SQL można wykonać w tym samym interfejsie wiersza poleceń za pomocą polecenia gcloud sql connect lub alternatywnie w Cloud SQL Studio. Wszelkimi złożonymi zapytaniami z wieloma wierszami lepiej zarządzać w Cloud SQL Studio.
Uruchamianie Cloud SQL Studio
W konsoli kliknij wcześniej utworzoną instancję Cloud SQL.
Gdy otworzysz panel po prawej stronie, zobaczysz Cloud SQL Studio. Kliknij go.
Otworzy się okno, w którym możesz podać nazwę bazy danych i swoje dane logowania:
- Baza danych: quickstart_db
- Użytkownik: postgres
- Hasło: zanotowane hasło głównego użytkownika bazy danych.
Kliknij przycisk „AUTORYZUJ”.
Otworzy się kolejne okno, w którym po prawej stronie kliknij kartę „Edytor”, aby otworzyć edytor kodu SQL.
Możemy już 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 tej okolicy?”
Oto zapytanie, które możesz wykonać, aby wybrać 10 elementów najbardziej pasujących do Twojego zapytania:
SELECT
cp.product_name,
left(cp.product_description,80) as description,
cp.sale_price,
cs.zip_code,
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::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 10;
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.
Oto lista wybranych produktów pasujących do zapytania.
product_name | description | sale_price | zip_code | distance -------------------------+----------------------------------------------------------------------------------+------------+----------+--------------------- Cherry Tree | This is a beautiful cherry tree that will produce delicious cherries. It is an d | 75.00 | 93230 | 0.43922018972266397 Meyer Lemon Tree | Meyer Lemon trees are California's favorite lemon tree! Grow your own lemons by | 34 | 93230 | 0.4685112926118228 Toyon | This is a beautiful toyon tree that can grow to be over 20 feet tall. It is an e | 10.00 | 93230 | 0.4835677149651668 California Lilac | This is a beautiful lilac tree that can grow to be over 10 feet tall. It is an d | 5.00 | 93230 | 0.4947204525907498 California Peppertree | This is a beautiful peppertree that can grow to be over 30 feet tall. It is an e | 25.00 | 93230 | 0.5054166905547247 California Black Walnut | This is a beautiful walnut tree that can grow to be over 80 feet tall. It is a d | 100.00 | 93230 | 0.5084219510932597 California Sycamore | This is a beautiful sycamore tree that can grow to be over 100 feet tall. It is | 300.00 | 93230 | 0.5140519790508755 Coast Live Oak | This is a beautiful oak tree that can grow to be over 100 feet tall. It is an ev | 500.00 | 93230 | 0.5143126438081371 Fremont Cottonwood | This is a beautiful cottonwood tree that can grow to be over 100 feet tall. It i | 200.00 | 93230 | 0.5174774727252058 Madrone | This is a beautiful madrona tree that can grow to be over 80 feet tall. It is an | 50.00 | 93230 | 0.5227400803389093 (10 rows)
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 podanych 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
Zmodyfikuj zapytanie, aby wygenerować dane wyjściowe w formacie JSON i zwrócić tylko 1 wiersz, który ma zostać przekazany do Vertex AI.
Cloud SQL dla PostgreSQL
Oto przykład zapytania:
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
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
A tutaj oczekiwany kod JSON na wyjściu:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
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 Vertex AI Studio Chat w konsoli Google Cloud.
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: [{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}] 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 wynik, gdy uruchomimy prompt z wartościami JSON i modelem gemini-2.0-flash:
Oto odpowiedź, którą otrzymaliśmy od modelu w tym przykładzie. Pamiętaj, że Twoja odpowiedź może być inna ze względu na zmiany modelu i parametrów w czasie:
„Zgodnie z listą dostępnych produktów najlepszym drzewem, które może dobrze rosnąć w Twojej okolicy, jest drzewo wiśniowe”.
Kosztuje 75 USD.
Nie mam szczegółowych informacji o warunkach uprawy w Twoim kodzie pocztowym (93230), ale ogólnie wiadomo, że drzewa wiśniowe dobrze rosną w obszarach o umiarkowanym klimacie i dobrze odwodnionej glebie. Zwykle wymagają one zimnego okresu, aby wytworzyć owoce, więc należy o tym pamiętać. Mogą jednak stanowić wspaniały dodatek do ogrodu, zapewniając piękno i pyszne wiśnie, gdy tylko warunki są odpowiednie”.
Uruchamianie promptu 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. Aby jednak móc korzystać z modelu gemini-2.0-flash-exp, musimy go najpierw zarejestrować.
Uruchamianie w Cloud SQL for PostgreSQL
Zaktualizuj rozszerzenie do wersji 1.4.2 lub nowszej (jeśli bieżąca wersja jest starsza). Połącz się z bazą danych quickstart_db za pomocą polecenia gcloud sql connect (lub użyj Cloud SQL Studio) i wykonaj:
SELECT extversion from pg_extension where extname='google_ml_integration';
Jeśli zwrócona wartość jest mniejsza niż 1.4.2, wykonaj:
ALTER EXTENSION google_ml_integration UPDATE TO '1.4.2';
Następnie musimy ustawić flagę bazy danych google_ml_integration.enable_model_support na „on” (wł.). Możesz to zrobić w interfejsie konsoli internetowej lub uruchomić to polecenie gcloud.
gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on
Wykonanie tego polecenia w tle zajmuje około 1–3 minut. Następnie możesz sprawdzić nową flagę w sesji psql lub za pomocą Cloud SQL Studio połączyć się z bazą danych quickstart_db.
show google_ml_integration.enable_model_support;
Oczekiwane dane wyjściowe z sesji psql to „on”:
quickstart_db => show google_ml_integration.enable_model_support; google_ml_integration.enable_model_support -------------------------------------------- on (1 row)
Następnie musimy zarejestrować 2 modele. Pierwszy z nich to już używany model text-embedding-004. Musisz go zarejestrować, ponieważ włączyliśmy możliwość rejestracji modeli.
Aby zarejestrować uruchomienie modelu w psql lub Cloud SQL Studio, użyj tego kodu:
CALL
google_ml.create_model(
model_id => 'text-embedding-004',
model_provider => 'google',
model_qualified_name => 'text-embedding-004',
model_type => 'text_embedding',
model_auth_type => 'cloudsql_service_agent_iam',
model_in_transform_fn => 'google_ml.vertexai_text_embedding_input_transform',
model_out_transform_fn => 'google_ml.vertexai_text_embedding_output_transform');
Kolejny model, który musimy zarejestrować, to gemini-2.0-flash-001. Będzie on używany do generowania przyjaznych dla użytkownika danych wyjściowych.
CALL
google_ml.create_model(
model_id => 'gemini-2.0-flash-001',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.0-flash-001:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'cloudsql_service_agent_iam');
Listę zarejestrowanych modeli możesz sprawdzić w dowolnym momencie, wybierając informacje z google_ml.model_info_view.
select model_id,model_type from google_ml.model_info_view;
Oto przykładowe dane wyjściowe
quickstart_db=> select model_id,model_type from google_ml.model_info_view; model_id | model_type --------------------------------------+---------------- textembedding-gecko | text_embedding textembedding-gecko@001 | text_embedding gemini-1.5-pro:streamGenerateContent | generic gemini-1.5-pro:generateContent | generic gemini-1.0-pro:generateContent | generic text-embedding-004 | text_embedding gemini-2.0-flash-001 | generic
Teraz możemy użyć danych wygenerowanych w subzapytaniu JSON, aby przekazać je jako część prompta do generatywnego modelu tekstowego AI za pomocą kodu SQL.
W sesji psql lub Cloud SQL Studio dotyczącej bazy danych wykonaj zapytanie.
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
(cp.embedding <=> google_ml.embedding('text-embedding-004',
'What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1),
prompt AS (
SELECT
'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_agg(trees) || '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
json_array_elements(google_ml.predict_row( model_id =>'gemini-2.0-flash-001',
request_body => json_build_object('contents',
json_build_object('role',
'user',
'parts',
json_build_object('text',
prompt_text)))))->'candidates'->0->'content'->'parts'->0->'text' AS resp
FROM
prompt)
SELECT
string_agg(resp::text,
' ')
FROM
response;
Oto oczekiwany wynik. Dane wyjściowe mogą się różnić w zależności od wersji modelu i parametrów:
"That" "'s a great question! Based on your location (assuming you're" " in zip code 93230), I have a suggestion for a" " fruit tree that should thrive.\n\nWe have the **Cherry Tree** available.\n\n**Product Name:** Cherry Tree\n\n**Description:** This is a beautiful cherry" " tree that will produce delicious cherries. It's a deciduous tree (meaning it loses its leaves in the fall) growing to about 15 feet tall." " The leaves are dark green in summer, turning a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy.\n\n**Sale Price:** $75.00\n\n**Important Considerations for Growing" " Cherry Trees:**\n\n* **Climate:** Cherry trees prefer a cool, moist climate, and 93230 falls within a suitable range (USDA zones 4-9). However, it's always a good idea to" " check the specific microclimate of your property (sun exposure, drainage etc.).\n* **Soil:** They do best in sandy soil. If your soil is different, you may need to amend it to improve drainage.\n* **Pollination:** Many cherry varieties require a second, compatible cherry tree for proper pollination" ". Check the specific pollination needs of this variety before purchase if you want a significant cherry yield.\n\nThis cherry tree is a beautiful addition to any yard and will provide you with delicious cherries if you can meet its needs. Would you like to know more about its pollination requirements, or perhaps see if we have any other" " fruit trees suitable for your area?\n" ""
10. Tworzenie indeksu najbliższych sąsiadów
Nasz zbiór danych jest dość 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 HNSW
W naszym teście użyjemy indeksu HNSW. HNSW to skrót od hierarchicznej, nawigowalnej małej sieci świata i reprezentuje wielowarstwowy indeks grafu.
Aby utworzyć indeks kolumny z wbudowanymi elementami, musimy zdefiniować tę kolumnę, funkcję odległości i opcjonalnie parametry takie jak m lub ef_constructions. Szczegółowe informacje o parametrach znajdziesz w dokumentacji.
CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
Oczekiwany wynik:
quickstart_db=> CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64); CREATE INDEX quickstart_db=>
Porównaj odpowiedź
Teraz możemy uruchomić zapytanie wektorowe w trybie EXPLAIN i sprawdzić, czy został użyty indeks.
EXPLAIN (analyze)
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
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Oczekiwany wynik:
Aggregate (cost=779.12..779.13 rows=1 width=32) (actual time=1.066..1.069 rows=1 loops=1) -> Subquery Scan on trees (cost=769.05..779.12 rows=1 width=142) (actual time=1.038..1.041 rows=1 loops=1) -> Limit (cost=769.05..779.11 rows=1 width=158) (actual time=1.022..1.024 rows=1 loops=1) -> Nested Loop (cost=769.05..9339.69 rows=852 width=158) (actual time=1.020..1.021 rows=1 loops=1) -> Nested Loop (cost=768.77..9316.48 rows=852 width=945) (actual time=0.858..0.859 rows=1 loops=1) -> Index Scan using cymbal_products_embeddings_hnsw on cymbal_products cp (cost=768.34..2572.47 rows=941 width=941) (actual time=0.532..0.539 rows=3 loops=1) Order By: (embedding <=> '[0.008864171,0.03693164,-0.024245683,... <redacted> ...,0.017593635,-0.040275685,-0.03914233,-0.018452475,0.00826032,-0.07372604 ]'::vector) -> Index Scan using product_inventory_pkey on cymbal_inventory ci (cost=0.42..7.17 rows=1 width=37) (actual time=0.104..0.104 rows=0 loops=3) Index Cond: ((store_id = 1583) AND (uniq_id = (cp.uniq_id)::text)) Filter: (inventory > 0) Rows Removed by Filter: 1 -> Materialize (cost=0.28..8.31 rows=1 width=8) (actual time=0.133..0.134 rows=1 loops=1) -> Index Scan using product_stores_pkey on cymbal_stores cs (cost=0.28..8.30 rows=1 width=8) (actual time=0.129..0.129 rows=1 loops=1) Index Cond: (store_id = 1583) Planning Time: 112.398 ms Execution Time: 1.221 ms
Z wyników widać wyraźnie, że zapytanie korzystało z „Index Scan using cymbal_products_embeddings_hnsw”.
A jeśli uruchomimy zapytanie bez wyjaśnienia:
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
(cp.embedding <=> embedding('text-embedding-004','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;
Oczekiwany wynik:
[{"product_name":"Cherry Tree","description":"This is a beautiful cherry tree that will produce delicious cherries. It is an d","sale_price":75.00,"zip_code":93230,"product_id":"d536e9e823296a2eba198e52dd23e712"}]
Widzimy, że wynik jest taki sam i zwraca tę samą czereśnię, która była na szczycie w naszym wyszukiwaniu bez indeksu. W zależności od parametrów i typu indeksu wynik może się nieznacznie różnić. Podczas testów zapytanie z indeksem zwracało wyniki w 131,301 ms w porównaniu z 167,631 ms bez indeksu, ale mieliśmy do czynienia z bardzo małym zbiorem danych, a różnica byłaby większa w przypadku większych danych.
Możesz wypróbować różne indeksy dostępne dla wektorów oraz skorzystać z większej liczby laboratoriów i przykładów z integracją langchain, które znajdziesz w dokumentacji.
11. Czyszczenie środowiska
Usuwanie instancji Cloud SQL
Po zakończeniu ćwiczenia usuń instancję Cloud SQL
Jeśli połączenie zostało utracone i wszystkie poprzednie ustawienia zostały utracone, 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 PostgreSQL
- 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 podobny case study dotyczący AlloyDB z indeksem ScaNN zamiast HNSW.
13. Ankieta
Dane wyjściowe: