1. Omówienie
Aplikacje korzystające z generatywnej AI wymagają możliwości obserwacji jak każda inna aplikacja. Czy w przypadku generatywnej AI są wymagane specjalne techniki obserwowalności?
W tym module utworzysz prostą aplikację wykorzystującą generatywną AI. Wdróż ją w Cloud Run. Dodaj do niego niezbędne funkcje monitorowania i logowania, korzystając z usług i produktów dostrzegalności Google Cloud.
Czego się nauczysz
- napisać aplikację korzystającą z Vertex AI za pomocą edytora Cloud Shell.
- Przechowywanie kodu aplikacji w GitHubie
- Wdrażanie kodu źródłowego aplikacji w Cloud Run za pomocą interfejsu wiersza poleceń gcloud
- Dodawanie funkcji monitorowania i logowania do aplikacji z generatywną AI
- Korzystanie ze wskaźników opartych na logach
- Implementacja logowania i monitorowania za pomocą pakietu Open Telemetry SDK
- Informacje o odpowiedzialnym przetwarzaniu danych przez AI
2. Wymagania wstępne
Jeśli nie masz jeszcze konta Google, utwórz nowe konto.
3. Konfigurowanie projektu
- Zaloguj się w konsoli Google Cloud za pomocą konta Google.
- Utwórz nowy projekt lub użyj istniejącego. Zapisz identyfikator projektu, który został właśnie utworzony lub wybrany.
- Włącz płatności w projekcie.
- Przeprowadzenie tego ćwiczenia powinno kosztować mniej niż 5 USD.
- Aby uniknąć dalszych opłat, możesz usunąć zasoby, wykonując czynności podane na końcu tego laboratorium.
- Nowi użytkownicy mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
- Sprawdź, czy płatności są włączone w sekcji Moje projekty w Rozliczeniach usługi Google Cloud.
- Jeśli w kolumnie
Billing account
nowego projektu widać wartośćBilling is disabled
:- Kliknij 3 kropki w kolumnie
Actions
. - Kliknij Zmień rozliczenia.
- Wybierz konto rozliczeniowe, którego chcesz użyć.
- Kliknij 3 kropki w kolumnie
- Jeśli uczestniczysz w wydarzeniu na żywo, konto będzie prawdopodobnie nazywać się Próbne konto rozliczeniowe Google Cloud Platform.
- Jeśli w kolumnie
4. Przygotowanie edytora Cloud Shell
- Otwórz Edytor Cloud Shell. Jeśli pojawi się to pytanie o autoryzację Cloud Shell do wywoływania gcloud za pomocą Twoich danych logowania, kliknij Autoryzuj, aby kontynuować.
- Otwórz okno terminala
- Kliknij menu z 3 kreskami
- Kliknij Terminal.
- Kliknij Nowy terminal
.
- Kliknij menu z 3 kreskami
- W terminalu skonfiguruj identyfikator projektu:
Zastąpgcloud config set project [PROJECT_ID]
[PROJECT_ID]
identyfikatorem projektu. Jeśli np. identyfikator projektu tolab-example-project
, polecenie będzie wyglądać tak: Jeśli pojawi się komunikat, że gcloud prosi o Twoje dane logowania do interfejsu GCPI API, kliknij Autoryzuj, aby kontynuować.gcloud config set project lab-project-id-example
Po pomyślnym wykonaniu tej czynności powinien wyświetlić się komunikat: Jeśli widziszUpdated property [core/project].
WARNING
i pojawia się pytanieDo you want to continue (Y/N)?
, prawdopodobnie nieprawidłowo wpisano identyfikator projektu. Gdy znajdziesz prawidłowy identyfikator projektu, naciśnijN
, a potemEnter
i spróbuj ponownie uruchomić poleceniegcloud config set project
. - (Opcjonalnie) Jeśli masz problem ze znalezieniem identyfikatora projektu, uruchom to polecenie, aby wyświetlić identyfikatory wszystkich swoich projektów posortowane według czasu utworzenia w kolejności malejącej:
gcloud projects list \ --format='value(projectId,createTime)' \ --sort-by=~createTime
5. Włączanie interfejsów API Google
W terminalu włącz interfejsy API Google wymagane w tym module:
gcloud services enable \
run.googleapis.com \
cloudbuild.googleapis.com \
aiplatform.googleapis.com \
logging.googleapis.com \
monitoring.googleapis.com \
cloudtrace.googleapis.com
Wykonanie tego polecenia może trochę potrwać. W efekcie wyświetli się komunikat o udanym przeprowadzeniu operacji podobny do tego:
Operation "operations/acf.p2-73d90d00-47ee-447a-b600" finished successfully.
Jeśli pojawi się komunikat o błędzie rozpoczynający się od ERROR: (gcloud.services.enable) HttpError accessing
i zawierający informacje o błędzie podobne do tych poniżej, powtórz polecenie po 1–2 minutach.
"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. Tworzenie aplikacji generatywnej AI
Na tym etapie napiszesz kod prostej aplikacji działającej na podstawie żądań, która korzysta z modelu Gemini, aby wyświetlać 10 ciekawych faktów o wybranym przez Ciebie zwierzęciu. Aby utworzyć kod aplikacji, wykonaj te czynności.
- Utwórz w terminalu katalog
codelab-o11y
:mkdir "${HOME}/codelab-o11y"
- Zmień bieżący katalog na
codelab-o11y
:cd "${HOME}/codelab-o11y"
- Pobierz kod bootstrap aplikacji w Javie za pomocą narzędzia startowego frameworku Spring:
curl https://start.spring.io/starter.zip \ -d dependencies=web \ -d javaVersion=17 \ -d type=maven-project \ -d bootVersion=3.4.1 -o java-starter.zip
- Wypakuj kod bootstrap do bieżącego folderu:
unzip java-starter.zip
- Usuń plik archiwum z folderu:
rm java-starter.zip
- Utwórz plik
project.toml
, aby określić wersję środowiska wykonawczego Java, która ma być używana podczas wdrażania kodu w Cloud Run:cat > "${HOME}/codelab-o11y/project.toml" << EOF [[build.env]] name = "GOOGLE_RUNTIME_VERSION" value = "17" EOF
- Dodaj zależności pakietu Google Cloud SDK do pliku
pom.xml
:- Dodaj pakiet Google Cloud Core:
sed -i 's/<dependencies>/<dependencies>\ \ <dependency>\ <groupId>com.google.cloud<\/groupId>\ <artifactId>google-cloud-core<\/artifactId>\ <version>2.49.1<\/version>\ <\/dependency>\ /g' "${HOME}/codelab-o11y/pom.xml"
- Dodaj pakiet Google Cloud Vertex AI:
sed -i 's/<dependencies>/<dependencies>\ \ <dependency>\ <groupId>com.google.cloud<\/groupId>\ <artifactId>google-cloud-vertexai<\/artifactId>\ <version>1.16.0<\/version>\ <\/dependency>\ /g' "${HOME}/codelab-o11y/pom.xml"
- Dodaj pakiet Google Cloud Core:
- Otwórz plik
DemoApplication.java
w edytorze Cloud Shell: W oknie edytora nad terminalem powinien pojawić się szkielet kodu źródłowego plikucloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
DemoApplication.java
. Kod źródłowy pliku będzie wyglądał mniej więcej tak:package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
- Zastąp kod w edytorze wersją widoczną poniżej. Aby zastąpić kod, usuń zawartość pliku, a potem skopiuj do edytora kod poniżej:
Po kilku sekundach edytor Cloud Shell automatycznie zapisze kod.package com.example.demo; import java.io.IOException; import java.util.Collections; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.google.cloud.ServiceOptions; import com.google.cloud.vertexai.VertexAI; import com.google.cloud.vertexai.api.GenerateContentResponse; import com.google.cloud.vertexai.generativeai.GenerativeModel; import com.google.cloud.vertexai.generativeai.ResponseHandler; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { String port = System.getenv().getOrDefault("PORT", "8080"); SpringApplication app = new SpringApplication(DemoApplication.class); app.setDefaultProperties(Collections.singletonMap("server.port", port)); app.run(args); } } @RestController class HelloController { private final String projectId = ServiceOptions.getDefaultProjectId(); private VertexAI vertexAI; private GenerativeModel model; @PostConstruct public void init() { vertexAI = new VertexAI(projectId, "us-central1"); model = new GenerativeModel("gemini-1.5-flash", vertexAI); } @PreDestroy public void destroy() { vertexAI.close(); } @GetMapping("/") public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException { String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks."; GenerateContentResponse response = model.generateContent(prompt); return ResponseHandler.getText(response); } }
Wdrażanie kodu aplikacji generatywnej AI w Cloud Run
- W oknie terminala uruchom polecenie, aby wdrożyć kod źródłowy aplikacji do Cloud Run.
Jeśli zobaczysz taki komunikat, oznacza to, że polecenie utworzy nowe repozytorium. Kliknijgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Proces wdrażania może potrwać kilka minut. Po zakończeniu procesu wdrażania zobaczysz dane wyjściowe podobne do tych: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
- Skopiuj wyświetlony adres URL usługi Cloud Run na osobną kartę lub do osobnego okna w przeglądarce. Możesz też uruchomić to polecenie w terminalu, aby wydrukować adres URL usługi, a potem kliknąć wyświetlony adres URL, przytrzymując klawisz Ctrl, aby go otworzyć:
Po otwarciu adresu URL może pojawić się błąd 500 lub komunikat:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Oznacza to, że usługi nie zostały wdrożone. Zaczekaj chwilę i odśwież stronę. Na końcu zobaczysz tekst zaczynający się od słów Ciekawostki o psach i zawierający 10 ciekawostek o tych zwierzętach.Sorry, this is just a placeholder...
Spróbuj wejść w interakcję z aplikacją, aby dowiedzieć się ciekawych faktów o różnych zwierzętach. Aby to zrobić, dodaj parametr animal
do adresu URL, np. ?animal=[ANIMAL]
, gdzie [ANIMAL]
to nazwa zwierzęcia. Na przykład dodaj ?animal=cat
, aby uzyskać 10 ciekawostek o kotach, lub ?animal=sea turtle
, aby uzyskać 10 ciekawostek o żółwiach morskich.
7. Sprawdzanie wywołań interfejsu Vertex API
Audyt wywołań interfejsu Google API pozwala uzyskać odpowiedzi na pytania w rodzaju „kto, gdzie i kiedy wywołał dany interfejs API?”. Weryfikacja jest ważna podczas rozwiązywania problemów z aplikacją, badania wykorzystania zasobów lub przeprowadzania analizy kryminalistycznej oprogramowania.
Logi kontrolne umożliwiają śledzenie działań administracyjnych i systemowych, a także rejestrowanie wywołań operacji interfejsu API „odczytywanie danych” i „zapisywanie danych”. Aby sprawdzić żądania Vertex AI dotyczące generowania treści, musisz włączyć logi kontrolne „Odczyt danych” w konsoli Cloud.
- Kliknij przycisk poniżej, aby otworzyć stronę Dzienniki kontrolne w konsoli Google Cloud
- Upewnij się, że na stronie wybrany jest projekt utworzony na potrzeby tego laboratorium. Wybrany projekt jest widoczny w lewym górnym rogu strony obok menu hamburgera:
W razie potrzeby wybierz odpowiedni projekt z menu. - W tabeli Konfiguracja logów kontrolnych dostępu do danych w kolumnie Usługa znajdź usługę
Vertex AI API
i kliknij pole wyboru po lewej stronie jej nazwy. - W panelu informacyjnym po prawej stronie wybierz typ audytu „Odczyt danych”.
- Kliknij Zapisz.
Aby wygenerować dzienniki kontrolne, otwórz adres URL usługi. Aby uzyskać inne wyniki, odśwież stronę, zmieniając wartość parametru ?animal=
.
Poznawanie dzienników kontrolnych
- Kliknij przycisk poniżej, aby otworzyć stronę Eksplorator logów w konsoli Google Cloud:
- Wklej ten filtr w panelu Zapytanie.
Panel Zapytanie to edytor znajdujący się u góry strony Eksplorator logów:LOG_ID("cloudaudit.googleapis.com%2Fdata_access") AND protoPayload.serviceName="aiplatform.googleapis.com"
- Kliknij Uruchom zapytanie.
- Wybierz jeden z wpisów w dzienniku kontrolnym i rozwiń pola, aby sprawdzić informacje zarejestrowane w dzienniku.
Możesz zobaczyć szczegóły wywołania interfejsu Vertex API, w tym użytą metodę i model. Możesz też zobaczyć tożsamość wywołującego i uprawnienia autoryzujące wywołanie.
8. Rejestrowanie interakcji z generatywną AI
W dziennikach kontrolnych nie ma parametrów żądania ani danych odpowiedzi interfejsu API. Te informacje mogą jednak być ważne w przypadku problemów z analizą aplikacji i przepływu pracy. W tym kroku wypełniamy tę lukę, dodając rejestrowanie aplikacji.
Implementacja używa Logback z Spring Boot do drukowania logów aplikacji na standardowe wyjście. Ta metoda wykorzystuje możliwość Cloud Run do przechwytywania informacji drukowanych na standardowym wyjściu i automatycznego przesyłania ich do Cloud Logging. Aby rejestrowane dane były uporządkowane, wydrukowane dzienniki należy odpowiednio sformatować. Aby dodać do aplikacji funkcję uporządkowanych logów, postępuj zgodnie z instrukcjami podanymi poniżej.
- Wróć do okna (lub karty) Cloud Shell w przeglądarce.
- Utwórz i otwórz nowy plik
LoggingEventGoogleCloudEncoder.java
w edytorze Cloud Shell:cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/LoggingEventGoogleCloudEncoder.java"
- Skopiuj i wklej ten kod, aby zaimplementować koder Logback, który koduje log w postaci ciągu znaków JSON zgodnie ze strukturyzowanym formatem logów Google Cloud:
package com.example.demo; import static ch.qos.logback.core.CoreConstants.UTF_8_CHARSET; import java.time.Instant; import ch.qos.logback.core.encoder.EncoderBase; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import java.util.HashMap; import com.google.gson.Gson; public class LoggingEventGoogleCloudEncoder extends EncoderBase<ILoggingEvent> { private static final byte[] EMPTY_BYTES = new byte[0]; private final Gson gson = new Gson(); @Override public byte[] headerBytes() { return EMPTY_BYTES; } @Override public byte[] encode(ILoggingEvent e) { var timestamp = Instant.ofEpochMilli(e.getTimeStamp()); var fields = new HashMap<String, Object>() { { put("timestamp", timestamp.toString()); put("severity", severityFor(e.getLevel())); put("message", e.getMessage()); } }; var params = e.getKeyValuePairs(); if (params != null && params.size() > 0) { params.forEach(kv -> fields.putIfAbsent(kv.key, kv.value)); } var data = gson.toJson(fields) + "\n"; return data.getBytes(UTF_8_CHARSET); } @Override public byte[] footerBytes() { return EMPTY_BYTES; } private static String severityFor(Level level) { switch (level.toInt()) { case Level.TRACE_INT: return "DEBUG"; case Level.DEBUG_INT: return "DEBUG"; case Level.INFO_INT: return "INFO"; case Level.WARN_INT: return "WARNING"; case Level.ERROR_INT: return "ERROR"; default: return "DEFAULT"; } } }
- Utwórz i otwórz nowy plik
logback.xml
w edytorze Cloud Shell:cloudshell edit "${HOME}/codelab-o11y/src/main/resources/logback.xml"
- Aby skonfigurować Logback do korzystania z kodera z załącznikiem Logback, który drukuje dzienniki na standardowe wyjście, skopiuj i wklej ten kod XML:
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="com.example.demo.LoggingEventGoogleCloudEncoder"/> </appender> <root level="info"> <appender-ref ref="Console" /> </root> </configuration>
- Ponownie otwórz plik
DemoApplication.java
w edytorze Cloud Shell:cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
- Aby rejestrować żądania i odpowiedzi Gen AI, zastąp kod w edytorze wersją widoczną poniżej. Aby zastąpić kod, usuń zawartość pliku, a potem skopiuj do edytora kod poniżej:
package com.example.demo; import java.io.IOException; import java.util.Collections; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.google.cloud.ServiceOptions; import com.google.cloud.vertexai.VertexAI; import com.google.cloud.vertexai.api.GenerateContentResponse; import com.google.cloud.vertexai.generativeai.GenerativeModel; import com.google.cloud.vertexai.generativeai.ResponseHandler; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { String port = System.getenv().getOrDefault("PORT", "8080"); SpringApplication app = new SpringApplication(DemoApplication.class); app.setDefaultProperties(Collections.singletonMap("server.port", port)); app.run(args); } } @RestController class HelloController { private final String projectId = ServiceOptions.getDefaultProjectId(); private VertexAI vertexAI; private GenerativeModel model; private final Logger LOGGER = LoggerFactory.getLogger(HelloController.class); @PostConstruct public void init() { vertexAI = new VertexAI(projectId, "us-central1"); model = new GenerativeModel("gemini-1.5-flash", vertexAI); } @PreDestroy public void destroy() { vertexAI.close(); } @GetMapping("/") public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException { String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks."; GenerateContentResponse response = model.generateContent(prompt); LOGGER.atInfo() .addKeyValue("animal", animal) .addKeyValue("prompt", prompt) .addKeyValue("response", response) .log("Content is generated"); return ResponseHandler.getText(response); } }
Po kilku sekundach edytor Cloud Shell automatycznie zapisuje zmiany.
Wdrażanie kodu aplikacji generatywnej AI w Cloud Run
- W oknie terminala uruchom polecenie, aby wdrożyć kod źródłowy aplikacji do Cloud Run.
Jeśli zobaczysz taki komunikat, oznacza to, że polecenie utworzy nowe repozytorium. Kliknijgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Proces wdrażania może potrwać kilka minut. Po zakończeniu procesu wdrażania zobaczysz dane wyjściowe podobne do tych: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
- Skopiuj wyświetlony adres URL usługi Cloud Run na osobną kartę lub do osobnego okna w przeglądarce. Możesz też uruchomić to polecenie w terminalu, aby wydrukować adres URL usługi, a potem kliknąć wyświetlony adres URL, przytrzymując klawisz Ctrl, aby go otworzyć:
Po otwarciu adresu URL może pojawić się błąd 500 lub komunikat:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Oznacza to, że usługi nie zostały wdrożone. Zaczekaj chwilę i odśwież stronę. Na końcu zobaczysz tekst zaczynający się od słów Ciekawostki o psach i zawierający 10 ciekawostek o tych zwierzętach.Sorry, this is just a placeholder...
Aby wygenerować dzienniki aplikacji, otwórz adres URL usługi. Aby uzyskać inne wyniki, odśwież stronę, zmieniając wartość parametru ?animal=
.
Aby wyświetlić logi aplikacji:
- Kliknij przycisk poniżej, aby otworzyć stronę Eksplorator logów w konsoli Google Cloud:
- Wklej ten filtr w panelu Zapytanie (pozycja 2 w interfejsie Eksploratora logów):
LOG_ID("run.googleapis.com%2Fstdout") AND severity=DEBUG
- Kliknij Uruchom zapytanie.
Wynik zapytania zawiera logi z promptem i odpowiedzią Vertex AI, w tym oceny bezpieczeństwa.
9. Liczenie interakcji z generatywną AI
Cloud Run zapisuje dane zarządzane, których można używać do monitorowania wdrożonych usług. Dane monitorowania zarządzane przez użytkowników zapewniają większą kontrolę nad danymi i częstotliwością ich aktualizacji. Wdrożenie takiej metryki wymaga napisania kodu, który zbiera dane i zapisują je w Cloud Monitoring. Aby dowiedzieć się, jak zaimplementować tę funkcję za pomocą pakietu OpenTelemetry SDK, przejdź do następnego (opcjonalnego) kroku.
Ten krok pokazuje alternatywę dla implementowania danych o użytkownikach w kodzie – dane oparte na logach. Dane oparte na logach umożliwiają generowanie danych monitorowania na podstawie wpisów logów zapisywanych przez aplikację w Cloud Logging. Do zdefiniowania danych typu licznik na podstawie dzienników aplikacji użyjemy dzienników aplikacji zaimplementowanych w poprzednim kroku. Dane zliczają liczbę udanych wywołań interfejsu Vertex API.
- Spójrz na okno Eksploratora logów, którego użyliśmy w poprzednim kroku. W panelu Zapytanie odszukaj menu Działania i kliknij je, aby je otworzyć. Menu znajdziesz na zrzucie ekranu poniżej:
- W otwartym menu kliknij Utwórz wskaźnik, aby otworzyć panel Utwórz wskaźnik oparty na logach.
- Aby skonfigurować nowy wskaźnik licznika w panelu Utwórz dane oparte na logach:
- Ustaw Typ wskaźnika: wybierz Licznik.
- W sekcji Szczegóły ustaw te pola:
- Nazwa wskaźnika logu: ustaw nazwę na
model_interaction_count
. Obowiązują pewne ograniczenia dotyczące nazw. Szczegółowe informacje znajdziesz w rozdziale dotyczącym rozwiązywania problemów z ograniczeniami dotyczącymi nazw. - Opis: wpisz opis danych. na przykład
Number of log entries capturing successful call to model inference.
. - Jednostki: pozostaw to pole puste lub wstaw cyfrę
1
.
- Nazwa wskaźnika logu: ustaw nazwę na
- Pozostaw wartości w sekcji Wybór filtra. Pamiętaj, że pole Filtrowanie wersji zawiera ten sam filtr, który został użyty do wyświetlenia dzienników aplikacji.
- (Opcjonalnie) Dodaj etykietę, która pomoże zliczać liczbę połączeń dla każdego zwierzęcia. UWAGA: ta etykieta może znacznie zwiększyć liczebność danych i nie jest zalecana do użytku w produkcji:
- Kliknij Dodaj etykietę.
- W sekcji Etykiety ustaw te pola:
- Nazwa etykiety: ustaw nazwę na
animal
. - Opis: wpisz opis etykiety. Na przykład:
Animal parameter
. - Typ etykiety: kliknij
STRING
. - Nazwa pola: wpisz
jsonPayload.animal
. - Wyrażenie regularne: pozostaw puste.
- Nazwa etykiety: ustaw nazwę na
- Kliknij przycisk Gotowe.
- Aby utworzyć dane, kliknij Utwórz dane.
Możesz też utworzyć wskaźnik oparty na logach na stronie Wskaźniki oparte na logach, używając gcloud logging metrics create
polecenia wiersza poleceń lub google_logging_metric
zasobu Terraform.
Aby wygenerować dane, otwórz adres URL usługi. Odśwież otwartą stronę kilka razy, aby wykonać kilka wywołań modelu. Podobnie jak wcześniej, spróbuj użyć w tym parametrze różnych zwierząt.
Wpisz zapytanie PromQL, aby wyszukać dane wskaźnika opartego na logach. Aby wpisać zapytanie PromQL:
- Kliknij przycisk poniżej, aby otworzyć stronę Eksplorator danych w konsoli Google Cloud:
- Na pasku narzędzi w panelu kreatora zapytań kliknij przycisk o nazwie < > MQL lub < > PromQL. Lokalizacja przycisku – patrz obraz poniżej.
- Sprawdź, czy w opcji Język wybrana jest opcja PromQL. Przełącznik języka znajduje się na tej samej belce narzędzi, która umożliwia formatowanie zapytania.
- Wpisz zapytanie w edytorze Zapytania:
Więcej informacji o używaniu PromQL znajdziesz w artykule PromQL w Cloud Monitoring.sum(rate(logging_googleapis_com:user_model_interaction_count{monitored_resource="cloud_run_revision"}[${__interval}]))
- Kliknij Uruchom zapytanie. Zobaczysz wykres liniowy podobny do tego:
Pamiętaj, że gdy włączony jest przełącznik Automatyczne uruchamianie, przycisk Uruchom zapytanie nie jest widoczny.
10. (Opcjonalnie) Używanie OpenTelemetry do monitorowania i śledzenia
Jak wspomnieliśmy w poprzednim kroku, dane można implementować za pomocą pakietu OpenTelemetry (Otel) SDK. Zalecane jest używanie usługi OTel w architekturach wielousługowych. Ten krok pokazuje dodawanie pomiarów OTel do aplikacji Spring Boot. Na tym etapie wykonasz te czynności:
- Dodawanie do aplikacji Spring Boot możliwości automatycznego śledzenia
- Wdrożenie licznika do monitorowania liczby udanych wywołań modelu
- Korelacja śledzenia z logami aplikacji
Zalecana architektura usług na poziomie usługi polega na użyciu kolektora Otel do zbierania i przetwarzania wszystkich danych dotyczących możliwości obserwacji z wielu usług. Ze względu na prostotę kod na tym etapie nie korzysta z kolekcjonera. Zamiast tego używa eksportów OTel, które zapisują dane bezpośrednio w Google Cloud.
Konfigurowanie aplikacji Spring Boot z komponentami OTel i automatycznym śledzeniem
- Wróć do okna (lub karty) Cloud Shell w przeglądarce.
- W terminalu zaktualizuj plik
application.permissions
, dodając do niego dodatkowe parametry konfiguracji: Te parametry definiują eksportowanie danych o obserwowalności do Cloud Trace i Cloud Monitoring oraz wymuszają próbkowanie wszystkich śladów.cat >> "${HOME}/codelab-o11y/src/main/resources/application.properties" << EOF otel.logs.exporter=none otel.traces.exporter=google_cloud_trace otel.metrics.exporter=google_cloud_monitoring otel.resource.attributes.service.name=codelab-o11y-service otel.traces.sampler=always_on EOF
- Dodaj do pliku
pom.xml
wymagane zależności OpenTelemetry:sed -i 's/<dependencies>/<dependencies>\ \ <dependency>\ <groupId>io.opentelemetry.instrumentation<\/groupId>\ <artifactId>opentelemetry-spring-boot-starter<\/artifactId>\ <\/dependency>\ <dependency>\ <groupId>com.google.cloud.opentelemetry<\/groupId>\ <artifactId>exporter-auto<\/artifactId>\ <version>0.33.0-alpha<\/version>\ <\/dependency>\ <dependency>\ <groupId>com.google.cloud.opentelemetry<\/groupId>\ <artifactId>exporter-trace<\/artifactId>\ <version>0.33.0<\/version>\ <\/dependency>\ <dependency>\ <groupId>com.google.cloud.opentelemetry<\/groupId>\ <artifactId>exporter-metrics<\/artifactId>\ <version>0.33.0<\/version>\ <\/dependency>\ /g' "${HOME}/codelab-o11y/pom.xml"
- Dodaj plik BOM OpenTelemetry do pliku
pom.xml
:sed -i 's/<\/properties>/<\/properties>\ <dependencyManagement>\ <dependencies>\ <dependency>\ <groupId>io.opentelemetry.instrumentation<\/groupId>\ <artifactId>opentelemetry-instrumentation-bom<\/artifactId>\ <version>2.12.0<\/version>\ <type>pom<\/type>\ <scope>import<\/scope>\ <\/dependency>\ <\/dependencies>\ <\/dependencyManagement>\ /g' "${HOME}/codelab-o11y/pom.xml"
- Ponownie otwórz plik
DemoApplication.java
w edytorze Cloud Shell:cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/DemoApplication.java"
- Zastąp bieżący kod wersją, która zwiększa dane o skuteczności. Aby zastąpić kod, usuń zawartość pliku, a potem skopiuj do edytora kod poniżej:
package com.example.demo; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.metrics.LongCounter; import java.io.IOException; import java.util.Collections; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.google.cloud.ServiceOptions; import com.google.cloud.vertexai.VertexAI; import com.google.cloud.vertexai.api.GenerateContentResponse; import com.google.cloud.vertexai.generativeai.GenerativeModel; import com.google.cloud.vertexai.generativeai.ResponseHandler; @SpringBootApplication public class DemoApplication { public static void main(String[] args) { String port = System.getenv().getOrDefault("PORT", "8080"); SpringApplication app = new SpringApplication(DemoApplication.class); app.setDefaultProperties(Collections.singletonMap("server.port", port)); app.run(args); } } @RestController class HelloController { private final String projectId = ServiceOptions.getDefaultProjectId(); private VertexAI vertexAI; private GenerativeModel model; private final Logger LOGGER = LoggerFactory.getLogger(HelloController.class); private static final String INSTRUMENTATION_NAME = "genai-o11y/java/workshop/example"; private static final AttributeKey<String> ANIMAL = AttributeKey.stringKey("animal"); private final LongCounter counter; public HelloController(OpenTelemetry openTelemetry) { this.counter = openTelemetry.getMeter(INSTRUMENTATION_NAME) .counterBuilder("model_call_counter") .setDescription("Number of successful model calls") .build(); } @PostConstruct public void init() { vertexAI = new VertexAI(projectId, "us-central1"); model = new GenerativeModel("gemini-1.5-flash", vertexAI); } @PreDestroy public void destroy() { vertexAI.close(); } @GetMapping("/") public String getFacts(@RequestParam(defaultValue = "dog") String animal) throws IOException { String prompt = "Give me 10 fun facts about " + animal + ". Return this as html without backticks."; GenerateContentResponse response = model.generateContent(prompt); LOGGER.atInfo() .addKeyValue("animal", animal) .addKeyValue("prompt", prompt) .addKeyValue("response", response) .log("Content is generated"); counter.add(1, Attributes.of(ANIMAL, animal)); return ResponseHandler.getText(response); } }
- Ponownie otwórz plik
LoggingEventGoogleCloudEncoder.java
w edytorze Cloud Shell:cloudshell edit "${HOME}/codelab-o11y/src/main/java/com/example/demo/LoggingEventGoogleCloudEncoder.java"
- Zastąp bieżący kod wersją, która dodaje atrybuty śledzenia do zapisanych dzienników. Dodanie atrybutów umożliwia powiązanie logów z odpowiednimi przedziałami śledzenia. Aby zastąpić kod, usuń zawartość pliku, a potem skopiuj do edytora kod poniżej:
package com.example.demo; import static ch.qos.logback.core.CoreConstants.UTF_8_CHARSET; import java.time.Instant; import java.util.HashMap; import ch.qos.logback.core.encoder.EncoderBase; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import com.google.cloud.ServiceOptions; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.SpanContext; import io.opentelemetry.context.Context; import com.google.gson.Gson; public class LoggingEventGoogleCloudEncoder extends EncoderBase<ILoggingEvent> { private static final byte[] EMPTY_BYTES = new byte[0]; private final Gson gson; private final String projectId; private final String tracePrefix; public LoggingEventGoogleCloudEncoder() { this.gson = new Gson(); this.projectId = lookUpProjectId(); this.tracePrefix = "projects/" + (projectId == null ? "" : projectId) + "/traces/"; } private static String lookUpProjectId() { return ServiceOptions.getDefaultProjectId(); } @Override public byte[] headerBytes() { return EMPTY_BYTES; } @Override public byte[] encode(ILoggingEvent e) { var timestamp = Instant.ofEpochMilli(e.getTimeStamp()); var fields = new HashMap<String, Object>() { { put("timestamp", timestamp.toString()); put("severity", severityFor(e.getLevel())); put("message", e.getMessage()); SpanContext context = Span.fromContext(Context.current()).getSpanContext(); if (context.isValid()) { put("logging.googleapis.com/trace", tracePrefix + context.getTraceId()); put("logging.googleapis.com/spanId", context.getSpanId()); put("logging.googleapis.com/trace_sampled", Boolean.toString(context.isSampled())); } } }; var params = e.getKeyValuePairs(); if (params != null && params.size() > 0) { params.forEach(kv -> fields.putIfAbsent(kv.key, kv.value)); } var data = gson.toJson(fields) + "\n"; return data.getBytes(UTF_8_CHARSET); } @Override public byte[] footerBytes() { return EMPTY_BYTES; } private static String severityFor(Level level) { switch (level.toInt()) { case Level.TRACE_INT: return "DEBUG"; case Level.DEBUG_INT: return "DEBUG"; case Level.INFO_INT: return "INFO"; case Level.WARN_INT: return "WARNING"; case Level.ERROR_INT: return "ERROR"; default: return "DEFAULT"; } } }
Po kilku sekundach edytor Cloud Shell automatycznie zapisuje zmiany.
Wdrażanie kodu aplikacji generatywnej AI w Cloud Run
- W oknie terminala uruchom polecenie, aby wdrożyć kod źródłowy aplikacji do Cloud Run.
Jeśli zobaczysz taki komunikat, oznacza to, że polecenie utworzy nowe repozytorium. Kliknijgcloud run deploy codelab-o11y-service \ --source="${HOME}/codelab-o11y/" \ --region=us-central1 \ --allow-unauthenticated
Enter
. Proces wdrażania może potrwać kilka minut. Po zakończeniu procesu wdrażania zobaczysz dane wyjściowe podobne do tych: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
- Skopiuj wyświetlony adres URL usługi Cloud Run na osobną kartę lub do osobnego okna w przeglądarce. Możesz też uruchomić to polecenie w terminalu, aby wydrukować adres URL usługi, a potem kliknąć wyświetlony adres URL, przytrzymując klawisz Ctrl, aby go otworzyć:
Po otwarciu adresu URL może pojawić się błąd 500 lub komunikat:gcloud run services list \ --format='value(URL)' \ --filter='SERVICE:"codelab-o11y-service"'
Oznacza to, że usługi nie zostały wdrożone. Zaczekaj chwilę i odśwież stronę. Na końcu zobaczysz tekst zaczynający się od słów Ciekawostki o psach i zawierający 10 ciekawostek o tych zwierzętach.Sorry, this is just a placeholder...
Aby wygenerować dane telemetryczne, otwórz adres URL usługi. Aby uzyskać inne wyniki, odśwież stronę, zmieniając wartość parametru ?animal=
.
Analiza śladów aplikacji
- Kliknij przycisk poniżej, aby otworzyć stronę Eksplorator logów czasu w konsoli Cloud:
- Wybierz jeden z najnowszych śladów. Powinieneś/powinnaś zobaczyć 5 lub 6 elementów, które wyglądają jak na zrzucie ekranu poniżej.
- Znajdź blok kodu, który śledzi wywołanie do metody obsługi zdarzenia (metoda
fun_facts
). Będzie to ostatni element o nazwie/
. - W panelu Szczegóły śledzenia kliknij Logi i zdarzenia. Zobaczysz logi aplikacji powiązane z tym konkretnym spanem. Korelacja jest wykrywana na podstawie identyfikatorów śledzenia i spanu w logu czasu. Powinieneś zobaczyć log aplikacji, który zawiera prompt i odpowiedź interfejsu Vertex API.
Wskaźnik licznika
- Kliknij przycisk poniżej, aby otworzyć stronę Eksplorator danych w konsoli Google Cloud:
- Na pasku narzędzi w panelu kreatora zapytań kliknij przycisk o nazwie < > MQL lub < > PromQL. Lokalizacja przycisku – patrz obraz poniżej.
- Sprawdź, czy w opcji Język wybrana jest opcja PromQL. Przełącznik języka znajduje się na tej samej belce narzędzi, która umożliwia formatowanie zapytania.
- Wpisz zapytanie w edytorze Zapytania:
sum(rate(workload_googleapis_com:model_call_counter{monitored_resource="generic_task"}[${__interval}]))
- Kliknij Uruchom zapytanie.Gdy włączony jest przełącznik Automatyczne uruchamianie, przycisk Uruchom zapytanie nie jest widoczny.
11. (Opcjonalnie) Zaciemnione informacje poufne z logów
W kroku 10 odnotowaliśmy informacje o interakcjach aplikacji z modelem Gemini. Informacje te obejmowały nazwę zwierzęcia, prompt i odpowiedź modelu. Przechowywanie tych informacji w dzienniku powinno być bezpieczne, ale niekoniecznie w wielu innych przypadkach. Prośba może zawierać dane osobowe lub wrażliwe, których użytkownik nie chce przechowywać. Aby to rozwiązać, możesz zafałszować dane wrażliwe zapisywane w Cloud Logging. Aby zminimalizować modyfikacje kodu, zalecamy zastosowanie tego rozwiązania.
- Tworzenie tematu Pub/Sub do przechowywania przychodzących wpisów w logach
- Utwórz ujście logów, które przekierowuje pozyskane logi do tematu Pub/Sub.
- Utwórz potok Dataflow, który modyfikuje dzienniki przekierowywane do tematu Pub/Sub. Aby to zrobić:
- Czytanie wpisu w logu z tematu PubSub
- Sprawdzanie danych wejściowych rekordu pod kątem informacji poufnych za pomocą interfejsu DLP inspection API
- Usuń informacje poufne z ładunku za pomocą jednej z metod zapobiegania utracie danych.
- Zapisywanie zafałszowanego wpisu w pliku logów w Cloud Logging
- Wdrażanie potoku
12. (Opcjonalnie) Czyszczenie
Aby uniknąć opłat za zasoby i interfejsy API używane w tym samouczku, zalecamy wyczyszczenie po jego ukończeniu. Najprostszym sposobem na uniknięcie płatności jest usunięcie projektu utworzonego na potrzeby tego samouczka.
- Aby usunąć projekt, uruchom w terminalu polecenie usuwania projektu:
Usunięcie projektu Cloud powoduje zaprzestanie naliczania opłat za wszystkie zasoby i interfejsy API używane w tym projekcie. Powinien pojawić się komunikat, w którymPROJECT_ID=$(gcloud config get-value project) gcloud projects delete ${PROJECT_ID} --quiet
PROJECT_ID
będzie identyfikatorem projektu: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.
- (Opcjonalnie) Jeśli pojawi się błąd, w kroku 5 sprawdź, jak znaleźć identyfikator projektu użyty w tym module. Zastąp nim polecenie w pierwszej instrukcji. Jeśli np. identyfikator projektu to
lab-example-project
, polecenie będzie wyglądać tak:gcloud projects delete lab-project-id-example --quiet
13. Gratulacje
W tym module udało Ci się utworzyć aplikację generatywnej AI, która do prognozowania korzysta z modela Gemini. W aplikacji zostały też zaimplementowane podstawowe funkcje monitorowania i logowania. Wdrożysz aplikację i zmiany z kodu źródłowego w Cloud Run. Następnie możesz używać usług Google Cloud Observability do śledzenia wydajności aplikacji, aby mieć pewność, że jest ona niezawodna.
Jeśli chcesz wziąć udział w badaniu wrażeń użytkowników (UX), aby ulepszyć produkty, z których korzystasz, zarejestruj się tutaj.
Oto kilka opcji dalszej nauki:
- Codelab Wdrażanie aplikacji do czatu opartej na Gemini w Cloud Run
- Codelab Jak używać wywoływania funkcji Gemini z Cloud Run
- Jak za pomocą interfejsu Cloud Run Jobs Video Intelligence API przetwarzać filmy według scen
- Warsztat na żądanie Google Kubernetes Engine – wprowadzenie
- Dowiedz się więcej o konfigurowaniu wskaźników licznika i rozkładu za pomocą dzienników aplikacji
- Zapisywanie wskaźników OTLP za pomocą podrzędnego komponentu OpenTelemetry
- Informacje o korzystaniu z Open Telemetry w Google Cloud