Erste Schritte mit Vektoreinbettungen in Cloud SQL for PostgreSQL

1. Einführung

In diesem Codelab erfahren Sie, wie Sie die KI-Integration von Cloud SQL for PostgreSQL nutzen, indem Sie die Vektorsuche mit Vertex AI-Einbettungen kombinieren.

8aa6ba3bc12a1593.png

Voraussetzungen

  • Grundkenntnisse in Google Cloud und der Google Cloud Console
  • Grundkenntnisse in der Befehlszeile und Cloud Shell

Lerninhalte

Voraussetzungen

  • Ein Google Cloud-Konto und ein Google Cloud-Projekt
  • Ein Webbrowser wie Chrome, der die Google Cloud Console und Cloud Shell unterstützt

2. Einrichtung und Anforderungen

Projekteinrichtung

  1. Melden Sie sich in der Google Cloud Console an. Wenn Sie noch kein Gmail- oder Google Workspace-Konto haben, müssen Sie eins erstellen.

Verwenden Sie ein privates Konto anstelle eines Arbeitskontos oder eines Kontos einer Bildungseinrichtung.

  1. Erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Klicken Sie zum Erstellen eines neuen Projekts in der Google Cloud Console in der Kopfzeile auf die Schaltfläche „Projekt auswählen“, um ein Pop-up-Fenster zu öffnen.

295004821bab6a87.png

Klicken Sie im Fenster „Projekt auswählen“ auf die Schaltfläche „Neues Projekt“, um ein Dialogfeld für das neue Projekt zu öffnen.

37d264871000675d.png

Geben Sie im Dialogfeld den gewünschten Projektnamen ein und wählen Sie den Speicherort aus.

96d86d3d5655cdbe.png

  • Der Projektname ist der Anzeigename für die Teilnehmer dieses Projekts. Der Projektname wird von Google APIs nicht verwendet und kann jederzeit geändert werden.
  • Die Projekt-ID ist für alle Google Cloud-Projekte eindeutig und unveränderlich. Sie kann also nicht mehr geändert werden, nachdem sie festgelegt wurde. In der Google Cloud Console wird automatisch eine eindeutige ID generiert, die Sie aber anpassen können. Wenn Ihnen die generierte ID nicht gefällt, können Sie eine weitere zufällige ID generieren oder eine eigene ID angeben, um die Verfügbarkeit zu prüfen. In den meisten Codelabs müssen Sie auf Ihre Projekt-ID verweisen, die in der Regel mit dem Platzhalter PROJECT_ID angegeben wird.
  • Zur Information: Es gibt einen dritten Wert, die Projektnummer, die von einigen APIs verwendet wird. Weitere Informationen zu diesen drei Werten

Abrechnung aktivieren

Sie haben zwei Möglichkeiten, die Abrechnung zu aktivieren. Sie können entweder Ihr privates Abrechnungskonto verwenden oder Guthaben mit den folgenden Schritten einlösen.

Google Cloud-Guthaben im Wert von 5 $einlösen (optional)

Für diesen Workshop benötigen Sie ein Rechnungskonto mit Guthaben. Wenn Sie Ihre eigene Abrechnung verwenden möchten, können Sie diesen Schritt überspringen.

  1. Klicken Sie auf diesen Link und melden Sie sich mit einem privaten Google-Konto an.
  2. Die Ansicht sieht ungefähr so aus:

f54628965f465486.png

  1. Klicken Sie auf die Schaltfläche CLICK HERE TO ACCESS YOUR CREDITS (HIER KLICKEN, UM AUF IHR GUTHABEN ZUZUGREIFEN). Sie werden dann auf eine Seite weitergeleitet, auf der Sie Ihr Abrechnungsprofil einrichten können. Wenn ein Bildschirm zur Anmeldung für ein Probeabo angezeigt wird, klicke auf „Abbrechen“ und fahre mit dem Verknüpfen der Abrechnung fort.

20e88842cf2a732e.png

  1. Klicken Sie auf „Bestätigen“. Sie sind jetzt mit einem Google Cloud Platform-Testrechnungskonto verbunden.

cdc87f1c57777951.png

Privates Rechnungskonto einrichten

Wenn Sie die Abrechnung mit Google Cloud-Guthaben einrichten, können Sie diesen Schritt überspringen.

