1. Cele
Celem tych warsztatów jest zapewnienie użytkownikom i praktykom praktycznego doświadczenia dotyczącego Duet AI.
Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak:
- Aktywuj Duet AI w projekcie GCP i skonfiguruj ją do użycia w IDE oraz konsoli Cloud.
- Używaj Duet AI do generowania, uzupełniania i wyjaśniania informacji.
- Użyj Duet AI, aby wyjaśnić i rozwiązać problem z aplikacją.
- Funkcje Duet AI, takie jak czat w IDE i czat wieloetapowy, generowanie kodu na czacie lub w tekście oraz inteligentne działania, takie jak objaśnianie kodu i potwierdzenie recytacji.
Narrative
Aby pokazać autentyczne wykorzystanie Duet AI dla programistów w codziennym rozwoju aplikacji, ćwiczenia mają miejsce w kontekście narracyjnym.
Do firmy e-commerce dołącza nowy deweloper. Mają oni dodać nową usługę do istniejącej aplikacji e-commerce (która składa się z wielu usług). Nowa usługa dostarcza dodatkowych informacji (o wymiarach, wadze itp.) na temat produktów w katalogu. Ta usługa umożliwia uzyskanie lepszych lub tańszych kosztów dostawy na podstawie wymiarów i wagi produktów.
Ponieważ deweloper dopiero zaczyna korzystać z firmy, będzie używać Duet AI do generowania kodu, wyjaśnień i dokumentacji.
Po zakodowaniu usługi administrator platformy użyje Duet AI (czatu), aby pomóc utworzyć artefakt (kontener Dockera) i zasoby potrzebne do wdrożenia artefaktu w GCP (np.Artifact Registry, uprawnienia uprawnień, repozytorium kodu, infrastruktura obliczeniowa, np. GKE lub CloudRun).
Po wdrożeniu aplikacji w GCP operator aplikacji/środowisko SRE będzie korzystać z Duet AI (i Cloud Ops) do rozwiązania problemów z błędami w nowej usłudze.
Profil klienta
Warsztaty obejmują następujące profile:
- Programista aplikacji – wymagana jest pewna wiedza z zakresu programowania i tworzenia oprogramowania.
Ta odmiana warsztatów Duet AI jest przeznaczona tylko dla deweloperów. Nie wymaga znajomości zasobów chmury GCP. Skrypty pokazujące, jak skompilować zasoby GCP wymagane do uruchomienia tej aplikacji, znajdziesz tutaj. Aby wdrożyć wymagane zasoby GCP, postępuj zgodnie z instrukcjami w tym przewodniku.
2. Przygotowywanie środowiska
Aktywuję Duet AI
Możesz aktywować Duet AI w projekcie GCP za pomocą interfejsu API (gcloud lub narzędzi IaC, takich jak Terraform) albo za pomocą interfejsu użytkownika konsoli Cloud.
Aby aktywować Duet AI w projekcie Google Cloud, włącz interfejs Cloud AI Companion API i przypisz do użytkowników role uprawnień Użytkownik usługi Cloud AI Companion oraz Wyświetlający wykorzystanie usług.
Przez gcloud
Aktywuj Cloud Shell:
Skonfiguruj PROJECT_ID
i USER
oraz włącz interfejs Cloud AI Companion API.
export PROJECT_ID=<YOUR PROJECT ID> export USER=<YOUR USERNAME> # Use your full LDAP, e.g. name@example.com gcloud config set project ${PROJECT_ID} gcloud services enable cloudaicompanion.googleapis.com --project ${PROJECT_ID}
Dane wyjściowe wyglądają tak:
Updated property [core/project]. Operation "operations/acat.p2-60565640195-f37dc7fe-b093-4451-9b12-934649e2a435" finished successfully.
Przypisz do konta USER role Użytkownik usługi Cloud AI Companion oraz Wyświetlający wykorzystanie usług. Interfejs Cloud Companion API znajduje się w tyle za funkcjami dostępnymi w IDE i konsoli, których będziemy używać. Uprawnienie Wyświetlający wykorzystanie usług służy do szybkiego sprawdzenia przed włączeniem interfejsu użytkownika w konsoli (dzięki czemu interfejs Duet AI jest widoczny tylko w projektach, w których interfejs API jest włączony).
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER} --role=roles/cloudaicompanion.user gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member=user:${USER} --role=roles/serviceusage.serviceUsageViewer
Dane wyjściowe wyglądają tak:
... - members: - user:<YOUR USER ACCOUNT> role: roles/cloudaicompanion.user ... - members: - user:<YOUR USER ACCOUNT> role: roles/serviceusage.serviceUsageViewer
W konsoli Cloud
Aby włączyć ten interfejs API, otwórz stronę Cloud AI Companion API w konsoli Google Cloud.
W selektorze projektów wybierz projekt.
Kliknij Włącz.
Strona zostanie zaktualizowana i wyświetli się stan Włączona. Usługa Duet AI jest teraz dostępna w wybranym projekcie Google Cloud dla wszystkich użytkowników, którzy mają przypisane wymagane role uprawnień.
Aby przypisać role uprawnień wymagane do korzystania z Duet AI, otwórz stronę IAM.
W kolumnie Podmiot zabezpieczeń znajdź UŻYTKOWNIKA, któremu chcesz włączyć dostęp do Duet AI, a potem kliknij ikonę ołówka ✏️ Edytuj podmiot zabezpieczeń w tym wierszu.
W panelu dostępu Edytowanie kliknij dodaj Dodaj kolejną rolę.
W sekcji Wybierz rolę wybierz Użytkownik usługi Cloud AI Companion.
Kliknij Dodaj kolejną rolę i wybierz Wyświetlający wykorzystanie usług.
Kliknij Zapisz.
Konfigurowanie IDE
Deweloperzy mogą wybierać spośród różnych IDE, które najlepiej odpowiadają ich potrzebom. Pomoc dotycząca kodu w Duet AI jest dostępna w wielu IDE, takich jak Visual Studio Code, JetBrains IDE (IntelliJ, PyCharm, GoLand, WebStorm i inne), Cloud Workstations oraz edytor Cloud Shell.
W tym module możesz użyć Cloud Workstations lub edytora Cloud Shell.
W tym warsztatach używany jest edytor Cloud Shell.
Pamiętaj, że konfiguracja Cloud Workstations może potrwać 20–30 minut.
Aby od razu z niej skorzystać, użyj edytora Cloud Shell.
Otwórz edytor Cloud Shell, klikając ikonę ołówka ✏️ na górnym pasku menu Cloud Shell.
Interfejs użytkownika i UX edytora Cloud Shell jest bardzo podobny do interfejsu VSCode.
Kliknij CTRL (Windows)/CMD (Mac) + , (przecinek), aby otworzyć okienko Ustawienia.
Na pasku wyszukiwania wpisz „duet ai”.
Sprawdź lub włącz Cloudcode › Duet AI: Włącz i Cloudcode › Duet AI › Wbudowane sugestie: włącz automatyczne
Na pasku stanu u dołu kliknij Cloud Code – Sign In (Cloud Code – logowanie) i postępuj zgodnie z instrukcjami logowania.
Jeśli jesteś już zalogowany(-a), na pasku stanu wyświetli się komunikat Cloud Code – Brak projektu.
Kliknij Cloud Code – Brak projektu. U góry pojawi się okienko akcji. Kliknij Wybierz projekt Google Cloud.
Zacznij wpisywać identyfikator PROJEKTU, a Twój projekt powinien pojawić się na liście.
Z listy projektów wybierz swój PROJECT_ID.
Pasek stanu u dołu zmieni się i będzie wyświetlał identyfikator projektu. Jeśli tak się nie stanie, być może trzeba będzie odświeżyć kartę edytora Cloud Shell.
Kliknij ikonę Duet AI na pasku menu po lewej stronie, aby wyświetlić okno czatu z Duet AI. Jeśli pojawi się komunikat Wybierz projekt GCP. Kliknij projekt i wybierz go ponownie.
Zobaczysz teraz okno czatu z Duet AI
3. Konfigurowanie infrastruktury
Aby uruchomić nową usługę dostawy w GCP, potrzebujesz tych zasobów GCP:
- Instancja Cloud SQL z bazą danych.
- Klaster GKE do uruchomienia skonteneryzowanej usługi.
- Artifact Registry do przechowywania obrazu Dockera.
- Cloud Source Repositories dla kodu.
W terminalu Cloud Shell skopiuj poniższe repozytorium i uruchom następujące polecenia, aby skonfigurować infrastrukturę w projekcie GCP.
# Set your project export PROJECT_ID=<INSERT_YOUR_PROJECT_ID> gcloud config set core/project ${PROJECT_ID} # Enable Cloudbuild and grant Cloudbuild SA owner role export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format 'value(projectNumber)') gcloud services enable cloudbuild.googleapis.com gcloud projects add-iam-policy-binding ${PROJECT_ID} --member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com --role roles/owner # Clone the repo git clone https://github.com/duetailabs/dev.git ~/duetaidev cd ~/duetaidev # Run Cloudbuild to create the necessary resources gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} # To destroy all GCP resources, run the following # gcloud builds submit --substitutions=_PROJECT_ID=${PROJECT_ID} --config=cloudbuild_destroy.yaml
4. Opracowywanie usługi Python Flask
Ostatecznie utworzona usługa będzie się składać z poniższych plików. Nie musisz tworzyć tych plików teraz. Możesz tworzyć je pojedynczo, postępując zgodnie z poniższymi instrukcjami:
package-service.yaml
– specyfikacja interfejsu Open API w usłudze pakietu z danymi, takimi jak wysokość, szerokość, waga i specjalne instrukcje obsługi.data_model.py
– model danych na potrzeby specyfikacji interfejsu API usługi pakietów. Tworzy też tabelępackages
w bazie danych product_details.connect_connector.py
– połączenie z Cloud SQL (definicja silnika, sesji i podstawowego ORM)db_init.py
– generuje przykładowe dane w tabelipackages
.main.py
– usługa Python Flask z punktem końcowymGET
do pobierania szczegółów pakietu z danychpackages
na podstawie elementu product_id.test.py
– test jednostkowyrequirement.txt
– wymagania PythonaDockerfile
– aby skonteneryzować tę aplikację
Jeśli podczas ćwiczeń napotkasz jakieś problemy, wszystkie gotowe pliki znajdziesz w DODATEK do tego ćwiczenia z programowania.
W poprzednim kroku utworzyliśmy repozytorium Cloud Source Repositories. Skopiuj repozytorium. Pliki aplikacji skompilujesz w folderze sklonowanego repozytorium.
W terminalu Cloud Shell uruchom poniższe polecenie, aby sklonować repozytorium.
cd ~ gcloud source repos clone shipping shipping cd ~/shipping
Otwórz pasek boczny czatu Duet AI w menu po lewej stronie edytora Cloud Shell. Wygląd ikony: . Aby uzyskać pomoc w kodowaniu, możesz teraz używać Duet AI.
package-service.yaml
Jeśli nie masz otwartych plików, poproś Duet o wygenerowanie specyfikacji Open API dla usługi dostawy.
Prompt 1. Wygeneruj specyfikację yaml OpenAPI dla usługi, która dostarcza informacje o dostawie i przesyłce na podstawie liczbowego identyfikatora produktu. Usługa powinna zawierać informacje o wysokości, szerokości, głębokości i wadze paczki oraz specjalne instrukcje obsługi.
W prawym górnym rogu wygenerowanego okna kodu dostępne są 3 opcje.
Możesz COPY
kod i WKLEJ go do pliku.
Możesz ADD
kod do obecnie otwartego pliku w edytorze.
Możesz też OPEN
kod w nowym pliku.
Kliknij OPEN
kod w nowym pliku.
Kliknij CTRL/CMD + s
, aby zapisać plik, i zapisz go w folderze aplikacji pod nazwą package-service.yaml
. Kliknij przycisk OK.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Możesz też wypróbować różne prompty, aby zobaczyć odpowiedzi Duet AI.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
data_model.py
Następnie utwórz plik Python modelu danych dla usługi na podstawie specyfikacji OpenAPI.
Po otwarciu pliku package-service.yaml
wpisz ten prompt.
Prompt 1. Wygeneruj model danych dla tej usługi interfejsu API przy użyciu języka sqlalchemy ORM w języku Python. Dołącz też oddzielną funkcję i główny punkt wejścia, który tworzy tabele bazy danych.
Przyjrzyjmy się każdej wygenerowanej części. Duet AI to nadal asystent i choć może szybko pomóc w tworzeniu kodu, warto jednak sprawdzać wygenerowane treści i rozumieć je na bieżąco.
Pierwszy z nich to Class o nazwie Package
rodzajuBase
, która określa model danych dla bazy danych packages
w ten sposób:
class Package(Base):
__tablename__ = 'packages'
id = Column(Integer, primary_key=True)
product_id = Column(String(255))
height = Column(Float)
width = Column(Float)
depth = Column(Float)
weight = Column(Float)
special_handling_instructions = Column(String(255))
Następnie potrzebujesz funkcji, która tworzy tabelę w bazie danych w podobny sposób:
def create_tables(engine):
Base.metadata.create_all(engine)
Aby utworzyć tabelę w bazie danych Cloud SQL, potrzebujesz głównej funkcji, która uruchamia funkcję create_tables
, na przykład:
if __name__ == '__main__':
from sqlalchemy import create_engine
engine = create_engine('sqlite:///shipping.db')
create_tables(engine)
print('Tables created successfully.')
Pamiętaj, że funkcja main
tworzy silnik z użyciem lokalnej bazy danych sqlite
. Aby używać Cloud SQL, musisz go zmienić. Zrobisz to później.
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie
data_model.py
(zwróć uwagę na podkreślenie w nazwie, a nie znak myślnika).
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
connect-connector.py
Utwórz oprogramowanie sprzęgające Cloud SQL.
Po otwarciu pliku data_model.py
wpisz te prompty.
Prompt 1. Wygeneruj funkcję inicjującą pulę połączeń dla instancji Postgres w Cloud SQL przy użyciu biblioteki cloud-sql-python-connector.
Pamiętaj, że odpowiedź nie korzysta z biblioteki cloud-sql-python-connector
. Możesz doprecyzować prompty, dodając konkretne informacje do tego samego wątku czatu, aby dać usłudze Duet ponaglenia.
Użyjmy innego promptu.
Prompt 2. Musi używać biblioteki cloud-sql-python-connector.
Upewnij się, że korzysta z biblioteki cloud-sql-python-connector
.
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie
connect_conector.py
. Może być konieczne ręczne zaimportowanie biblioteki pg8000
. Zapoznaj się z plikiem poniżej.
Wyczyść historię czatu z Duet AI. W otwartym pliku connect_connector.py
wygeneruj ORM DB engine
, sessionmaker
i base
, którego będziesz używać w aplikacji.
Prompt 1. Utwórz silnik, klasę Sessionmaker i Base ORM przy użyciu metody connect_with_connector
Odpowiedź może dołączać engine
, Session
i Base
do pliku connect_connector.py
.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Możesz też wypróbować różne prompty, aby zobaczyć potencjalną zmianę odpowiedzi Duet AI.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
Aktualizowanie pliku data_model.py
Aby utworzyć tabelę w bazie danych Cloud SQL, musisz użyć silnika utworzonego w poprzednim kroku (w pliku connect_connector.py
).
Wyczyść historię czatu Duet AI. Otwórz plik data_model.py
. Wypróbuj ten prompt.
Prompt 1. W funkcji głównej zaimportuj i użyj silnika z pliku Connect_connector.py
Powinna wyświetlić się odpowiedź importująca plik engine
z serwera connect_connector
(dla Cloud SQL). create_table
używa tego silnika (zamiast domyślnej lokalnej bazy danych sqlite
).
Zaktualizuj plik data_model.py
.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Możesz też wypróbować różne prompty, aby zobaczyć różne odpowiedzi Duet AI.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
requirements.txt
Utwórz plik requirements.txt
dla aplikacji.
Otwórz zarówno plik connect_connector.py
, jak i plik data_model.py
, a następnie wprowadź następujący prompt.
Prompt 1. Wygeneruj plik wymagań dotyczących pip dla tego modelu danych i usługi
Prompt 2. Wygeneruj plik wymagań dotyczących pip dla tego modelu danych i usługi przy użyciu najnowszych wersji
Sprawdź, czy nazwy i wersje są prawidłowe. Na przykład w powyższej odpowiedzi nazwa i wersja elementu google-cloud-sql-connecter
są nieprawidłowe. Napraw ręcznie błędy wersji i utwórz plik requirements.txt
podobny do tego:
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
W terminalu poleceń uruchom to polecenie:
pip3 install -r requirements.txt
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
Tworzenie tabeli pakietów w Cloud SQL
Ustaw zmienne środowiskowe dla oprogramowania sprzęgającego bazy danych Cloud SQL.
export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)') export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)") export DB_USER=evolution export DB_PASS=evolution export DB_NAME=product_details
Teraz uruchom plik data_model.py.
python data_model.py
Wyniki są podobne do poniższych (sprawdź w kodzie, co rzeczywiście jest oczekiwane):
Tables created successfully.
Połącz się z instancją Cloud SQL i sprawdź, czy baza danych została utworzona.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Po wpisaniu hasła (również ewolucji) wyświetl tabele.
product_details=> \dt
Dane wyjściowe są podobne do tych:
List of relations Schema | Name | Type | Owner --------+----------+-------+----------- public | packages | table | evolution (1 row)
Możesz też sprawdzić szczegóły modelu danych i tabeli.
product_details=> \d+ packages
Dane wyjściowe są podobne do tych:
Table "public.packages" Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description -------------------------------+-------------------+-----------+----------+--------------------------------------+----------+-------------+--------------+------------- id | integer | | not null | nextval('packages_id_seq'::regclass) | plain | | | product_id | integer | | not null | | plain | | | height | double precision | | not null | | plain | | | width | double precision | | not null | | plain | | | depth | double precision | | not null | | plain | | | weight | double precision | | not null | | plain | | | special_handling_instructions | character varying | | | | extended | | | Indexes: "packages_pkey" PRIMARY KEY, btree (id) Access method: heap
Wpisz \q
, aby wyjść z Cloud SQL.
db_init.py
Teraz dodajmy kilka przykładowych danych do tabeli packages
.
Wyczyść historię czatu Duet AI. Po otwarciu pliku data_model.py
postępuj zgodnie z tymi instrukcjami.
Prompt 1. Wygeneruj funkcję, która tworzy 10 wierszy przykładowych pakietów i zatwierdza je w tabeli pakietów
Prompt 2. Przy użyciu sesji z connect_connector wygeneruj funkcję, która tworzy 10 przykładowych wierszy pakietów i zatwierdza je w tabeli pakietów
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie
db_init.py
.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Możesz też wypróbować różne prompty, aby zobaczyć różne odpowiedzi Duet AI.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
Tworzę dane przykładowych pakietów
Uruchom db_init.py
z poziomu wiersza poleceń.
python db_init.py
Dane wyjściowe są podobne do tych:
Packages created successfully.
Ponownie połącz się z instancją Cloud SQL i sprawdź, czy przykładowe dane zostały dodane do tabeli pakietów.
Połącz się z instancją Cloud SQL i sprawdź, czy baza danych została utworzona.
gcloud sql connect ${INSTANCE_NAME} --user=evolution --database=product_details
Po wpisaniu hasła (również ewolucji) pobierz wszystkie dane z tabeli pakietów.
product_details=> SELECT * FROM packages;
Dane wyjściowe są podobne do tych:
id | product_id | height | width | depth | weight | special_handling_instructions ----+------------+--------+-------+-------+--------+----------------------------------- 1 | 0 | 10 | 10 | 10 | 10 | No special handling instructions. 2 | 1 | 10 | 10 | 10 | 10 | No special handling instructions. 3 | 2 | 10 | 10 | 10 | 10 | No special handling instructions. 4 | 3 | 10 | 10 | 10 | 10 | No special handling instructions. 5 | 4 | 10 | 10 | 10 | 10 | No special handling instructions. 6 | 5 | 10 | 10 | 10 | 10 | No special handling instructions. 7 | 6 | 10 | 10 | 10 | 10 | No special handling instructions. 8 | 7 | 10 | 10 | 10 | 10 | No special handling instructions. 9 | 8 | 10 | 10 | 10 | 10 | No special handling instructions. 10 | 9 | 10 | 10 | 10 | 10 | No special handling instructions. (10 rows)
Wpisz \q
, aby wyjść z Cloud SQL.
main.py
Po otwarciu plików data_model.py
, package-service.yaml
i connect_connector.py
utwórz main.py
dla aplikacji.
Prompt 1. Przy użyciu biblioteki kolby w Pythonie – utwórz implementację, która w tej usłudze korzysta z punktów końcowych HTTP odpoczynku
Prompt 2. Przy użyciu biblioteki kolby w Pythonie – utwórz implementację, która w tej usłudze wykorzystuje punkty końcowe HTTP. w celu zaimportowania danych pakietów i zaimportowania elementów SessionMaker (z connect_conector.py do).
Prompt 3. Przy użyciu biblioteki kolby w Pythonie – utwórz implementację, która w tej usłudze korzysta z punktów końcowych protokołu HTTP. W przypadku danych pakietów zaimportuj pakiet z pliku data_model.py oraz użyj kreatora sesji (z connect_conector.py do) i użyj go.
Prompt 4. Przy użyciu biblioteki kolby w Pythonie – utwórz implementację, która w tej usłudze korzysta z punktów końcowych protokołu HTTP. zaimportuj pakiet z pliku data_model.py i użyj kreatora sesji z pliku connect_conector.py do, aby uzyskać dane pakietów. Użyj adresu IP hosta 0.0.0.0 na potrzeby app.run
Zaktualizuj wymagania dotyczące funkcji main.py
.
Prompt: utwórz plik wymagań dla pliku main.py
Dołącz do pliku requirements.txt
. Pamiętaj, aby używać Flask w wersji 3.0.0.
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie
main.py
.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
5. Testowanie i uruchamianie aplikacji
Zainstaluj wymagania.
pip3 install -r requirements.txt
Uruchom main.py
.
python main.py
Dane wyjściowe są podobne do tych:
* Serving Flask app 'main' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:5000 * Running on http://10.88.0.3:5000 Press CTRL+C to quit
Przetestuj punkt końcowy /packages/<product_id>
z drugiego terminala.
curl localhost:5000/packages/1
Dane wyjściowe są podobne do tych:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Możesz też przetestować pozostałe identyfikatory produktu w przykładowych danych.
Wpisz CTRL_C
, aby wyjść z działającego kontenera Dockera w terminalu.
Generuję testy jednostkowe
Po otwarciu pliku main.py
wygeneruj testy jednostkowe.
Prompt 1. Wygeneruj testy jednostkowe.
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie
test.py
.
W funkcji test_get_package
musi być zdefiniowana wartość product_id
. Możesz ją dodać ręcznie.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Zresetuj historię czatu w Duet AI, klikając ikonę kosza u góry paska bocznego Duet AI.
Przeprowadzanie testów jednostkowych
Uruchom test jednostkowy.
python test.py
Dane wyjściowe są podobne do tych:
. ---------------------------------------------------------------------- Ran 1 test in 1.061s OK
Zamknij wszystkie pliki w edytorze Cloud Shell i wyczyść historię czatu, klikając ikonę kosza na pasku stanu u góry.
Dockerfile
Utwórz Dockerfile
dla tej aplikacji.
Otwórz aplikację main.py
i skorzystaj z podanych niżej promptów.
Prompt 1. Wygeneruj plik Dockerfile dla tej aplikacji.
Prompt 2. Wygeneruj plik Dockerfile dla tej aplikacji. Skopiuj wszystkie pliki do kontenera.
Musisz też skonfigurować ENVARS
dla usług INSTANCE_CONNECTION_NAME
, DB_USER
, DB_PASS
i DB_NAME
. Możesz to zrobić ręcznie. Twój plik Dockerfile powinien wyglądać tak:
FROM python:3.10-slim
WORKDIR /app
COPY . ./
RUN pip install -r requirements.txt
# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details
CMD ["python", "main.py"]
Użyj kodu OPEN
w nowym przepływie pracy związanym z plikiem, tak jak poprzednio. Zapisz kod w pliku o nazwie Dockerfile.
Ostateczny plik znajdziesz w sekcji DODATEK tego ćwiczenia z programowania. Jeśli tak nie jest, ręcznie wprowadź odpowiednie zmiany.
Lokalne uruchamianie aplikacji
Po otwarciu aplikacji Dockerfile
wykonaj te czynności.
Prompt 1. Jak lokalnie uruchomić kontener za pomocą tego pliku Dockerfile
Postępuj zgodnie z instrukcjami.
# Build docker build -t shipping . # And run docker run -p 5000:5000 -it shipping
Dane wyjściowe są podobne do tych:
* Serving Flask app 'main' * Debug mode: off WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:5000 * Running on http://172.17.0.2:5000 Press CTRL+C to quit
Z drugiego okna terminala przejdź do kontenera.
curl localhost:5000/packages/1
Dane wyjściowe są podobne do tych:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Skonteneryzowana aplikacja działa.
Wpisz CTRL_C
, aby wyjść z działającego kontenera Dockera w terminalu.
Kompiluję obraz kontenera w Artifact Registry
Utwórz obraz kontenera i wypchnij go do Artifact Registry.
cd ~/shipping gcloud auth configure-docker us-central1-docker.pkg.dev docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping . docker push us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
Kontener aplikacji znajduje się teraz w lokalizacji us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping
, którą można wdrożyć w GKE.
6. Wdrażam aplikację w klastrze GKE
Klaster z Autopilotem w GKE został utworzony podczas tworzenia zasobów GCP na potrzeby tego warsztatu. Połącz się z klastrem GKE.
gcloud container clusters get-credentials gke1 \ --region=us-central1
Dodaj do domyślnego konta usługi Kubernetes adnotację z kontem usługi Google.
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com
Dane wyjściowe są podobne do tych:
serviceaccount/default annotated
Przygotuj i zastosuj plik k8s.yaml.
cp ~/duetaidev/k8s.yaml_tmpl ~/shipping/. export INSTANCE_NAME=$(gcloud sql instances list --format='value(name)') export INSTANCE_CONNECTION_NAME=$(gcloud sql instances describe ${INSTANCE_NAME} --format="value(connectionName)") export IMAGE_REPO=us-central1-docker.pkg.dev/${PROJECT_ID}/shipping/shipping envsubst < ~/shipping/k8s.yaml_tmpl > k8s.yaml kubectl apply -f k8s.yaml
Dane wyjściowe są podobne do tych:
deployment.apps/shipping created service/shipping created
Poczekaj, aż pody zostaną uruchomione, a do usługi zostanie przypisany adres IP zewnętrznego systemu równoważenia obciążenia.
kubectl get pods kubectl get service shipping
Dane wyjściowe są podobne do tych:
# kubectl get pods NAME READY STATUS RESTARTS AGE shipping-f5d6f8d5-56cvk 1/1 Running 0 4m47s shipping-f5d6f8d5-cj4vv 1/1 Running 0 4m48s shipping-f5d6f8d5-rrdj2 1/1 Running 0 4m47s # kubectl get service shipping NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE shipping LoadBalancer 34.118.225.125 34.16.39.182 80:30076/TCP 5m41s
W przypadku klastrów z Autopilotem w GKE poczekaj chwilę, aż zasoby będą gotowe.
Uzyskaj dostęp do usługi za pomocą adresu EXTERNAL-IP
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Dane wyjściowe są podobne do tych:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
7. Dodatkowe środki: rozwiązywanie problemów ze zgłoszeniem
Usuń rolę uprawnień klienta Cloud SQL z konta usługi cloudsqlsa
. Powoduje to błąd podczas łączenia z bazą danych Cloud SQL.
gcloud projects remove-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
Ponownie uruchom kapsułę dostawy.
kubectl rollout restart deployment shipping
Po ponownym uruchomieniu poda spróbuj ponownie uzyskać dostęp do usługi shipping
.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Dane wyjściowe są podobne do tych:
... <title>500 Internal Server Error</title> <h1>Internal Server Error</h1> <p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p>
Sprawdź logi, przechodząc do Kubernetes Engine > Zadania
Kliknij wdrożenie shipping
, a następnie kliknij kartę Logi.
Po prawej stronie paska stanu kliknij ikonę Wyświetl w Eksploratorze logów . Otworzy się nowe okno Eksplorator logów.
Kliknij jeden z Traceback
wpisów z błędami, a następnie kliknij Wyjaśnij ten wpis logu.
Przeczytaj opis błędu.
Teraz wypróbujmy Duet AI, które pomogą Ci rozwiązać problem.
Wypróbuj ten prompt.
Prompt 1. Pomóż mi rozwiązać ten problem
Wpisz w komunikacie o błędzie komunikat o błędzie.
Prompt 2. Dostęp zabroniony: wygląda na to, że uwierzytelniony podmiot zabezpieczeń uprawnień nie może wysłać żądania do interfejsu API. Weryfikacja interfejsu Cloud SQL Admin API jest włączona w projekcie GCP i w „Klientie Cloud SQL” rola została przypisana do podmiotu zabezpieczeń Uprawnień
A potem.
Prompt 3. Jak za pomocą gcloud przypisać rolę klienta Cloud SQL do konta usługi Google?
Przypisz rolę klienta Cloud SQL do: cloudsqlsa
.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member="serviceAccount:cloudsqlsa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/cloudsql.client"
Zaczekaj chwilę i spróbuj ponownie uzyskać dostęp do aplikacji.
export EXTERNAL_IP=$(kubectl get svc shipping --output jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://${EXTERNAL_IP}/packages/1
Dane wyjściowe są podobne do tych:
{"depth":10.0,"height":10.0,"special_handling_instructions":"No special handling instructions.","weight":10.0,"width":10.0}
Udało Ci się rozwiązać problem za pomocą funkcji Duet AI w Cloud Logging, Eksploratorze logów i funkcji Wyjaśnienie logów.
8. Podsumowanie
Gratulacje! Udało Ci się ukończyć to ćwiczenia z programowania.
Dzięki temu ćwiczeniu z programowania omówiliśmy te kwestie:
- Aktywuj Duet AI w projekcie GCP i skonfiguruj ją do użycia w IDE oraz konsoli Cloud.
- Używaj Duet AI do generowania, uzupełniania i wyjaśniania informacji.
- Użyj Duet AI, aby wyjaśnić i rozwiązać problem z aplikacją.
- Funkcje Duet AI, takie jak czat w IDE i czat wieloetapowy, generowanie kodu na czacie lub w tekście oraz inteligentne działania, takie jak objaśnianie kodu i potwierdzenie recytacji.
9. Dodatek
package-service.yaml
swagger: "2.0"
info:
title: Shipping and Package Information API
description: This API provides information about shipping and packages.
version: 1.0.0
host: shipping.googleapis.com
schemes:
- https
produces:
- application/json
paths:
/packages/{product_id}:
get:
summary: Get information about a package
description: This method returns information about a package, including its height, width, depth, weight, and any special handling instructions.
parameters:
- name: product_id
in: path
required: true
type: integer
format: int64
responses:
"200":
description: A successful response
schema:
type: object
properties:
height:
type: integer
format: int64
width:
type: integer
format: int64
depth:
type: integer
format: int64
weight:
type: integer
format: int64
special_handling_instructions:
type: string
"404":
description: The product_id was not found
data_model.py
from sqlalchemy import Column, Integer, String, Float
from sqlalchemy.ext.declarative import declarative_base
from connect_connector import engine
Base = declarative_base()
class Package(Base):
__tablename__ = 'packages'
id = Column(Integer, primary_key=True)
product_id = Column(Integer, nullable=False)
height = Column(Float, nullable=False)
width = Column(Float, nullable=False)
depth = Column(Float, nullable=False)
weight = Column(Float, nullable=False)
special_handling_instructions = Column(String, nullable=True)
def create_tables():
Base.metadata.create_all(engine)
if __name__ == '__main__':
create_tables()
print('Tables created successfully.')
connect_connector.py
import os
from google.cloud.sql.connector import Connector, IPTypes
import sqlalchemy
# You may need to manually import pg8000 and Base as follows
import pg8000
from sqlalchemy.ext.declarative import declarative_base
def connect_with_connector() -> sqlalchemy.engine.base.Engine:
"""Initializes a connection pool for a Cloud SQL instance of Postgres."""
# Note: Saving credentials in environment variables is convenient, but not
# secure - consider a more secure solution such as
# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
# keep secrets safe.
instance_connection_name = os.environ[
"INSTANCE_CONNECTION_NAME"
] # e.g. 'project:region:instance'
db_user = os.environ["DB_USER"] # e.g. 'my-database-user'
db_pass = os.environ["DB_PASS"] # e.g. 'my-database-password'
db_name = os.environ["DB_NAME"] # e.g. 'my-database'
ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC
connector = Connector()
def getconn() -> sqlalchemy.engine.base.Engine:
conn: sqlalchemy.engine.base.Engine = connector.connect(
instance_connection_name,
"pg8000",
user=db_user,
password=db_pass,
db=db_name,
ip_type=ip_type,
)
return conn
pool = sqlalchemy.create_engine(
"postgresql+pg8000://",
creator=getconn,
# ...
)
return pool
# Create a connection pool
engine = connect_with_connector()
# Create a sessionmaker class to create new sessions
SessionMaker = sqlalchemy.orm.sessionmaker(bind=engine)
# Create a Base class for ORM
# You may need to manually fix the following
Base = declarative_base()
db_init.py
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from connect_connector import engine
from data_model import Package
def create_packages():
# Create a session
session = sessionmaker(bind=engine)()
# Create 10 sample packages
for i in range(10):
package = Package(
product_id=i,
height=10.0,
width=10.0,
depth=10.0,
weight=10.0,
special_handling_instructions="No special handling instructions."
)
# Add the package to the session
session.add(package)
# Commit the changes
session.commit()
if __name__ == '__main__':
create_packages()
print('Packages created successfully.')
main.py
from flask import Flask, request, jsonify
from data_model import Package
from connect_connector import SessionMaker
app = Flask(__name__)
session_maker = SessionMaker()
@app.route("/packages/<int:product_id>", methods=["GET"])
def get_package(product_id):
"""Get information about a package."""
session = session_maker
package = session.query(Package).filter(Package.product_id == product_id).first()
if package is None:
return jsonify({"message": "Package not found."}), 404
return jsonify(
{
"height": package.height,
"width": package.width,
"depth": package.depth,
"weight": package.weight,
"special_handling_instructions": package.special_handling_instructions,
}
), 200
if __name__ == "__main__":
app.run(host="0.0.0.0")
test.py
import unittest
from data_model import Package
from connect_connector import SessionMaker
from main import app
class TestPackage(unittest.TestCase):
def setUp(self):
self.session_maker = SessionMaker()
def tearDown(self):
self.session_maker.close()
def test_get_package(self):
"""Test the `get_package()` function."""
package = Package(
product_id=11, # Ensure that the product_id different from the sample data
height=10,
width=10,
depth=10,
weight=10,
special_handling_instructions="Fragile",
)
session = self.session_maker
session.add(package)
session.commit()
response = app.test_client().get("/packages/11")
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.json,
{
"height": 10,
"width": 10,
"depth": 10,
"weight": 10,
"special_handling_instructions": "Fragile",
},
)
if __name__ == "__main__":
unittest.main()
requirements.txt
cloud-sql-python-connector==1.2.4
sqlalchemy==1.4.36
pg8000==1.22.0
Flask==3.0.0
gunicorn==20.1.0
psycopg2-binary==2.9.3
Dockerfile
FROM python:3.10-slim
WORKDIR /app
COPY . ./
RUN pip install -r requirements.txt
# Add these manually for your project
ENV INSTANCE_CONNECTION_NAME=YOUR_INSTANCE_CONNECTION_NAME
ENV DB_USER=evolution
ENV DB_PASS=evolution
ENV DB_NAME=product_details
CMD ["python", "main.py"]