Пакетный режим

Пакетный режим Gemini API предназначен для асинхронной обработки больших объёмов запросов за 50% от стандартной стоимости . Целевое время выполнения — 24 часа, но в большинстве случаев оно значительно меньше.

Используйте пакетный режим для масштабных несрочных задач, таких как предварительная обработка данных или проведение оценок, где не требуется немедленный ответ.

Создание пакетного задания

У вас есть два способа отправки запросов в пакетном режиме:

  • Встроенные запросы : список объектов GenerateContentRequest , непосредственно включённых в запрос на создание пакета. Подходит для небольших пакетов, общий размер запроса которых не превышает 20 МБ. Модель возвращает список объектов inlineResponse .
  • Входной файл : JSON-файл (JSONL) , каждая строка которого содержит полный объект GenerateContentRequest . Этот метод рекомендуется для больших запросов. Выходные данные, возвращаемые моделью, представляют собой JSONL-файл, каждая строка которого представляет собой либо GenerateContentResponse , либо объект состояния.

Встроенные запросы

Для небольшого количества запросов вы можете напрямую встроить объекты GenerateContentRequest в BatchGenerateContentRequest . В следующем примере метод BatchGenerateContent вызывается со встроенными запросами:

Питон


from google import genai
from google.genai import types

client = genai.Client()

# A list of dictionaries, where each is a GenerateContentRequest
inline_requests = [
    {
        'contents': [{
            'parts': [{'text': 'Tell me a one-sentence joke.'}],
            'role': 'user'
        }]
    },
    {
        'contents': [{
            'parts': [{'text': 'Why is the sky blue?'}],
            'role': 'user'
        }]
    }
]

inline_batch_job = client.batches.create(
    model="models/gemini-2.5-flash",
    src=inline_requests,
    config={
        'display_name': "inlined-requests-job-1",
    },
)

print(f"Created batch job: {inline_batch_job.name}")

ОТДЫХ

curl https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:batchGenerateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-X POST \
-H "Content-Type:application/json" \
-d '{
    "batch": {
        "display_name": "my-batch-requests",
        "input_config": {
            "requests": {
                "requests": [
                    {
                        "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},
                        "metadata": {
                            "key": "request-1"
                        }
                    },
                    {
                        "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},
                        "metadata": {
                            "key": "request-2"
                        }
                    }
                ]
            }
        }
    }
}'

Входной файл

Для больших наборов запросов подготовьте файл JSON Lines (JSONL). Каждая строка в этом файле должна быть JSON-объектом, содержащим пользовательский ключ и объект запроса, где запрос — это допустимый объект GenerateContentRequest . Пользовательский ключ используется в ответе для указания того, какой вывод является результатом запроса. Например, запрос с ключом request-1 будет иметь ответ, аннотированный тем же именем ключа.

Этот файл загружен с помощью File API . Максимально допустимый размер входного файла — 2 ГБ.

Ниже приведён пример JSONL-файла. Вы можете сохранить его в файле с именем my-batch-requests.json :

