1. Übersicht
Generative KI-Anwendungen erfordern wie alle anderen Anwendungen Beobachtbarkeit. Sind für generative KI spezielle Verfahren zur Beobachtung erforderlich?
In diesem Lab erstellen Sie eine einfache Gen AI-Anwendung. Stellen Sie sie in Cloud Run bereit. Außerdem können Sie sie mit wichtigen Monitoring- und Logging-Funktionen mithilfe der Google Cloud-Dienste und -Produkte für die Beobachtbarkeit ausstatten.
Lerninhalte
- Anwendung mit Vertex AI mit dem Cloud Shell-Editor schreiben
- Anwendungscode in GitHub speichern
- Quellcode Ihrer Anwendung mit der gcloud CLI in Cloud Run bereitstellen
- Ihrer Anwendung mit generativer KI Monitoring- und Logging-Funktionen hinzufügen
- Logbasierte Messwerte verwenden
- Logging und Monitoring mit dem OpenTelemetry SDK implementieren
- Informationen zur verantwortungsbewussten Datenverarbeitung bei KI
2. Vorbereitung
Wenn Sie noch kein Google-Konto haben, müssen Sie ein neues Konto erstellen.
3. Projekt einrichten
- Melden Sie sich mit Ihrem Google-Konto in der Google Cloud Console an.
- Erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes. Notieren Sie sich die Projekt-ID des Projekts, das Sie gerade erstellt oder ausgewählt haben.
- Aktivieren Sie die Abrechnung für das Projekt.
- Die Durchführung dieses Labs sollte weniger als 5 $in Rechnung stellen.
- Sie können die Schritte am Ende dieses Labs ausführen, um Ressourcen zu löschen und weitere Kosten zu vermeiden.
- Neue Nutzer können das kostenlose Testabo mit einem Guthaben von 300$ nutzen.
- Prüfen Sie, ob die Abrechnung unter Meine Projekte in der Cloud-Abrechnung aktiviert ist.
- Wenn in der Spalte
Billing account
für Ihr neues ProjektBilling is disabled
angezeigt wird:- Klicken Sie in der Spalte
Actions
auf das Dreipunkt-Menü. - Klicken Sie auf Abrechnung ändern.
- Wählen Sie das Rechnungskonto aus, das Sie verwenden möchten.
- Klicken Sie in der Spalte
- Wenn Sie an einer Live-Veranstaltung teilnehmen, lautet der Name des Kontos wahrscheinlich Google Cloud Platform-Testrechnungskonto.
- Wenn in der Spalte
4. Cloud Shell-Editor vorbereiten
- Rufen Sie den Cloud Shell-Editor auf. Wenn Sie die folgende Aufforderung sehen, Cloud Shell zu autorisieren, gcloud mit Ihren Anmeldedaten aufzurufen, klicken Sie auf Autorisieren, um fortzufahren.
- Terminalfenster öffnen
- Klicke auf das Dreistrich-Menü
.
- Klicken Sie auf Terminal.
- Klicken Sie auf Neues Terminal
.
- Klicke auf das Dreistrich-Menü
- Konfigurieren Sie im Terminal Ihre Projekt-ID:
Ersetzen Siegcloud config set project [PROJECT_ID]
[PROJECT_ID]
durch die ID Ihres Projekts. Wenn Ihre Projekt-ID beispielsweiselab-example-project
lautet, lautet der Befehl: Wenn Sie die folgende Meldung erhalten, dass gcloud Ihre Anmeldedaten für die GCPI API anfordert, klicken Sie auf Autorisieren, um fortzufahren.gcloud config set project lab-project-id-example
Nach erfolgreicher Ausführung sollte die folgende Meldung angezeigt werden: Wenn du die MeldungUpdated property [core/project].
WARNING
und die FrageDo you want to continue (Y/N)?
siehst, hast du wahrscheinlich die Projekt-ID falsch eingegeben. Drücken SieN
,Enter
und versuchen Sie dann noch einmal, den Befehlgcloud config set project
auszuführen, nachdem Sie die richtige Projekt-ID gefunden haben. - Optional: Wenn Sie die Projekt-ID nicht finden können, führen Sie den folgenden Befehl aus, um die Projekt-IDs aller Ihrer Projekte in absteigender Reihenfolge nach Erstellungszeit aufzulisten:
gcloud projects list \ --format='value(projectId,createTime)' \ --sort-by=~createTime
5. Google APIs aktivieren
Aktivieren Sie im Terminal die für dieses Lab erforderlichen Google APIs:
gcloud services enable \
run.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com \
logging.googleapis.com \
monitoring.googleapis.com \
cloudtrace.googleapis.com
Die Ausführung dieses Befehls kann einige Zeit dauern. Schließlich wird eine Meldung wie die folgende angezeigt:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
Wenn Sie eine Fehlermeldung erhalten, die mit ERROR: (gcloud.services.enable) HttpError accessing
beginnt und Fehlerdetails wie unten enthält, wiederholen Sie den Befehl nach einer Verzögerung von 1 bis 2 Minuten.
"error": { "code": 429, "message": "Quota exceeded for quota metric 'Mutate requests' and limit 'Mutate requests per minute' of service 'serviceusage.googleapis.com' ...", "status": "RESOURCE_EXHAUSTED", ... }
6. Generative AI-Go-Anwendung erstellen
In diesem Schritt schreiben Sie den Code für die einfache anfragebasierte Anwendung, die mit dem Gemini-Modell 10 lustige Fakten zu einem Tier Ihrer Wahl anzeigt. So erstellen Sie den Anwendungscode:
- Erstellen Sie im Terminal das Verzeichnis
codelab-o11y
:mkdir ~/codelab-o11y
- Ändern Sie das aktuelle Verzeichnis in
codelab-o11y
:cd ~/codelab-o11y
- Go-Module initialisieren:
go mod init codelab
- So installieren Sie das Vertex AI SDK for Go:
go get cloud.google.com/go/vertexai/genai
- Installieren Sie die Metadatenbibliothek für Go, um die aktuelle Projekt-ID abzurufen:
go get cloud.google.com/go/compute/metadata
- Erstellen Sie eine
setup.go
-Datei und öffnen Sie sie im Cloud Shell-Editor: Wird zum Hosten des Initialisierungscodes verwendet. Im Editorfenster wird eine neue leere Datei mit dem Namencloudshell edit setup.go
setup.go
angezeigt. - Kopieren Sie den folgenden Code und fügen Sie ihn in die geöffnete
setup.go
-Datei ein:package main import ( "context" "os" "cloud.google.com/go/compute/metadata" ) func projectID(ctx context.Context) (string, error) { var projectID = os.Getenv("GOOGLE_CLOUD_PROJECT") if projectID == "" { return metadata.ProjectIDWithContext(ctx) } return projectID, nil }
- Kehren Sie zum Terminalfenster zurück und führen Sie den folgenden Befehl aus, um eine
main.go
-Datei im Cloud Shell-Editor zu erstellen und zu öffnen: Im Editorfenster über dem Terminal sollte jetzt eine leere Datei angezeigt werden. Ihr Bildschirm sollte in etwa so aussehen:cloudshell edit main.go
- Kopieren Sie den folgenden Code und fügen Sie ihn in die geöffnete
main.go
-Datei ein: Nach einigen Sekunden wird der Code im Cloud Shell-Editor automatisch gespeichert.package main import ( "context" "fmt" "net/http" "os" "cloud.google.com/go/vertexai/genai" ) var model *genai.GenerativeModel func main() { ctx := context.Background() projectID, err := projectID(ctx) if err != nil { return } var client *genai.Client client, err = genai.NewClient(ctx, projectID, "us-central1") if err != nil { return } defer client.Close() model = client.GenerativeModel("gemini-1.5-flash-001") http.HandleFunc("/", Handler) port := os.Getenv("PORT") if port == "" { port = "8080" } if err := http.ListenAndServe(":"+port, nil); err != nil { return } } func Handler(w http.ResponseWriter, r *http.Request) { animal := r.URL.Query().Get("animal") if animal == "" { animal = "dog" } prompt := fmt.Sprintf("Give me 10 fun facts about %s. Return the results as HTML without markdown backticks.", animal) resp, err := model.GenerateContent(r.Context(), genai.Text(prompt)) if err != nil { w.WriteHeader(http.StatusTooManyRequests) return } if len(resp.Candidates) > 0 && len(resp.Candidates[0].Content.Parts) > 0 { htmlContent := resp.Candidates[0].Content.Parts[0] w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, htmlContent) } }
Code der Gen AI-Anwendung in Cloud Run bereitstellen
- Führen Sie im Terminalfenster den Befehl aus, um den Quellcode der Anwendung in Cloud Run bereitzustellen.
Sie sehen die folgende Aufforderung, dass mit dem Befehl ein neues Repository erstellt wird. Klicken Sie aufgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Die Bereitstellung kann einige Minuten dauern. Nach Abschluss des Bereitstellungsvorgangs wird eine Ausgabe wie die folgende angezeigt:Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-central1] will be created. Do you want to continue (Y/n)?
Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic. Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
- Kopieren Sie die angezeigte Cloud Run-Dienst-URL in einen separaten Tab oder ein separates Fenster in Ihrem Browser. Alternativ können Sie den folgenden Befehl im Terminal ausführen, um die Dienst-URL zu drucken, und dann bei gedrückter Strg-Taste auf die angezeigte URL klicken, um sie zu öffnen:
Wenn die URL geöffnet wird, erhalten Sie möglicherweise den Fehler 500 oder die Meldung:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Die Bereitstellung der Dienste wurde nicht abgeschlossen. Warten Sie einen Moment und aktualisieren Sie die Seite. Am Ende sehen Sie einen Text, der mit Fun Dog Facts beginnt und 10 lustige Fakten über Hunde enthält.Sorry, this is just a placeholder...
Interagieren Sie mit der App, um interessante Fakten über verschiedene Tiere zu erfahren. Fügen Sie dazu den Parameter animal
an die URL an, z. B. ?animal=[ANIMAL]
, wobei [ANIMAL]
der Name eines Tieres ist. Fügen Sie beispielsweise ?animal=cat
hinzu, um 10 lustige Fakten über Katzen zu erhalten, oder ?animal=sea turtle
, um 10 lustige Fakten über Meeresschildkröten zu erhalten.
7. Vertex API-Aufrufe prüfen
Durch die Analyse von Google API-Aufrufen erhalten Sie Antworten auf Fragen wie „Wer ruft eine bestimmte API wo und wann auf?“. Audits sind wichtig, wenn Sie Probleme mit Ihrer Anwendung beheben, den Ressourcenverbrauch untersuchen oder eine forensische Softwareanalyse durchführen.
Mit Audit-Logs können Sie Administrator- und Systemaktivitäten erfassen sowie Aufrufe von API-Vorgängen vom Typ „Daten lesen“ und „Daten schreiben“ protokollieren. Wenn Sie Vertex AI-Anfragen zur Generierung von Inhalten prüfen möchten, müssen Sie in der Cloud Console Audit-Logs für „Datenlesevorgänge“ aktivieren.
- Klicken Sie auf die Schaltfläche unten, um die Seite „Audit-Logs“ in der Cloud Console zu öffnen.
- Achten Sie darauf, dass auf der Seite das Projekt ausgewählt ist, das Sie für dieses Lab erstellt haben. Das ausgewählte Projekt wird links oben auf der Seite direkt neben dem Dreistrich-Menü angezeigt:
Wählen Sie bei Bedarf das richtige Projekt aus der Drop-down-Liste aus. - Suchen Sie in der Tabelle Konfiguration für Audit-Logs zum Datenzugriff in der Spalte „Dienst“ nach dem Dienst
Vertex AI API
und wählen Sie ihn aus, indem Sie das Kästchen links neben dem Dienstnamen aktivieren. - Wählen Sie im Infofeld rechts den Analysetyp „Datenlesevorgang“ aus.
- Klicken Sie auf Speichern.
Öffnen Sie die Dienst-URL, um Audit-Logs zu generieren. Aktualisieren Sie die Seite und ändern Sie dabei den Wert des Parameters ?animal=
, um andere Ergebnisse zu erhalten.
Audit-Logs analysieren
- Klicken Sie auf die Schaltfläche unten, um die Seite „Log-Explorer“ in der Cloud Console zu öffnen:
- Fügen Sie den folgenden Filter in den Bereich „Abfrage“ ein.
Der Bereich „Abfrage“ ist ein Editor, der sich oben auf der Seite „Log-Explorer“ befindet:LOG_ID("cloudaudit.googleapis.com%2Fdata_access") AND protoPayload.serviceName="aiplatform.googleapis.com"
- Klicken Sie auf Abfrage ausführen.
- Wählen Sie einen der Einträge im Audit-Log aus und maximieren Sie die Felder, um die im Log erfassten Informationen zu prüfen.
Sie können Details zum Vertex API-Aufruf sehen, einschließlich der verwendeten Methode und des Modells. Außerdem sehen Sie die Identität des Aufrufers und die Berechtigungen, die den Aufruf autorisiert haben.
8. Interaktionen mit generativer KI protokollieren
In Audit-Logs finden Sie keine API-Anfrageparameter oder Antwortdaten. Diese Informationen können jedoch für die Fehlerbehebung bei der Anwendungs- und Workflowanalyse wichtig sein. In diesem Schritt schließen wir diese Lücke, indem wir Anwendungsprotokolle hinzufügen. Für das Logging wird das standardmäßige Go-log/slog
-Paket zum Schreiben strukturierter Logs verwendet. Das log/slog
-Paket weiß nicht, dass Protokolle in Google Cloud geschrieben werden sollen. Es unterstützt das Schreiben in die Standardausgabe. Cloud Run bietet jedoch Funktionen, mit denen Informationen, die in der Standardausgabe ausgegeben werden, automatisch in Cloud Logging aufgenommen werden. Damit die strukturierten Protokolle richtig erfasst werden, sollte das gedruckte Protokoll entsprechend formatiert sein. Folgen Sie der Anleitung unten, um unserer Go-Anwendung Funktionen für strukturiertes Logging hinzuzufügen.
- Kehren Sie im Browser zum Cloud Shell-Fenster (oder -Tab) zurück.
- Öffnen Sie
setup.go
noch einmal im Terminal:cloudshell edit ~/codelab-o11y/setup.go
- Ersetzen Sie den Code durch die Version, mit der die Protokollierung eingerichtet wird. Wenn Sie den Code ersetzen möchten, löschen Sie den Inhalt der Datei und kopieren Sie den folgenden Code. Fügen Sie ihn dann in den Editor ein:
package main import ( "context" "os" "log/slog" "cloud.google.com/go/compute/metadata" ) func projectID(ctx context.Context) (string, error) { var projectID = os.Getenv("GOOGLE_CLOUD_PROJECT") if projectID == "" { return metadata.ProjectIDWithContext(ctx) } return projectID, nil } func setupLogging() { opts := &slog.HandlerOptions{ Level: slog.LevelDebug, ReplaceAttr: func(group []string, a slog.Attr) slog.Attr { switch a.Key { case slog.LevelKey: a.Key = "severity" if level := a.Value.Any().(slog.Level); level == slog.LevelWarn { a.Value = slog.StringValue("WARNING") } case slog.MessageKey: a.Key = "message" case slog.TimeKey: a.Key = "timestamp" } return a }, } jsonHandler := slog.NewJSONHandler(os.Stdout, opts) slog.SetDefault(slog.New(jsonHandler)) }
- Kehren Sie zum Terminal zurück und öffnen Sie
main.go
noch einmal:cloudshell edit ~/codelab-o11y/main.go
- Ersetzen Sie den Anwendungscode durch die Version, die die Interaktion mit dem Modell protokolliert. Wenn Sie den Code ersetzen möchten, löschen Sie den Inhalt der Datei und kopieren Sie dann den folgenden Code und fügen Sie ihn in den Editor ein:
package main import ( "context" "fmt" "net/http" "os" "encoding/json" "log/slog" "cloud.google.com/go/vertexai/genai" ) var model *genai.GenerativeModel func main() { ctx := context.Background() projectID, err := projectID(ctx) if err != nil { return } setupLogging() var client *genai.Client client, err = genai.NewClient(ctx, projectID, "us-central1") if err != nil { slog.ErrorContext(ctx, "Failed to marshal response to JSON", slog.Any("error", err)) os.Exit(1) } defer client.Close() model = client.GenerativeModel("gemini-1.5-flash-001") http.HandleFunc("/", Handler) port := os.Getenv("PORT") if port == "" { port = "8080" } if err := http.ListenAndServe(":"+port, nil); err != nil { slog.ErrorContext(ctx, "Failed to start the server", slog.Any("error", err)) os.Exit(1) } } func Handler(w http.ResponseWriter, r *http.Request) { animal := r.URL.Query().Get("animal") if animal == "" { animal = "dog" } prompt := fmt.Sprintf("Give me 10 fun facts about %s. Return the results as HTML without markdown backticks.", animal) resp, err := model.GenerateContent(r.Context(), genai.Text(prompt)) if err != nil { w.WriteHeader(http.StatusTooManyRequests) return } jsonBytes, err := json.Marshal(resp) if err != nil { slog.Error("Failed to marshal response to JSON", slog.Any("error", err)) } else { slog.DebugContext(r.Context(), "content is generated", slog.String("animal", animal), slog.String("prompt", prompt), slog.String("response", string(jsonBytes))) } if len(resp.Candidates) > 0 && len(resp.Candidates[0].Content.Parts) > 0 { htmlContent := resp.Candidates[0].Content.Parts[0] w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, htmlContent) } }
Das Logging ist so konfiguriert, dass Logs in stdout
ausgegeben werden, wo sie vom Cloud Run-Logging-Agent erfasst und asynchron in Cloud Logging aufgenommen werden. Die Funktion main()
wird so geändert, dass das standardmäßige strukturierte Go-Log JSON-Schema verwendet, das den Richtlinien für die strukturierte Formatierung entspricht. Alle return
-Anweisungen werden durch den Code ersetzt, der vor dem Beenden Fehlerprotokolle schreibt. Die Funktion Handler()
ist so instrumentiert, dass beim Empfang der Antwort vom Vertex AI API-Aufruf ein strukturiertes Protokoll geschrieben wird. Das Protokoll erfasst den Tierparameter der Anfrage sowie den Prompt und die Antwort des Modells.
Nach einigen Sekunden werden Ihre Änderungen automatisch im Cloud Shell-Editor gespeichert.
Code der Gen AI-Anwendung in Cloud Run bereitstellen
- Führen Sie im Terminalfenster den Befehl aus, um den Quellcode der Anwendung in Cloud Run bereitzustellen.
Sie sehen die folgende Aufforderung, dass mit dem Befehl ein neues Repository erstellt wird. Klicken Sie aufgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Die Bereitstellung kann einige Minuten dauern. Nach Abschluss des Bereitstellungsvorgangs wird eine Ausgabe wie die folgende angezeigt:Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-central1] will be created. Do you want to continue (Y/n)?
Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic. Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
- Kopieren Sie die angezeigte Cloud Run-Dienst-URL in einen separaten Tab oder ein separates Fenster in Ihrem Browser. Alternativ können Sie den folgenden Befehl im Terminal ausführen, um die Dienst-URL zu drucken, und dann bei gedrückter Strg-Taste auf die angezeigte URL klicken, um sie zu öffnen:
Wenn die URL geöffnet wird, erhalten Sie möglicherweise den Fehler 500 oder die Meldung:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Die Bereitstellung der Dienste wurde nicht abgeschlossen. Warten Sie einen Moment und aktualisieren Sie die Seite. Am Ende sehen Sie einen Text, der mit Fun Dog Facts beginnt und 10 lustige Fakten über Hunde enthält.Sorry, this is just a placeholder...
Öffnen Sie die Dienst-URL, um Anwendungsprotokolle zu generieren. Aktualisieren Sie die Seite und ändern Sie den Wert des Parameters ?animal=
, um andere Ergebnisse zu erhalten.
So rufen Sie die Anwendungsprotokolle auf:
- Klicken Sie auf die Schaltfläche unten, um die Seite „Log-Explorer“ in der Cloud Console zu öffnen:
- Fügen Sie den folgenden Filter in den Abfragebereich 2 in der Log-Explorer-Benutzeroberfläche ein:
LOG_ID("run.googleapis.com%2Fstdout") AND severity=DEBUG
- Klicken Sie auf Abfrage ausführen.
Das Ergebnis der Abfrage enthält Protokolle mit Prompt und Vertex AI-Antwort, einschließlich Sicherheitsbewertungen.
9. Interaktionen mit generativer KI zählen
Cloud Run schreibt verwaltete Messwerte, mit denen bereitgestellte Dienste überwacht werden können. Von Nutzern verwaltete Monitoring-Messwerte bieten mehr Kontrolle über Daten und Häufigkeit der Aktualisierung der Messwerte. Zur Implementierung eines solchen Messwerts muss Code geschrieben werden, der Daten erfasst und in Cloud Monitoring schreibt. Im nächsten (optionalen) Schritt erfahren Sie, wie Sie dies mit dem OpenTelemetry SDK implementieren.
In diesem Schritt wird eine Alternative zur Implementierung von Nutzermesswerten im Code gezeigt: logbasierte Messwerte. Mit logbasierten Messwerten können Sie Monitoring-Messwerte aus den Logeinträgen generieren, die Ihre Anwendung in Cloud Logging schreibt. Wir verwenden die im vorherigen Schritt implementierten Anwendungsprotokolle, um einen logbasierten Messwert des Typzählers zu definieren. Der Messwert zählt die Anzahl der erfolgreichen Aufrufe der Vertex API.
- Sehen Sie sich das Fenster des Log-Explorers an, den wir im vorherigen Schritt verwendet haben. Klicken Sie im Bereich „Abfrage“ auf das Drop-down-Menü Aktionen, um es zu öffnen. Im Screenshot unten sehen Sie das Menü:
- Wählen Sie im Menü die Option Messwert erstellen aus, um den Bereich Logbasierten Messwert erstellen zu öffnen.
- So konfigurieren Sie einen neuen Zählermesswert im Bereich Logbasierten Messwert erstellen:
- Legen Sie den Messwerttyp fest: Wählen Sie Zähler aus.
- Legen Sie im Abschnitt Details die folgenden Felder fest:
- Name des Logmesswerts: Legen Sie als Namen
model_interaction_count
fest. Für die Benennung gelten einige Einschränkungen. Weitere Informationen dazu finden Sie unter Fehlerbehebung bei Benennungsbeschränkungen. - Beschreibung: Geben Sie eine Beschreibung für den Messwert ein. z. B.
Number of log entries capturing successful call to model inference.
. - Einheiten: Lassen Sie dieses Feld leer oder geben Sie die Zahl
1
ein.
- Name des Logmesswerts: Legen Sie als Namen
- Lassen Sie die Werte im Abschnitt Filterauswahl unverändert. Beachten Sie, dass im Feld Build-Filter derselbe Filter verwendet wird, mit dem wir die Anwendungsprotokolle aufgerufen haben.
- Optional: Fügen Sie ein Label hinzu, mit dem sich die Anzahl der Anrufe für jedes Tier zählen lässt. HINWEIS: Dieses Label kann die Kardinalität des Messwerts erheblich erhöhen und wird für die Produktion nicht empfohlen:
- Klicken Sie auf Label hinzufügen.
- Legen Sie im Abschnitt Labels die folgenden Felder fest:
- Labelname: Legen Sie als Namen
animal
fest. - Beschreibung: Geben Sie die Beschreibung des Labels ein. Beispiel:
Animal parameter
. - Labeltyp: Wählen Sie
STRING
aus. - Feldname: Geben Sie
jsonPayload.animal
ein. - Regulärer Ausdruck: Lassen Sie das Feld leer.
- Labelname: Legen Sie als Namen
- Klicken Sie auf Fertig.
- Klicken Sie auf Messwert erstellen, um den Messwert zu erstellen.
Sie können einen logbasierten Messwert auch auf der Seite Logbasierte Messwerte, mit dem gcloud logging metrics create
-Befehl oder mit der google_logging_metric
-Terraform-Ressource erstellen.
Öffnen Sie die Dienst-URL, um Messwertdaten zu generieren. Aktualisieren Sie die geöffnete Seite mehrmals, um das Modell mehrmals aufzurufen. Verwenden Sie wie zuvor verschiedene Tiere im Parameter.
Geben Sie die PromQL-Abfrage ein, um nach den logbasierten Messwertdaten zu suchen. So geben Sie eine PromQL-Abfrage ein:
- Klicken Sie auf die Schaltfläche unten, um die Seite „Metrics Explorer“ in der Cloud Console zu öffnen:
- Klicken Sie in der Symbolleiste des Bereichs „Query Builder“ auf die Schaltfläche < > MQL oder < > PromQL. Die Schaltfläche befindet sich an der Stelle, die auf der Abbildung unten markiert ist.
- Prüfen Sie, ob PromQL im Schalter Sprache ausgewählt ist. Die Sprachschaltfläche befindet sich in derselben Symbolleiste, mit der Sie Ihre Abfrage formatieren können.
- Geben Sie die Abfrage in den Editor Abfragen ein:
Weitere Informationen zur Verwendung von PromQL finden Sie unter PromQL in Cloud Monitoring.sum(rate(logging_googleapis_com:user_model_interaction_count{monitored_resource="cloud_run_revision"}[${__interval}]))
- Klicken Sie auf Abfrage ausführen. Sie sehen ein Liniendiagramm, das diesem Screenshot ähnelt:
Wenn die Ein/Aus-Schaltfläche Automatisch ausführen aktiviert ist, wird die Schaltfläche Abfrage ausführen nicht angezeigt.
10. Optional: OpenTelemetry für Monitoring und Tracing verwenden
Wie im vorherigen Schritt erwähnt, ist es möglich, Messwerte mit dem OpenTelemetry (Otel) SDK zu implementieren. Die Verwendung von OTel in Mikrodienstarchitekturen wird empfohlen. In diesem Schritt wird Folgendes beschrieben:
- OTel-Komponenten initialisieren, um das Tracing und Monitoring der Anwendung zu unterstützen
- OTel-Konfiguration mit Ressourcenmetadaten der Cloud Run-Umgebung füllen
- Flask-Anwendung mit automatischen Tracing-Funktionen instrumentieren
- Zählermesswert zum Überwachen der Anzahl der erfolgreichen Modellaufrufe implementieren
- Traces mit Anwendungslogs korrelieren
Für Dienste auf Produktebene wird die Verwendung des OTel-Collectors empfohlen, um alle Observabilitätsdaten für einen oder mehrere Dienste zu erfassen und zu verarbeiten. Der Code in diesem Schritt verwendet aus Gründen der Einfachheit keinen Collector. Stattdessen werden OTel-Exporte verwendet, die Daten direkt in Google Cloud schreiben.
OTel-Komponenten für Tracing und Messwertüberwachung einrichten
- Kehren Sie im Browser zum Cloud Shell-Fenster (oder -Tab) zurück.
- Öffnen Sie
setup.go
noch einmal im Terminal:cloudshell edit ~/codelab-o11y/setup.go
- Ersetzen Sie den Code durch die Version, die OpenTelemetry-Tracing und die Messwerterfassung initialisiert. Wenn Sie den Code ersetzen möchten, löschen Sie den Inhalt der Datei und kopieren Sie dann den folgenden Code und fügen Sie ihn in den Editor ein:
package main import ( "context" "errors" "fmt" "net/http" "os" "log/slog" "go.opentelemetry.io/contrib/detectors/gcp" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/contrib/propagators/autoprop" "go.opentelemetry.io/otel" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.27.0" "go.opentelemetry.io/otel/trace" cloudmetric "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric" cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" "cloud.google.com/go/compute/metadata" ) var ( projID string ) func projectID(ctx context.Context) (string, error) { var projectID = os.Getenv("GOOGLE_CLOUD_PROJECT") if projectID == "" { return metadata.ProjectIDWithContext(ctx) } return projectID, nil } func setupLogging() { opts := &slog.HandlerOptions{ Level: slog.LevelDebug, ReplaceAttr: func(group []string, a slog.Attr) slog.Attr { switch a.Key { case slog.LevelKey: a.Key = "severity" if level := a.Value.Any().(slog.Level); level == slog.LevelWarn { a.Value = slog.StringValue("WARNING") } case slog.MessageKey: a.Key = "message" case slog.TimeKey: a.Key = "timestamp" } return a }, } jsonHandler := slog.NewJSONHandler(os.Stdout, opts) instrumentedHandler := handlerWithSpanContext(jsonHandler) slog.SetDefault(slog.New(instrumentedHandler)) } type spanContextLogHandler struct { slog.Handler } func handlerWithSpanContext(handler slog.Handler) *spanContextLogHandler { return &spanContextLogHandler{Handler: handler} } func (t *spanContextLogHandler) Handle(ctx context.Context, record slog.Record) error { if s := trace.SpanContextFromContext(ctx); s.IsValid() { trace := fmt.Sprintf("projects/%s/traces/%s", projID, s.TraceID()) record.AddAttrs( slog.Any("logging.googleapis.com/trace", trace), ) record.AddAttrs( slog.Any("logging.googleapis.com/spanId", s.SpanID()), ) record.AddAttrs( slog.Bool("logging.googleapis.com/trace_sampled", s.TraceFlags().IsSampled()), ) } return t.Handler.Handle(ctx, record) } func setupTelemetry(ctx context.Context) (shutdown func(context.Context) error, err error) { var shutdownFuncs []func(context.Context) error shutdown = func(ctx context.Context) error { var err error for _, fn := range shutdownFuncs { err = errors.Join(err, fn(ctx)) } shutdownFuncs = nil return err } projID, err = projectID(ctx) if err != nil { err = errors.Join(err, shutdown(ctx)) return } res, err2 := resource.New( ctx, resource.WithDetectors(gcp.NewDetector()), resource.WithTelemetrySDK(), resource.WithAttributes(semconv.ServiceNameKey.String(os.Getenv("K_SERVICE"))), ) if err2 != nil { err = errors.Join(err2, shutdown(ctx)) return } otel.SetTextMapPropagator(autoprop.NewTextMapPropagator()) texporter, err2 := cloudtrace.New(cloudtrace.WithProjectID(projID)) if err2 != nil { err = errors.Join(err2, shutdown(ctx)) return } tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithResource(res), sdktrace.WithBatcher(texporter)) shutdownFuncs = append(shutdownFuncs, tp.Shutdown) otel.SetTracerProvider(tp) mexporter, err2 := cloudmetric.New(cloudmetric.WithProjectID(projID)) if err2 != nil { err = errors.Join(err2, shutdown(ctx)) return } mp := sdkmetric.NewMeterProvider( sdkmetric.WithReader(sdkmetric.NewPeriodicReader(mexporter)), sdkmetric.WithResource(res), ) shutdownFuncs = append(shutdownFuncs, mp.Shutdown) otel.SetMeterProvider(mp) return shutdown, nil } func registerHttpHandler(route string, handleFn http.HandlerFunc) { instrumentedHandler := otelhttp.NewHandler(otelhttp.WithRouteTag(route, handleFn), route) http.Handle(route, instrumentedHandler) }
- Kehren Sie zum Terminal zurück und führen Sie den folgenden Befehl aus, um die Go-Moduldefinitionen in der Datei
go.mod
zu aktualisieren:go mod tidy
- Kehren Sie zum Terminal zurück und öffnen Sie
main.go
noch einmal:cloudshell edit ~/codelab-o11y/main.go
- Ersetzen Sie den aktuellen Code durch die Version, die HTTP-Tracing instrumentiert und Leistungsmesswerte aufzeichnet. Wenn Sie den Code ersetzen möchten, löschen Sie den Inhalt der Datei und kopieren Sie dann den folgenden Code und fügen Sie ihn in den Editor ein:
package main import ( "context" "errors" "fmt" "net/http" "os" "encoding/json" "log/slog" "cloud.google.com/go/vertexai/genai" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" ) var model *genai.GenerativeModel var counter metric.Int64Counter const scopeName = "genai-o11y/go/workshop/example" func main() { ctx := context.Background() projectID, err := projectID(ctx) if err != nil { return } setupLogging() shutdown, err := setupTelemetry(ctx) if err != nil { slog.ErrorContext(ctx, "error setting up OpenTelemetry", slog.Any("error", err)) os.Exit(1) } meter := otel.Meter(scopeName) counter, err = meter.Int64Counter("model_call_counter") if err != nil { slog.ErrorContext(ctx, "error setting up OpenTelemetry", slog.Any("error", err)) os.Exit(1) } var client *genai.Client client, err = genai.NewClient(ctx, projectID, "us-central1") if err != nil { slog.ErrorContext(ctx, "Failed to marshal response to JSON", slog.Any("error", err)) os.Exit(1) } defer client.Close() model = client.GenerativeModel("gemini-1.5-flash-001") registerHttpHandler("/", Handler) port := os.Getenv("PORT") if port == "" { port = "8080" } if err = errors.Join(http.ListenAndServe(":"+port, nil), shutdown(ctx)); err != nil { slog.ErrorContext(ctx, "Failed to start the server", slog.Any("error", err)) os.Exit(1) } } func Handler(w http.ResponseWriter, r *http.Request) { animal := r.URL.Query().Get("animal") if animal == "" { animal = "dog" } prompt := fmt.Sprintf("Give me 10 fun facts about %s. Return the results as HTML without markdown backticks.", animal) resp, err := model.GenerateContent(r.Context(), genai.Text(prompt)) if err != nil { w.WriteHeader(http.StatusTooManyRequests) return } jsonBytes, err := json.Marshal(resp) if err != nil { slog.ErrorContext(r.Context(), "Failed to marshal response to JSON", slog.Any("error", err)) } else { slog.DebugContext(r.Context(), "content is generated", slog.String("animal", animal), slog.String("prompt", prompt), slog.String("response", string(jsonBytes))) } if len(resp.Candidates) > 0 && len(resp.Candidates[0].Content.Parts) > 0 { clabels := []attribute.KeyValue{attribute.Key("animal").String(animal)} counter.Add(r.Context(), 1, metric.WithAttributes(clabels...)) htmlContent := resp.Candidates[0].Content.Parts[0] w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprint(w, htmlContent) } }
Die Anwendung verwendet jetzt das OpenTelemetry SDK, um die Codeausführung mit Tracing zu instrumentieren und die Anzahl der erfolgreichen Ausführungen als Messwert zu zählen. Die main()
-Methode wird so geändert, dass die OpenTelemetry-Exporter für Traces und Messwerte eingerichtet werden, die direkt in Google Cloud Tracing und Monitoring geschrieben werden. Außerdem werden zusätzliche Konfigurationen durchgeführt, um die erfassten Traces und Messwerte mit Metadaten zu füllen, die sich auf die Cloud Run-Umgebung beziehen. Die Funktion Handler()
wird aktualisiert, um den Messwertzähler jedes Mal zu erhöhen, wenn der Vertex AI API-Aufruf gültige Ergebnisse zurückgibt.
Nach einigen Sekunden werden Ihre Änderungen automatisch im Cloud Shell-Editor gespeichert.
Code der Gen AI-Anwendung in Cloud Run bereitstellen
- Führen Sie im Terminalfenster den Befehl aus, um den Quellcode der Anwendung in Cloud Run bereitzustellen.
Sie sehen die folgende Aufforderung, dass mit dem Befehl ein neues Repository erstellt wird. Klicken Sie aufgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Die Bereitstellung kann einige Minuten dauern. Nach Abschluss des Bereitstellungsvorgangs wird eine Ausgabe wie die folgende angezeigt:Deploying from source requires an Artifact Registry Docker repository to store built containers. A repository named [cloud-run-source-deploy] in region [us-central1] will be created. Do you want to continue (Y/n)?
Service [codelab-o11y-service] revision [codelab-o11y-service-00001-t2q] has been deployed and is serving 100 percent of traffic. Service URL: https://codelab-o11y-service-12345678901.us-central1.run.app
- Kopieren Sie die angezeigte Cloud Run-Dienst-URL in einen separaten Tab oder ein separates Fenster in Ihrem Browser. Alternativ können Sie den folgenden Befehl im Terminal ausführen, um die Dienst-URL zu drucken, und dann bei gedrückter Strg-Taste auf die angezeigte URL klicken, um sie zu öffnen:
Wenn die URL geöffnet wird, wird möglicherweise der Fehler 500 oder die folgende Meldung angezeigt:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Die Bereitstellung der Dienste wurde nicht abgeschlossen. Warten Sie einen Moment und aktualisieren Sie die Seite. Am Ende sehen Sie einen Text, der mit Fun Dog Facts beginnt und 10 lustige Fakten über Hunde enthält.Sorry, this is just a placeholder...
Wenn Sie Telemetry-Daten generieren möchten, öffnen Sie die Dienst-URL. Aktualisieren Sie die Seite und ändern Sie den Wert des Parameters ?animal=
, um andere Ergebnisse zu erhalten.
Anwendungs-Traces untersuchen
- Klicken Sie auf die Schaltfläche unten, um die Seite „Trace Explorer“ in der Cloud Console zu öffnen:
- Wählen Sie einen der letzten Protokolle aus. Sie sollten fünf oder sechs Bereiche sehen, die wie im Screenshot unten aussehen.
- Suchen Sie den Span, der den Aufruf an den Ereignis-Handler (die Methode
fun_facts
) nachverfolgt. Es ist die letzte Span-Element mit dem Namen/
. - Wählen Sie im Bereich Trace-Details die Option Protokolle und Ereignisse aus. Sie sehen Anwendungslogs, die mit diesem bestimmten Span übereinstimmen. Die Korrelation wird anhand der Trace- und Span-IDs im Trace und im Log erkannt. Sie sollten das Anwendungsprotokoll sehen, in dem der Prompt geschrieben wurde, und die Antwort der Vertex API.
Zählermesswert ansehen
- Klicken Sie auf die Schaltfläche unten, um die Seite „Metrics Explorer“ in der Cloud Console zu öffnen:
- Klicken Sie in der Symbolleiste des Bereichs „Query Builder“ auf die Schaltfläche < > MQL oder < > PromQL. Die Schaltfläche befindet sich an der Stelle, die auf der Abbildung unten markiert ist.
- Prüfen Sie, ob PromQL im Schalter Sprache ausgewählt ist. Die Sprachschaltfläche befindet sich in derselben Symbolleiste, mit der Sie Ihre Abfrage formatieren können.
- Geben Sie die Abfrage in den Editor Abfragen ein:
sum(rate(workload_googleapis_com:model_call_counter{monitored_resource="generic_task"}[${__interval}]))
- Klicken Sie auf Abfrage ausführen.Wenn die Ein/Aus-Schaltfläche Automatisch ausführen aktiviert ist, wird die Schaltfläche Abfrage ausführen nicht angezeigt.
11. (Optional) Verschleierte vertrauliche Informationen aus Protokollen
In Schritt 10 haben wir Informationen zur Interaktion der Anwendung mit dem Gemini-Modell protokolliert. Dazu gehörten der Name des Tieres, der eigentliche Prompt und die Antwort des Modells. Das Speichern dieser Informationen im Protokoll sollte zwar sicher sein, ist aber für viele andere Szenarien nicht unbedingt erforderlich. Der Prompt kann personenbezogene oder anderweitig vertrauliche Daten enthalten, die ein Nutzer nicht speichern lassen möchte. Sie können die sensiblen Daten, die in Cloud Logging geschrieben werden, unkenntlich machen. Um Codeänderungen zu minimieren, wird die folgende Lösung empfohlen.
- Pub/Sub-Thema zum Speichern eingehender Logeinträge erstellen
- Erstellen Sie eine Log-Senke, die aufgenommene Protokolle an das Pub/Sub-Thema weiterleitet.
- So erstellen Sie eine Dataflow-Pipeline, die Logs, die an ein Pub/Sub-Thema weitergeleitet werden, ändert:
- Logeintrag aus dem Pub/Sub-Thema lesen
- Mit der DLP Inspection API die Nutzlast des Eintrags auf vertrauliche Informationen prüfen
- Entfernen Sie die sensiblen Daten in der Nutzlast mit einer der DLP-Entfernungsmethoden.
- Verschleierten Logeintrag in Cloud Logging schreiben
- Stellen Sie die Pipeline bereit.
12. (Optional) Bereinigen
Um zu vermeiden, dass Ihnen Kosten für die im Codelab verwendeten Ressourcen und APIs in Rechnung gestellt werden, sollten Sie nach Abschluss des Labs eine Bereinigung durchführen. Am einfachsten vermeiden Sie weitere Kosten, indem Sie das für das Codelab erstellte Projekt löschen.
- Führen Sie zum Löschen des Projekts den Befehl „delete project“ im Terminal aus:
Wenn Sie Ihr Cloud-Projekt löschen, wird die Abrechnung für alle in diesem Projekt verwendeten Ressourcen und APIs beendet. Es sollte folgende Meldung angezeigt werden, wobeiPROJECT_ID=$(gcloud config get-value project) gcloud projects delete ${PROJECT_ID} --quiet
PROJECT_ID
Ihre Projekt-ID ist:Deleted [https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID]. You can undo this operation for a limited period by running the command below. $ gcloud projects undelete PROJECT_ID See https://cloud.google.com/resource-manager/docs/creating-managing-projects for information on shutting down projects.
- Optional: Wenn Sie eine Fehlermeldung erhalten, sehen Sie in Schritt 5 nach, wie Sie die Projekt-ID ermitteln, die Sie während des Labs verwendet haben. Ersetzen Sie ihn durch den Befehl in der ersten Anweisung. Wenn Ihre Projekt-ID beispielsweise
lab-example-project
lautet, lautet der Befehl:gcloud projects delete lab-project-id-example --quiet
13. Glückwunsch
In diesem Lab haben Sie eine Anwendung für generative KI erstellt, die mit dem Gemini-Modell Vorhersagen trifft. und die Anwendung mit wichtigen Monitoring- und Logging-Funktionen ausgestattet. Sie haben die Anwendung und die Änderungen aus dem Quellcode in Cloud Run bereitgestellt. Anschließend können Sie mit den Google Cloud-Produkten zur Beobachtbarkeit die Leistung der Anwendung im Blick behalten und so für deren Zuverlässigkeit sorgen.
Wenn Sie an einer UX-Forschungsstudie teilnehmen möchten, um die Produkte zu verbessern, mit denen Sie heute gearbeitet haben, registrieren Sie sich hier.
Hier sind einige Möglichkeiten, wie Sie Ihr Wissen vertiefen können:
- Codelab Gemini-gestützte Chat-App in Cloud Run bereitstellen
- Codelab Gemini-Funktionsaufrufe mit Cloud Run verwenden
- Videos mit der Video Intelligence API in Cloud Run-Jobs szenenweise verarbeiten
- On-Demand-Workshop Google Kubernetes Engine einrichten
- Weitere Informationen zum Konfigurieren von Zähler- und Verteilungsmesswerten mithilfe von Anwendungsprotokollen
- OTLP-Messwerte mit einem OpenTelemetry-Sidecar schreiben
- Referenz zur Verwendung von OpenTelemetry in Google Cloud