API Gemini в Python: тот же безсостоянийный цикл с ролями модели и объектами чата.
Вызов Gemini из Python с помощью SDK google-genai: содержимое и компоненты, system_instruction, использование токенов и объект чата для отслеживания истории на клиенте.
Источники: Part 4 — Call the Gemini API in Python (user / model, same loop)
После OpenAI и Claude Gemini от Google становится третьим поставщиком, демонстрирующим аналогичную схему: безсостоянийный конечный пункт, диалог с маркировкой ролей и отправка полной истории при каждом вызове. Gemini добавляет к этому одну приятную особенность в названии.
Переименование, а не полная переработка
Структура диалога в Gemini совпадает со структурой у OpenAI и Claude, за исключением двух переименований. Роль ассистента теперь называется model. Это название, пожалуй, более точное, поскольку термин «ассистент» намекает на определенный персонаж, тогда как model просто указывает на то, что текст генерировался моделью. Он занимает ту же позицию в списке. Системное указание теперь называется system_instruction и передается в объекте конфигурации, а не в списке сообщений. Это развитие идеи «системы в стороне» от Claude на новый уровень.
Список сообщений доступен по ключу contents. Каждый элемент этого списка содержит parts, поскольку Gemini поддерживает текст, изображения и аудио нативно. При обычном текстовом чате всё это не отображается: вводятся строки, а выводится resp.text.
Прежде чем приступить к коду, важно сделать одно предупреждение относительно библиотек. За годы Google выпустила несколько пакетов на Python, и старые учебные материалы полны устаревших импортов, таких как google-generativeai и оберток времен Bard. Текущий официальный SDK — это google-genai, который импортируется с помощью from google import genai, и именно его используется здесь.
Настройка и один обмен сообщениями
Установите его с помощью команды pip install google-genai, создайте ключ в Google AI Studio и экспортируйте его как GEMINI_API_KEY. Клиент берет ключ из среды, поэтому он никогда не появляется в коде.
# 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)
По сравнению с двумя предыдущими поставщиками теперь вместо messages используется contents, причем один ход может представлять собой простую строку. Параметры системного запроса находятся в GenerateContentConfig. Параметр температуры снова является обычным полем конфигурации, которое было убрано в текущей версии SDK Claude. Ответ представлен как resp.text, а количество токенов указано в resp.usage_metadata под названиями prompt_token_count и candidates_token_count — это те же показатели, только с именами, присвоенными Google. Всегда записывайте их.
Цикл управляемой истории
Возможно прямое портирование собственной функции ask(): сохраняйте значения user и model в списке, добавляйте каждый обмен сообщениями и снова передавайте параметр contents= при каждом вызове. Этот способ работает. Однако SDK предоставляет удобство, отсутствующее у клиентов OpenAI и Anthropic из коробки: объект чата, который самостоятельно обрабатывает добавление данных.
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)
Ответ на последующий вопрос даётся в контексте, поскольку объект чата тихо воспроизводит предыдущий диалог, что и делала бы реализованная вручную функция. Если пройтись по результатам get_history() в конце, можно увидеть чередование ходов user и model — именно тот же список, который был отправлен при последнем запросе. На стороне сервера ничего не запоминается. Объект чата сохраняет введённый текст на клиенте, поэтому токены ввода продолжают накапливаться с каждым ходом, и длительные чаты стоят дороже за один вызов.
Одно остаётся неизменным: сервис, стоящий за SDK, ничего не запоминает между запросами.
У удобства есть своя цена, и это становится важным позже при работе с фреймворками. Управляемая история означает меньше кода и меньше ошибок, прямо до того момента, когда необходимо убрать старые записи, свести их в краткое изложение или вставить полученные документы в середину разговора. Тогда вам снова понадобится простой список. LangChain находится на том же уровне этой шкалы, но на один пункт выше. Привыкните к какому-либо из вариантов — к ручно ведомому списку или к управляемым объектам, — и ни один из них не сможет ограничить вас.
Запуск примера
pip install -r requirements.txt
export GEMINI_API_KEY="AIza..."
python examples/part04_gemini.py
Скрипт по порядку охватывает три аспекта: один раунд общения, цикл ручного перечисления для подтверждения его эквивалентности и управляемый чат с отображением истории. После каждого вызова фиксируется количество токенов. Если ключ не установлен, скрипт немедленно останавливается с четким сообщением. Поскольку вызовы осуществляются в реальном времени и оплачиваются, его не следует запускать в CI.
Три провайдера, одна структура
Краткое сравнение всех трех. OpenAI рассматривает параметр system как сообщение и оставляет историю на ваше усмотрение. Claude делает system отдельным параметром, требует указания max_tokens и также оставляет историю на ваше усмотрение. Gemini включает system_instruction в настройки, называет ассистента model и сохраняет историю, если вы этого разрешите. Все три решения используют один и тот же безсостоянийный цикл: отправляется полное содержимое разговора, получается ответ, он добавляется к истории, после чего процесс повторяется.
Вот почему фреймворки с несколькими поставщиками услуг могут оставаться легкими, и почему смена поставщика не обязательно должна вызывать страх. Миграция — это просто замена имен, а не полная переработка кода.