1. Wprowadzenie
Przegląd
Jesteś programistą w firmie zajmującej się marketingiem w branży turystycznej. Twój dział sprzedaży uznał, że potrzebuje nowej aplikacji do czatowania, aby nadążyć za większymi firmami zajmującymi się rezerwacjami i wyszukiwaniem. Słyszeli też o generatywnej AI, ale nie wiedzą o niej zbyt wiele. Inne działy dowiedziały się o tej inicjatywie i zastanawiają się, jak może ona wpłynąć na wrażenia klientów.
Jakie zadania wykonasz
W tym module utworzysz czatbota będącego asystentem podróży przy użyciu modelu Gemini 2.5 Flash w Vertex AI.
Aplikacja powinna:
- Pomaga użytkownikom zadawać pytania dotyczące podróży, rezerwować podróże i uzyskiwać informacje o miejscach, do których planują się udać.
- zapewnia użytkownikom sposoby uzyskiwania pomocy dotyczącej konkretnych planów podróży;
- pobierać dane w czasie rzeczywistym, np. informacje o pogodzie, za pomocą narzędzi;
Będziesz pracować w wstępnie skonfigurowanym środowisku Google Cloud, a konkretnie w edytorze Cloud Shell. Podstawowy interfejs aplikacji internetowej jest już skonfigurowany, podobnie jak niezbędne uprawnienia dostępu do Vertex AI. Ta aplikacja została utworzona za pomocą Streamlit.
Czego się nauczysz
Z tego modułu nauczysz się, jak:
- Zapoznaj się z platformą Vertex AI, aby poznać dostępne modele generatywnej AI.
- Tworzenie w edytorze Cloud Shell i terminalu
- Korzystaj z Gemini Code Assist, aby zrozumieć kod.
- Użyj pakietu Vertex AI SDK w Pythonie, aby wysyłać prompty do modelu LLM Gemini i otrzymywać od niego odpowiedzi.
- Stosuj podstawowe inżynierowanie promptów (instrukcje systemowe, parametry modelu), aby dostosowywać dane wyjściowe modelu LLM Gemini.
- Testuj i iteracyjnie ulepszaj aplikację do czatu opartą na LLM, modyfikując prompty i parametry, aby poprawić odpowiedzi.
- Zdefiniuj i używaj narzędzi z modelem Gemini, aby włączyć wywoływanie funkcji.
- Przeprowadź refaktoryzację kodu, aby używać sesji czatu z zachowywaniem stanu, co jest sprawdzoną metodą w przypadku aplikacji konwersacyjnych.
2. Konfigurowanie projektu
Konto Google
Jeśli nie masz jeszcze osobistego konta Google, musisz je utworzyć.
Używaj konta osobistego zamiast konta służbowego lub szkolnego.
Logowanie w konsoli Google Cloud
Zaloguj się w konsoli Google Cloud za pomocą osobistego konta Google.
Włącz płatności
Wykorzystaj środki na Google Cloud o wartości 5 USD (opcjonalnie)
Aby przeprowadzić te warsztaty, musisz mieć konto rozliczeniowe z określonymi środkami. Jeśli planujesz używać własnego konta rozliczeniowego, możesz pominąć ten krok.
- Kliknij ten link i zaloguj się na osobiste konto Google.Zobaczysz coś takiego:

- Kliknij przycisk KLIKNIJ TUTAJ, ABY UZYSKAĆ DOSTĘP DO ŚRODKÓW. Spowoduje to przejście na stronę, na której możesz skonfigurować profil płatności.

- Kliknij Potwierdź.
Twoje konto jest teraz połączone z próbnym kontem rozliczeniowym Google Cloud Platform.

Konfigurowanie osobistego konta rozliczeniowego
Jeśli skonfigurujesz płatności za pomocą środków w Google Cloud, możesz pominąć ten krok.
Aby skonfigurować osobiste konto rozliczeniowe, włącz płatności w Cloud Console.
Uwagi:
- Pod względem opłat za zasoby chmury ukończenie tego modułu powinno kosztować mniej niż 1 USD.
- Jeśli chcesz uniknąć dalszych opłat, wykonaj czynności opisane na końcu tego modułu, aby usunąć zasoby.
- Nowi użytkownicy mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
Tworzenie projektu (opcjonalnie)
Jeśli nie masz bieżącego projektu, którego chcesz użyć w tym ćwiczeniu, utwórz nowy projekt.
3. Otwórz edytor Cloud Shell
- Kliknij ten link, aby przejść bezpośrednio do edytora Cloud Shell
- Jeśli w dowolnym momencie pojawi się prośba o autoryzację, kliknij Autoryzuj, aby kontynuować.

- Jeśli terminal nie pojawia się u dołu ekranu, otwórz go:
- Kliknij Wyświetl.
- Kliknij Terminal
.
- W terminalu ustaw projekt za pomocą tego polecenia:
gcloud config set project [PROJECT_ID]- Przykład:
gcloud config set project lab-project-id-example - Jeśli nie pamiętasz identyfikatora projektu, możesz wyświetlić listę wszystkich identyfikatorów projektów za pomocą tego polecenia:
gcloud projects list | awk '/PROJECT_ID/{print $2}'
- Przykład:
- Powinien wyświetlić się ten komunikat:
>aside negative Jeśli zobaczysz `WARNING` i zostanie wyświetlone pytanie `Do you want to continue (Y/n)?`, prawdopodobnie wpisano nieprawidłowy identyfikator projektu. Naciśnij „n”, a potem „Enter” i spróbuj ponownie uruchomić polecenie `gcloud config set project`. >Updated property [core/project].
4. Włącz interfejsy API
Aby używać pakietu SDK Vertex AI i wchodzić w interakcje z modelem Gemini, musisz włączyć interfejs Vertex AI API w projekcie Google Cloud.
- W terminalu włącz interfejsy API:
gcloud services enable \ aiplatform.googleapis.com
Wprowadzenie do pakietu Vertex AI SDK dla Pythona
Aby wchodzić w interakcje z modelami hostowanymi w Vertex AI z poziomu aplikacji w Pythonie, użyjesz pakietu Vertex AI SDK for Python. Ten pakiet SDK upraszcza proces wysyłania promptów, określania parametrów modelu i otrzymywania odpowiedzi bez konieczności bezpośredniego obsługi złożonych wywołań interfejsu API.
Pełną dokumentację pakietu Vertex AI SDK dla Pythona znajdziesz tutaj: Wprowadzenie do pakietu Vertex AI SDK dla Pythona | Google Cloud.
5. Tworzenie środowiska wirtualnego i instalowanie zależności
Przed rozpoczęciem dowolnego projektu w Pythonie warto utworzyć środowisko wirtualne. Izoluje to zależności projektu, zapobiegając konfliktom z innymi projektami lub globalnymi pakietami Pythona w systemie.
- Utwórz folder o nazwie
wanderbot, w którym będziesz przechowywać kod aplikacji asystenta podróży. Uruchom w terminalu ten kod:mkdir wanderbot && cd wanderbot - Utwórz i aktywuj środowisko wirtualne:
Przed promptem terminala zobaczysz prefiks (uv venv --python 3.12 source .venv/bin/activatewanderbot), który oznacza, że środowisko wirtualne jest aktywne. Będzie to wyglądać mniej więcej tak:
6. Tworzenie plików początkowych dla wanderbot
- Utwórz i otwórz nowy plik
app.pydla aplikacji. Uruchom w terminalu ten kod: Poleceniecloudshell edit app.pycloudshell editotworzy plikapp.pyw edytorze nad terminalem. - Wklej do pliku
app.pyten kod początkowy aplikacji:import streamlit as st from google import genai from google.genai import types import requests import logging # --- Defining variables and parameters --- REGION = "global" PROJECT_ID = None # TO DO: Insert Project ID GEMINI_MODEL_NAME = "gemini-2.5-flash" temperature = .2 top_p = 0.95 system_instructions = None # --- Tooling --- # TODO: Define the weather tool function declaration # TODO: Define the get_current_temperature function # --- Initialize the Vertex AI Client --- try: # TODO: Initialize the Vertex AI client print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}") except Exception as e: st.error(f"Error initializing VertexAI client: {e}") st.stop() # TODO: Add the get_chat function here in Task 15. # --- Call the Model --- def call_model(prompt: str, model_name: str) -> str: """ This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions. It will be replaced in a later step with a more advanced version that handles tooling. """ try: # TODO: Prepare the content for the model # TODO: Define generate_content configuration (needed for system instructions and parameters) # TODO: Define response logging.info(f"[call_model_response] LLM Response: \"{response.text}\"") # TODO: Uncomment the below "return response.text" line # return response.text except Exception as e: return f"Error: {e}" # --- Presentation Tier (Streamlit) --- # Set the title of the Streamlit application st.title("Travel Chat Bot") # Initialize session state variables if they don't exist if "messages" not in st.session_state: # Initialize the chat history with a welcome message st.session_state["messages"] = [ {"role": "assistant", "content": "How can I help you today?"} ] # Display the chat history for msg in st.session_state.messages: st.chat_message(msg["role"]).write(msg["content"]) # Get user input if prompt := st.chat_input(): # Add the user's message to the chat history st.session_state.messages.append({"role": "user", "content": prompt}) # Display the user's message st.chat_message("user").write(prompt) # Show a spinner while waiting for the model's response with st.spinner("Thinking..."): # Get the model's response using the call_model function model_response = call_model(prompt, GEMINI_MODEL_NAME) # Add the model's response to the chat history st.session_state.messages.append( {"role": "assistant", "content": model_response} ) # Display the model's response st.chat_message("assistant").write(model_response) - Utwórz i otwórz nowy plik
requirements.txtna kod aplikacji. Uruchom w terminalu ten kod: Poleceniecloudshell edit requirements.txtcloudshell editotworzy plikrequirements.txtw edytorze nad terminalem. - Wklej do pliku
requirements.txtten kod początkowy aplikacji.google-genai streamlit requests - Zainstaluj wymagane zależności Pythona dla tego projektu. Uruchom w terminalu ten kod:
uv pip install -r requirements.txt
7. Poznaj kod
Utworzone przez Ciebie pliki zawierają podstawowy interfejs aplikacji do czatowania. To m.in.:
app.py: w tym pliku będziemy pracować. Obecnie zawiera te informacje:- niezbędne importy,
- zmienne środowiskowe i parametry (niektóre z nich to symbole zastępcze);
- pustą funkcję
call_model, którą będziemy wypełniać. - Kod Streamlit aplikacji do obsługi czatu w interfejsie
requirements.txt:- zawiera wymagania dotyczące instalacji, które są niezbędne do uruchomienia
app.py.
- zawiera wymagania dotyczące instalacji, które są niezbędne do uruchomienia
Czas na zapoznanie się z kodem.
Otwieranie czatu Gemini Code Assist
Czat Gemini Code Assist powinien być już otwarty w panelu po prawej stronie edytora Cloud Shell. Jeśli czat Gemini Code Assist nie jest jeszcze otwarty, możesz go otworzyć, wykonując te czynności:
- Kliknij przycisk Gemini Code Assist (
) u góry ekranu. - Kliknij Otwórz czat Gemini Code Assist.

Korzystanie z Gemini Code Assist do zrozumienia kodu
Aby lepiej zrozumieć kod, możesz użyć Gemini Code Assist Chat.
- Wyróżnij lub wybierz odpowiednią sekcję kodu.
- Wpisz „Wyjaśnij ten kod” w czacie Gemini.
- Aby przesłać, naciśnij Enter

8. Uruchamianie aplikacji internetowej
Zanim połączysz tę aplikację z LLM, uruchom ją, aby sprawdzić, jak działa na początku.
- Z poziomu katalogu
wanderboturuchom w terminalu to polecenie, aby uruchomić aplikację Streamlit i udostępnić ją lokalnie w środowisku Cloud Shell: Nie zamykaj okna terminala, ponieważ aplikacja Streamlit będzie nadal działać. Aby uruchomić inne polecenia, możesz otworzyć nowe okno terminala w Cloud Shell.streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - Po uruchomieniu polecenia kliknij przycisk Podgląd w przeglądarce u góry edytora Cloud Shell i wybierz Podejrzyj na porcie 8080.

Wyświetli się prosty interfejs czatu aplikacji podróżniczej. - Wpisz dowolną wiadomość (np.
Hi!) i naciśnij ENTER.
Zauważysz, że wiadomość pojawi się w historii czatu, ale zamiast odpowiedzi od asystenta otrzymasz komunikat o błędzie. Dzieje się tak, ponieważ aplikacja nie jest jeszcze połączona z dużym modelem językowym. Obserwuj to zachowanie, aby poznać punkt wyjścia modułu.
9. Inicjowanie klienta Vertex AI
Poznaj dostępne modele w Vertex AI
Platforma Vertex AI w Google Cloud zapewnia dostęp do różnych modeli generatywnej AI. Zanim zintegrujesz usługę, możesz zapoznać się z dostępnymi opcjami w konsoli Google Cloud.
- W konsoli Google Cloud otwórz Model Garden. Aby to zrobić, wpisz „Baza modeli” na pasku wyszukiwania u góry ekranu i wybierz Vertex AI.

- Przejrzyj dostępne modele. Możesz filtrować według takich kryteriów jak modalności, typy zadań i funkcje.
Na potrzeby tego laboratorium będziesz używać modelu Gemini 2.5 Flash, który ze względu na szybkość jest dobrym wyborem do tworzenia responsywnych aplikacji do czatowania.
Inicjowanie klienta Vertex AI
Teraz zmodyfikujesz sekcję --- Initialize the Vertex AI Client --- w app.py, aby zainicjować klienta Vertex AI. Ten obiekt klienta będzie używany do wysyłania promptów do modelu.
- Otwórz plik
app.pyw edytorze Cloud Shell. - W pliku
app.pyznajdź wierszPROJECT_ID = None. - Zastąp
Noneidentyfikatorem projektu Google Cloud w cudzysłowie. (np.PROJECT_ID = "google-cloud-labs")
Jeśli nie pamiętasz identyfikatora projektu, możesz wyświetlić wszystkie identyfikatory projektów za pomocą tego polecenia:gcloud projects list | awk '/PROJECT_ID/{print $2}' - Zdefiniuj klienta: w bloku
tryzainicjuj klienta Vertex AI.client = genai.Client( vertexai=True, project=PROJECT_ID, location=REGION, )
Zaktualizowana inicjalizacja klienta Vertex AI
W tym momencie sekcja Initialize the Vertex AI Client (Inicjowanie klienta Vertex AI) będzie wyglądać tak:
# --- Initialize the Vertex AI Client ---
try:
client = genai.Client(
vertexai=True,
project=PROJECT_ID,
location=REGION,
)
print(f"VertexAI Client initialized successfully with model {GEMINI_MODEL_NAME}")
except Exception as e:
st.error(f"Error initializing VertexAI client: {e}")
st.stop()
10. Przygotowywanie danych i wywoływanie modelu
Teraz przygotujesz treść do wysłania do modelu i wywołasz model Gemini.
- Znajdź sekcję
--- Call the Model ---, w której zdefiniowana jest funkcjacall_model. - Określ zawartość: w sekcji
# TODO: Prepare the content for the modelokreśl zawartość wejściową , która zostanie wysłana do modelu. W przypadku podstawowego prompta będzie to wiadomość wpisana przez użytkownika.contents = [prompt] - Określ odpowiedź: wklej ten kod pod
# TODO: Define response.response = client.models.generate_content( model=model_name, contents=contents, ) - Wysyłanie odpowiedzi: usuń znacznik komentarza w tym wierszu:
return response.text - Sprawdź wiersz, w którym wywoływana jest funkcja
call_model, w dolnej części pliku w blokuwith. Jeśli nie rozumiesz, co się tu dzieje, zaznacz wiersz i poproś Gemini Code Assist o wyjaśnienie.
Bardziej jednoznaczny sposób definiowania contents
Powyższy sposób definiowania contents działa, ponieważ pakiet SDK jest wystarczająco inteligentny, aby zrozumieć, że lista zawierająca ciągi znaków reprezentuje tekst wprowadzony przez użytkownika. Automatycznie formatuje go w odpowiedni sposób dla interfejsu API modelu.
Bardziej jednoznaczny i podstawowy sposób strukturyzacji danych wejściowych polega jednak na użyciu obiektów types.Part i types.Content, np. tak:
user_message_parts = [types.Part.from_text(text=prompt)]
contents = [
types.Content(
role="user", # Indicates the content is from the user
parts=user_message_parts, # A list, allowing multiple types of content
),
]
Zaktualizowana funkcja call_model
W tym momencie funkcja call_model powinna wyglądać tak:
def call_model(prompt: str, model_name: str) -> str:
"""
This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions.
It will be replaced in a later step with a more advanced version that handles tooling.
"""
try:
contents = [prompt]
# TODO: Define generate_content configuration (needed later for system instructions and parameters)
response = client.models.generate_content(
model=model_name,
contents=contents,
)
logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
return response.text
except Exception as e:
return f"Error: {e}"
11. Testowanie połączonej aplikacji
- W terminalu zatrzymaj aktualnie działający proces (CTRL+C).
- Ponownie uruchom polecenie, aby ponownie uruchomić aplikację Streamlit.
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - Odśwież aplikację Streamlit. Jeśli aplikacja Streamlit nadal działa, wystarczy odświeżyć stronę podglądu w przeglądarce.
- Teraz wpisz w polu czatu pytanie, np.:
What is the best time of year to go to Iceland? - Naciśnij ENTER.
Powinna się wyświetlić aplikacja z Twoją wiadomością, spinnerem „Myślenie…” i odpowiedzią wygenerowaną przez model Gemini. Jeśli tak, oznacza to, że udało Ci się połączyć aplikację internetową z modelem LLM w Vertex AI. 🙌 🥳
12. Określanie instrukcji systemowych
Podstawowe połączenie działa, ale jakość i styl odpowiedzi modelu LLM są w dużej mierze uzależnione od otrzymanych danych wejściowych. Tworzenie promptów to proces projektowania i dopracowywania tych danych wejściowych (promptów), aby kierować modelem w stronę generowania pożądanych wyników.
W tym celu zaczniesz od utworzenia instrukcji systemowych i przekazania ich do modelu.
Aby tworzyć przydatne instrukcje systemowe, będziesz używać funkcji Zapytaj Gemini.
- W sekcji
app.pyznajdź zmiennąsystem_instructions, która jest obecnie ustawiona naNone. Zastąpiszsystem_instructions = NoneNoneciągiem wielowierszowym zawierającym instrukcje dla naszego bota asystenta podróży. - Zadaj pytanie Gemini Code Assist: przekaż Gemini Code Assist ten prompt (lub wymyśl własny):
I am a developer at a travel marketing company, and my sales department has decided that they need a new chat application to keep up with the bigger booking and search companies. I'm building a simple travel assistant chatbot using the Gemini 2.5 Flash model on Vertex AI. The application should: - Helps users ask questions about travel, book travel, and learn about places they are going to go - Provides users ways to get help about their specific travel plans - Provides all this in a production quality way (multiple environments, logging and monitoring, etc.) Please create system instructions appropriate for that chat app. Be thorough. Do not alter the code in any way beyond providing me with system instructions. - Zdefiniuj
system_instructions: ustawsystem_instructionsjako instrukcje systemowe wygenerowane za pomocą Gemini Code Assist. Możesz też użyć tych instrukcji systemowych, które zostały utworzone przez Gemini na podstawie podobnego prompta.system_instructions = """ You are a sophisticated travel assistant chatbot designed to provide comprehensive support to users throughout their travel journey. Your capabilities include answering travel-related questions, assisting with booking travel arrangements, offering detailed information about destinations, and providing support for existing travel plans. **Core Functionalities:** 1. **Travel Information and Recommendations:** * Answer user inquiries about travel destinations, including popular attractions, local customs, visa requirements, weather conditions, and safety advice. * Provide personalized recommendations for destinations, activities, and accommodations based on user preferences, interests, and budget. * Offer insights into the best times to visit specific locations, considering factors like weather, crowds, and pricing. * Suggest alternative destinations or activities if the user's initial choices are unavailable or unsuitable. 2. **Booking Assistance:** * Facilitate the booking of flights, hotels, rental cars, tours, and activities. * Search for available options based on user-specified criteria such as dates, destinations, budget, and preferences. * Present clear and concise information about available options, including pricing, amenities, and booking terms. * Guide users through the booking process, ensuring accurate information and secure transactions. * Provide booking confirmations and relevant details, such as booking references and contact information. 3. **Travel Planning and Itinerary Management:** * Assist users in creating detailed travel itineraries, including flights, accommodations, activities, and transportation. * Offer suggestions for optimizing travel plans, such as minimizing travel time or maximizing sightseeing opportunities. * Provide tools for managing and modifying existing itineraries, including adding or removing activities, changing booking dates, or upgrading accommodations. * Offer reminders and notifications for upcoming travel events, such as flight check-in or tour departure times. 4. **Customer Support and Troubleshooting:** * Provide prompt and helpful support to users with questions or issues related to their travel plans. * Assist with resolving booking discrepancies, cancellations, or modifications. * Offer guidance on travel-related emergencies, such as lost luggage or travel delays. * Provide access to relevant contact information for airlines, hotels, and other travel providers. **Interaction Guidelines:** * **Professionalism:** Maintain a polite, respectful, and professional tone in all interactions. * **Clarity and Conciseness:** Provide clear, concise, and easy-to-understand information. Avoid jargon or technical terms unless necessary and always explain them. * **Accuracy:** Ensure all information provided is accurate and up-to-date. Double-check details before sharing them with users. If unsure about something, admit that you don't know and offer to find the information. * **Personalization:** Tailor your responses and recommendations to the specific needs and preferences of each user. * **Proactive Assistance:** Anticipate user needs and offer relevant information or suggestions proactively. * **Error Handling:** Gracefully handle user errors or misunderstandings. Provide helpful guidance and alternative options when necessary. * **Confidentiality:** Respect user privacy and handle personal information with the utmost confidentiality and in compliance with data protection regulations. **Example Interactions:** **User:** "I want to go on a beach vacation in the Caribbean. I have a budget of $2000 per person for a week." **Chatbot:** "Certainly! The Caribbean offers many beautiful beach destinations within your budget. Some popular options include Punta Cana in the Dominican Republic, Cancun in Mexico, and Montego Bay in Jamaica. These destinations offer stunning beaches, all-inclusive resorts, and various activities. Would you like me to search for flights and accommodations for these locations based on your travel dates?" **User:** "My flight is delayed. What should I do?" **Chatbot:** "I'm sorry to hear about the delay. Please check with the airline for the updated departure time and any assistance they can offer. You may be entitled to compensation or rebooking options depending on the length of the delay and the airline's policy. Do you have your flight number handy so I can look up the current status for you?" **User:** "Tell me about the best time to visit Japan." **Chatbot:** "Japan is a fantastic destination with distinct seasons offering unique experiences. Spring (March-May) is famous for the beautiful cherry blossoms, while autumn (September-November) boasts stunning fall foliage. Both seasons have pleasant temperatures, making them ideal for sightseeing. Summer (June-August) can be hot and humid, but it's a great time for festivals and outdoor activities in the mountains. Winter (December-February) offers opportunities for skiing and snowboarding in the Japanese Alps, though some areas may experience heavy snowfall. To recommend the best time for you, could you tell me what you'd like to experience in Japan?" By following these instructions, you will be able to provide exceptional travel assistance and create a positive experience for every user. """ - Zdefiniuj konfigurację generate_content: zainicjuj obiekt konfiguracji, do którego przekażesz te instrukcje systemowe. Ponieważ zmienna
system_instructionsjest zdefiniowana globalnie w naszym skrypcie, funkcja może uzyskać do niej bezpośredni dostęp.generate_content_config = types.GenerateContentConfig( system_instruction=[ types.Part.from_text(text=system_instructions) ], ) logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}") - Aby dodać instrukcje systemowe do odpowiedzi, dodaj parametr
configdo metodygenerate contenti ustaw go na wartość obiektugenerate_content_configutworzonego powyżej.response = client.models.generate_content( model=model_name, contents=contents, config=generate_content_config, # This is the new line )
Zaktualizowana funkcja call_model
Pełna funkcja call_model wygląda teraz tak:
def call_model(prompt: str, model_name: str) -> str:
"""
This function interacts with a large language model (LLM) to generate text based on a given prompt and system instructions.
It will be replaced in a later step with a more advanced version that handles tooling.
"""
try:
contents = [prompt]
generate_content_config = types.GenerateContentConfig(
system_instruction=[
types.Part.from_text(text=system_instructions)
],
)
logging.info(f"[generate_config_details] System Instruction: {generate_content_config.system_instruction[0].text}")
response = client.models.generate_content(
model=model_name,
contents=contents,
config=generate_content_config,
)
logging.info(f"[call_model_response] LLM Response: \"{response.text}\"")
return response.text
except Exception as e:
return f"Error: {e}"
13. Testowanie aplikacji za pomocą instrukcji systemowych
- W terminalu zatrzymaj aktualnie działający proces (CTRL+C).
- Ponownie uruchom polecenie, aby ponownie uruchomić aplikację Streamlit.
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - Odśwież aplikację Streamlit. Jeśli aplikacja Streamlit nadal działa, wystarczy odświeżyć stronę podglądu w przeglądarce.
- Spróbuj zadać to samo pytanie co wcześniej:
What is the best time of year to go to Iceland? - Naciśnij ENTER.
Porównaj, jak odpowiada tym razem w porównaniu z poprzednim razem.
14. Określanie narzędzia pogodowego
Nasz chatbot ma dużą wiedzę, ale jest ona ograniczona do danych, na których został wytrenowany. Nie ma dostępu do informacji w czasie rzeczywistym. W przypadku bota podróżniczego możliwość pobierania danych na żywo, takich jak prognozy pogody, jest ogromną zaletą.
W tym przypadku przydają się narzędzia, czyli wywoływanie funkcji. Możemy zdefiniować zestaw narzędzi (funkcji Pythona), które LLM może wywoływać, aby uzyskać informacje zewnętrzne.
Jak działa narzędzie
- Opisujemy modelowi nasze narzędzia, w tym ich działanie i parametry.
- Użytkownik wysyła prompt (np. „Jaka jest pogoda w Londynie?”
- Model otrzymuje prompt i widzi, że użytkownik pyta o coś, co może znaleźć za pomocą jednego z narzędzi.
- Zamiast odpowiadać tekstem, model zwraca specjalny obiekt
function_call, który wskazuje, które narzędzie ma zostać wywołane i z jakimi argumentami. - Nasz kod w Pythonie odbiera ten
function_call, wykonuje naszą rzeczywistą funkcjęget_current_temperaturez podanymi argumentami i uzyskuje wynik (np. 15°C). - Wynik ten przesyłamy z powrotem do modelu.
- Model otrzymuje wynik i generuje dla użytkownika odpowiedź w języku naturalnym (np. „Obecna temperatura w Londynie to 15°C”.
Dzięki temu model może odpowiadać na pytania wykraczające daleko poza dane treningowe, co czyni go znacznie bardziej zaawansowanym i przydatnym asystentem.
Określanie narzędzia pogodowego
Jeśli podróżny szuka porady, co robić, i wybiera spośród atrakcji, na które ma wpływ pogoda, narzędzie pogodowe może się przydać. Utwórzmy narzędzie, które umożliwi naszemu modelowi uzyskiwanie informacji o aktualnej pogodzie. Potrzebujemy 2 elementów: deklaracji funkcji, która opisuje narzędzie dla modelu, oraz rzeczywistej funkcji w języku Python, która je implementuje.
- W sekcji
app.pyznajdź komentarz# TODO: Define the weather tool function declaration. - Pod tym komentarzem dodaj zmienną
weather_function. Jest to słownik, który zawiera wszystkie informacje o funkcji, jej parametrach i wymaganych argumentach.weather_function = { "name": "get_current_temperature", "description": "Gets the current temperature for a given location.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "The city name, e.g. San Francisco", }, }, "required": ["location"], }, } - Następnie znajdź komentarz
# TODO: Define the get_current_temperature function. Pod nim dodaj ten kod w Pythonie. Ta funkcja:- Wywołaj interfejs geokodowania API, aby uzyskać współrzędne lokalizacji.
- Użyj tych współrzędnych, aby wywołać interfejs API pogodowy.
- Zwróć prosty ciąg znaków z temperaturą i jednostką.
def get_current_temperature(location: str) -> str: """Gets the current temperature for a given location.""" try: # --- Get Latitude and Longitude for the location --- geocode_url = f"https://geocoding-api.open-meteo.com/v1/search?name={location}&count=1&language=en&format=json" geocode_response = requests.get(geocode_url) geocode_data = geocode_response.json() if not geocode_data.get("results"): return f"Could not find coordinates for {location}." lat = geocode_data["results"][0]["latitude"] lon = geocode_data["results"][0]["longitude"] # --- Get Weather for the coordinates --- weather_url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true" weather_response = requests.get(weather_url) weather_data = weather_response.json() temperature = weather_data["current_weather"]["temperature"] unit = "°C" return f"{temperature}{unit}" except Exception as e: return f"Error fetching weather: {e}"
15. Refaktoryzacja czatu i narzędzi
Obecna funkcja call_model korzysta z prostego wywołania generate_content. To świetne rozwiązanie w przypadku pojedynczych pytań, ale nie sprawdza się w rozmowach wieloetapowych, zwłaszcza tych, które wymagają wymiany informacji w celu korzystania z narzędzi.
Lepszym rozwiązaniem jest użycie sesji czatu, która zachowuje kontekst rozmowy. Teraz zmodyfikujemy nasz kod, aby używać sesji czatu, co jest niezbędne do prawidłowego wdrożenia narzędzi.
- Usuń istniejącą funkcję
call_model. Zastąpimy ją bardziej zaawansowaną wersją. - Zamiast niej dodaj nową funkcję
call_modelz bloku kodu poniżej. Ta nowa funkcja zawiera logikę obsługi pętli wywoływania narzędzi, o której wspominaliśmy wcześniej. Zwróć uwagę, że zawiera on kilka komentarzy TODO, które uzupełnimy w następnych krokach.# --- Call the Model --- def call_model(prompt: str, model_name: str) -> str: """ This function interacts with a large language model (LLM) to generate text based on a given prompt. It maintains a chat session and handles function calls from the model to external tools. """ try: # TODO: Get the existing chat session or create a new one. message_content = prompt # Start the tool-calling loop while True: # TODO: Send the message to the model. # Check if the model wants to call a tool has_tool_calls = False for part in response.candidates[0].content.parts: if part.function_call: has_tool_calls = True function_call = part.function_call logging.info(f"Function to call: {function_call.name}") logging.info(f"Arguments: {function_call.args}") # TODO: Call the appropriate function if the model requests it. # If no tool call was made, break the loop if not has_tool_calls: break # TODO: Return the model's final text response. except Exception as e: return f"Error: {e}" - Teraz dodajmy funkcję pomocniczą do zarządzania sesją czatu. Nad nową funkcją
call_modeldodaj funkcjęget_chat. Ta funkcja utworzy nową sesję czatu z instrukcjami systemowymi i definicjami narzędzi lub pobierze istniejącą sesję. To dobra praktyka organizowania kodu.def get_chat(model_name: str): if f"chat-{model_name}" not in st.session_state: # TODO: Define the tools configuration for the model # TODO: Define the generate_content configuration, including tools # TODO: Create a new chat session st.session_state[f"chat-{model_name}"] = chat return st.session_state[f"chat-{model_name}"]
Masz już skonfigurowane ramy naszej zaawansowanej logiki czatu z użyciem narzędzi.
16. Zaimplementuj logikę wywoływania narzędzi
Teraz wypełnijmy pole TODOs, aby logika wywoływania narzędzi była w pełni funkcjonalna.
Wdróż get_chat
- W funkcji
get_chatw komentarzu# TODO: Define the tools configuration...zdefiniuj obiekttools, tworząc instancjętypes.Toolz deklaracjiweather_function.tools = types.Tool(function_declarations=[weather_function]) - W sekcji
# TODO: Define the generate_content configuration...zdefiniujgenerate_content_config, pamiętając o przekazaniu do modelu obiektutools. W ten sposób model uczy się, jakich narzędzi może używać.generate_content_config = types.GenerateContentConfig( system_instruction=[types.Part.from_text(text=system_instructions)], tools=[tools] # Pass the tool definition here ) - W sekcji
# TODO: Create a new chat sessionutwórz obiekt czatu za pomocąclient.chats.create(), przekazując nazwę modelu i konfigurację.chat = client.chats.create( model=model_name, config=generate_content_config, )
Wdróż call_model
- W funkcji
call_modelw sekcji# TODO: Get the existing chat session...wywołaj naszą nową funkcję pomocnicząget_chat.chat = get_chat(model_name) - Następnie znajdź
# TODO: Send the message to the model. Wyślij wiadomość użytkownika za pomocą metodychat.send_message().response = chat.send_message(message_content) - Znajdź
# TODO: Call the appropriate function.... W tym miejscu sprawdzamy, której funkcji oczekuje model, i ją wykonujemy.
if function_call.name == "get_current_temperature":
result = get_current_temperature(**function_call.args)
function_response_part = types.Part.from_function_response(
name=function_call.name,
response={"result": result},
)
message_content = [function_response_part]
- Na koniec znajdź
# TODO: Return the model's final text responsei dodaj instrukcję zwrotu.return response.text
Zaktualizowana funkcja get_chat
Zaktualizowana funkcja get_chat powinna teraz wyglądać tak:
def get_chat(model_name: str):
if f"chat-{model_name}" not in st.session_state:
#Tools
tools = types.Tool(function_declarations=[weather_function])
# Initialize a confiburation object
generate_content_config = types.GenerateContentConfig(
system_instruction=[types.Part.from_text(text=system_instructions)],
tools=[tools]
)
chat = client.chats.create(
model=model_name,
config=generate_content_config,
)
st.session_state[f"chat-{model_name}"] = chat
return st.session_state[f"chat-{model_name}"]
Zaktualizowana funkcja call_model
Zaktualizowana funkcja call_model powinna teraz wyglądać tak:
def call_model(prompt: str, model_name: str) -> str:
try:
chat = get_chat(model_name)
message_content = prompt
while True:
response = chat.send_message(message_content)
has_tool_calls = False
for part in response.candidates[0].content.parts:
if part.function_call:
has_tool_calls = True
function_call = part.function_call
logging.info(f"Function to call: {function_call.name}")
logging.info(f"Arguments: {function_call.args}")
if function_call.name == "get_current_temperature":
result = get_current_temperature(**function_call.args)
function_response_part = types.Part.from_function_response(
name=function_call.name,
response={"result": result},
)
message_content = [function_response_part]
elif part.text:
logging.info("No function call found in the response.")
logging.info(response.text)
if not has_tool_calls:
break
return response.text
except Exception as e:
return f"Error: {e}"
17. Testowanie aplikacji z włączonymi narzędziami
Zobaczmy, jak działa nowa funkcja.
- W terminalu zatrzymaj aktualnie działający proces (CTRL+C).
- Ponownie uruchom polecenie, aby ponownie uruchomić aplikację Streamlit.
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - Odśwież aplikację Streamlit. Jeśli aplikacja Streamlit nadal działa, wystarczy odświeżyć stronę podglądu w przeglądarce.
- Teraz zadaj pytanie, które powinno uruchomić nowe narzędzie, np. takie:
I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island? - Naciśnij ENTER.
Porównaj tę odpowiedź z wcześniejszymi. Co się zmieniło?
Powinna się wyświetlić odpowiedź zawierająca temperaturę z funkcji. Sprawdź też terminal Cloud Shell. Powinny się w nim pojawić instrukcje drukowania potwierdzające wykonanie funkcji Pythona.
18. Ulepszanie wyników modelu za pomocą parametrów
Dobra robota! Asystent podróży może teraz korzystać z narzędzi do pobierania zewnętrznych danych w czasie rzeczywistym, co znacznie zwiększa jego możliwości.
Teraz, gdy zwiększyliśmy możliwości naszego modelu, dostosujmy sposób, w jaki odpowiada. Parametry modelu pozwalają kontrolować styl i losowość generowanego przez LLM tekstu. Dostosowując te ustawienia, możesz sprawić, że wyniki działania bota będą bardziej ukierunkowane i deterministyczne lub bardziej kreatywne i zróżnicowane.
W tym module skupimy się na temperature i top_p. (Pełną listę parametrów, które można skonfigurować, i ich opisy znajdziesz w GenerateContentConfig w naszej dokumentacji interfejsu API).
temperature: określa losowość danych wyjściowych. Niższa wartość (bliższa 0) sprawia, że dane wyjściowe są bardziej deterministyczne i skoncentrowane, a wyższa wartość (bliższa 2) zwiększa losowość i kreatywność. W przypadku bota do zadawania pytań i odpowiedzi lub asystenta zwykle preferowana jest niższa temperatura, aby uzyskać bardziej spójne i rzeczowe odpowiedzi.top_p: maksymalne skumulowane prawdopodobieństwo tokenów, które należy uwzględnić podczas próbkowania. Tokeny są sortowane na podstawie przypisanych im prawdopodobieństw, dzięki czemu brane pod uwagę są tylko najbardziej prawdopodobne tokeny. Model bierze pod uwagę najbardziej prawdopodobne tokeny, których prawdopodobieństwa sumują się do wartościtop_p. Niższa wartość ogranicza wybór tokenów, co skutkuje mniej zróżnicowanymi danymi wyjściowymi.
Parametry wywołania
- Znajdź zmienne
temperatureitop_pzdefiniowane u góry sekcjiapp.py. Zwróć uwagę, że nie zostały jeszcze nigdzie wywołane. - Dodaj
temperatureitop_pdo parametrów zdefiniowanych wGenerateContentConfigw funkcjicall_model.generate_content_config = types.GenerateContentConfig( temperature=temperature, top_p=top_p, system_instruction=[types.Part.from_text(text=system_instructions)], tools=[tools] # Pass the tool definition here )
Zaktualizowana funkcja get_chat
Aplikacja get_chat wygląda teraz tak:
def get_chat(model_name: str):
if f"chat-{model_name}" not in st.session_state:
#Tools
tools = types.Tool(function_declarations=[weather_function])
# Initialize a confiburation object
generate_content_config = types.GenerateContentConfig(
temperature=temperature,
top_p=top_p,
system_instruction=[types.Part.from_text(text=system_instructions)],
tools=[tools]
)
chat = client.chats.create(
model=model_name,
config=generate_content_config,
)
st.session_state[f"chat-{model_name}"] = chat
return st.session_state[f"chat-{model_name}"]
19. Testowanie za pomocą parametrów modelu
- W terminalu zatrzymaj aktualnie działający proces (CTRL+C).
- Ponownie uruchom polecenie, aby ponownie uruchomić aplikację Streamlit.
streamlit run app.py --browser.serverAddress=localhost --server.enableCORS=false --server.enableXsrfProtection=false --server.port 8080 - Odśwież aplikację Streamlit. Jeśli aplikacja Streamlit nadal działa, wystarczy odświeżyć stronę podglądu w przeglądarce.
- Zadaj to samo pytanie co wcześniej.
I'm looking for something to do in New York today. What do you recommend? Would it be a good day to go to Ellis Island? - Naciśnij ENTER.
Porównaj tę odpowiedź z wcześniejszymi.
20. Gratulacje!
Aplikacja do zadawania pytań i odpowiedzi została zaktualizowana o narzędzia, czyli zaawansowaną funkcję, która umożliwia aplikacji opartej na Gemini interakcję z systemami zewnętrznymi i dostęp do informacji w czasie rzeczywistym.
Dalsze eksperymenty
Istnieje wiele sposobów na dalszą optymalizację promptu. Oto kilka kwestii, które warto rozważyć:
- Dostosuj wartości
temperatureitop_pi zobacz, jak zmienia się odpowiedź modelu LLM. - Pełną listę konfigurowalnych parametrów i ich opisów znajdziesz w
GenerateContentConfigw naszej dokumentacji interfejsu API. Spróbuj zdefiniować więcej parametrów i dostosować je, aby zobaczyć, co się stanie.
Podsumowanie
W tym module:
- Do programowania użyto edytora Cloud Shell i terminala.
- Użyj pakietu Vertex AI SDK dla Pythona, aby połączyć aplikację z modelem Gemini.
- Zastosowano instrukcje systemowe i parametry modelu, aby kierować odpowiedziami LLM.
- Poznanie koncepcji narzędzi (wywoływanie funkcji) i ich zalet.
- Przebudowano kod, aby używać sesji czatu z zachowywaniem stanu, co jest sprawdzoną metodą w przypadku konwersacyjnej AI.
- zdefiniowano narzędzie dla modelu za pomocą deklaracji funkcji;
- Wdrożono funkcję Pythona, która zapewnia logikę narzędzia.
- Napisz kod do obsługi żądań wywoływania funkcji modelu i zwracania wyników.