Milion wektorów, zero pętli: generowanie wektorów dystrybucyjnych na dużą skalę za pomocą AlloyDB

1. Przegląd

W tym ćwiczeniu utworzysz skalowalną aplikację do wyszukiwania w bazie wiedzy. Zamiast zarządzać złożonym potokiem ETL ze skryptami i pętlami w Pythonie do generowania wektorów dystrybucyjnych, użyjesz AlloyDB AI do obsługi generowania wektorów dystrybucyjnych natywnie w bazie danych za pomocą jednego polecenia SQL.

d4324260c68d4a70.png

Co utworzysz

Wydajna aplikacja bazy danych z bazą wiedzy, którą można przeszukiwać.

Czego się nauczysz

Zapoznasz się z tymi zagadnieniami:

  • udostępnić klaster AlloyDB i włączyć rozszerzenia AI,
  • wygenerować dane syntetyczne (ponad 50 tys. wierszy) za pomocą SQL,
  • Uzupełnij wektory dystrybucyjne dla całego zbioru danych za pomocą przetwarzania wsadowego.
  • Skonfiguruj aktywatory przyrostowe w czasie rzeczywistym, aby automatycznie umieszczać nowe dane.
  • Wykonaj wyszukiwanie hybrydowe (wektory + filtry SQL) dla „Flexing Context”.

Wymagania

  • Przeglądarka, np. Chrome lub Firefox.
  • projekt Google Cloud z włączonymi płatnościami,
  • Podstawowa znajomość SQL.

2. Zanim zaczniesz

Utwórz projekt

  1. W konsoli Google Cloud na stronie selektora projektów wybierz lub utwórz projekt Google Cloud.
  2. Sprawdź, czy w projekcie Cloud włączone są płatności. Dowiedz się, jak sprawdzić, czy w projekcie są włączone płatności.
  3. Będziesz używać Cloud Shell, czyli środowiska wiersza poleceń działającego w Google Cloud. Kliknij Aktywuj Cloud Shell na górze konsoli Google Cloud.

Obraz przycisku aktywowania Cloud Shell

  1. Po połączeniu z Cloud Shell sprawdź, czy uwierzytelnianie zostało już przeprowadzone, a projekt jest ustawiony na Twój identyfikator projektu. Aby to zrobić, użyj tego polecenia:
gcloud auth list
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project
  1. Jeśli projekt nie jest ustawiony, użyj tego polecenia:
gcloud config set project <YOUR_PROJECT_ID>
  1. Włącz wymagane interfejsy API: kliknij link i włącz interfejsy API.

Możesz też użyć polecenia gcloud. Polecenia gcloud i sposób ich użycia znajdziesz w dokumentacji.

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

Pułapki i rozwiązywanie problemów

Syndrom „projektu widmo”

Uruchomiono polecenie gcloud config set project, ale w interfejsie konsoli wyświetlany jest inny projekt. Sprawdź identyfikator projektu w menu w lewym górnym rogu.

The Billing Barricade

Projekt został włączony, ale nie zostało dodane konto rozliczeniowe. AlloyDB to silnik o wysokiej wydajności, który nie uruchomi się, jeśli „zbiornik paliwa” (płatności) jest pusty.

Opóźnienie propagacji interfejsu API

Kliknięto „Włącz interfejsy API”, ale w wierszu poleceń nadal wyświetla się Service Not Enabled. Odczekaj 60 sekund. Chmura potrzebuje chwili, aby obudzić swoje neurony.

Quota Quags

Jeśli używasz nowego konta próbnego, możesz osiągnąć limit regionalny dla instancji AlloyDB. Jeśli us-central1 nie działa, spróbuj us-east1.

„Ukryty” agent usługi

Czasami agent usługi AlloyDB nie ma automatycznie przypisanej roli aiplatform.user. Jeśli zapytania SQL nie mogą później komunikować się z Gemini, zwykle jest to przyczyną.

3. Konfiguracja bazy danych