Klicken Sie hier, um die Abrechnung in der Cloud Console zu aktivieren.

Hinweise:

  • Die Kosten für Cloud-Ressourcen für dieses Lab sollten weniger als 3 $betragen.
  • Sie können die Schritte am Ende dieses Labs ausführen, um Ressourcen zu löschen und so weitere Kosten zu vermeiden.
  • Neuen Nutzern steht eine kostenlose Testversion mit einem Guthaben von 300$ zur Verfügung.

Cloud Shell starten

Während Sie Google Cloud von Ihrem Laptop aus per Fernzugriff nutzen können, wird in diesem Codelab Google Cloud Shell verwendet, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.

Klicken Sie in der Google Cloud Console rechts oben in der Symbolleiste auf das Cloud Shell-Symbol:

Cloud Shell aktivieren

Alternativ können Sie auch G und dann S drücken. Mit dieser Sequenz wird Cloud Shell aktiviert, wenn Sie sich in der Google Cloud Console befinden oder diesen Link verwenden.

Die Bereitstellung und Verbindung mit der Umgebung sollte nur wenige Augenblicke dauern. Anschließend sehen Sie in etwa Folgendes:

Screenshot des Google Cloud Shell-Terminals, auf dem zu sehen ist, dass die Umgebung verbunden ist

Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Sie bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und läuft in Google Cloud, was die Netzwerkleistung und Authentifizierung erheblich verbessert. Alle Aufgaben in diesem Codelab können in einem Browser ausgeführt werden. Sie müssen nichts installieren.

3. Hinweis

API aktivieren

Ausgabe:

Wenn Sie Cloud SQL, Compute Engine, Netzwerkdienste und Vertex AI verwenden möchten, müssen Sie die entsprechenden APIs in Ihrem Google Cloud-Projekt aktivieren.

Prüfen Sie im Cloud Shell-Terminal, ob Ihre Projekt-ID eingerichtet ist:

gcloud config set project [YOUR-PROJECT-ID]

Legen Sie die Umgebungsvariable PROJECT_ID fest:

PROJECT_ID=$(gcloud config get-value project)

Aktivieren Sie alle erforderlichen Dienste:

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

Erwartete Ausgabe

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.

Einführung in die APIs

  • Mit der Cloud SQL Admin API (sqladmin.googleapis.com) können Sie Cloud SQL-Instanzen programmatisch erstellen, konfigurieren und verwalten. Sie stellt die Steuerungsebene für den vollständig verwalteten relationalen Datenbankdienst von Google (mit Unterstützung für MySQL, PostgreSQL und SQL Server) bereit und übernimmt Aufgaben wie die Bereitstellung, Sicherung, hohe Verfügbarkeit und Skalierung.
  • Mit der Compute Engine API (compute.googleapis.com) können Sie virtuelle Maschinen (VMs), nichtflüchtige Speicher und Netzwerkeinstellungen erstellen und verwalten. Sie bietet die erforderliche IaaS-Grundlage (Infrastructure-as-a-Service) für die Ausführung Ihrer Arbeitslasten und das Hosting der zugrunde liegenden Infrastruktur für viele verwaltete Dienste.
  • Mit der Cloud Resource Manager API (cloudresourcemanager.googleapis.com) können Sie die Metadaten und Konfiguration Ihres Google Cloud-Projekts programmatisch verwalten. Damit können Sie Ressourcen organisieren, IAM-Richtlinien (Identity and Access Management) verarbeiten und Berechtigungen in der gesamten Projekthierarchie validieren.
  • Mit der Service Networking API (servicenetworking.googleapis.com) können Sie die Einrichtung privater Verbindungen zwischen Ihrem VPC-Netzwerk (Virtual Private Cloud) und den verwalteten Diensten von Google automatisieren. Er ist insbesondere erforderlich, um den Zugriff über private IP-Adressen für Dienste wie AlloyDB einzurichten, damit diese sicher mit Ihren anderen Ressourcen kommunizieren können.
  • Mit der Vertex AI API (aiplatform.googleapis.com) können Sie in Ihren Anwendungen Machine-Learning-Modelle erstellen, bereitstellen und skalieren. Sie bietet die einheitliche Schnittstelle für alle KI-Dienste von Google Cloud, einschließlich des Zugriffs auf generative KI-Modelle (wie Gemini) und des benutzerdefinierten Modelltrainings.

