1. Übersicht
Stellen Sie sich vor, Sie betreten virtuell oder persönlich einen Spielzeugladen, in dem Sie ganz einfach das perfekte Geschenk finden. Sie können beschreiben, wonach Sie suchen, ein Bild eines Spielzeugs hochladen oder sogar Ihre eigene Kreation entwerfen. Der Shop versteht sofort Ihre Anforderungen und bietet Ihnen eine individuelle Auswahl. Das ist keine futuristische Fantasie, sondern eine Realität, die auf KI, Cloud-Technologie und einer Vision für personalisierten E-Commerce basiert.
Die Herausforderung:Es kann schwierig sein, das perfekte Produkt zu finden, das Ihrer Vorstellung entspricht. Generische Suchbegriffe, Keywords und unscharfe Suchanfragen reichen oft nicht aus, das Durchsuchen endloser Seiten kann mühsam sein und die Diskrepanz zwischen dem, was Sie sich vorstellen, und dem, was verfügbar ist, kann zu Frustration führen.
Die Lösung:Die Demoanwendung geht diese Herausforderung direkt an und nutzt die Vorteile von KI, um eine wirklich personalisierte und nahtlose Nutzung mit kontextbezogener Suche und benutzerdefinierter Generierung des Produkts zu ermöglichen, das zum Suchkontext passt.
Aufgaben
In diesem Lab lernen Sie Folgendes:
- AlloyDB-Instanz erstellen und Spielzeugdatensatz laden
- pgvector- und generative KI-Modell-Erweiterungen in AlloyDB aktivieren
- Einbettungen aus der Produktbeschreibung generieren und eine Echtzeit-Kosinussimilarity-Suche für den Suchtext des Nutzers durchführen
- Gemini 2.0 Flash aufrufen, um das vom Nutzer hochgeladene Bild für die kontextbezogene Suche nach Spielzeug zu beschreiben
- Aufruf von Imagen 3, um ein Spielzeug basierend auf den Interessen der Nutzer individuell zu erstellen
- Preisdetails des benutzerdefinierten Spielzeugs mit einem Preisvorhersagetool abrufen, das mit der Gen AI Toolbox for Databases erstellt wurde
- Lösung in serverlosen Cloud Run Functions bereitstellen
Voraussetzungen
2. Architektur
Datenfluss: Sehen wir uns genauer an, wie Daten durch unser System fließen:
- Kontextbezogene Suche mit KI-gestützter RAG (Retrieval Augmented Generation)
Stellen Sie sich Folgendes vor: Anstatt nur nach „rotes Auto“ zu suchen, versteht das System Folgendes:
„Kleines Fahrzeug für einen 3-jährigen Jungen geeignet.“
AlloyDB als Grundlage:Wir verwenden AlloyDB, die vollständig verwaltete, PostgreSQL-kompatible Datenbank von Google Cloud, um unsere Spielzeugdaten zu speichern, einschließlich Beschreibungen, Bild-URLs und anderer relevanter Attribute.
pgvector für die semantische Suche:Mit pgvector, einer PostgreSQL-Erweiterung, können wir Vektoreinbettungen sowohl von Spielzeugbeschreibungen als auch von Suchanfragen von Nutzern speichern. Dies ermöglicht eine semantische Suche, d. h. das System versteht die Bedeutung der Wörter, nicht nur die genauen Keywords.
Kosinusähnlichkeit für die Relevanz:Mit der Kosinusähnlichkeit wird die semantische Ähnlichkeit zwischen dem Suchvektor des Nutzers und den Vektoren der Spielzeugbeschreibung gemessen, um die relevantesten Ergebnisse zu präsentieren.
ScaNN-Index für Geschwindigkeit und Genauigkeit:Um schnelle und präzise Ergebnisse zu erzielen, insbesondere wenn unser Spielzeuginventar wächst, integrieren wir den ScaNN-Index (Scalable Nearest Neighbors). Dadurch werden Effizienz und Trefferquote unserer Vektorsuche deutlich verbessert.
- Bildbasierte Suche und Bildverständnis mit Gemini 2.0 Flash
Angenommen, der Nutzer möchte anstelle des Kontexts als Text ein Bild eines bekannten Spielzeugs hochladen, mit dem er suchen möchte. Nutzer können ein Bild eines Spielzeugs hochladen, das ihnen gefällt, und erhalten so relevante Funktionen. Wir nutzen das Gemini 2.0-Flash-Modell von Google, das mit LangChain4j aufgerufen wird, um das Bild zu analysieren und relevanten Kontext zu extrahieren, z. B. Farbe, Material, Typ und Zielgruppe des Spielzeugs.
- Mit generativer KI das Traumspielzeug erstellen: Imagen 3
Das Beste kommt aber erst, wenn Nutzer ihr eigenes Spielzeug erstellen. Mit Imagen 3 können sie ihr Traumspielzeug mithilfe einfacher Textprompts beschreiben. Stellen Sie sich vor, Sie könnten sagen: „Ich möchte einen Plüschdrachen mit lila Flügeln und einem freundlichen Gesicht“ und dieser Drache würde auf Ihrem Bildschirm zum Leben erwachen. Imagen 3 generiert dann ein Bild des benutzerdefinierten Spielzeugs, das dem Nutzer eine klare Visualisierung seiner Kreation bietet.
- Preisvorhersage mithilfe von KI-Bots und der Gen AI Toolbox für Datenbanken
Wir haben eine Preisvorhersagefunktion implementiert, mit der die Kosten für die Herstellung des individuell gestalteten Spielzeugs geschätzt werden. Das Tool basiert auf einem Agenten mit einem ausgefeilten Preisberechnungstool.
Gen AI Toolbox for Databases:Dieser Agent ist über das neue Open-Source-Tool von Google, Gen AI Toolbox for Databases, nahtlos in unsere Datenbank eingebunden. So kann der Kundenservicemitarbeiter auf Echtzeitdaten zu Materialkosten, Herstellungsprozessen und anderen relevanten Faktoren zugreifen, um eine genaue Preisschätzung abzugeben. Weitere Informationen
- Java Spring Boot, Gemini Code Assist und Cloud Run für eine optimierte Entwicklung und serverlose Bereitstellung
Die gesamte Anwendung wurde mit Java Spring Boot erstellt, einem robusten und skalierbaren Framework. Wir haben Gemini Code Assist während des gesamten Entwicklungszyklus eingesetzt, insbesondere für die Front-End-Entwicklung, wodurch der Entwicklungszyklus erheblich beschleunigt und die Codequalität verbessert wurde. Wir haben Cloud Run für die Bereitstellung der gesamten Anwendung und Cloud Run Functions für die Bereitstellung der Datenbank- und Agentenfunktionen als unabhängige Endpunkte verwendet.
3. Hinweis
Projekt erstellen
- Wählen Sie in der Google Cloud Console auf der Seite der Projektauswahl ein Google Cloud-Projekt aus oder erstellen Sie eines.
- Die Abrechnung für das Cloud-Projekt muss aktiviert sein. So prüfen Sie, ob die Abrechnung für ein Projekt aktiviert ist.
- Sie verwenden Cloud Shell, eine Befehlszeilenumgebung, die in Google Cloud ausgeführt wird und bq bereits vorinstalliert hat. Klicken Sie oben in der Google Cloud Console auf „Cloud Shell aktivieren“.
- Nachdem Sie eine Verbindung zu Cloud Shell hergestellt haben, prüfen Sie mit dem folgenden Befehl, ob Sie bereits authentifiziert sind und das Projekt auf Ihre Projekt-ID festgelegt ist:
gcloud auth list
- Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob der gcloud-Befehl Ihr Projekt kennt.
gcloud config list project
- Wenn Ihr Projekt nicht festgelegt ist, verwenden Sie den folgenden Befehl, um es festzulegen:
gcloud config set project <YOUR_PROJECT_ID>
- Aktivieren Sie die erforderlichen APIs, indem Sie die folgenden Befehle nacheinander in Ihrem Cloud Shell-Terminal ausführen:
Es gibt auch einen einzelnen Befehl, um die folgenden Schritte auszuführen. Wenn Sie jedoch ein Testkonto verwenden, kann es zu Kontingentproblemen kommen, wenn Sie diese Funktionen im Bulk-Verfahren aktivieren. Deshalb werden die Befehle einzeln pro Zeile eingegeben.
gcloud services enable alloydb.googleapis.com
gcloud services enable compute.googleapis.com
gcloud services enable cloudresourcemanager.googleapis.com
gcloud services enable servicenetworking.googleapis.com
gcloud services enable run.googleapis.com
gcloud services enable cloudbuild.googleapis.com
gcloud services enable cloudfunctions.googleapis.com
gcloud services enable aiplatform.googleapis.com
Alternativ können Sie in der Console nach den einzelnen Produkten suchen oder diesen Link verwenden.
Wenn eine API fehlt, können Sie sie jederzeit während der Implementierung aktivieren.
Weitere Informationen zu gcloud-Befehlen und deren Verwendung finden Sie in der Dokumentation.
4. Datenbank einrichten
In diesem Lab verwenden wir AlloyDB als Datenbank für die Daten des Spielzeuggeschäfts. Alle Ressourcen wie Datenbanken und Protokolle werden in Clustern gespeichert. Jeder Cluster hat eine primäre Instanz, die einen Zugriffspunkt auf die Daten bietet. Die tatsächlichen Daten werden in Tabellen gespeichert.
Erstellen wir einen AlloyDB-Cluster, eine Instanz und eine Tabelle, in die das E-Commerce-Dataset geladen wird.
Cluster und Instanz erstellen
- Rufen Sie in der Cloud Console die Seite „AlloyDB“ auf. Die meisten Seiten in der Cloud Console lassen sich ganz einfach über die Suchleiste der Console finden.
- Wählen Sie auf dieser Seite CLUSTER ERSTELLEN aus:
- Daraufhin wird ein Bildschirm wie der unten gezeigte angezeigt. Erstellen Sie einen Cluster und eine Instanz mit den folgenden Werten. Achten Sie darauf, dass die Werte übereinstimmen, falls Sie den Anwendungscode aus dem Repository klonen:
- Cluster-ID: „
vector-cluster
“ - password: "
alloydb
" - Mit PostgreSQL 15 kompatibel
- Region: „
us-central1
“ - Netzwerk: „
default
“
- Wenn Sie das Standardnetzwerk auswählen, wird ein Bildschirm wie der unten angezeigt.
Wählen Sie VERKNÜPFUNG EINRICHTEN aus.
- Wählen Sie dort Automatisch zugewiesenen IP-Bereich verwenden aus und klicken Sie auf „Weiter“. Nachdem Sie sich die Informationen angesehen haben, wählen Sie VERBINDUNG ERSTELLEN aus.
- Sobald Ihr Netzwerk eingerichtet ist, können Sie mit dem Erstellen des Clusters fortfahren. Klicken Sie auf CLUSTER ERSTEHEN, um die Einrichtung des Clusters abzuschließen (siehe unten):
Ändern Sie die Instanz-ID in „
vector-instance"
.
Die Clustererstellung dauert etwa 10 Minuten. Wenn der Vorgang erfolgreich war, sollte ein Bildschirm mit einer Übersicht über den gerade erstellten Cluster angezeigt werden.
5. Datenaufnahme
Jetzt fügen Sie eine Tabelle mit den Daten zum Geschäft hinzu. Rufen Sie AlloyDB auf, wählen Sie den primären Cluster und dann AlloyDB Studio aus:
Möglicherweise müssen Sie warten, bis die Instanz erstellt wurde. Melden Sie sich dann mit den Anmeldedaten an, die Sie beim Erstellen des Clusters erstellt haben. Verwenden Sie die folgenden Daten für die Authentifizierung bei PostgreSQL:
- Nutzername: „
postgres
“ - Datenbank: „
postgres
“ - Passwort: „
alloydb
“
Nachdem Sie sich in AlloyDB Studio authentifiziert haben, werden SQL-Befehle in den Editor eingegeben. Über das Pluszeichen rechts neben dem letzten Fenster können Sie weitere Editorfenster hinzufügen.
Sie geben Befehle für AlloyDB in Editorfenstern ein und verwenden nach Bedarf die Optionen „Ausführen“, „Formatieren“ und „Löschen“.
Erweiterungen aktivieren
Für diese App verwenden wir die Erweiterungen pgvector
und google_ml_integration
. Mit der pgvector-Erweiterung können Sie Vektoreinbettungen speichern und darin suchen. Die Erweiterung google_ml_integration bietet Funktionen, mit denen Sie auf Vertex AI-Vorhersageendpunkte zugreifen und Vorhersagen in SQL abrufen können. Aktivieren Sie diese Erweiterungen, indem Sie die folgenden DDLs ausführen:
CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
Wenn Sie die in Ihrer Datenbank aktivierten Erweiterungen prüfen möchten, führen Sie den folgenden SQL-Befehl aus:
select extname, extversion from pg_extension;
Tabelle erstellen
Erstellen Sie eine Tabelle mit der folgenden DDL-Anweisung:
CREATE TABLE toys ( id VARCHAR(25), name VARCHAR(25), description VARCHAR(20000), quantity INT, price FLOAT, image_url VARCHAR(200), text_embeddings vector(768)) ;
Wenn der Befehl erfolgreich ausgeführt wurde, sollte die Tabelle in der Datenbank angezeigt werden.
Daten aufnehmen
Für dieses Lab haben wir Testdaten mit etwa 72 Einträgen in dieser SQL-Datei. Sie enthält die Felder id, name, description, quantity, price, image_url
. Die anderen Felder werden später im Lab ausgefüllt.
Kopieren Sie die Zeilen/Einfügeanweisungen von dort, fügen Sie sie in einen leeren Editortab ein und wählen Sie „AUSFÜHREN“ aus.
Maximieren Sie den Bereich „Explorer“, bis Sie die Tabelle „apparels“ sehen, um den Tabelleninhalt zu sehen. Klicken Sie auf das Dreipunkt-Menü ⋮, um die Option „Tabelle abfragen“ zu sehen. Eine SELECT-Anweisung wird in einem neuen Editor-Tab geöffnet.
Berechtigung gewähren
Führen Sie die folgende Anweisung aus, um dem Nutzer postgres
Ausführungsrechte für die Funktion embedding
zu gewähren:
GRANT EXECUTE ON FUNCTION embedding TO postgres;
Dem AlloyDB-Dienstkonto die Rolle „Vertex AI User“ gewähren
Rufen Sie das Cloud Shell-Terminal auf und geben Sie den folgenden Befehl ein:
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"
6. Einbettungen für den Kontext erstellen
Für Computer ist es viel einfacher, Zahlen zu verarbeiten als Text. Ein Einbettungssystem wandelt Text in eine Reihe von Fließkommazahlen um, die den Text unabhängig von der Formulierung und Sprache darstellen sollen.
Beschreiben Sie einen Ort am Meer. Die Bezeichnung kann „am Wasser“, „Strand“, „Fußweg vom Zimmer zum Meer“, „sur la mer“ oder „на берегу океана“ lauten. Diese Begriffe sehen alle unterschiedlich aus, aber ihre semantische Bedeutung oder in der Terminologie des Machine Learning ihre Einbettungen sollten sehr nah beieinander liegen.
Nachdem Daten und Kontext bereit sind, führen wir die SQL-Abfrage aus, um der Tabelle im Feld embedding
die Einbettungen der Produktbeschreibung hinzuzufügen. Es gibt verschiedene Einbettungsmodelle, die Sie verwenden können. Wir verwenden text-embedding-005
von Vertex AI. Achten Sie darauf, im gesamten Projekt dasselbe Einbettungsmodell zu verwenden.
Hinweis: Wenn Sie ein Google Cloud-Projekt verwenden, das vor einiger Zeit erstellt wurde, müssen Sie möglicherweise weiterhin ältere Versionen des Text-Embedding-Modells wie „textembedding-gecko“ verwenden.
Kehren Sie zum Tab „AlloyDB Studio“ zurück und geben Sie die folgende DML ein:
UPDATE toys set text_embeddings = embedding( 'text-embedding-005', description);
Sehen Sie sich noch einmal die Tabelle toys
an, um einige Einbettungen zu sehen. Führen Sie die SELECT-Anweisung noch einmal aus, um die Änderungen zu sehen.
SELECT id, name, description, price, quantity, image_url, text_embeddings FROM toys;
Dadurch sollte der Einbettungsvektor, der wie ein Array von Gleitkommazahlen aussieht, für die Spielzeugbeschreibung zurückgegeben werden, wie unten dargestellt:
Hinweis:Bei neu erstellten Google Cloud-Projekten im Rahmen des kostenlosen Tarifs kann es zu Kontingentproblemen bei der Anzahl der zulässigen Einbettungsanfragen pro Sekunde an die Einbettungsmodelle kommen. Wir empfehlen, eine Filterabfrage für die ID zu verwenden und dann beim Generieren des Embeds selektiv 1–5 Einträge auszuwählen.
7. Vektorsuche ausführen
Nachdem Tabelle, Daten und Einbettungen bereit sind, führen wir die Echtzeit-Vektorsuche für den Suchtext des Nutzers aus.
Angenommen, der Nutzer stellt folgende Frage:
„I want a white plush teddy bear toy with a floral pattern
.“
Mit der folgenden Abfrage können Sie entsprechende Übereinstimmungen finden:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 5;
Sehen wir uns diese Abfrage genauer an:
In dieser Abfrage:
- Der Suchbegriff des Nutzers lautet: „
I want a white plush teddy bear toy with a floral pattern.
“ - Wir konvertieren sie in der Methode
embedding()
mit dem Modelltext-embedding-005
in Einbettungen. Dieser Schritt sollte Ihnen nach dem letzten Schritt bekannt vorkommen, in dem wir die Einbettungsfunktion auf alle Elemente in der Tabelle angewendet haben. - „
<=>
“ steht für die Verwendung der Distanzmethode KOSINISCHE ÄHNLICHKEIT. Alle verfügbaren Ähnlichkeitsmaße finden Sie in der Dokumentation von pgvector. - Wir konvertieren das Ergebnis der Einbettungsmethode in den Vektortyp, damit es mit den in der Datenbank gespeicherten Vektoren kompatibel ist.
- Mit LIMIT 5 geben wir an, dass wir 5 nächste Nachbarn für den Suchtext extrahieren möchten.
Das Ergebnis sieht so aus:
Wie Sie in den Ergebnissen sehen, stimmen die Übereinstimmungen ziemlich genau mit dem Suchtext überein. Ändern Sie den Text und sehen Sie, wie sich die Ergebnisse ändern.
Wichtiger Hinweis:
Angenommen, wir möchten die Leistung (Abfragezeit), Effizienz und den Recall dieses Vektorsuchergebnisses mit dem ScaNN-Index verbessern. In diesem Blogpost finden Sie eine Anleitung, wie Sie den Unterschied zwischen den Ergebnissen mit und ohne Index vergleichen können.
Optionaler Schritt: Effizienz und Abruf mit dem ScaNN-Index verbessern
Hier sind die Schritte zum Erstellen eines Index:
- Da wir bereits Cluster, Instanz, Kontext und Einbettungen erstellt haben, müssen wir nur noch die ScaNN-Erweiterung mit der folgenden Anweisung installieren:
CREATE EXTENSION IF NOT EXISTS alloydb_scann;
- Als Nächstes erstellen wir den Index (ScaNN):
CREATE INDEX toysearch_index ON toys
USING scann (text_embeddings cosine)
WITH (num_leaves=9);
In der obigen DDL ist „apparel_index“ der Name des Index.
„Spielzeuge“ ist meine Tabelle
„scann“ ist die Indexmethode.
„embedding“ ist die Spalte in der Tabelle, die ich indexieren möchte.
„cosine“ ist die Entfernungsmethode, die ich für den Index verwenden möchte.
„8“ ist die Anzahl der Partitionen, die auf diesen Index angewendet werden sollen. Legen Sie einen Wert zwischen 1 und 1048576 fest. Weitere Informationen zur Auswahl dieses Werts finden Sie unter ScaNN-Index optimieren.
Ich habe die QUADRATWURZEL der Anzahl der Datenpunkte verwendet, wie im ScaNN-Repository empfohlen. Bei der Partitionierung sollte „num_leaves“ ungefähr der Quadratwurzel der Anzahl der Datenpunkte entsprechen.
- Prüfen Sie mit der folgenden Abfrage, ob der Index erstellt wurde:
SELECT * FROM pg_stat_ann_indexes;
- Führen Sie die Vektorsuche mit derselben Abfrage aus, die wir ohne Index verwendet haben:
select * from toys
ORDER BY text_embeddings <=> CAST(embedding('text-embedding-005', 'I want a white plush teddy bear toy with a floral pattern') as vector(768))
LIMIT 5;
Die obige Abfrage ist dieselbe, die wir im Lab in Schritt 8 verwendet haben. Jetzt ist das Feld jedoch indexiert.
- Testen Sie mit einer einfachen Suchanfrage mit und ohne Index (indem Sie den Index löschen):
Dieser Anwendungsfall umfasst nur 72 Einträge, sodass der Index nicht wirklich wirksam wird. Bei einem Test in einem anderen Anwendungsfall sehen die Ergebnisse so aus:
Die gleiche Vektorsuchanfrage für die INDEXIERTEN Einbettungsdaten führt zu hochwertigen Suchergebnissen und Effizienz. Die Effizienz wird durch den Index erheblich verbessert (in Bezug auf die Ausführungszeit: 10,37 ms ohne ScaNN und 0,87 ms mit ScaNN). Weitere Informationen zu diesem Thema finden Sie in diesem Blog.
8. Abgleichsbestätigung mit dem LLM
Bevor wir fortfahren und einen Dienst erstellen, der die besten Übereinstimmungen für eine Anwendung zurückgibt, prüfen wir mit einem generativen KI-Modell, ob diese potenziellen Antworten wirklich relevant und sicher für die Weitergabe an den Nutzer sind.
Prüfen, ob die Instanz für Gemini eingerichtet ist
Prüfen Sie zuerst, ob die Google ML-Integration für Ihren Cluster und Ihre Instanz bereits aktiviert ist. Geben Sie in AlloyDB Studio den folgenden Befehl ein:
show google_ml_integration.enable_model_support;
Wenn der Wert „an“ lautet, können Sie die nächsten beiden Schritte überspringen und direkt mit der Einrichtung der AlloyDB- und Vertex AI-Modellintegration fortfahren.
- Rufen Sie die primäre Instanz Ihres AlloyDB-Clusters auf und klicken Sie auf PRÄMIRE INSTANZ BEARBEITEN.
- Rufen Sie in den erweiterten Konfigurationsoptionen den Bereich „Flags“ auf. und
google_ml_integration.enable_model_support flag
muss aufon
festgelegt sein, wie unten dargestellt:
Wenn die Option nicht aktiviert ist, klicken Sie auf „An“ und dann auf die Schaltfläche INSTANZ AKTUALISIEREN. Dieser Schritt dauert einige Minuten.
Integration von AlloyDB und Vertex AI-Modellen
Sie können jetzt eine Verbindung zu AlloyDB Studio herstellen und die folgende DML-Anweisung ausführen, um den Gemini-Modellzugriff über AlloyDB einzurichten. Geben Sie dabei an der entsprechenden Stelle Ihre Projekt-ID an. Möglicherweise werden Sie vor der Ausführung des Befehls auf einen Syntaxfehler hingewiesen. Er sollte aber trotzdem ausgeführt werden.
Zuerst erstellen wir die Gemini 1.5-Modellverbindung, wie unten dargestellt. Ersetzen Sie im folgenden Befehl $PROJECT_ID
durch Ihre Google Cloud-Projekt-ID.
CALL
google_ml.create_model( model_id => 'gemini-1.5',
model_request_url => 'https://us-central1-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/us-central1/publishers/google/models/gemini-1.5-pro:streamGenerateContent',
model_provider => 'google',
model_auth_type => 'alloydb_service_agent_iam');
Mit dem folgenden Befehl in AlloyDB Studio können Sie die für den Zugriff konfigurierten Modelle prüfen:
select model_id,model_type from google_ml.model_info_view;
Schließlich müssen wir Datenbanknutzern die Berechtigung erteilen, die Funktion ml_predict_row auszuführen, um Vorhersagen über Google Vertex AI-Modelle auszuführen. Führen Sie dazu diesen Befehl aus:
GRANT EXECUTE ON FUNCTION ml_predict_row to postgres;
Hinweis: Wenn Sie ein vorhandenes Google Cloud-Projekt und einen vorhandenen Cluster/eine vorhandene Instanz von AlloyDB verwenden, die vor einiger Zeit erstellt wurden, müssen Sie möglicherweise die alten Verweise auf das gemini-1.5-Modell löschen und mit der obigen CALL-Anweisung neu erstellen. Führen Sie dann noch einmal „grant execute on function ml_predict_row“ aus, falls bei den nächsten Aufrufen von gemini-1.5 Probleme auftreten.
Antworten auswerten
Im nächsten Abschnitt verwenden wir zwar eine große Abfrage, um sicherzustellen, dass die Antworten auf die Abfrage angemessen sind, aber die Abfrage kann schwer verständlich sein. Wir sehen uns jetzt die einzelnen Teile an und wie sie in wenigen Minuten zusammengesetzt werden.
- Zuerst senden wir eine Anfrage an die Datenbank, um die zehn besten Übereinstimmungen mit einer Nutzerabfrage zu erhalten.
- Um zu bestimmen, wie gültig die Antworten sind, verwenden wir eine äußere Abfrage, in der wir erklären, wie die Antworten bewertet werden. Dabei werden das Feld
recommended_text
(Suchtext) undcontent
(Feld für die Spielzeugbeschreibung) der inneren Tabelle als Teil der Abfrage verwendet. - Anhand dieser Informationen prüfen wir dann die Qualität der zurückgegebenen Antworten.
- Die
predict_row
gibt das Ergebnis im JSON-Format zurück. Mit dem Code „-> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text'"
“ wird der tatsächliche Text aus dieser JSON-Datei extrahiert. Wenn Sie die tatsächlich zurückgegebene JSON-Datei sehen möchten, können Sie diesen Code entfernen. - Um die LLM-Antwort abzurufen, extrahieren wir sie mit
REGEXP_REPLACE(gemini_validation,
'[^a-zA-Z,: ]',
'',
'g')
.
SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
CAST(ARRAY_AGG(LLM_RESPONSE) AS TEXT) AS gemini_validation
FROM (SELECT id,
name,
content,
quantity,
price,
image_url,
recommended_text,
json_array_elements(google_ml.predict_row(model_id => 'gemini-1.5',
request_body => CONCAT('{ "contents": [ { "role": "user", "parts": [ { "text": "User wants to buy a toy and this is the description of the toy they wish to buy: ', recommended_text, '. Check if the following product items from the inventory are close enough to really, contextually match the user description. Here are the items: ', content, '. Return a ONE-LINE response with 3 values: 1) MATCH: if the 2 contexts are reasonably matching in terms of any of the color or color family specified in the list, approximate style match with any of the styles mentioned in the user search text: This should be a simple YES or NO. Choose NO only if it is completely irrelevant to users search criteria. 2) PERCENTAGE: percentage of match, make sure that this percentage is accurate 3) DIFFERENCE: A clear one-line easy description of the difference between the 2 products. Remember if the user search text says that some attribute should not be there, and the record has it, it should be a NO match. " } ] } ] }')::JSON)) -> 'candidates' -> 0 -> 'content' -> 'parts' -> 0 -> 'text' :: TEXT AS LLM_RESPONSE
FROM (SELECT id,
name,
description AS content,
quantity,
price,
image_url,
'Pink panther standing' AS recommended_text
FROM toys
ORDER BY text_embeddings <=> embedding('text-embedding-005',
'Pink panther standing')::VECTOR
LIMIT 10) AS xyz) AS X
GROUP BY id,
name,
content,
quantity,
price,
image_url,
recommended_text) AS final_matches
WHERE REGEXP_REPLACE(gemini_validation, '[^a-zA-Z,: ]', '', 'g') LIKE '%MATCH%:%YES%';
Das mag zwar immer noch einschüchternd wirken, aber hoffentlich können Sie es jetzt etwas besser nachvollziehen. Die Ergebnisse geben an, ob eine Übereinstimmung vorliegt, wie hoch der Prozentsatz der Übereinstimmung ist und wie die Altersfreigabe begründet wird.
Beachten Sie, dass das Streaming für das Gemini-Modell standardmäßig aktiviert ist. Daher ist die tatsächliche Antwort auf mehrere Zeilen verteilt:
9. Die Spielzeugsuche serverlos in die Cloud bringen
Sind Sie bereit, diese App im Web zu veröffentlichen? Führen Sie die folgenden Schritte aus, um diese Knowledge Engine mit Cloud Run-Funktionen serverlos zu machen:
- Rufen Sie in der Google Cloud Console die Seite „Cloud Run-Funktionen“ auf, um eine neue Cloud Run-Funktion zu ERSTELLEN, oder verwenden Sie den Link https://console.cloud.google.com/functions/add.
- Wählen Sie als Umgebung Cloud Run-Funktion aus. Geben Sie den Funktionsnamen „get-toys-alloydb“ ein und wählen Sie „us-central1“ als Region aus. Wählen Sie für die Authentifizierung die Option „Nicht authentifizierte Aufrufe zulassen“ aus und klicken Sie auf WEITER. Wählen Sie als Laufzeit Java 17 und als Quellcode Inline-Editor aus.
- Standardmäßig wird der Einstiegspunkt auf „
gcfv2.HelloHttpFunction
“ festgelegt. Ersetzen Sie den Platzhaltercode inHelloHttpFunction.java
undpom.xml
Ihrer Cloud Run-Funktion durch den Code aus HelloHttpFunction.java bzw. pom.xml. - Ersetzen Sie den Platzhalter <<YOUR_PROJECT>> und die AlloyDB-Anmeldedaten in der Java-Datei durch Ihre Werte. Die AlloyDB-Anmeldedaten sind dieselben, die wir zu Beginn dieses Codelabs verwendet haben. Wenn Sie andere Werte verwendet haben, ändern Sie diese bitte in der Java-Datei.
- Klicken Sie auf Bereitstellen.
Nach der Bereitstellung erstellen wir den VPC-Connector, damit die Cloud-Funktion auf unsere AlloyDB-Datenbankinstanz zugreifen kann.
WICHTIG:
Sobald die Bereitstellung abgeschlossen ist, sollten Sie die Funktionen in der Cloud Run Functions Console sehen können. Suchen Sie nach der neu erstellten Funktion (get-toys-alloydb
), klicken Sie darauf und dann auf BEARBEITEN. Ändern Sie Folgendes:
- Gehen Sie zu „Laufzeit, Build, Verbindungen und Sicherheitseinstellungen“.
- Zeitlimit auf 180 Sekunden erhöhen
- Rufen Sie den Tab „VERBINDUNGEN“ auf:
- Achten Sie darauf, dass unter „Ingress-Einstellungen“ die Option „Gesamten Traffic zulassen“ ausgewählt ist.
- Klicken Sie unter „Einstellungen für ausgehenden Traffic“ auf das Drop-down-Menü „Netzwerk“ und wählen Sie die Option „Neuen VPC-Connector hinzufügen“ aus. Folgen Sie dann der Anleitung im angezeigten Dialogfeld:
- Geben Sie einen Namen für den VPC-Connector an und achten Sie darauf, dass die Region mit der Ihrer Instanz übereinstimmt. Lassen Sie den Wert für „Netzwerk“ als Standard bei und legen Sie „Subnetz“ als benutzerdefinierten IP-Bereich mit dem IP-Bereich 10.8.0.0 oder einem ähnlichen verfügbaren Bereich fest.
- Maximieren Sie die Konfiguration „ANZEIGENSKALIBRIERUNGS-EINSTELLUNGEN“ und prüfen Sie, ob die Konfiguration genau so festgelegt ist:
- Klicken Sie auf „ERSTELLEN“. Dieser Connector sollte jetzt in den Einstellungen für ausgehenden Traffic aufgeführt sein.
- Wählen Sie den neu erstellten Connector aus.
- Legen Sie fest, dass der gesamte Traffic über diesen VPC-Connector weitergeleitet werden soll.
- Klicken Sie auf WEITER und dann auf Bereitstellen.
10. Cloud Run-Funktion testen
Sobald die aktualisierte Cloud-Funktion bereitgestellt wurde, sollte der Endpunkt im folgenden Format angezeigt werden:
https://us-central1-YOUR_PROJECT_ID.cloudfunctions.net/get-toys-alloydb
Alternativ können Sie die Cloud Run-Funktion so testen:
PROJECT_ID=$(gcloud config get-value project)
curl -X POST https://us-central1-$PROJECT_ID.cloudfunctions.net/get-toys-alloydb \
-H 'Content-Type: application/json' \
-d '{"search":"I want a standing pink panther toy"}' \
| jq .
Das Ergebnis:
Geschafft! So einfach ist es, mit dem Embeddings-Modell eine Ähnlichkeitsvektorsuche in AlloyDB-Daten durchzuführen.
11. Webanwendungsclient erstellen
In diesem Teil erstellen wir eine Webanwendung, mit der Nutzer anhand von Text und Bildern nach passenden Spielsachen suchen und sogar ein neues Spielzeug nach ihren Bedürfnissen erstellen können. Da die Anwendung bereits erstellt wurde, können Sie die folgenden Schritte ausführen, um sie in Ihre IDE zu kopieren und die App einzurichten.
- Da wir Gemini 2.0 Flash verwenden, um das Bild zu beschreiben, das der Nutzer hochladen kann, um passende Spielzeuge zu finden, müssen wir den API-KEY für diese Anwendung abrufen. Rufen Sie dazu https://aistudio.google.com/apikey auf, rufen Sie den API-Schlüssel für Ihr aktives Google Cloud-Projekt ab, in dem Sie diese Anwendung implementieren, und speichern Sie ihn an einem beliebigen Ort:
- Cloud Shell-Terminal aufrufen
- Klonen Sie das Repository mit dem folgenden Befehl:
git clone https://github.com/AbiramiSukumaran/toysearch
cd toysearch
- Sobald das Repository geklont wurde, sollten Sie über den Cloud Shell-Editor auf das Projekt zugreifen können.
- Sie müssen die Ordner „get-toys-alloydb“ und „toolbox-toys“ aus dem geklonten Projekt löschen, da sie Cloud Run-Funktionscode enthalten, auf den bei Bedarf aus dem Repository verwiesen werden kann.
- Achten Sie darauf, dass alle erforderlichen Umgebungsvariablen festgelegt sind, bevor Sie die App erstellen und bereitstellen. Rufen Sie das Cloud Shell-Terminal auf und führen Sie Folgendes aus:
PROJECT_ID=$(gcloud config get-value project)
export PROJECT_ID $PROJECT_ID
export GOOGLE_API_KEY <YOUR API KEY that you saved>
- So erstellen Sie die App und führen sie lokal aus:
Führen Sie die folgenden Befehle aus, während Sie sich im Projektverzeichnis befinden:
mvn package
mvn spring-boot:run
- In Cloud Run bereitstellen
gcloud run deploy --source .
12. Details zur generativen KI
Es sind keine Maßnahmen erforderlich. Zur Information:
Jetzt, da Sie die Anwendung bereitgestellt haben, nehmen Sie sich einen Moment Zeit, um zu erfahren, wie wir die Suche (Text und Bild) und die Generierung durchgeführt haben.
- Nutzertextbasierte Vektorsuche:
Dies wird bereits in den Cloud Run-Funktionen berücksichtigt, die wir im Abschnitt „Die Vektorsuchanwendung im Web verwenden“ bereitgestellt haben.
- Vektorsuche basierend auf Bilduploads:
Angenommen, der Nutzer möchte anstelle des Kontexts als Text ein Bild eines bekannten Spielzeugs hochladen, mit dem er suchen möchte. Nutzer können ein Bild eines Spielzeugs hochladen, das ihnen gefällt, und erhalten so relevante Funktionen.
Wir nutzen das Gemini 2.0-Flash-Modell von Google, das mit LangChain4j aufgerufen wird, um das Bild zu analysieren und relevanten Kontext zu extrahieren, z. B. Farbe, Material, Typ und Zielgruppe des Spielzeugs.
In nur fünf Schritten haben wir die multimodalen Nutzerdaten mithilfe eines Open-Source-Frameworks mit der Aufrufung eines Large Language Model abgeglichen. Weitere Informationen:
package cloudcode.helloworld.web;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.googleai.GoogleAiGeminiChatModel;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.model.output.Response;
import dev.langchain4j.data.message.ImageContent;
import dev.langchain4j.data.message.TextContent;
import java.util.Base64;
import java.util.Optional;
public class GeminiCall {
public String imageToBase64String(byte[] imageBytes) {
String base64Img = Base64.getEncoder().encodeToString(imageBytes);
return base64Img;
}
public String callGemini(String base64ImgWithPrefix) throws Exception {
String searchText = "";
// 1. Remove the prefix
String base64Img = base64ImgWithPrefix.replace("data:image/jpeg;base64,", "");
// 2. Decode base64 to bytes
byte[] imageBytes = Base64.getDecoder().decode(base64Img);
String image = imageToBase64String(imageBytes);
// 3. Get API key from environment variable
String apiKey = Optional.ofNullable(System.getenv("GOOGLE_API_KEY"))
.orElseThrow(() -> new IllegalArgumentException("GOOGLE_API_KEY environment variable not set"));
// 4. Invoke Gemini 2.0
ChatLanguageModel gemini = GoogleAiGeminiChatModel.builder()
.apiKey(apiKey)
.modelName("gemini-2.0-flash-001")
.build();
Response<AiMessage> response = gemini.generate(
UserMessage.from(
ImageContent.from(image, "image/jpeg"),
TextContent.from(
"The picture has a toy in it. Describe the toy in the image in one line. Do not add any prefix or title to your description. Just describe that toy that you see in the image in one line, do not describe the surroundings and other objects around the toy in the image. If you do not see any toy in the image, send response stating that no toy is found in the input image.")));
// 5. Get the text from the response and send it back to the controller
searchText = response.content().text().trim();
System.out.println("searchText inside Geminicall: " + searchText);
return searchText;
}
}
- Hier erfahren Sie, wie wir mithilfe von generativer KI und Imagen 3 ein benutzerdefiniertes Spielzeug auf der Grundlage einer Nutzeranfrage erstellt haben.
Imagen 3 generiert dann ein Bild des benutzerdefinierten Spielzeugs, das dem Nutzer eine klare Visualisierung seiner Kreation bietet. So haben wir es in nur fünf Schritten geschafft:
// Generate an image using a text prompt using an Imagen model
public String generateImage(String projectId, String location, String prompt)
throws ApiException, IOException {
final String endpoint = String.format("%s-aiplatform.googleapis.com:443", location);
PredictionServiceSettings predictionServiceSettings =
PredictionServiceSettings.newBuilder().setEndpoint(endpoint).build();
// 1. Set up the context and prompt
String context = "Generate a photo-realistic image of a toy described in the following input text from the user. Make sure you adhere to all the little details and requirements mentioned in the prompt. Ensure that the user is only describing a toy. If it is anything unrelated to a toy, politely decline the request stating that the request is inappropriate for the current context. ";
prompt = context + prompt;
// 2. Initialize a client that will be used to send requests. This client only needs to be created
// once, and can be reused for multiple requests.
try (PredictionServiceClient predictionServiceClient =
PredictionServiceClient.create(predictionServiceSettings)) {
// 3. Invoke Imagen 3
final EndpointName endpointName =
EndpointName.ofProjectLocationPublisherModelName(
projectId, location, "google", "imagen-3.0-generate-001"); //"imagegeneration@006"; imagen-3.0-generate-001
Map<String, Object> instancesMap = new HashMap<>();
instancesMap.put("prompt", prompt);
Value instances = mapToValue(instancesMap);
Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("sampleCount", 1);
paramsMap.put("aspectRatio", "1:1");
paramsMap.put("safetyFilterLevel", "block_few");
paramsMap.put("personGeneration", "allow_adult");
paramsMap.put("guidanceScale", 21);
paramsMap.put("imagenControlScale", 0.95); //Setting imagenControlScale
Value parameters = mapToValue(paramsMap);
// 4. Get prediction response image
PredictResponse predictResponse =
predictionServiceClient.predict(
endpointName, Collections.singletonList(instances), parameters);
// 5. Return the Base64 Encoded String to the controller
for (Value prediction : predictResponse.getPredictionsList()) {
Map<String, Value> fieldsMap = prediction.getStructValue().getFieldsMap();
if (fieldsMap.containsKey("bytesBase64Encoded")) {
bytesBase64EncodedOuput = fieldsMap.get("bytesBase64Encoded").getStringValue();
}
}
return bytesBase64EncodedOuput.toString();
}
}
Preisprognose
Im vorherigen Abschnitt haben wir erläutert, wie Imagen das Bild eines Spielzeugs generiert, das der Nutzer selbst entwerfen möchte. Damit sie es kaufen können, muss die App einen Preis dafür festlegen. Wir haben eine intuitive Logik verwendet, um einen Preis für das individuell gefertigte Spielzeug zu definieren. Es wird der durchschnittliche Preis der fünf am besten passenden Spielzeuge (in Bezug auf die Beschreibung) des vom Nutzer entworfenen Spielzeugs verwendet.
Die Preisvorhersage für das generierte Spielzeug ist ein wichtiger Bestandteil dieser Anwendung. Wir haben einen agentischen Ansatz verwendet, um sie zu generieren. Die Gen AI Toolbox für Datenbanken
13. Gen AI Toolbox für Datenbanken
Die Gen AI Toolbox for Databases ist ein Open-Source-Server von Google, mit dem sich Gen AI-Tools zum Interagieren mit Datenbanken einfacher erstellen lassen. Sie können damit Tools einfacher, schneller und sicherer entwickeln, da komplexe Aufgaben wie Verbindungspooling und Authentifizierung übernommen werden. Sie können damit Tools für generative KI erstellen, mit denen Ihre Kundenservicemitarbeiter auf Daten in Ihrer Datenbank zugreifen können.
So richten Sie das Tool ein, damit unsere Anwendung verwaltet werden kann: Link zum Toolbox Codelab
Ihre Anwendung kann jetzt diesen bereitgestellten Cloud Run-Funktions-Endpunkt verwenden, um den Preis zusammen mit dem generierten Bildergebnis für das benutzerdefinierte Spielzeugbild einzufügen.
14. Webanwendung testen
Nachdem alle Komponenten Ihrer Anwendung erstellt und bereitgestellt wurden, kann sie in der Cloud bereitgestellt werden. Testen Sie Ihre Anwendung für alle Szenarien. Hier ist ein Video, das zeigt, was Sie erwartet:
https://www.youtube.com/shorts/ZMqUAWsghYQ
So sieht die Landingpage aus:
15. Bereinigen
Mit den folgenden Schritten vermeiden Sie, dass Ihrem Google Cloud-Konto die in diesem Beitrag verwendeten Ressourcen in Rechnung gestellt werden:
- Rufen Sie in der Google Cloud Console die Seite Ressourcen verwalten auf.
- Wählen Sie in der Projektliste das Projekt aus, das Sie löschen möchten, und klicken Sie auf Löschen.
- Geben Sie im Dialogfeld die Projekt-ID ein und klicken Sie auf Beenden, um das Projekt zu löschen.
16. Glückwunsch
Glückwunsch! Sie haben mit AlloyDB, pgvector, Imagen und Gemini 2.0 eine kontextbezogene Suche und Generierung für ein Spielzeuggeschäft durchgeführt und dabei Open-Source-Bibliotheken genutzt, um robuste Integrationen zu erstellen. Durch die Kombination der Funktionen von AlloyDB, Vertex AI und Vektorsuche haben wir einen großen Schritt nach vorn gemacht, um kontextbezogene und Vektorsuchen zugänglich, effizient und wirklich aussagekräftig zu machen.