W tym module jako bazy danych do przechowywania danych testowych użyjemy AlloyDB. Do przechowywania wszystkich zasobów, takich jak bazy danych i logi, używa klastrów. Każdy klaster ma instancję główną, która zapewnia punkt dostępu do danych. Tabele będą zawierać rzeczywiste dane.

Utwórzmy klaster, instancję i tabelę AlloyDB, do których zostanie wczytany testowy zbiór danych.

  1. Kliknij przycisk lub skopiuj poniższy link do przeglądarki, w której jesteś zalogowany(-a) jako użytkownik konsoli Google Cloud.

  1. Po wykonaniu tego kroku repozytorium zostanie skopiowane do lokalnego edytora Cloud Shell i będzie można uruchomić poniższe polecenie z folderu projektu (ważne jest, aby upewnić się, że znajdujesz się w katalogu projektu):
sh run.sh
  1. Teraz użyj interfejsu (kliknij link w terminalu lub link „Podgląd w internecie” w terminalu).
  2. Aby rozpocząć, wpisz identyfikator projektu oraz nazwy klastra i instancji.
  3. Możesz napić się kawy, podczas gdy logi będą się przewijać. Tutaj możesz przeczytać, jak to działa za kulisami. Może to potrwać około 10–15 minut.

Pułapki i rozwiązywanie problemów

Problem z cierpliwością

Klastry baz danych to ciężka infrastruktura. Jeśli odświeżysz stronę lub zamkniesz sesję Cloud Shell, ponieważ „wygląda na zawieszoną”, możesz otrzymać instancję „widmo”, która jest częściowo udostępniona i nie można jej usunąć bez ręcznej interwencji.

Niezgodność regionu

Jeśli interfejsy API zostały włączone w regionie us-central1, ale próbujesz udostępnić klaster w regionie asia-south1, mogą wystąpić problemy z limitami lub opóźnienia w uprawnieniach konta usługi. Przez cały czas trwania modułu korzystaj z jednego regionu.

Klastry zombie

Jeśli wcześniej użyto tej samej nazwy klastra i nie została ona usunięta, skrypt może wyświetlić komunikat, że nazwa klastra już istnieje. Nazwy klastrów muszą być unikalne w obrębie projektu.

Limit czasu Cloud Shell

Jeśli Twoja przerwa na kawę trwa 30 minut, Cloud Shell może przejść w stan uśpienia i rozłączyć proces sh run.sh. Nie zamykaj karty.

4. Obsługa administracyjna schematu

W tym kroku omówimy te kwestie:

879263c907f3cac6.png

Gdy klaster i instancja AlloyDB będą już działać, przejdź do edytora SQL w AlloyDB Studio, aby włączyć rozszerzenia AI i udostępnić schemat.

1e3ac974b18a8113.png

Być może musisz poczekać na zakończenie tworzenia instancji. Gdy to nastąpi, zaloguj się w AlloyDB za pomocą danych logowania utworzonych podczas tworzenia klastra. Użyj tych danych do uwierzytelnienia w PostgreSQL:

  • Nazwa użytkownika: „postgres”
  • Baza danych: „postgres”
  • Hasło: „alloydb” (lub inne ustawione podczas tworzenia)

Po pomyślnym uwierzytelnieniu w AlloyDB Studio polecenia SQL są wprowadzane w edytorze. Możesz dodać wiele okien edytora, klikając plus po prawej stronie ostatniego okna.

28cb9a8b6aa0789f.png

Polecenia dla AlloyDB wpiszesz w oknach edytora, korzystając w razie potrzeby z opcji Uruchom, Formatuj i Wyczyść.

Włączanie rozszerzeń

Do utworzenia tej aplikacji użyjemy rozszerzeń pgvector i google_ml_integration. Rozszerzenie pgvector umożliwia przechowywanie i wyszukiwanie wektorów dystrybucyjnych. Rozszerzenie google_ml_integration udostępnia funkcje, których możesz używać do uzyskiwania dostępu do punktów końcowych prognoz Vertex AI w celu generowania prognoz w SQL. Włącz te rozszerzenia, uruchamiając te instrukcje DDL:

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;