4. Cloud SQL-Instanz erstellen

Cloud SQL-Instanz mit Datenbankeinbindung in Vertex AI erstellen

Datenbankpasswort erstellen

Legen Sie ein Passwort für den Standarddatenbanknutzer fest. Sie können ein eigenes Passwort definieren oder eine Zufallsfunktion verwenden, um eines zu generieren:

export CLOUDSQL_PASSWORD=`openssl rand -hex 12`

Notieren Sie sich den generierten Wert für das Passwort:

echo $CLOUDSQL_PASSWORD

Cloud SQL for PostgreSQL-Instanz erstellen

Cloud SQL-Instanzen können auf verschiedene Arten erstellt werden, z. B. über die Google Cloud Console, Automatisierungstools wie Terraform oder das Google Cloud SDK. In diesem Lab verwenden wir hauptsächlich das gcloud-Tool des Google Cloud SDK. In der Dokumentation erfahren Sie, wie Sie eine Instanz mit anderen Tools erstellen.

Führen Sie in der Cloud Shell-Sitzung Folgendes aus:

gcloud sql instances create my-cloudsql-instance \
--database-version=POSTGRES_17 \
--tier=db-custom-1-3840 \
--region=us-central1 \
--edition=ENTERPRISE \
--enable-google-ml-integration \
--database-flags cloudsql.enable_google_ml_integration=on

Nachdem die Instanz erstellt wurde, müssen wir ein Passwort für den Standardnutzer in der Instanz festlegen und prüfen, ob wir uns mit dem Passwort verbinden können.

gcloud sql users set-password postgres \
    --instance=my-cloudsql-instance \
    --password=$CLOUDSQL_PASSWORD

Führen Sie den Befehl gcloud sql connect wie im Feld angezeigt aus und geben Sie Ihr Passwort ein, wenn Sie dazu aufgefordert werden.

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

Beenden Sie die psql-Sitzung vorerst mit der Tastenkombination Strg + D oder mit dem Befehl „exit“.

exit

Vertex AI-Einbindung aktivieren

Gewähren Sie dem internen Cloud SQL-Dienstkonto die erforderlichen Berechtigungen, damit die Vertex AI-Integration verwendet werden kann.

Rufen Sie die E‑Mail-Adresse des internen Cloud SQL-Dienstkontos ab und exportieren Sie sie als Variable.

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

Gewähren Sie dem Cloud SQL-Dienstkonto Zugriff auf Vertex AI:

PROJECT_ID=$(gcloud config get-value project)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/aiplatform.user"

Weitere Informationen zum Erstellen und Konfigurieren von Instanzen finden Sie in der Cloud SQL-Dokumentation.

5. Datenbank vorbereiten

Als Nächstes müssen wir eine Datenbank erstellen und die Unterstützung von Vektoren aktivieren.

Datenbank erstellen

Erstellen Sie eine Datenbank mit dem Namen quickstart_db. Dazu haben Sie verschiedene Möglichkeiten, z. B. Befehlszeilen-Datenbankclients wie psql für PostgreSQL, SDK oder Cloud SQL Studio. Wir verwenden das SDK (gcloud), um Datenbanken zu erstellen und eine Verbindung zur Instanz herzustellen.

Führen Sie in Cloud Shell den Befehl zum Erstellen der Datenbank aus.

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

Erweiterungen aktivieren

Damit wir mit Vertex AI und Vektoren arbeiten können, müssen wir zwei Erweiterungen in unserer erstellten Datenbank aktivieren.

Führen Sie in Cloud Shell den Befehl zum Herstellen einer Verbindung zur erstellten Datenbank aus (Sie müssen Ihr Passwort angeben).

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Nachdem die Verbindung hergestellt wurde, müssen Sie in der SQL-Sitzung zwei Befehle ausführen:

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

SQL-Sitzung beenden:

exit;

6. Daten laden

Jetzt müssen wir Objekte in der Datenbank erstellen und Daten laden. Wir verwenden fiktive Daten des Cymbal Store. Die Daten sind im öffentlichen Google Storage-Bucket im CSV-Format verfügbar.

Zuerst müssen wir alle erforderlichen Objekte in unserer Datenbank erstellen. Dazu verwenden wir die bereits bekannten Befehle gcloud sql connect und gcloud storage, um die Schemaobjekte herunterzuladen und in unsere Datenbank zu importieren.