{"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generation_config": {"temperature": 0.7}}}
{"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}

Аналогично встроенным запросам вы можете указать другие параметры, такие как системные инструкции, инструменты или другие конфигурации в каждом запросе JSON.

Вы можете загрузить этот файл с помощью File API , как показано в следующем примере. При работе с многомодальным вводом вы можете ссылаться на другие загруженные файлы в вашем JSONL-файле.

Питон


from google import genai
from google.genai import types

client = genai.Client()

# Create a sample JSONL file
with open("my-batch-requests.jsonl", "w") as f:
    requests = [
        {"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]}},
        {"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}
    ]
    for req in requests:
        f.write(json.dumps(req) + "\n")

# Upload the file to the File API
uploaded_file = client.files.upload(
    file='my-batch-requests.jsonl',
    config=types.UploadFileConfig(display_name='my-batch-requests', mime_type='jsonl')
)

print(f"Uploaded file: {uploaded_file.name}")

ОТДЫХ

tmp_batch_input_file=batch_input.tmp
echo -e '{"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generationConfig": {"temperature": 0.7}}\n{"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}' > batch_input.tmp
MIME_TYPE=$(file -b --mime-type "${tmp_batch_input_file}")
NUM_BYTES=$(wc -c < "${tmp_batch_input_file}")
DISPLAY_NAME=BatchInput

tmp_header_file=upload-header.tmp

# Initial resumable request defining metadata.
# The upload url is in the response headers dump them to a file.
curl "https://generativelanguage.googleapis.com/upload/v1beta/files \
-D "${tmp_header_file}" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "X-Goog-Upload-Protocol: resumable" \
-H "X-Goog-Upload-Command: start" \
-H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \
-H "Content-Type: application/jsonl" \
-d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null

upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")
rm "${tmp_header_file}"

# Upload the actual bytes.
curl "${upload_url}" \
-H "Content-Length: ${NUM_BYTES}" \
-H "X-Goog-Upload-Offset: 0" \
-H "X-Goog-Upload-Command: upload, finalize" \
--data-binary "@${tmp_batch_input_file}" 2> /dev/null > file_info.json

file_uri=$(jq ".file.uri" file_info.json)

В следующем примере вызывается метод BatchGenerateContent с входным файлом, загруженным с помощью File API:

Питон


# Assumes `uploaded_file` is the file object from the previous step
file_batch_job = client.batches.create(
    model="gemini-2.5-flash",
    src=uploaded_file.name,
    config={
        'display_name': "file-upload-job-1",
    },
)

print(f"Created batch job: {file_batch_job.name}")

ОТДЫХ

BATCH_INPUT_FILE='files/123456' # File ID
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:batchGenerateContent \
-X POST \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" \
-d "{
    'batch': {
        'display_name': 'my-batch-requests',
        'input_config': {
            'requests': {
                'file_name': ${BATCH_INPUT_FILE}
            }
        }
    }
}"

При создании пакетного задания вы получите его имя. Используйте это имя для отслеживания статуса задания, а также для получения результатов после его завершения.

Ниже приведен пример вывода, содержащего имя задания:


Created batch job from file: batches/123456789

Запросить конфигурацию

Вы можете включить любые конфигурации запроса, которые вы бы использовали в стандартном непакетном запросе. Например, можно указать температуру, системные инструкции или даже передать другие параметры. В следующем примере показан пример встроенного запроса, содержащего системную инструкцию для одного из запросов:

inline_requests_list = [
    {'contents': [{'parts': [{'text': 'Write a short poem about a cloud.'}]}]},
    {'contents': [{'parts': [{'text': 'Write a short poem about a cat.'}]}], 'system_instructions': {'parts': [{'text': 'You are a cat. Your name is Neko.'}]}}
]

Аналогичным образом можно указать инструменты, используемые для запроса. В следующем примере показан запрос, который включает инструмент поиска Google :

inline_requests_list = [
    {'contents': [{'parts': [{'text': 'Who won the euro 1998?'}]}]},
    {'contents': [{'parts': [{'text': 'Who won the euro 2025?'}]}], 'tools': [{'google_search ': {}}]}
]

Вы также можете указать структурированный вывод . В следующем примере показано, как это сделать для пакетных запросов.

from google import genai
from pydantic import BaseModel, TypeAdapter

class Recipe(BaseModel):
    recipe_name: str
    ingredients: list[str]

client = genai.Client()

# A list of dictionaries, where each is a GenerateContentRequest
inline_requests = [
    {
        'contents': [{
            'parts': [{'text': 'List a few popular cookie recipes, and include the amounts of ingredients.'}],
            'role': 'user'
        }],
        'config': {
            'response_mime_type': 'application/json',
            'response_schema': list[Recipe]
        }
    },
    {
        'contents': [{
            'parts': [{'text': 'List a few popular gluten free cookie recipes, and include the amounts of ingredients.'}],
            'role': 'user'
        }],
        'config': {
            'response_mime_type': 'application/json',
            'response_schema': list[Recipe]
        }
    }
]

inline_batch_job = client.batches.create(
    model="models/gemini-2.5-flash",
    src=inline_requests,
    config={
        'display_name': "structured-output-job-1"
    },
)

# wait for the job to finish
job_name = inline_batch_job.name
print(f"Polling status for job: {job_name}")

while True:
    batch_job_inline = client.batches.get(name=job_name)
    if batch_job_inline.state.name in ('JOB_STATE_SUCCEEDED', 'JOB_STATE_FAILED', 'JOB_STATE_CANCELLED'):
        break
    print(f"Job not finished. Current state: {batch_job_inline.state.name}. Waiting 30 seconds...")
    time.sleep(30)

print(f"Job finished with state: {batch_job_inline.state.name}")

# print the response
for i, inline_response in enumerate(batch_job_inline.dest.inlined_responses):
    print(f"\n--- Response {i+1} ---")

    # Check for a successful response
    if inline_response.response:
        # The .text property is a shortcut to the generated text.
        print(inline_response.response.text)

Мониторинг статуса задания

Используйте имя операции, полученное при создании пакетного задания, для проверки его состояния. Поле состояния пакетного задания отобразит его текущий статус. Пакетное задание может находиться в одном из следующих состояний:

  • JOB_STATE_PENDING : Задание создано и ожидает обработки службой.
  • JOB_STATE_SUCCEEDED : Задание выполнено успешно. Теперь вы можете получить результаты.
  • JOB_STATE_FAILED : Задание не выполнено. Подробнее см. в описании ошибки.
  • JOB_STATE_CANCELLED : Задание было отменено пользователем.

Вы можете периодически опрашивать статус задания, чтобы проверить его завершение.

Питон


# Use the name of the job you want to check
# e.g., inline_batch_job.name from the previous step
job_name = "YOUR_BATCH_JOB_NAME"  # (e.g. 'batches/your-batch-id')
batch_job = client.batches.get(name=job_name)

completed_states = set([
    'JOB_STATE_SUCCEEDED',
    'JOB_STATE_FAILED',
    'JOB_STATE_CANCELLED',
])

print(f"Polling status for job: {job_name}")
batch_job = client.batches.get(name=job_name) # Initial get
while batch_job.state.name not in completed_states:
  print(f"Current state: {batch_job.state.name}")
  time.sleep(30) # Wait for 30 seconds before polling again
  batch_job = client.batches.get(name=job_name)

print(f"Job finished with state: {batch_job.state.name}")
if batch_job.state.name == 'JOB_STATE_FAILED':
    print(f"Error: {batch_job.error}")

Получение результатов

Как только статус задания покажет, что пакетное задание выполнено успешно, результаты будут доступны в поле response .

Питон

import json

# Use the name of the job you want to check
# e.g., inline_batch_job.name from the previous step
job_name = "YOUR_BATCH_JOB_NAME"
batch_job = client.batches.get(name=job_name)

if batch_job.state.name == 'JOB_STATE_SUCCEEDED':

    # If batch job was created with a file
    if batch_job.dest and batch_job.dest.file_name:
        # Results are in a file
        result_file_name = batch_job.dest.file_name
        print(f"Results are in file: {result_file_name}")

        print("Downloading result file content...")
        file_content = client.files.download(file=result_file_name)
        # Process file_content (bytes) as needed
        print(file_content.decode('utf-8'))

    # If batch job was created with inline request
    elif batch_job.dest and batch_job.dest.inlined_responses:
        # Results are inline
        print("Results are inline:")
        for i, inline_response in enumerate(batch_job.dest.inlined_responses):
            print(f"Response {i+1}:")
            if inline_response.response:
                # Accessing response, structure may vary.
                try:
                    print(inline_response.response.text)
                except AttributeError:
                    print(inline_response.response) # Fallback
            elif inline_response.error:
                print(f"Error: {inline_response.error}")
    else:
        print("No results found (neither file nor inline).")
else:
    print(f"Job did not succeed. Final state: {batch_job.state.name}")
    if batch_job.error:
        print(f"Error: {batch_job.error}")

ОТДЫХ

BATCH_NAME="batches/123456" # Your batch job name

curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" 2> /dev/null > batch_status.json

if jq -r '.done' batch_status.json | grep -q "false"; then
    echo "Batch has not finished processing"
fi

batch_state=$(jq -r '.metadata.state' batch_status.json)
if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then
    if [[ $(jq '.response | has("inlinedResponses")' batch_status.json) = "true" ]]; then
        jq -r '.response.inlinedResponses' batch_status.json
        exit
    fi
    responses_file_name=$(jq -r '.response.responsesFile' batch_status.json)
    curl https://generativelanguage.googleapis.com/download/v1beta/$responses_file_name:download?alt=media \
    -H "x-goog-api-key: $GEMINI_API_KEY" 2> /dev/null
elif [[ $batch_state = "JOB_STATE_FAILED" ]]; then
    jq '.error' batch_status.json
elif [[ $batch_state == "JOB_STATE_CANCELLED" ]]; then
    echo "Batch was cancelled by the user"
fi

Отмена пакетного задания

Вы можете отменить текущее пакетное задание, указав его имя. При отмене задания обработка новых запросов прекращается.

Питон

# Cancel a batch job
client.batches.cancel(name=batch_job_to_cancel.name)

ОТДЫХ

BATCH_NAME="batches/123456" # Your batch job name

# Cancel the batch
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME:cancel \
-H "x-goog-api-key: $GEMINI_API_KEY" \

# Confirm that the status of the batch after cancellation is JOB_STATE_CANCELLED
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" 2> /dev/null | jq -r '.metadata.state'

Удаление пакетного задания

Вы можете удалить существующее пакетное задание, указав его имя. При удалении задание прекращает обработку новых запросов и удаляется из списка пакетных заданий.

Питон

# Delete a batch job
client.batches.delete(name=batch_job_to_delete.name)

ОТДЫХ

BATCH_NAME="batches/123456" # Your batch job name

# Cancel the batch
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME:delete \
-H "x-goog-api-key: $GEMINI_API_KEY" \

Технические детали

  • Поддерживаемые модели: Пакетный режим поддерживает ряд моделей Gemini. Подробнее о поддержке пакетного режима каждой моделью см. на странице «Модели» . Поддерживаемые модальности пакетного режима аналогичны тем, что поддерживаются в интерактивном (не пакетном) API.
  • Цены: использование пакетного режима стоит 50% от стандартной стоимости интерактивного API для эквивалентной модели. Подробности см. на странице цен . Подробности об ограничениях скорости для этой функции см. на странице ограничений скорости.
  • Целевой уровень обслуживания (SLO): пакетные задания должны быть выполнены в течение 24 часов. Многие задания могут быть выполнены гораздо быстрее в зависимости от их размера и текущей нагрузки на систему.
  • Кэширование: Кэширование контекста включено для пакетных запросов. Если запрос в пакете приводит к попаданию в кэш, стоимость кэшированных токенов будет такой же, как и для трафика в обычном режиме.

Лучшие практики

  • Используйте входные файлы для больших запросов: при большом количестве запросов всегда используйте метод ввода файлов для лучшей управляемости и во избежание превышения ограничений на размер запроса для самого вызова BatchGenerateContent . Обратите внимание, что размер входного файла ограничен 2 ГБ.
  • Обработка ошибок: Проверьте значение failedRequestCount batchStats после завершения задания. При использовании выходного файла проанализируйте каждую строку, чтобы определить, является ли она GenerateContentResponse или объектом состояния, указывающим на ошибку для данного конкретного запроса. Полный список кодов ошибок см. в руководстве по устранению неполадок .
  • Отправьте задания один раз: создание пакетного задания не является идемпотентным. Если вы отправите один и тот же запрос на создание дважды, будут созданы два отдельных пакетных задания.
  • Разбивайте очень большие партии: целевое время выполнения составляет 24 часа, но фактическое время обработки может варьироваться в зависимости от загрузки системы и размера задания. Для больших заданий рассмотрите возможность разбивки на более мелкие партии, если промежуточные результаты требуются быстрее.

Что дальше?

Дополнительные примеры можно найти в блокноте пакетного режима .