Пакетный режим 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 часа, но фактическое время обработки может варьироваться в зависимости от загрузки системы и размера задания. Для больших заданий рассмотрите возможность разбивки на более мелкие партии, если промежуточные результаты требуются быстрее.
Что дальше?
Дополнительные примеры можно найти в блокноте пакетного режима .