Führen Sie in der Cloud Shell den folgenden Befehl aus und geben Sie das Passwort an, das beim Erstellen der Instanz notiert wurde:

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

Was haben wir im vorherigen Befehl genau gemacht? Wir haben eine Verbindung zu unserer Datenbank hergestellt und den heruntergeladenen SQL-Code ausgeführt, wodurch Tabellen, Indexe und Sequenzen erstellt wurden.

Als Nächstes müssen wir die Daten laden. Dazu müssen wir die CSV-Dateien aus Google Cloud Storage herunterladen.

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 .

Als Nächstes müssen wir eine Verbindung zur Datenbank herstellen.

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Außerdem können Sie Daten aus unseren CSV-Dateien importieren.

\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

Wenn Sie eigene Daten haben und Ihre CSV-Dateien mit dem Cloud SQL-Importtool kompatibel sind, das in der Cloud Console verfügbar ist, können Sie dieses anstelle des Befehlszeilenansatzes verwenden.

7. Einbettungen erstellen

Im nächsten Schritt erstellen wir Einbettungen für unsere Produktbeschreibungen mit dem Modell „textembedding-004“ von Google Vertex AI und speichern sie als Vektordaten.

Stellen Sie eine Verbindung zur Datenbank her, wenn Sie die Verbindung getrennt haben oder Ihre vorherige Sitzung getrennt wurde:

gcloud sql connect my-cloudsql-instance --database quickstart_db --user=postgres

Außerdem erstellen wir mit der Einbettungsfunktion eine virtuelle Spalte embedding in der Tabelle „cymbal_products“. Mit dem Befehl wird die virtuelle Spalte embedding erstellt, in der unsere Vektoren mit Einbettungen gespeichert werden, die auf Grundlage der Spalte product_description generiert wurden. Außerdem werden Einbettungen für alle vorhandenen Zeilen in der Tabelle erstellt. Das Modell wird als erster Parameter für die Einbettungsfunktion und die Quelldaten als zweiter Parameter definiert.

ALTER TABLE cymbal_products ADD COLUMN embedding vector(768) GENERATED ALWAYS AS (embedding('text-embedding-005',product_description)) STORED;

Das kann etwas dauern, sollte aber bei 900 bis 1.000 Zeilen nicht länger als 5 Minuten dauern. Normalerweise geht es viel schneller.

Wenn wir eine neue Zeile in die Tabelle einfügen oder die product_description für eine vorhandene Zeile aktualisieren, werden die Daten der virtuellen Spalte für die Spalte embedding anhand der product_description neu generiert.

8. Ähnlichkeitssuche ausführen

Wir können jetzt unsere Suche mit der Ähnlichkeitssuche basierend auf Vektorwerten ausführen, die für die Beschreibungen und den Vektorwert berechnet wurden, den wir für unsere Anfrage erhalten.

Die SQL-Abfrage kann über dieselbe Befehlszeilenschnittstelle mit gcloud sql connect oder alternativ über Cloud SQL Studio ausgeführt werden. Alle mehrzeiligen und komplexen Abfragen lassen sich besser in Cloud SQL Studio verwalten.

Cloud SQL Studio starten

Klicken Sie in der Konsole auf die Cloud SQL-Instanz, die wir zuvor erstellt haben.

903eeb9bbaf4a419.png

Wenn es im rechten Bereich geöffnet ist, sehen wir Cloud SQL Studio. Klicke darauf.

7874a11b28519b71.png

Daraufhin wird ein Dialogfeld geöffnet, in dem Sie den Datenbanknamen und Ihre Anmeldedaten eingeben können:

  • Datenbank: quickstart_db
  • Nutzer: postgres
  • Passwort: Das von Ihnen notierte Passwort für den Hauptdatenbanknutzer

Klicken Sie auf die Schaltfläche „AUTHENTICATE“ (AUTHENTIFIZIEREN).

d5ee9e56dfef3905.png

Dadurch wird das nächste Fenster geöffnet. Klicken Sie dort rechts auf den Tab „Editor“, um den SQL-Editor zu öffnen.

19a6ebd18ef6ae34.png

Jetzt können wir unsere Abfragen ausführen.

Abfrage ausführen

