API Gemini w Pythonie: ten sam bezstanowy pętla z rolami modeli i obiektami chatu.
Wywołanie Gemini z Pythona za pomocą SDK google-genai: zawartość i komponenty, system_instruction, użycie tokenów oraz obiekt chatu, który rejestruje historię na stronie klienta.
Źródła: Part 4 — Call the Gemini API in Python (user / model, same loop)
Po OpenAI i Claude, Gemini od Google jest trzecim dostawcą, który stosuje ten sam schemat: endpoint bez stanu, rozmowa oznaczona rolą oraz pełna historia wysyłana przy każdym połączeniu. Gemini dodaje do tego jeszcze jedną przyjemną cechę w swojej nazwie.
Zmiana nazw, a nie przebudowa
Konstrukcja rozmowy w Gemini jest identyczna jak w OpenAI i Claude, z wyjątkiem dwóch zmian nazw. Rola asystenta nazywa się model. Ta nazwa jest chyba bardziej szczera, ponieważ „asystent” sugeruje określoną osobowość, natomiast model po prostu wskazuje, że tekst pochodzi z modelu. Zajmuje ona to samo miejsce na liście. Prompt systemowy staje się system_instruction i jest przekazywany w obiekcie konfiguracyjnym, a nie na liście wiadomości. To rozwinięcie koncepcji „systemu na boku” z Claude o jeden poziom dalej.
Lista wiadomości jest dostępna pod nazwą contents. Każda z nich zawiera elementy typu parts, ponieważ Gemini obsługuje natywnie tekst, obrazy i dźwięk. W przypadku czatu z prostym tekstem nic z tego nie jest widoczne: wprowadza się ciągi znaków, a jako wynik otrzymuje się resp.text.
Jedno ostrzeżenie dotyczące bibliotek przed pokazaniem kodu. Przez lata Google wydał kilka pakietów w języku Python, a starsze poradniki są pełne przestarzałych importów, takich jak google-generativeai oraz narzędzi z okresu Bard. Obecnym oficjalnym SDK jest google-genai, importowanym za pomocą from google import genai, i to właśnie ono jest tutaj używane.
Ustawienia i jeden ruch
Zainstaluj go za pomocą pip install google-genai, utwórz klucz w Google AI Studio i wyeksportuj go jako GEMINI_API_KEY. Klient pobiera ten klucz z środowiska, więc w kodzie nigdy nie pojawi się on bezpośrednio.
# current official SDK: pip install google-genai
from google import genai
from google.genai import types
client = genai.Client() # key from env
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="Why does Gemini name the reply "
"role 'model', not 'assistant'?",
config=types.GenerateContentConfig(
system_instruction="Be concise.",
temperature=0,
),
)
print(resp.text)
W odróżnieniu od dwóch poprzednich dostawców, messages został teraz zastąpiony przez contents, a pojedynczy ruch może być zwykłą łańcuchem znaków. Komenda systemowa trafia do GenerateContentConfig. Temperatura ponownie jest standardowym polem konfiguracyjnym, które poprzednie Claude SDK usunęło. Odpowiedź to po prostu resp.text, a liczby tokenów znajdują się w resp.usage_metadata jako prompt_token_count i candidates_token_count – to te same wartości, tylko oznaczone nazwami używanymi przez Google. Zawsze je rejestruj.
Zarządzany cykl historii
Możliwe jest bezpośrednie przeniesienie własnej funkcji ask(): przechowuj wartości user i model w liście, dodawaj każdą wymianę informacji i za każdym razem przekazuj contents=. To działa. Jednak SDK oferuje udogodnienie, którego klienci OpenAI i Anthropic nie mają od razu: obiekt rozmowy, który zajmuje się dodawaniem tych danych.
chat = client.chats.create(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction="Be concise.",
),
)
r1 = chat.send_message(
"Define a context window."
)
print(r1.text)
r2 = chat.send_message(
"Now for a five-year-old."
)
print(r2.text)
for turn in chat.get_history():
part = turn.parts[0].text[:40]
print(turn.role, "->", part)
Odpowiedź na to pytanie pojawia się w kontekście, ponieważ obiekt czatu cicho odtwarza wcześniejszą wymianę wiadomości, dokładnie tak jak zrobiłaby to funkcja napisana ręcznie. Jeśli przejrzysz get_history() na końcu, zobaczysz naprzemienną kolejność ról user i model – to jest ta sama lista, która została wysłana w ostatniej prośbie. Po stronie serwera nic nie jest przechowywane. Obiekt czatu zapisuje to, co piszemy po stronie klienta, więc tokeny wprowadzanych danych nadal gromadzą się przy każdej kolejności, a długie rozmowy są droższe za każdą próbę połączenia.
Jedna rzecz się nie zmieniła: usługa stojąca za SDK nie pamięta nic między poszczególnymi prośbami.
Wygoda ma swoją cenę, a w przypadku frameworków ma to znaczenie później. Zarządzana historia oznacza mniej kodu i mniej błędów, aż do momentu, gdy musisz usunąć stare wpisy, je podsumować lub włączyć pobraane dokumenty do rozmowy. Wtedy zapragniesz z powrotem prostego listy. LangChain znajduje się na tym samym poziomie skali, ale o jeden stopień wyżej. Bądź zaznajomiony zarówno z listą utrzymywaną ręcznie, jak i z zarządzanym obiektem – żaden z nich nie może cię ograniczyć.
Rozpoczynanie pracy z przykładem
pip install -r requirements.txt
export GEMINI_API_KEY="AIza..."
python examples/part04_gemini.py
Skrypt omawia kolejno trzy kwestie: pojedynczą rundę rozmowy, pętlę ręcznego wyliczania tokenów w celu potwierdzenia ich równoważności oraz zarządzany czat z wyświetlaną historią. Liczba tokenów jest rejestrowana po każdej próbie wywołania. Jeśli nie zostanie ustawiony żaden klucz, skrypt natychmiast się zatrzymuje z wyraźną wiadomością. Ponieważ te wywołania są realizowane w czasie rzeczywistym i opłacane, nie należy go uruchamiać w środowisku CI.
Trzy dostawcy, jeden format
Szybkie porównanie wszystkich trzech. OpenAI traktuje pole system jako zwykłą wiadomość i pozostawia historię użytkownikowi. Claude przekształca system w odrębny parametr, wymaga ustawienia max_tokens i również pozostawia historię użytkownikowi. Gemini umieszcza system_instruction w konfiguracji, nazywa asystenta model i przechowuje historię, jeśli na to pozwolisz. Wszystkie trzy opierają się na tej samej pętli bezstanowej: wysyła się pełną rozmowę, otrzymuje się odpowiedź, dodaje ją do historii i robi się to ponownie.
Dlatego właśnie frameworki wielopodawcze mogą pozostać lekkie, a zmiana dostawcy nie musi być przerażająca. Migracja polega na utworzeniu mapy przemiany nazw, a nie na przepisywaniu kodu.