Tworzenie tabeli

Potrzebujemy zbioru danych, aby zademonstrować skalę. Zamiast importować plik CSV, wygenerujemy natychmiast 50 000 wierszy syntetycznych „artykułów pomocy” za pomocą SQL.

Możesz utworzyć tabelę za pomocą tej instrukcji DDL w AlloyDB Studio:

-- 1. Create the table
CREATE TABLE help_articles (
    id SERIAL PRIMARY KEY,
    title TEXT,
    category TEXT,
    product_version TEXT,
    content_body TEXT,
    embedding vector(768) -- Dimension for text-embedding-005
);

-- 2. Generate 50,000 rows of synthetic data
INSERT INTO help_articles (title, category, product_version, content_body)
SELECT
    'Help Article ' || i,
    CASE 
        WHEN i % 3 = 0 THEN 'Billing' 
        WHEN i % 3 = 1 THEN 'Technical' 
        ELSE 'General' 
    END,
    CASE 
        WHEN i % 2 = 0 THEN '2.0' 
        ELSE '1.0' 
    END,
    'This article covers common issues regarding ' || 
    CASE 
        WHEN i % 3 = 0 THEN 'payment failures, invoice disputes, and credit card updates.'
        WHEN i % 3 = 1 THEN 'connection timeouts, latency issues, and API errors.'
        ELSE 'account profile settings, password resets, and user roles.' 
    END
FROM generate_series(1, 50000) AS i;

Kolumna item_vector umożliwi przechowywanie wartości wektorowych tekstu.

Sprawdź dane:

SELECT count(*) FROM help_articles;
-- Output: 50000

Włącz flagi bazy danych

Otwórz konsolę konfiguracji instancji, kliknij „Edytuj instancję główną”, przejdź do konfiguracji zaawansowanej i kliknij „Dodaj flagi bazy danych”.

  1. Sprawdź, czy flaga google_ml_integration.enable_model_support jest włączona:

Jeśli nie, wpisz ją w menu flag, ustaw na „ON” i zaktualizuj instancję.

  1. Sprawdź, czy flaga google_ml_integration.enable_faster_embedding_generation jest włączona:

Jeśli nie, wpisz ją w menu flag, ustaw na „ON” (WŁ.) i zaktualizuj instancję.

Aby skonfigurować flagi bazy danych:

  1. W konsoli Google Cloud otwórz stronę Klastry.

Otwórz stronę Klastry

  1. Kliknij klaster w kolumnie Nazwa zasobu.
  2. Na stronie Przegląd przejdź do sekcji Instancje w klastrze, wybierz instancję, a następnie kliknij Edytuj.
  3. Dodaj, zmodyfikuj lub usuń flagę bazy danych z instancji:

Dodawanie flagi

  1. Aby dodać flagę bazy danych do instancji, kliknij Dodaj flagę.
  2. Wybierz flagę z listy Nowa flaga bazy danych.
  3. Podaj wartość flagi.
  4. Kliknij Gotowe.
  5. Kliknij Zaktualizuj instancję.
  6. Sprawdź, czy rozszerzenie google_ml_integration jest w wersji 1.5.2 lub nowszej:

Aby sprawdzić wersję rozszerzenia, użyj tego polecenia:

SELECT extversion FROM pg_extension WHERE extname = 'google_ml_integration';

Jeśli chcesz zaktualizować rozszerzenie do wyższej wersji, użyj polecenia:

ALTER EXTENSION google_ml_integration UPDATE;

Przyznaj uprawnienia

  1. Aby umożliwić użytkownikowi zarządzanie automatycznym generowaniem wektorów dystrybucyjnych, przyznaj uprawnienia INSERT, UPDATE i DELETE w tabelach google_ml.embed_gen_progress i google_ml.embed_gen_settings:
GRANT INSERT, UPDATE, DELETE ON google_ml.embed_gen_progress TO postgres;

„postgres” to NAZWA_UŻYTKOWNIKA, któremu przyznano uprawnienia.

  1. Uruchom poniższą instrukcję, aby przyznać uprawnienia do wykonywania funkcji „embedding”:
GRANT EXECUTE ON FUNCTION embedding TO postgres;

Przyznawanie roli użytkownika Vertex AI kontu usługi AlloyDB

W konsoli Google Cloud IAM przyznaj kontu usługi AlloyDB (które wygląda tak: service-<<PROJECT_NUMBER>>@gcp-sa-alloydb.iam.gserviceaccount.com) dostęp do roli „Użytkownik Vertex AI”. PROJECT_NUMBER będzie zawierać numer projektu.

Możesz też uruchomić to polecenie w terminalu Cloud Shell:

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"

Pułapki i rozwiązywanie problemów

Pętla „zapominania hasła”

Jeśli użyto konfiguracji „Jedno kliknięcie” i nie pamiętasz hasła, przejdź na stronę podstawowych informacji o instancji w konsoli i kliknij „Edytuj”, aby zresetować hasło do postgres.

Błąd „Nie znaleziono rozszerzenia”

Jeśli CREATE EXTENSION się nie powiedzie, często jest to spowodowane tym, że instancja nadal znajduje się w stanie „Konserwacja” lub „Aktualizowanie” od czasu początkowego udostępnienia. Sprawdź, czy krok tworzenia instancji został zakończony. W razie potrzeby poczekaj kilka sekund.

5. Generowanie wektorów „na hita”

To jest główna część modułu. Zamiast pisać pętlę w Pythonie,aby przetworzyć te 50 000 wierszy, użyjemy funkcji ai.initialize_embeddings.

To jedno polecenie wykonuje 2 czynności:

  1. Uzupełnia wszystkie istniejące wiersze.
  2. Tworzy aktywator, który automatycznie osadza przyszłe wiersze.

Uruchom poniższą instrukcję SQL w edytorze zapytań AlloyDB.

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional'
);

Weryfikacja wektorów dystrybucyjnych

Sprawdź, czy kolumna embedding jest teraz wypełniona:

SELECT id, left(content_body, 30), substring(embedding::text, 1, 30) as vector_partial 
FROM help_articles;

Powinien pojawić się wynik podobny do tego:

a872b8926a164275.png

Co się właśnie stało?

  1. Uzupełnianie na dużą skalę: automatycznie przeszukuje istniejące 50 000 wierszy i generuje wektory dystrybucyjne za pomocą Vertex AI.
  2. Automatyzacja: po ustawieniu incremental_refresh_mode => 'transactional' AlloyDB automatycznie konfiguruje wewnętrzne aktywatory. Każdy nowy wiersz wstawiony do tabeli help_articles będzie miał natychmiast wygenerowany wektor dystrybucyjny.
  3. Opcjonalnie możesz ustawić incremental_refresh_mode => ‘None', aby uzyskać tylko instrukcję do zbiorczego aktualizowania i ręcznie wywołać ai.refresh_embeddings() w celu zaktualizowania wektorów dystrybucyjnych wszystkich wierszy.

Właśnie zastąpiliśmy kolejkę Kafka, skrypt w Pythonie i skrypt migracji 6 wierszami kodu SQL. Tutaj znajdziesz szczegółową oficjalną dokumentację dotyczącą wszystkich atrybutów.

Test reguły działającej w czasie rzeczywistym

Sprawdźmy, czy automatyzacja „Zero Loop” działa w przypadku nowych danych.

  1. Wstawianie nowego wiersza:
INSERT INTO help_articles (title, category, product_version, content_body)
VALUES ('New Scaling Guide', 'Technical', '2.0', 'How to scale AlloyDB to millions of transactions.');
  1. Sprawdź natychmiast:
SELECT embedding FROM help_articles WHERE title = 'New Scaling Guide';

Wynik:

Wektor powinien zostać wygenerowany natychmiast, bez konieczności uruchamiania zewnętrznego skryptu.

Wielkość wsadu dostrajania

Obecnie AlloyDB domyślnie ustawia rozmiar wsadu na 50. Chociaż ustawienia domyślne działają świetnie, AlloyDB nadal daje użytkownikom możliwość dostosowania konfiguracji do unikalnego modelu i zbioru danych.

CALL ai.initialize_embeddings(
  model_id => 'text-embedding-005',
  table_name => 'help_articles',
  content_column => 'content_body',
  embedding_column => 'embedding',
  incremental_refresh_mode => 'transactional',
  batch_size => 20
);

Użytkownicy muszą jednak pamiętać o limitach, które mogą ograniczać wydajność. Zalecane limity AlloyDB znajdziesz w sekcji „Zanim zaczniesz” w dokumentacji.

Pułapki i rozwiązywanie problemów

Opóźnienie propagacji uprawnień

Uruchomiono polecenie uprawnień gcloud, ale polecenie SQL CALL nadal kończy się błędem uprawnień. Zastosowanie zmian uprawnień w sieci szkieletowej Google może trochę potrwać. Weź oddech.

Niezgodność wymiarów wektora

help_articles Tabela jest ustawiona na VECTOR(768) w kolumnie content_body. Jeśli później spróbujesz użyć innego modelu (np. modelu 1536-wymiarowego), wstawienia nie będą działać. Trzymaj się text-embedding-005.

6. Wyszukiwanie kontekstowe Flexing

Teraz przeprowadzimy wyszukiwanie hybrydowe. Łączymy rozumienie semantyczne (wektor) z logiką biznesową (filtry SQL).

Uruchom to zapytanie, aby znaleźć problemy z płatnościami dotyczące konkretnie wersji 2.0 usługi:

SELECT
  title,
  left(content_body, 100) as content_snippet,
  1 - (embedding <=> embedding('text-embedding-005', 'Invoice did not go through')::vector) as relevance
FROM help_articles
WHERE category = 'Billing'  -- Hard SQL Filter
  AND product_version = '2.0' -- Hard SQL Filter
ORDER BY relevance DESC
LIMIT 5;

To jest kontekst elastyczny. Wyszukiwanie „dostosowuje się”, aby zrozumieć intencję użytkownika („problemy z płatnościami”), jednocześnie przestrzegając rygorystycznych ograniczeń biznesowych (wersja 2.0).

f0fdb50d6195c462.png

Dlaczego to rozwiązanie jest korzystne dla startupów i migracji

  1. Brak długu infrastrukturalnego: nie utworzono oddzielnej wektorowej bazy danych (Pinecone/Milvus). Nie trzeba było pisać osobnego zadania ETL. Wszystko jest w Postgres.
  2. Aktualizacje w czasie rzeczywistym: dzięki trybowi „transakcyjnemu” indeks wyszukiwarki nigdy nie jest nieaktualny. Dane są gotowe do wektoryzacji od momentu ich zatwierdzenia.
  3. Skala: AlloyDB opiera się na infrastrukturze Google. Może on obsłużyć zbiorcze generowanie milionów wektorów szybciej niż skrypt w Pythonie.

Pułapki i rozwiązywanie problemów

Pułapka związana z wydajnością w środowisku produkcyjnym

Problem: szybkie działanie w przypadku 50 000 wierszy. Bardzo wolne w przypadku miliona wierszy, jeśli filtrowanie kategorii nie jest wystarczająco selektywne.Rozwiązanie:Dodaj indeks wektorowy: w przypadku skali produkcyjnej musisz utworzyć indeks:CREATE INDEX ON help_articles USING hnsw (embedding vector_cosine_ops);Sprawdź użycie indeksu: uruchom EXPLAIN ANALYZE SELECT ..., aby upewnić się, że baza danych używa indeksu, a nie wykonuje skanowania sekwencyjnego.

Katastrofa „Niezgodność modelu”

Problem: kolumna została zainicjowana za pomocą modelu text-embedding-005 w procedurze CALL. Jeśli w funkcji zapytania SELECT embedding('model-name', ...) przypadkowo użyjesz innego modelu (np. text-embedding-004 lub modelu OSS), wymiary mogą się zgadzać (768), ale przestrzeń wektorowa będzie zupełnie inna. Zapytanie zostanie wykonane bez błędu, ale wyniki będą zupełnie nieistotne (błędne wyniki trafności). Rozwiązanie problemu:upewnij się, że identyfikator model_id w ai.initialize_embeddings dokładnie odpowiada identyfikatorowi model_id w zapytaniu SELECT.

Wynik „Cicha pustka” (nadmierne filtrowanie)

Problem: wyszukiwanie hybrydowe to operacja „AND”. Wymaga dopasowania semantycznego ORAZ dopasowania SQL.Jeśli użytkownik wyszuka „Pomoc dotycząca płatności”, ale kolumna product_version zawiera ‘2.0.1' zamiast ‘2.0', wynik będzie wynosił 0 wierszy, nawet jeśli dopasowanie wektorowe wynosi 99%.Rozwiązywanie problemów:

  • Najpierw uruchom zapytanie bez sortowania wektorowego, aby sprawdzić, czy filtry SQL (WHERE category...) rzeczywiście zwracają dane.
  • Sprawdź, czy wielkość liter ma znaczenie (Billing i billing).

4. Błędy uprawnień/limitu (błąd 500)

Problem:funkcja embedding() w klauzuli SELECT wykonuje wywołanie sieciowe w czasie rzeczywistym do Vertex AI.Jeśli konto usługi bazy danych utraci rolę Użytkownik Vertex AI lub jeśli osiągniesz limit Vertex AI API (QPM), całe zapytanie SQL zakończy się niepowodzeniem.Rozwiązanie problemu:

  • Sprawdź Cloud Logging pod kątem AlloyDB.
  • Sprawdź, czy rola uprawnień jest nadal aktywna.
  • Jeśli wymagana jest wysoka odporność, umieść funkcję w bloku TRY/CATCH w procedurach składowanych.

5. Puste wektory dystrybucyjne

Problem:jeśli wstawisz dane przed pełną inicjalizacją modelu lub jeśli proces roboczy w tle zakończy się niepowodzeniem, niektóre wiersze mogą zawierać wartość NULL w kolumnie embedding. NULL <=> Vector zwraca wartość NULL. Te wiersze znikną z kolejności sortowania.Rozwiązywanie problemów:

  • Uruchom SELECT count(*) FROM help_articles WHERE embedding IS NULL;, aby sprawdzić, czy pokrycie wynosi 100%.

7. Czyszczenie danych

Po zakończeniu tego modułu nie zapomnij usunąć klastra i instancji AlloyDB.

Powinien on usunąć klaster wraz z instancjami.

8. Gratulacje

Udało Ci się utworzyć skalowalną aplikację do wyszukiwania w bazie wiedzy. Zamiast zarządzać złożonym potokiem ETL ze skryptami i pętlami w Pythonie w celu generowania wektorów dystrybucyjnych, użyto AlloyDB AI do obsługi generowania wektorów dystrybucyjnych natywnie w bazie danych za pomocą jednego polecenia SQL.

Omówione kwestie

  • Zrezygnowaliśmy z pętli for w Pythonie do przetwarzania danych.
  • Wygenerowaliśmy 50 000 wektorów za pomocą jednego polecenia SQL.
  • Zautomatyzowaliśmy generowanie przyszłych wektorów za pomocą aktywatorów.
  • Przeprowadziliśmy wyszukiwanie hybrydowe.

Następne kroki