Führen Sie eine Anfrage aus, um eine Liste der verfügbaren Produkte zu erhalten, die der Anfrage eines Kunden am ehesten entsprechen. Die Anfrage, die wir an Vertex AI übergeben, um den Vektorwert zu erhalten, lautet: „Welche Obstbäume wachsen hier gut?“

Mit dieser Abfrage können Sie die ersten zehn Elemente auswählen, die am besten für unsere Anfrage geeignet sind:

SELECT
        cp.product_name,
        left(cp.product_description,80) as description,
        cp.sale_price,
        cs.zip_code,
        (cp.embedding <=> embedding('text-embedding-005','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;

Kopieren Sie die Abfrage und fügen Sie sie in den Cloud SQL Studio-Editor ein. Klicken Sie dann auf „AUSFÜHREN“ oder fügen Sie sie in Ihre Befehlszeilensitzung ein, in der Sie eine Verbindung zur Datenbank „quickstart_db“ herstellen.

a8a2f83593aa5f37.png

Hier ist eine Liste der Produkte, die der Anfrage entsprechen.

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. LLM-Antwort mit abgerufenen Daten verbessern

Wir können die GenAI-LLM-Antwort auf eine Clientanwendung mithilfe des Ergebnisses der ausgeführten Anfrage verbessern und eine aussagekräftige Ausgabe vorbereiten, indem wir die bereitgestellten Anfrageergebnisse als Teil des Prompts für ein generatives Fundierungs-Sprachmodell von Vertex AI verwenden.

Dazu müssen wir eine JSON-Datei mit unseren Ergebnissen aus der Vektorsuche generieren und diese generierte JSON-Datei dann als Ergänzung zu einem Prompt für ein LLM-Modell in Vertex AI verwenden, um eine aussagekräftige Ausgabe zu erstellen. Im ersten Schritt generieren wir das JSON, dann testen wir es in Vertex AI Studio und im letzten Schritt binden wir es in eine SQL-Anweisung ein, die in einer Anwendung verwendet werden kann.

Ausgabe im JSON-Format generieren

Ändern Sie die Abfrage so, dass die Ausgabe im JSON-Format generiert wird und nur eine Zeile zurückgegeben wird, die an Vertex AI übergeben werden kann.

Cloud SQL for PostgreSQL

Hier ein Beispiel für die Abfrage:

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-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Und hier ist das erwartete JSON in der Ausgabe:

[{"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"}]

Prompt in Vertex AI Studio ausführen

Wir können das generierte JSON verwenden, um es als Teil des Prompts für das generative KI-Textmodell in Vertex AI Studio bereitzustellen.

Öffnen Sie Vertex AI Studio in der Cloud Console.

d48549b1b0f449b4.png

Möglicherweise werden Sie aufgefordert, zusätzliche APIs zu aktivieren. Sie können die Anfrage jedoch ignorieren. Wir benötigen keine zusätzlichen APIs, um das Lab abzuschließen.

Geben Sie einen Prompt in Studio ein.

2a6f5a338fefd229.png

Das ist der Prompt, den wir verwenden werden:

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.

So sieht es aus, wenn wir den JSON-Platzhalter durch die Antwort auf die Anfrage ersetzen:

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.

Und hier ist das Ergebnis, wenn wir den Prompt mit unseren JSON-Werten ausführen:

a0f7ead40d0a1d62.png

Die Antwort, die wir in diesem Beispiel vom Modell erhalten haben, folgt. Ihre Antwort kann sich im Laufe der Zeit aufgrund von Änderungen an Modellen und Parametern unterscheiden:

„Anhand der in unserer Produktliste angegebenen Postleitzahl (93230) scheint es, dass Sie sich in der Gegend von Hanford, Kalifornien, befinden.1346 Diese Region im San Joaquin Valley ist tatsächlich einer der besten Orte im Land für den Anbau von Steinobst.

Die beste Baumart aus unserem Sortiment für Ihre Region ist der Kirschbaum.

Hier sind die Details für Sie:

Produkt: Kirschbaum

Preis: 75,00 $

Beschreibung: Das ist ein wunderschöner Kirschbaum, der köstliche Kirschen hervorbringen wird.2

Warum wächst er hier am besten? Das Klima im San Joaquin Valley bietet die spezifischen Bedingungen, die Kirschen zum Gedeihen benötigen: lange, warme Sommertage für die Fruchtentwicklung und kühle Nächte.5 Da Hanford in einem wichtigen landwirtschaftlichen Zentrum liegt, das für seine Steinobstproduktion bekannt ist, können Sie davon ausgehen, dass dieser Baum in Ihrem lokalen Boden sehr produktiv sein wird. Achten Sie darauf, dass Sie sie an einem sonnigen Ort mit gut durchlässigem Boden pflanzen, um die beste Ernte zu erzielen.“

Prompt in PSQL ausführen

Wir können die Cloud SQL AI-Integration mit Vertex AI auch verwenden, um mit SQL direkt in der Datenbank eine ähnliche Antwort von einem generativen Modell zu erhalten. Um das Modell „gemini-2.0-flash-exp“ verwenden zu können, müssen wir es jedoch zuerst registrieren.

In Cloud SQL for PostgreSQL ausführen

Führen Sie ein Upgrade der Erweiterung auf Version 1.4.2 oder höher durch, falls die aktuelle Version niedriger ist. Stellen Sie über gcloud sql connect eine Verbindung zur Datenbank „quickstart_db“ her (oder verwenden Sie Cloud SQL Studio) und führen Sie Folgendes aus:

SELECT extversion from pg_extension where extname='google_ml_integration';

Wenn der zurückgegebene Wert kleiner als 1.4.3 ist, führen Sie Folgendes aus:

ALTER EXTENSION google_ml_integration UPDATE TO '1.4.3';

Anschließend müssen wir das Datenbank-Flag „google_ml_integration.enable_model_support“ auf „on“ setzen. So prüfen Sie die aktuellen Einstellungen:

show google_ml_integration.enable_model_support;

Die erwartete Ausgabe der psql-Sitzung ist „on“:

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Wenn „Aus“ angezeigt wird, müssen wir das Datenbank-Flag aktualisieren. Dazu können Sie die Webkonsolenoberfläche verwenden oder den folgenden gcloud-Befehl ausführen.

gcloud sql instances patch my-cloudsql-instance \
--database-flags google_ml_integration.enable_model_support=on,cloudsql.enable_google_ml_integration=on

Die Ausführung des Befehls im Hintergrund dauert etwa 1 bis 3 Minuten. Anschließend können Sie das neue Flag in der psql-Sitzung oder mit Cloud SQL Studio überprüfen, indem Sie eine Verbindung zur Datenbank „quickstart_db“ herstellen.

show google_ml_integration.enable_model_support;

Die erwartete Ausgabe der psql-Sitzung ist „on“:

quickstart_db => show google_ml_integration.enable_model_support;
 google_ml_integration.enable_model_support 
--------------------------------------------
 on
(1 row)

Dann müssen wir zwei Modelle registrieren. Das erste ist das bereits verwendete Modell text-embedding-005. Es muss registriert werden, da wir die Funktionen zur Modellregistrierung aktiviert haben.

Um den Modelllauf in psql oder Cloud SQL Studio zu registrieren, führen Sie den folgenden Code aus:

CALL
  google_ml.create_model(
    model_id => 'text-embedding-005',
    model_provider => 'google',
    model_qualified_name => 'text-embedding-005',
    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');

Das nächste Modell, das wir registrieren müssen, ist gemini-2.0-flash-001. Es wird verwendet, um die benutzerfreundliche Ausgabe zu generieren.

CALL
  google_ml.create_model(
    model_id => 'gemini-2.5-flash',
    model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-2.5-flash:streamGenerateContent',
    model_provider => 'google',
    model_auth_type => 'cloudsql_service_agent_iam');

Sie können die Liste der registrierten Modelle jederzeit überprüfen, indem Sie Informationen aus google_ml.model_info_view auswählen.

select model_id,model_type from google_ml.model_info_view;

Hier ein Beispiel für eine Ausgabe:

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-005                   | text_embedding
 gemini-2.5-flash                     | generic

Jetzt können wir das generierte JSON in einer Unterabfrage verwenden, um es als Teil des Prompts für das generative KI-Textmodell mit SQL bereitzustellen.

Führen Sie die Abfrage in der psql- oder Cloud SQL Studio-Sitzung für die Datenbank aus.

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-005',
        '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.5-flash',
        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;

Hier sehen Sie die erwartete Ausgabe. Ihre Ausgabe kann je nach Modellversion und Parametern unterschiedlich ausfallen:

"That's a great question! It sounds like you're looking to add some delicious fruit to your garden.\n\nBased on the products we have that are closely related to your search, I can tell you about a fantastic option:\n\n**Cherry Tree**" "\n* **Description:** This beautiful deciduous tree will produce delicious cherries. It grows to be about 15 feet tall, with dark green leaves in summer that turn a beautiful red in the fall. Cherry trees are known for their beauty, shade, and privacy. They prefer a cool, moist climate and sandy soil." "\n* **Price:** $75.00\n* **Grows well in:** USDA Zones 4-9.\n\nTo confirm if this Cherry Tree will thrive in your specific location, you might want to check which USDA Hardiness Zone your area falls into. If you're in zones 4-9, this" " could be a wonderful addition to your yard!"

10. Index für die nächsten Nachbarn erstellen

Unser Dataset ist recht klein und die Reaktionszeit hängt hauptsächlich von Interaktionen mit KI-Modellen ab. Wenn Sie jedoch Millionen von Vektoren haben, kann die Vektorsuche einen erheblichen Teil unserer Reaktionszeit in Anspruch nehmen und das System stark belasten. Um das zu verbessern, können wir einen Index für unsere Vektoren erstellen.

HNSW-Index erstellen

Wir werden den HNSW-Indextyp für unseren Test verwenden. HNSW steht für Hierarchical Navigable Small World und stellt einen mehrschichtigen Diagrammindex dar.

Um den Index für unsere Einbettungsspalte zu erstellen, müssen wir die Einbettungsspalte, die Distanzfunktion und optional Parameter wie „m“ oder „ef_constructions“ definieren. Eine detaillierte Beschreibung der Parameter finden Sie in der Dokumentation.

CREATE INDEX cymbal_products_embeddings_hnsw ON cymbal_products
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

Erwartete Ausgabe:

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=>

Antwort vergleichen

Jetzt können wir die Vektorsuchanfrage im EXPLAIN-Modus ausführen und prüfen, ob der Index verwendet wurde.

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-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Erwartete Ausgabe:

 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

Aus der Ausgabe geht deutlich hervor, dass für die Abfrage „Index Scan using cymbal_products_embeddings_hnsw“ verwendet wurde.

Wenn wir die Abfrage ohne „EXPLAIN“ ausführen:

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-005','What kind of fruit trees grow well here?')::vector) ASC
LIMIT 1)
SELECT json_agg(trees) FROM trees;

Erwartete Ausgabe (die Ausgabe kann je nach Modell und Index variieren):

[{"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"}]

Wir sehen, dass das Ergebnis dasselbe ist und derselbe Kirschbaum zurückgegeben wird, der in unserer Suche ohne Index oben stand. Je nach Parametern und Indextyp kann das Ergebnis leicht abweichen und ein anderer oberster Datensatz für den Baum zurückgegeben werden. Bei meinen Tests wurden bei der indexierten Abfrage Ergebnisse in 131,301 ms zurückgegeben, bei der Abfrage ohne Index in 167,631 ms. Wir haben jedoch mit einem sehr kleinen Dataset gearbeitet und der Unterschied wäre bei größeren Datenmengen erheblicher.

Sie können verschiedene für die Vektoren verfügbare Indexe ausprobieren. Weitere Labs und Beispiele mit Langchain-Integration finden Sie in der Dokumentation.

11. Umgebung bereinigen

Cloud SQL-Instanz löschen

Cloud SQL-Instanz löschen, wenn Sie das Lab abgeschlossen haben

Definieren Sie in Cloud Shell die Projekt- und Umgebungsvariablen, wenn die Verbindung getrennt wurde und alle vorherigen Einstellungen verloren gegangen sind:

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

Löschen Sie die Instanz:

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

Erwartete Konsolenausgabe:

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. Glückwunsch

Herzlichen Glückwunsch zum Abschluss des Codelabs.

Dieses Lab ist Teil des Lernpfads „Produktionsreife KI mit Google Cloud“.

Behandelte Themen

Ähnliches Codelab für AlloyDB mit ScaNN-Index anstelle von HNSW ausprobieren

13. Umfrage

Ausgabe:

Wie werden Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen durchführen