1. Wprowadzenie
Ten przewodnik z ćwiczeniami zawiera instrukcje wdrażania AlloyDB i wykorzystywania integracji AI do wyszukiwania semantycznego za pomocą osadzania wielomodalnego. Ten moduł należy do kolekcji modułów poświęconych funkcjom AI w AlloyDB. Więcej informacji znajdziesz na stronie AlloyDB AI w dokumentacji.
Wymagania wstępne
- Podstawowa wiedza o Google Cloud i konsoli
- Podstawowe umiejętności w zakresie interfejsu wiersza poleceń i Cloud Shell
Czego się nauczysz
- Wdrażanie AlloyDB for Postgres
- Jak korzystać z wielomodalnego wyszukiwania wektorowego
- Włączanie operatorów AI w AlloyDB
- Jak używać różnych operatorów AlloyDB AI do wyszukiwania multimodalnego
- Jak używać AlloyDB AI do łączenia wyników wyszukiwania tekstu i obrazów
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
Samodzielne konfigurowanie środowiska
- Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail lub Google Workspace, musisz je utworzyć.
- Nazwa projektu to wyświetlana nazwa dla uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Zawsze możesz ją zaktualizować.
- Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się tym przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle oznaczanego jako
PROJECT_ID
). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i pozostaje on taki przez cały czas trwania projektu. - Warto wiedzieć, że istnieje trzecia wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
- Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Wykonanie tego laboratorium nie będzie kosztować dużo, a może nawet nic. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
Uruchamianie Cloud Shell
Google Cloud można obsługiwać zdalnie z laptopa, ale w tym module praktycznym będziesz używać 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:
Udostępnienie środowiska i połączenie się z nim może zająć tylko kilka chwil. Po 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 zwiększa wydajność sieci i uwierzytelniania. Wszystkie zadania w tym laboratorium możesz wykonać w przeglądarce. Nie musisz niczego instalować.
3. Zanim zaczniesz
Włącz 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 alloydb.googleapis.com \
compute.googleapis.com \
cloudresourcemanager.googleapis.com \
servicenetworking.googleapis.com \
aiplatform.googleapis.com \
discoveryengine.googleapis.com \
secretmanager.googleapis.com
Oczekiwane dane wyjściowe
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 alloydb.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. Wdrażanie AlloyDB
Utwórz klaster AlloyDB i instancję główną. Poniższa procedura opisuje, jak utworzyć klaster i instancję AlloyDB za pomocą pakietu Google Cloud SDK. Jeśli wolisz korzystać z konsoli, zapoznaj się z dokumentacją tutaj.
Przed utworzeniem klastra AlloyDB potrzebujemy dostępnego zakresu prywatnych adresów IP w naszej sieci VPC, który będzie używany przez przyszłą instancję AlloyDB. Jeśli go nie mamy, musimy go utworzyć i przypisać do użytku przez wewnętrzne usługi Google. Dopiero wtedy będziemy mogli utworzyć klaster i instancję.
Tworzenie prywatnego zakresu adresów IP
Musimy skonfigurować w naszej sieci VPC prywatny dostęp do usług dla AlloyDB. Zakładamy, że w projekcie mamy sieć VPC „default”, która będzie używana do wszystkich działań.
Utwórz zakres prywatnych adresów IP:
gcloud compute addresses create psa-range \
--global \
--purpose=VPC_PEERING \
--prefix-length=24 \
--description="VPC private service access" \
--network=default
Utwórz połączenie prywatne, używając przydzielonego zakresu adresów IP:
gcloud services vpc-peerings connect \
--service=servicenetworking.googleapis.com \
--ranges=psa-range \
--network=default
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-402417)$ gcloud compute addresses create psa-range \ --global \ --purpose=VPC_PEERING \ --prefix-length=24 \ --description="VPC private service access" \ --network=default Created [https://www.googleapis.com/compute/v1/projects/test-project-402417/global/addresses/psa-range]. student@cloudshell:~ (test-project-402417)$ gcloud services vpc-peerings connect \ --service=servicenetworking.googleapis.com \ --ranges=psa-range \ --network=default Operation "operations/pssn.p24-4470404856-595e209f-19b7-4669-8a71-cbd45de8ba66" finished successfully. student@cloudshell:~ (test-project-402417)$
Tworzenie klastra AlloyDB
W tej sekcji utworzymy klaster AlloyDB w regionie us-central1.
Określ hasło użytkownika postgres. Możesz zdefiniować własne hasło lub użyć funkcji losowej, aby je wygenerować.
export PGPASSWORD=`openssl rand -hex 12`
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-402417)$ export PGPASSWORD=`openssl rand -hex 12`
Zapisz hasło do PostgreSQL, aby użyć go w przyszłości.
echo $PGPASSWORD
To hasło będzie Ci potrzebne w przyszłości do połączenia z instancją jako użytkownik postgres. Proponuję zapisać go lub skopiować w inne miejsce, aby móc go później użyć.
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-402417)$ echo $PGPASSWORD bbefbfde7601985b0dee5723
Tworzenie bezpłatnego klastra próbnego
Jeśli nie używasz jeszcze AlloyDB, możesz utworzyć bezpłatny klaster próbny:
Określ region i nazwę klastra AlloyDB. Użyjemy regionu us-central1 i nazwy klastra alloydb-aip-01:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Uruchom polecenie, aby utworzyć klaster:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION \
--subscription-type=TRIAL
Oczekiwane dane wyjściowe konsoli:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION \ --subscription-type=TRIAL Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
Utwórz instancję główną AlloyDB dla klastra w tej samej sesji Cloud Shell. Jeśli połączenie zostanie przerwane, musisz ponownie zdefiniować zmienne środowiskowe regionu i nazwy klastra.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=8 \
--region=$REGION \
--cluster=$ADBCLUSTER
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=8 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
Tworzenie klastra AlloyDB Standard
Jeśli nie jest to Twój pierwszy klaster AlloyDB w projekcie, utwórz klaster standardowy.
Określ region i nazwę klastra AlloyDB. Użyjemy regionu us-central1 i nazwy klastra alloydb-aip-01:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
Uruchom polecenie, aby utworzyć klaster:
gcloud alloydb clusters create $ADBCLUSTER \
--password=$PGPASSWORD \
--network=default \
--region=$REGION
Oczekiwane dane wyjściowe konsoli:
export REGION=us-central1 export ADBCLUSTER=alloydb-aip-01 gcloud alloydb clusters create $ADBCLUSTER \ --password=$PGPASSWORD \ --network=default \ --region=$REGION Operation ID: operation-1697655441138-6080235852277-9e7f04f5-2012fce4 Creating cluster...done.
Utwórz instancję główną AlloyDB dla klastra w tej samej sesji Cloud Shell. Jeśli połączenie zostanie przerwane, musisz ponownie zdefiniować zmienne środowiskowe regionu i nazwy klastra.
gcloud alloydb instances create $ADBCLUSTER-pr \
--instance-type=PRIMARY \
--cpu-count=2 \
--region=$REGION \
--cluster=$ADBCLUSTER
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-402417)$ gcloud alloydb instances create $ADBCLUSTER-pr \ --instance-type=PRIMARY \ --cpu-count=2 \ --region=$REGION \ --availability-type ZONAL \ --cluster=$ADBCLUSTER Operation ID: operation-1697659203545-6080315c6e8ee-391805db-25852721 Creating instance...done.
5. Przygotowywanie bazy danych
Musimy utworzyć bazę danych, włączyć integrację z Vertex AI, utworzyć obiekty bazy danych i zaimportować dane.
Przyznawanie AlloyDB niezbędnych uprawnień
Dodaj uprawnienia Vertex AI do agenta usługi AlloyDB.
Otwórz kolejną kartę Cloud Shell, klikając znak „+” u góry.
Na nowej karcie Cloud Shell wykonaj to polecenie:
PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
--role="roles/aiplatform.user"
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-001-402417)$ PROJECT_ID=$(gcloud config get-value project) Your active configuration is: [cloudshell-11039] student@cloudshell:~ (test-project-001-402417)$ gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \ --role="roles/aiplatform.user" Updated IAM policy for project [test-project-001-402417]. bindings: - members: - serviceAccount:service-4470404856@gcp-sa-alloydb.iam.gserviceaccount.com role: roles/aiplatform.user - members: ... etag: BwYIEbe_Z3U= version: 1
Zamknij kartę, wpisując na niej polecenie „exit”:
exit
Łączenie się z AlloyDB Studio
W kolejnych rozdziałach wszystkie polecenia SQL wymagające połączenia z bazą danych można alternatywnie wykonywać w AlloyDB Studio. Aby uruchomić to polecenie, musisz otworzyć interfejs konsoli internetowej klastra AlloyDB, klikając instancję główną.
Następnie po lewej stronie kliknij AlloyDB Studio:
Wybierz bazę danych postgres, użytkownika postgres i podaj hasło zanotowane podczas tworzenia klastra. Następnie kliknij przycisk „Uwierzytelnij”.
Otworzy się interfejs AlloyDB Studio. Aby uruchomić polecenia w bazie danych, kliknij kartę „Edytor 1” po prawej stronie.
Otworzy się interfejs, w którym możesz uruchamiać polecenia SQL.
Utwórz bazę danych
Krótkie wprowadzenie do tworzenia bazy danych.
W edytorze AlloyDB Studio wykonaj to polecenie.
Utwórz bazę danych:
CREATE DATABASE quickstart_db
Oczekiwane dane wyjściowe:
Statement executed successfully
Połącz się z bazą danych quickstart_db
Połącz się ponownie ze studiem, używając przycisku przełączania użytkownika lub bazy danych.
Na liście wybierz nową bazę danych quickstart_db i użyj tych samych danych logowania co wcześniej.
Otworzy się nowe połączenie, w którym możesz pracować z obiektami z bazy danych quickstart_db.
6. Przykładowe dane
Teraz musimy utworzyć obiekty w bazie danych i wczytać dane. Użyjemy fikcyjnego sklepu „Cymbal” z fikcyjnymi danymi.
Przed zaimportowaniem danych musimy włączyć rozszerzenia obsługujące typy danych i indeksy. Potrzebujemy 2 rozszerzeń: jedno obsługujące typ danych wektorowych, a drugie – indeks AlloyDB ScaNN.
W AlloyDB Studio połączonym z bazą danych quickstart_db wykonaj:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
Zbiór danych jest przygotowywany i umieszczany jako plik SQL, który można wczytać do bazy danych za pomocą interfejsu importu. W Cloud Shell wykonaj te polecenia:
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
gcloud alloydb clusters import $ADBCLUSTER --region=$REGION --database=quickstart_db --gcs-uri='gs://sample-data-and-media/ecomm-retail/ecom_generic_vectors.sql' --user=postgres --sql
Polecenie korzysta z pakietu AlloyDB SDK i tworzy użytkownika o nazwie agentspace_user, a następnie importuje przykładowe dane bezpośrednio z zasobnika GCS do bazy danych, tworząc wszystkie niezbędne obiekty i wstawiając dane.
Po zaimportowaniu możemy sprawdzić tabele w AlloyDB Studio. Tabele znajdują się w schemacie ecomm:
Sprawdź też liczbę wierszy w jednej z tabel.
Przykładowe dane zostały zaimportowane i możemy przejść do kolejnych kroków.
7. Wyszukiwanie semantyczne za pomocą wektorów dystrybucyjnych tekstu
W tym rozdziale spróbujemy użyć wyszukiwania semantycznego za pomocą osadzania tekstu i porównamy je z tradycyjnym wyszukiwaniem tekstowym i pełnotekstowym w Postgres.
Najpierw wypróbujmy klasyczne wyszukiwanie za pomocą standardowego języka SQL PostgreSQL z operatorem LIKE.
Jeśli spróbujemy wyszukać kurtkę przeciwdeszczową za pomocą tego zapytania:
SET session.my_search_var='%wet%conditions%jacket%';
SELECT
name,
product_description,
retail_price, replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM
ecomm.products
WHERE
name ILIKE current_setting('session.my_search_var')
OR product_description ILIKE current_setting('session.my_search_var')
LIMIT
10;
Zapytanie nie zwraca żadnych wierszy, ponieważ wymagałoby dokładnych słów, takich jak „mokre warunki” i „kurtka”, w nazwie lub opisie produktu. „Kurtka na mokre warunki” to nie to samo co „kurtka na deszcz”.
Możemy spróbować uwzględnić w wyszukiwaniu wszystkie możliwe warianty. Spróbujmy użyć tylko dwóch słów. Na przykład:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM
ecomm.products
WHERE
name ILIKE '%wet%jacket%'
OR name ILIKE '%jacket%wet%'
OR name ILIKE '%jacket%'
OR name ILIKE '%%wet%'
OR product_description ILIKE '%wet%jacket%'
OR product_description ILIKE '%jacket%wet%'
OR product_description ILIKE '%jacket%'
OR product_description ILIKE '%wet%'
LIMIT
10;
Zwróci to wiele wierszy, ale nie wszystkie będą idealnie pasować do naszego żądania dotyczącego kurtek, a sortowanie według trafności będzie trudne. Jeśli na przykład dodamy więcej warunków, takich jak „dla mężczyzn”, znacznie zwiększy to złożoność zapytania. Możemy też spróbować wyszukiwania pełnotekstowego, ale nawet w tym przypadku napotykamy ograniczenia związane z mniej lub bardziej dokładnymi słowami i trafnością odpowiedzi.
Teraz możemy przeprowadzić podobne wyszukiwanie za pomocą wektorów dystrybucyjnych. Wstępnie obliczyliśmy już osadzanie dla naszych produktów za pomocą różnych modeli. Użyjemy najnowszego modelu gemini-embedding-001 od Google. Przechowujemy je w kolumnie „product_embedding” w tabeli ecomm.products. Jeśli uruchomimy zapytanie dotyczące warunku wyszukiwania „kurtka przeciwdeszczowa męska” za pomocą tego zapytania:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_embedding <=> embedding ('gemini-embedding-001','wet conditions jacket for men')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
10;
Wyświetli nie tylko kurtki na mokrą pogodę, ale też posortuje wszystkie wyniki, umieszczając na górze te najbardziej trafne.
Zapytanie z wektorami zwraca wyniki w ciągu 90–150 ms, przy czym część tego czasu jest poświęcana na pobieranie danych z modelu wektorów w chmurze. Jeśli przyjrzymy się planowi wykonania, żądanie do modelu jest uwzględnione w czasie planowania. Część zapytania, która wykonuje wyszukiwanie, jest dość krótka. Wyszukiwanie w 29 tys. rekordów za pomocą indeksu ScaNN w AlloyDB trwa mniej niż 7 ms.
Limit (cost=2709.20..2718.82 rows=10 width=490) (actual time=6.966..7.049 rows=10 loops=1)
-> Index Scan using embedding_scann on products (cost=2709.20..30736.40 rows=29120 width=490) (actual time=6.964..7.046 rows=10 loops=1)
Order By: (product_embedding <=> '[-0.0020264734,-0.016582033,0.027258193
...
-0.0051468653,-0.012440448]'::vector)
Limit: 10
Planning Time: 136.579 ms
Execution Time: 6.791 ms
(6 rows)
To było wyszukiwanie wektorów dystrybucyjnych tekstu za pomocą modelu wektorów dystrybucyjnych tekstu. Mamy też zdjęcia naszych produktów, których możemy użyć w wyszukiwaniu. W następnym rozdziale pokażemy, jak model multimodalny wykorzystuje obrazy do wyszukiwania.
8. Korzystanie z wyszukiwania wielomodalnego
Wyszukiwanie semantyczne oparte na tekście jest przydatne, ale opisywanie skomplikowanych szczegółów może być trudne. Wyszukiwanie multimodalne w AlloyDB daje przewagę, ponieważ umożliwia odkrywanie produktów na podstawie obrazu. Jest to szczególnie przydatne, gdy wizualna reprezentacja skuteczniej wyjaśnia intencje wyszukiwania niż same opisy tekstowe. Na przykład „znajdź mi płaszcz podobny do tego na zdjęciu”.
Wróćmy do przykładu z kurtką. Jeśli mam zdjęcie kurtki podobnej do tej, którą chcę znaleźć, mogę przekazać je do multimodalnego modelu osadzania Google i porównać z osadzaniem obrazów moich produktów. W naszej tabeli mamy już obliczone osadzanie obrazów naszych produktów w kolumnie product_image_embedding, a model, który został użyty, możesz zobaczyć w kolumnie product_image_embedding_model.
Do wyszukiwania możemy użyć funkcji image_embedding, aby uzyskać wektor dystrybucyjny obrazu i porównać go z wcześniej obliczonymi wektorami dystrybucyjnymi. Aby włączyć tę funkcję, musimy mieć pewność, że używamy odpowiedniej wersji rozszerzenia google_ml_integration.
Sprawdźmy obecną wersję rozszerzenia. W AlloyDB Studio wykonaj:
SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';
Jeśli wersja jest starsza niż 1.4.4, wykonaj te czynności.
CALL google_ml.upgrade_to_preview_version();
i ponownie sprawdź wersję rozszerzenia. Powinna to być wersja 1.4.4.
Oto przykładowy obraz do wyszukiwania, ale możesz użyć dowolnego obrazu niestandardowego. Wystarczy przesłać go do pamięci Google lub innego publicznie dostępnego zasobu i umieścić identyfikator URI w zapytaniu.
Zostanie on przesłany do gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png.
Wyszukiwanie obrazem
Najpierw spróbujemy wyszukać tylko na podstawie obrazu:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_image_embedding <=> google_ml.image_embedding (model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
W asortymencie znaleźliśmy ciepłe kurtki.
Wyszukiwanie obrazem zwraca elementy podobne do obrazu podanego do porównania. Jak już wspomniałem, możesz spróbować przesłać własne zdjęcia do publicznego zasobnika i sprawdzić, czy znajdzie różne rodzaje ubrań.
Do wyszukiwania obrazów używamy modelu Google „multimodalembedding@001”. Nasza funkcja image_embedding wysyła obraz do Vertex AI, konwertuje go na wektor i zwraca, aby porównać go z przechowywanymi wektorami obrazów w naszej bazie danych.
Możemy też sprawdzić za pomocą polecenia „EXPLAIN ANALYZE”, jak szybko działa on z naszym indeksem AlloyDB ScaNN.
Limit (cost=971.70..975.55 rows=4 width=490) (actual time=2.453..2.477 rows=4 loops=1)
-> Index Scan using product_image_embedding_scann on products (cost=971.70..28998.90 rows=29120 width=490) (actual time=2.451..2.475 rows=4 loops=1)
Order By: (product_image_embedding <=> '[0.02119865,0.034206174,0.030682731,
...
,-0.010307034,-0.010053742]'::vector)
Limit: 4
Planning Time: 913.322 ms
Execution Time: 2.517 ms
(6 rows)
Podobnie jak w poprzednim przykładzie widzimy, że najwięcej czasu zajęło przekształcenie obrazu w wektory dystrybucyjne przy użyciu punktu końcowego w chmurze, a samo wyszukiwanie wektorowe trwało tylko 2,5 ms.
Wyszukiwanie obrazów za pomocą tekstu
W przypadku multimodalnego wyszukiwania możemy też przekazać do modelu opis tekstowy kurtki, której szukamy, za pomocą google_ml.text_embedding dla tego samego modelu i porównać go z wektorami dystrybucyjnymi obrazów, aby sprawdzić, jakie obrazy zostaną zwrócone.
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_image_embedding <=> google_ml.text_embedding (model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
Dostaliśmy zestaw puchowych kurtek w szarych lub ciemnych kolorach.
Otrzymaliśmy nieco inny zestaw kurtek, ale model prawidłowo wybrał kurtki na podstawie naszego opisu i wyszukiwania w osadzonych obrazach.
Spróbujmy innego sposobu wyszukiwania wśród opisów za pomocą reprezentacji właściwościowej obrazu wyszukiwania.
Wyszukiwanie tekstowe za pomocą obrazów
Próbowaliśmy wyszukać obrazy, przekazując osadzanie dla naszego obrazu, i porównać je z wcześniej obliczonymi osadzaniami obrazów dla naszych produktów. Próbowaliśmy też wyszukiwać obrazy, przekazując osadzenie dla naszego żądania tekstowego, i wyszukiwać wśród tego samego osadzenia obrazy produktów. Spróbujmy teraz użyć osadzania w przypadku obrazu i porównać je z osadzaniem tekstu w przypadku opisów produktów. Osadzanie jest przechowywane w kolumnie product_description_embedding i korzysta z tego samego modelu multimodalembedding@001.
Oto nasze zapytanie:
SELECT
name,
product_description,
retail_price,
replace(product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url,
product_description_embedding <=> google_ml.image_embedding (model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector AS distance
FROM
ecomm.products
ORDER BY distance
LIMIT
4;
W tym przypadku otrzymaliśmy nieco inny zestaw kurtek w szarych lub ciemnych kolorach. Niektóre z nich są takie same lub bardzo podobne do tych wybranych w inny sposób.
Zwraca te same kurtki co powyżej, ale w nieco innej kolejności. Na podstawie reprezentacji właściwościowych obrazów może porównać je z obliczonymi reprezentacjami właściwościowymi opisu tekstowego i zwrócić prawidłowy zestaw produktów.
Hybrydowe wyszukiwanie tekstu i obrazów
Możesz też eksperymentować z łączeniem osadzeń tekstu i obrazu, np. za pomocą fuzji odwrotnych rang. Oto przykład takiego zapytania, w którym połączyliśmy 2 wyszukiwania, przypisując każdemu miejscu ocenę i porządkując wyniki na podstawie łącznej oceny.
WITH image_search AS (
SELECT id,
RANK () OVER (ORDER BY product_image_embedding <=>google_ml.image_embedding(model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector) AS rank
FROM ecomm.products
ORDER BY product_image_embedding <=>google_ml.image_embedding(model_id => 'multimodalembedding@001',image => 'gs://pr-public-demo-data/alloydb-retail-demo/user_photos/4.png', mimetype => 'image/png')::vector LIMIT 5
),
text_search AS (
SELECT id,
RANK () OVER (ORDER BY product_description_embedding <=>google_ml.text_embedding(model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour'
)::vector) AS rank
FROM ecomm.products
ORDER BY product_description_embedding <=>google_ml.text_embedding(model_id => 'multimodalembedding@001',content => 'puffy jacket for men, grey or dark colour'
)::vector LIMIT 5
),
rrf_score AS (
SELECT
COALESCE(image_search.id, text_search.id) AS id,
COALESCE(1.0 / (60 + image_search.rank), 0.0) + COALESCE(1.0 / (60 + text_search.rank), 0.0) AS rrf_score
FROM image_search FULL OUTER JOIN text_search ON image_search.id = text_search.id
ORDER BY rrf_score DESC
)
SELECT
ep.name,
ep.product_description,
ep.retail_price,
replace(ep.product_image_uri,'gs://','https://storage.googleapis.com/') AS public_url
FROM ecomm.products ep, rrf_score
WHERE
ep.id=rrf_score.id
ORDER by rrf_score DESC
LIMIT 4;
Możesz spróbować zmienić różne parametry w zapytaniu i sprawdzić, czy poprawi to wyniki wyszukiwania.
To zakończy moduł. Aby uniknąć nieoczekiwanych opłat, zalecamy usunięcie nieużywanych zasobów.
Oprócz tego możesz używać innych operatorów AI do określania kolejności wyników zgodnie z opisem w dokumentacji.
9. Czyszczenie środowiska
Po zakończeniu modułu usuń instancje i klaster AlloyDB
Usuwanie klastra AlloyDB i wszystkich instancji
Klaster zostanie zniszczony z użyciem opcji force, która powoduje też usunięcie wszystkich instancji należących do klastra.
W Cloud Shell zdefiniuj projekt i zmienne środowiskowe, jeśli połączenie zostało przerwane i wszystkie poprzednie ustawienia zostały utracone:
gcloud config set project <your project id>
export REGION=us-central1
export ADBCLUSTER=alloydb-aip-01
export PROJECT_ID=$(gcloud config get-value project)
Usuń klaster:
gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-001-402417)$ gcloud alloydb clusters delete $ADBCLUSTER --region=$REGION --force All of the cluster data will be lost when the cluster is deleted. Do you want to continue (Y/n)? Y Operation ID: operation-1697820178429-6082890a0b570-4a72f7e4-4c5df36f Deleting cluster...done.
Usuwanie kopii zapasowych AlloyDB
Usuń wszystkie kopie zapasowe AlloyDB dla klastra:
for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done
Oczekiwane dane wyjściowe konsoli:
student@cloudshell:~ (test-project-001-402417)$ for i in $(gcloud alloydb backups list --filter="CLUSTER_NAME: projects/$PROJECT_ID/locations/$REGION/clusters/$ADBCLUSTER" --format="value(name)" --sort-by=~createTime) ; do gcloud alloydb backups delete $(basename $i) --region $REGION --quiet; done Operation ID: operation-1697826266108-60829fb7b5258-7f99dc0b-99f3c35f Deleting backup...done.
10. Gratulacje
Gratulujemy ukończenia ćwiczenia. Wiesz już, jak korzystać z wyszukiwania multimodalnego w AlloyDB za pomocą funkcji wektorów dystrybucyjnych dla tekstów i obrazów. Możesz przetestować wyszukiwanie multimodalne i ulepszyć je za pomocą funkcji google_ml.rank, korzystając z ćwiczeń z programowania dotyczących operatorów AI w AlloyDB.
Omówione zagadnienia
- Wdrażanie AlloyDB for Postgres
- Jak korzystać z wielomodalnego wyszukiwania wektorowego
- Włączanie operatorów AI w AlloyDB
- Jak używać różnych operatorów AlloyDB AI do wyszukiwania multimodalnego
- Jak używać AlloyDB AI do łączenia wyników wyszukiwania tekstu i obrazów
11. Ankieta
Dane wyjściowe: