Gemini API на Python: запросы через OpenAI SDK и OpenAI-формат

Рабочий пример Gemini API на Python без отдельной библиотеки: меняем base_url в OpenAI SDK, добавляем стриминг и JSON и сравниваем с google-genai.

5 мин · · разработка · API-ключи

Если вы ищете, как вызвать Gemini API на Python, у вас два пути: нативная библиотека Google или привычный OpenAI SDK с другим адресом. Ниже разберём второй путь на рабочем коде: клиент, обычный запрос, стриминг, JSON-ответ, обработка ошибок и расчёт стоимости. В конце сравним его с нативным google-genai и скажем, когда что удобнее.

Все примеры идут через шлюз Zukko: один ключ fetch_..., формат OpenAI и модель gemini-3.8-flash. Цены в статье указаны на 18 октября 2026.

Зачем вызывать Gemini через OpenAI SDK

Главное преимущество в том, что код не привязан к одному поставщику. Клиент OpenAI(...) знает только три вещи: адрес, ключ и имя модели. Чтобы перейти с Gemini на GPT или Claude, достаточно поменять строку model. Вы не переписываете ни разбор ответа, ни стриминг, ни обработку ошибок.

Это удобно в трёх случаях:

  • в проекте уже есть код на openai, и вы хотите добавить дешёвую модель для массовых задач;
  • вы сравниваете несколько моделей на своих данных и не хотите писать по адаптеру на каждую;
  • инструмент (LangChain, LlamaIndex, ваш собственный сервис) умеет только OpenAI-совместимый API.

Сама Google тоже поддерживает такой режим: в документации Gemini API есть раздел про совместимость с OpenAI-библиотеками, где меняются три строки (ключ, base URL и модель). Одновременно там сказано, что если вы не используете OpenAI-библиотеки, проще вызывать Gemini API напрямую. Мы вернёмся к этому в разделе про сравнение.

Установка и первый запрос

bash
pip install openai

Создайте ключ на странице API-ключей и положите его в переменную окружения, а не в код:

bash
export OPENAI_BASE_URL="https://api.zukko.pro/v1"
export OPENAI_API_KEY="fetch_ваш_ключ"

Теперь минимальный запрос:

bash
from openai import OpenAI

client = OpenAI()  # возьмёт OPENAI_BASE_URL и OPENAI_API_KEY

MODEL = "gemini-3.8-flash"

resp = client.chat.completions.create(
    model=MODEL,
    messages=[
        {"role": "system", "content": "Отвечай коротко и по делу."},
        {"role": "user", "content": "Чем list отличается от tuple в Python?"},
    ],
)
print(resp.choices[0].message.content)
print(resp.usage)

Если хотите задать адрес явно, не используя переменные окружения:

bash
client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_ваш_ключ")

Адрес оканчивается на /v1: OpenAI SDK сам добавляет только /chat/completions. Подробнее про клиент — в разделе Python справочника API, про сам эндпоинт — в описании chat completions там же.

Стриминг

Для интерфейсов и чат-ботов ответ удобно получать кусками:

bash
stream = client.chat.completions.create(
    model=MODEL,
    messages=[{"role": "user", "content": "Расскажи про генераторы в Python"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices:
        piece = chunk.choices[0].delta.content
        if piece:
            print(piece, end="", flush=True)
    elif chunk.usage:
        print(f"\n[вход: {chunk.usage.prompt_tokens}, выход: {chunk.usage.completion_tokens}]")

Проверка if chunk.choices: обязательна. В конце потока сервер присылает последний чанк с usage и пустым списком choices, и обращение к chunk.choices[0] без проверки упадёт с IndexError.

JSON вместо свободного текста

Если ответ нужно разобрать программой, просите JSON явно и всё равно проверяйте результат:

bash
import json

resp = client.chat.completions.create(
    model=MODEL,
    messages=[
        {
            "role": "system",
            "content": "Верни только JSON-объект с ключами name, date, participants (массив строк).",
        },
        {"role": "user", "content": "Анна и Борис идут на конференцию по ИИ в пятницу."},
    ],
    response_format={"type": "json_object"},
)

try:
    data = json.loads(resp.choices[0].message.content)
except json.JSONDecodeError:
    data = None  # повторите запрос или отправьте в очередь на ручной разбор
print(data)

Параметр response_format относится к OpenAI-формату. В документации Google для совместимого режима есть примеры структурированного вывода по схеме, но то, как именно параметр доходит до модели через шлюз, лучше проверить на своём запросе. Если получите ошибку 400, уберите response_format и оставьте только инструкцию в промпте и json.loads: на практике этого хватает для простых схем.

Ошибки и повторы

bash
from openai import OpenAI, APIStatusError, APIConnectionError

try:
    resp = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": "Привет!"}],
    )
except APIStatusError as e:
    if e.status_code == 401:
        print("Неверный ключ")
    elif e.status_code == 402:
        print("Не хватает баланса")
    elif e.status_code == 404:
        print("Модели нет в каталоге, сверьтесь с GET /v1/models")
    elif e.status_code in (429, 503):
        print("Лимит ключа или провайдер недоступен, повторите позже")
    else:
        raise
except APIConnectionError:
    print("Сеть недоступна")

Повторять запрос имеет смысл при 429 и 503, причём с растущей паузой. Ошибки 401, 402 и 403 повторами не лечатся. Если модель выключена, сервер вернёт 503 с кодом model_disabled: тогда возьмите другую модель из GET /v1/models. Список моделей каталога всегда можно получить запросом client.models.list().

Сколько это стоит

Цены Zukko на 18 октября 2026 для gemini-3.8-flash: $0.125 за 1M входных токенов и $0.6 за 1M выходных. Контекст — 1M токенов, на вход принимается только текст.

Пример с условными объёмами: 1000 запросов по 2000 входных и 500 выходных токенов.

  • вход: 1000 × 2000 = 2M токенов, 2 × 0.125 = $0.25;
  • выход: 1000 × 500 = 0.5M токенов, 0.5 × 0.6 = $0.30;
  • итого: 0.25 + 0.30 = $0.55.

По официальным ценам из нашей таблицы (вход $0.75, выход $3.75) тот же объём стоил бы 2 × 0.75 + 0.5 × 3.75 = $3.375. Реальную сумму по каждому запросу показывает заголовок X-Zukko-Cost-Micros (в микродолларах) через with_raw_response:

bash
raw = client.chat.completions.with_raw_response.create(
    model=MODEL,
    messages=[{"role": "user", "content": "Привет!"}],
)
print(raw.headers.get("x-zukko-cost-micros"))
resp = raw.parse()

Заголовок есть только у обычных (не потоковых) ответов. Актуальный список моделей и цен — GET https://api.zukko.pro/v1/models или страница «Модели» в кабинете. Если модель рассуждает перед ответом, эти токены учитываются в выходе, поэтому на сложных запросах смотрите на usage, а не на длину видимого ответа.

Нативный google-genai или OpenAI SDK

КритерийOpenAI SDK через шлюзНативный google-genai
Установкаpip install openaipip install google-genai
Формат запросаmessages, chat.completionsinput, interactions.create
Смена поставщикаменяется строка modelпридётся переписывать код
Специфика Geminiчерез параметры совместимого слояполный набор возможностей Google
Ключfetch_... шлюзаключ Google AI Studio

Нативный клиент выглядит так (по текущему quickstart Google, ключ берётся из GEMINI_API_KEY):

bash
from google import genai

client = genai.Client()
interaction = client.interactions.create(
    model="gemini-3.8-flash",
    input="Чем list отличается от tuple в Python?",
)
print(interaction.output_text)

Берите нативную библиотеку, если нужны функции, которых нет в совместимом слое, например настройки мышления в полном виде и всё, что Google выпускает раньше других. Берите OpenAI SDK, если важны переносимость кода, единый формат для разных моделей и общий баланс. Оговорка по параметрам: на странице диагностики Google указано, что у новых моделей линейки (3.6 и новее) собственные значения temperature и top_p игнорируются, так что не рассчитывайте на них как на ручку управления.

Попробуйте на своих данных: создайте ключ в кабинете, подставьте его в пример выше и сравните ответы gemini-3.8-flash с gpt-6.1-sol или deepseek-v4.1-flash, поменяв одну строку. Про выбор между моделями по цене и индексу силы читайте в статье Индекс силы моделей, а о подключении Gemini как отдельной модели — в материале Gemini 3.8 Flash через API.

Частые вопросы

Нужен ли отдельный ключ Google, чтобы вызвать Gemini по OpenAI SDK?

Через шлюз Zukko — нет, достаточно ключа fetch_.... Напрямую к Google нужен ключ из Google AI Studio, и доступность сервиса зависит от региона.

Какой base_url указывать?

https://api.zukko.pro/v1, с суффиксом /v1. Для Anthropic SDK адрес другой (без /v1), но к Gemini это не относится.

Работает ли стриминг и вызов функций?

Стриминг работает в OpenAI-формате, пример выше. Для вызова функций и других возможностей совместимого слоя ориентируйтесь на документацию Google и проверяйте поведение на своей задаче.

Как узнать точное имя модели?

Отправьте GET https://api.zukko.pro/v1/models со своим ключом или откройте страницу «Модели» в кабинете. Неизвестное имя даст ошибку 404 model_not_found.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.