Wsadowy interfejs Gemini API został zaprojektowany do asynchronicznego przetwarzania dużych ilości żądań przy 50% standardowego kosztu. Docelowy czas realizacji to 24 godziny, ale w większości przypadków jest on znacznie krótszy.
Używaj wsadowego interfejsu API do zadań na dużą skalę, które nie wymagają natychmiastowej odpowiedzi, takich jak wstępne przetwarzanie danych czy przeprowadzanie ocen.
Tworzenie zadania wsadowego
Żądania w wsadowym interfejsie API możesz przesyłać na 2 sposoby:
- Żądania w treści: lista obiektów
GenerateContentRequestdołączona bezpośrednio do żądania utworzenia zadania wsadowego. Ta metoda jest odpowiednia w przypadku mniejszych zadań wsadowych, w których łączny rozmiar żądania nie przekracza 20 MB. Dane wyjściowe zwracane przez model to lista obiektówinlineResponse. - Plik wejściowy: plik JSON Lines (JSONL)
, w którym każdy wiersz zawiera pełny
GenerateContentRequestobiekt. Ta metoda jest zalecana w przypadku większych żądań. Dane wyjściowe zwracane przez model to plik JSONL, w którym każdy wiersz jest obiektemGenerateContentResponselub obiektem stanu.
Żądania w treści
W przypadku niewielkiej liczby żądań możesz bezpośrednio osadzić obiekty
GenerateContentRequest
w BatchGenerateContentRequest. Ten
przykład wywołuje metodę
BatchGenerateContent
z żądaniami w treści:
Python
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="gemini-3.8-flash",
src=inline_requests,
config={
'display_name': "inlined-requests-job-1",
},
)
print(f"Created batch job: {inline_batch_job.name}")
JavaScript
import {GoogleGenAI} from '@google/genai';
const ai = new GoogleGenAI({});
const inlinedRequests = [
{
contents: [{
parts: [{text: 'Tell me a one-sentence joke.'}],
role: 'user'
}]
},
{
contents: [{
parts: [{'text': 'Why is the sky blue?'}],
role: 'user'
}]
}
]
const response = await ai.batches.create({
model: 'gemini-3.8-flash',
src: inlinedRequests,
config: {
displayName: 'inlined-requests-job-1',
}
});
console.log(response);
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-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"
}
}
]
}
}
}
}'
Plik wejściowy
W przypadku większych zestawów żądań przygotuj plik JSON Lines (JSONL). Każdy wiersz w
tym pliku musi być obiektem JSON zawierającym zdefiniowany przez użytkownika klucz i obiekt żądania, gdzie żądanie jest prawidłowym
GenerateContentRequest obiektem. Klucz zdefiniowany przez użytkownika jest używany w odpowiedzi do wskazania, które dane wyjściowe są wynikiem którego żądania. Na przykład odpowiedź na żądanie z kluczem zdefiniowanym jako request-1 będzie oznaczona tą samą nazwą klucza.
Ten plik jest przesyłany za pomocą interfejsu File API. Maksymalny dozwolony rozmiar pliku wejściowego to 2 GB.
Poniżej znajdziesz przykład pliku JSONL. Możesz go zapisać w pliku o nazwie 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?"}]}]}}
Podobnie jak w przypadku żądań w treści, w każdym żądaniu JSON możesz określić inne parametry, takie jak instrukcje systemowe, narzędzia lub inne konfiguracje.
Ten plik możesz przesłać za pomocą interfejsu File API, jak pokazano w tym przykładzie. Jeśli pracujesz z danymi wejściowymi multimodalnymi, możesz odwoływać się do innych przesłanych plików w pliku JSONL.
Python
import json
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}")
JavaScript
import {GoogleGenAI} from '@google/genai';
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from 'url';
const ai = new GoogleGenAI({});
const fileName = "my-batch-requests.jsonl";
// Define the requests
const 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?" }] }] } }
];
// Construct the full path to file
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const filePath = path.join(__dirname, fileName); // __dirname is the directory of the current script
async function writeBatchRequestsToFile(requests, filePath) {
try {
// Use a writable stream for efficiency, especially with larger files.
const writeStream = fs.createWriteStream(filePath, { flags: 'w' });
writeStream.on('error', (err) => {
console.error(`Error writing to file ${filePath}:`, err);
});
for (const req of requests) {
writeStream.write(JSON.stringify(req) + '\n');
}
writeStream.end();
console.log(`Successfully wrote batch requests to ${filePath}`);
} catch (error) {
// This catch block is for errors that might occur before stream setup,
// stream errors are handled by the 'error' event.
console.error(`An unexpected error occurred:`, error);
}
}
// Write to a file.
writeBatchRequestsToFile(requests, filePath);
// Upload the file to the File API.
const uploadedFile = await ai.files.upload({file: 'my-batch-requests.jsonl', config: {
mimeType: 'jsonl',
}});
console.log(uploadedFile.name);
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
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)
Ten przykład wywołuje metodę
BatchGenerateContent
z plikiem wejściowym przesłanym za pomocą interfejsu File API:
Python
from google import genai
# Assumes `uploaded_file` is the file object from the previous step
client = genai.Client()
file_batch_job = client.batches.create(
model="gemini-3.8-flash",
src=uploaded_file.name,
config={
'display_name': "file-upload-job-1",
},
)
print(f"Created batch job: {file_batch_job.name}")
JavaScript
// Assumes `uploadedFile` is the file object from the previous step
const fileBatchJob = await ai.batches.create({
model: 'gemini-3.8-flash',
src: uploadedFile.name,
config: {
displayName: 'file-upload-job-1',
}
});
console.log(fileBatchJob);
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
# Set the File ID taken from the upload response.
BATCH_INPUT_FILE='files/123456'
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-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': {
'file_name': '${BATCH_INPUT_FILE}'
}
}
}"
Gdy utworzysz zadanie wsadowe, otrzymasz jego nazwę. Użyj tej nazwy do monitorowania stanu zadania i pobierania wyników po jego zakończeniu.
Oto przykładowe dane wyjściowe zawierające nazwę zadania:
Created batch job from file: batches/123456789
Obsługa osadzania wsadowego
Aby zwiększyć przepustowość, możesz użyć wsadowego interfejsu API do interakcji z modelem
Embeddings.
Aby utworzyć zadanie wsadowe osadzania z żądaniami w treści
lub plikami wejściowymi, użyj interfejsu batches.create_embeddings API i
określ model osadzania.
Python
from google import genai
client = genai.Client()
# Creating an embeddings batch job with an input file request:
file_job = client.batches.create_embeddings(
model="gemini-embedding-2",
src={'file_name': uploaded_batch_requests.name},
config={'display_name': "Input embeddings batch"},
)
# Creating an embeddings batch job with an inline request:
batch_job = client.batches.create_embeddings(
model="gemini-embedding-2",
# For a predefined list of requests `inlined_requests`
src={'inlined_requests': inlined_requests},
config={'display_name': "Inlined embeddings batch"},
)
JavaScript
// Creating an embeddings batch job with an input file request:
let fileJob;
fileJob = await client.batches.createEmbeddings({
model: 'gemini-embedding-2',
src: {fileName: uploadedBatchRequests.name},
config: {displayName: 'Input embeddings batch'},
});
console.log(`Created batch job: ${fileJob.name}`);
// Creating an embeddings batch job with an inline request:
let batchJob;
batchJob = await client.batches.createEmbeddings({
model: 'gemini-embedding-2',
// For a predefined a list of requests `inlinedRequests`
src: {inlinedRequests: inlinedRequests},
config: {displayName: 'Inlined embeddings batch'},
});
console.log(`Created batch job: ${batchJob.name}`);
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
Więcej przykładów znajdziesz w sekcji Osadzanie w przewodniku po wsadowym interfejsie API .
Konfiguracja żądania
Możesz uwzględnić dowolne konfiguracje żądań, których używasz w standardowym żądaniu bez wsadowym. Możesz na przykład określić temperaturę, instrukcje systemowe lub nawet przekazać inne modalności. Ten przykład pokazuje przykładowe żądanie w treści, które zawiera instrukcję systemową dla jednego z żądań:
Python
inline_requests_list = [
{'contents': [{'parts': [{'text': 'Write a short poem about a cloud.'}]}]},
{'contents': [{
'parts': [{
'text': 'Write a short poem about a cat.'
}]
}],
'config': {
'system_instruction': {'parts': [{'text': 'You are a cat. Your name is Neko.'}]}}
}
]
JavaScript
inlineRequestsList = [
{contents: [{parts: [{text: 'Write a short poem about a cloud.'}]}]},
{contents: [{parts: [{text: 'Write a short poem about a cat.'}]}],
config: {systemInstruction: {parts: [{text: 'You are a cat. Your name is Neko.'}]}}}
]
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
Podobnie możesz określić narzędzia, których chcesz użyć w żądaniu. Ten przykład pokazuje żądanie, które włącza narzędzie wyszukiwarki Google:
Python
inlined_requests = [
{'contents': [{'parts': [{'text': 'Who won the euro 1998?'}]}]},
{'contents': [{'parts': [{'text': 'Who won the euro 2025?'}]}],
'config':{'tools': [{'google_search': {}}]}}]
JavaScript
inlineRequestsList = [
{contents: [{parts: [{text: 'Who won the euro 1998?'}]}]},
{contents: [{parts: [{text: 'Who won the euro 2025?'}]}],
config: {tools: [{googleSearch: {}}]}}
]
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
Możesz też określić uporządkowane dane wyjściowe. Ten przykład pokazuje, jak określić żądania wsadowe.
Python
import time
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="gemini-3.8-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', 'JOB_STATE_EXPIRED'):
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, start=1):
print(f"\n--- Response {i} ---")
# Check for a successful response
if inline_response.response:
# The .text property is a shortcut to the generated text.
print(inline_response.response.text)
JavaScript
import {GoogleGenAI, Type} from '@google/genai';
const ai = new GoogleGenAI({});
const inlinedRequests = [
{
contents: [{
parts: [{text: 'List a few popular cookie recipes, and include the amounts of ingredients.'}],
role: 'user'
}],
config: {
responseMimeType: 'application/json',
responseSchema: {
type: Type.ARRAY,
items: {
type: Type.OBJECT,
properties: {
'recipeName': {
type: Type.STRING,
description: 'Name of the recipe',
nullable: false,
},
'ingredients': {
type: Type.ARRAY,
items: {
type: Type.STRING,
description: 'Ingredients of the recipe',
nullable: false,
},
},
},
required: ['recipeName'],
},
},
}
},
{
contents: [{
parts: [{text: 'List a few popular gluten free cookie recipes, and include the amounts of ingredients.'}],
role: 'user'
}],
config: {
responseMimeType: 'application/json',
responseSchema: {
type: Type.ARRAY,
items: {
type: Type.OBJECT,
properties: {
'recipeName': {
type: Type.STRING,
description: 'Name of the recipe',
nullable: false,
},
'ingredients': {
type: Type.ARRAY,
items: {
type: Type.STRING,
description: 'Ingredients of the recipe',
nullable: false,
},
},
},
required: ['recipeName'],
},
},
}
}
]
const inlinedBatchJob = await ai.batches.create({
model: 'gemini-3.8-flash',
src: inlinedRequests,
config: {
displayName: 'inlined-requests-job-1',
}
});
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
Poniżej znajdziesz przykładowe dane wyjściowe tego zadania:
--- Response 1 ---
[
{
"recipe_name": "Chocolate Chip Cookies",
"ingredients": [
"1 cup (2 sticks) unsalted butter, softened",
"3/4 cup granulated sugar",
"3/4 cup packed light brown sugar",
"1 large egg",
"1 teaspoon vanilla extract",
"2 1/4 cups all-purpose flour",
"1 teaspoon baking soda",
"1/2 teaspoon salt",
"1 1/2 cups chocolate chips"
]
},
{
"recipe_name": "Oatmeal Raisin Cookies",
"ingredients": [
"1 cup (2 sticks) unsalted butter, softened",
"1 cup packed light brown sugar",
"1/2 cup granulated sugar",
"2 large eggs",
"1 teaspoon vanilla extract",
"1 1/2 cups all-purpose flour",
"1 teaspoon baking soda",
"1 teaspoon ground cinnamon",
"1/2 teaspoon salt",
"3 cups old-fashioned rolled oats",
"1 cup raisins"
]
},
{
"recipe_name": "Sugar Cookies",
"ingredients": [
"1 cup (2 sticks) unsalted butter, softened",
"1 1/2 cups granulated sugar",
"1 large egg",
"1 teaspoon vanilla extract",
"2 3/4 cups all-purpose flour",
"1 teaspoon baking powder",
"1/2 teaspoon salt"
]
}
]
--- Response 2 ---
[
{
"recipe_name": "Gluten-Free Chocolate Chip Cookies",
"ingredients": [
"1 cup (2 sticks) unsalted butter, softened",
"3/4 cup granulated sugar",
"3/4 cup packed light brown sugar",
"2 large eggs",
"1 teaspoon vanilla extract",
"2 1/4 cups gluten-free all-purpose flour blend (with xanthan gum)",
"1 teaspoon baking soda",
"1/2 teaspoon salt",
"1 1/2 cups chocolate chips"
]
},
{
"recipe_name": "Gluten-Free Peanut Butter Cookies",
"ingredients": [
"1 cup (250g) creamy peanut butter",
"1/2 cup (100g) granulated sugar",
"1/2 cup (100g) packed light brown sugar",
"1 large egg",
"1 teaspoon vanilla extract",
"1/2 teaspoon baking soda",
"1/4 teaspoon salt"
]
},
{
"recipe_name": "Gluten-Free Oatmeal Raisin Cookies",
"ingredients": [
"1/2 cup (1 stick) unsalted butter, softened",
"1/2 cup granulated sugar",
"1/2 cup packed light brown sugar",
"1 large egg",
"1 teaspoon vanilla extract",
"1 cup gluten-free all-purpose flour blend",
"1/2 teaspoon baking soda",
"1/2 teaspoon ground cinnamon",
"1/4 teaspoon salt",
"1 1/2 cups gluten-free rolled oats",
"1/2 cup raisins"
]
}
]
Monitorowanie stanu zadania
Aby sprawdzić stan zadania wsadowego, użyj nazwy operacji uzyskanej podczas jego tworzenia. Aktualny stan zadania wsadowego jest widoczny w polu stanu. Zadanie wsadowe może mieć jeden z tych stanów:
JOB_STATE_PENDING: zadanie zostało utworzone i czeka na przetworzenie przez usługę.JOB_STATE_RUNNING: zadanie jest w trakcie realizacji.JOB_STATE_SUCCEEDED: zadanie zostało ukończone. Możesz teraz pobrać wyniki.JOB_STATE_FAILED: zadanie nie powiodło się. Więcej informacji znajdziesz w szczegółach błędu.JOB_STATE_CANCELLED: zadanie zostało anulowane przez użytkownika.JOB_STATE_EXPIRED: zadanie wygasło, ponieważ było uruchomione lub oczekiwało na wykonanie przez ponad 48 godzin. Nie będzie można pobrać żadnych wyników. Możesz spróbować ponownie przesłać zadanie lub podzielić żądania na mniejsze zadania wsadowe.
Aby sprawdzić, czy zadanie zostało ukończone, możesz okresowo sprawdzać jego stan.
Python
import time
from google import genai
client = genai.Client()
# 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',
'JOB_STATE_EXPIRED',
])
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}")
JavaScript
// Use the name of the job you want to check
// e.g., inlinedBatchJob.name from the previous step
let batchJob;
const completedStates = new Set([
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_EXPIRED',
]);
try {
batchJob = await ai.batches.get({name: inlinedBatchJob.name});
while (!completedStates.has(batchJob.state)) {
console.log(`Current state: ${batchJob.state}`);
// Wait for 30 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 30000));
batchJob = await client.batches.get({ name: batchJob.name });
}
console.log(`Job finished with state: ${batchJob.state}`);
if (batchJob.state === 'JOB_STATE_FAILED') {
// The exact structure of `error` might vary depending on the SDK
// This assumes `error` is an object with a `message` property.
console.error(`Error: ${batchJob.state}`);
}
} catch (error) {
console.error(`An error occurred while polling job ${batchJob.name}:`, error);
}
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
Sprawdzanie i webhooki
Masz już dość sprawdzania? Gemini obsługuje teraz
webhooki do asynchronicznego przetwarzania uzupełnień.
Zamiast ciągle wywoływać GET / operations, zasubskrybuj batch.succeeded, aby interfejs Gemini API mógł wysyłać powiadomienia w czasie rzeczywistym na Twój serwer po zakończeniu operacji asynchronicznych lub długotrwałych.
Python
from google import genai
client = genai.Client()
webhook = client.webhooks.create(
name="MyBatchWebhook",
subscribed_events=["batch.succeeded", "batch.failed"],
uri="https://my-api.com/gemini-callback",
)
print(f"Created webhook: {webhook.name}")
JavaScript
import { GoogleGenAI } from "@google/genai";
const client = new GoogleGenAI();
async function createWebhook() {
const webhook = await client.webhooks.create({
name: "MyBatchWebhook",
subscribed_events: ["batch.succeeded", "batch.failed"],
uri: "https://my-api.com/gemini-callback",
});
console.log(`Created webhook: ${webhook.name}`);
}
createWebhook();
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
curl -X POST \
"https://generativelanguage.googleapis.com/v1/webhooks?webhook_id=my-example-webhook-123" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $GOOGLE_API_KEY" \
-d '{
"name": "My Example Webhook",
"uri": "https://my-api.com/gemini-callback",
"subscribed_events": ["batch.succeeded", "batch.failed"]
}'
Pobieranie wyników
Gdy stan zadania wskazuje, że zadanie wsadowe zostało ukończone, wyniki są dostępne w polu response.
Domyślnie wyniki zadań wsadowych są przechowywane i dostępne do pobrania przez 6 tygodni, zanim zostaną trwale usunięte.
Python
import json
from google import genai
client = genai.Client()
# 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
# (for embeddings, use batch_job.dest.inlined_embed_content_responses)
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}")
JavaScript
// Use the name of the job you want to check
// e.g., inlinedBatchJob.name from the previous step
const jobName = "YOUR_BATCH_JOB_NAME";
try {
const batchJob = await ai.batches.get({ name: jobName });
if (batchJob.state === 'JOB_STATE_SUCCEEDED') {
console.log('Found completed batch:', batchJob.displayName);
console.log(batchJob);
// If batch job was created with a file destination
if (batchJob.dest?.fileName) {
const resultFileName = batchJob.dest.fileName;
console.log(`Results are in file: ${resultFileName}`);
console.log("Downloading result file content...");
const fileContentBuffer = await ai.files.download({ file: resultFileName });
// Process fileContentBuffer (Buffer) as needed
console.log(fileContentBuffer.toString('utf-8'));
}
// If batch job was created with inline responses
else if (batchJob.dest?.inlinedResponses) {
console.log("Results are inline:");
for (let i = 0; i < batchJob.dest.inlinedResponses.length; i++) {
const inlineResponse = batchJob.dest.inlinedResponses[i];
console.log(`Response ${i + 1}:`);
if (inlineResponse.response) {
// Accessing response, structure may vary.
if (inlineResponse.response.text !== undefined) {
console.log(inlineResponse.response.text);
} else {
console.log(inlineResponse.response); // Fallback
}
} else if (inlineResponse.error) {
console.error(`Error: ${inlineResponse.error}`);
}
}
}
// If batch job was an embedding batch with inline responses
else if (batchJob.dest?.inlinedEmbedContentResponses) {
console.log("Embedding results found inline:");
for (let i = 0; i < batchJob.dest.inlinedEmbedContentResponses.length; i++) {
const inlineResponse = batchJob.dest.inlinedEmbedContentResponses[i];
console.log(`Response ${i + 1}:`);
if (inlineResponse.response) {
console.log(inlineResponse.response);
} else if (inlineResponse.error) {
console.error(`Error: ${inlineResponse.error}`);
}
}
} else {
console.log("No results found (neither file nor inline).");
}
} else {
console.log(`Job did not succeed. Final state: ${batchJob.state}`);
if (batchJob.error) {
console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);
}
}
} catch (error) {
console.error(`An error occurred while processing job ${jobName}:`, error);
}
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
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"
elif [[ $batch_state == "JOB_STATE_EXPIRED" ]]; then
echo "Batch expired after 48 hours"
fi
Wyświetlanie listy zadań wsadowych
Możesz wyświetlić listę ostatnich zadań wsadowych.
Python
batch_jobs = client.batches.list()
# Optional query config:
# batch_jobs = client.batches.list(config={'page_size': 5})
for batch_job in batch_jobs:
print(batch_job)
JavaScript
const batchJobs = await ai.batches.list();
// Optional query config:
// const batchJobs = await ai.batches.list({config: {'pageSize': 5}});
for await (const batchJob of batchJobs) {
console.log(batchJob);
}
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
curl https://generativelanguage.googleapis.com/v1beta/batches \
-H "x-goog-api-key: $GEMINI_API_KEY"
Anulowanie zadania wsadowego
Trwające zadanie wsadowe możesz anulować za pomocą jego nazwy. Gdy zadanie zostanie anulowane, przestanie przetwarzać nowe żądania.
Python
client.batches.cancel(name=batch_job_to_cancel.name)
JavaScript
await ai.batches.cancel({name: batchJobToCancel.name});
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
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'
Usuwanie zadania wsadowego
Istniejące zadanie wsadowe możesz usunąć za pomocą jego nazwy. Gdy zadanie zostanie usunięte, przestanie przetwarzać nowe żądania i zostanie usunięte z listy zadań wsadowych.
Python
client.batches.delete(name=batch_job_to_delete.name)
JavaScript
await ai.batches.delete({name: batchJobToDelete.name});
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
BATCH_NAME="batches/123456" # Your batch job name
# Delete the batch job
curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME" \
-H "x-goog-api-key: $GEMINI_API_KEY"
Generowanie obrazów w trybie wsadowym
Jeśli używasz Gemini Nano Banana i musisz wygenerować wiele obrazów, możesz użyć wsadowego interfejsu API, aby uzyskać wyższe limity liczby żądań w zamian za czas realizacji do 24 godzin.
W przypadku małych zadań wsadowych (poniżej 20 MB) możesz użyć żądań w treści, a w przypadku dużych zadań wsadowych (zalecane w przypadku generowania obrazów) – pliku wejściowego JSONL:
Żądania w treści dotyczące obrazów
Python
import time
import base64
import json
from google import genai
from google.genai import types
from PIL import Image
client = genai.Client()
# 1. Create batch job with inline requests
inline_requests = [
{
'contents': [{'parts': [{'text': 'A big letter A surrounded by animals starting with the A letter'}]}],
'config': {'response_modalities': ['TEXT', 'IMAGE']}
},
{
'contents': [{'parts': [{'text': 'A big letter B surrounded by animals starting with the B letter'}]}],
'config': {'response_modalities': ['TEXT', 'IMAGE']}
}
]
inline_batch_job = client.batches.create(
model="gemini-3-pro-image-preview",
src=inline_requests,
config={
'display_name': "inlined-image-requests-job-1",
},
)
print(f"Created batch job: {inline_batch_job.name}")
# 2. Monitor job status
job_name = inline_batch_job.name
print(f"Polling status for job: {job_name}")
completed_states = set([
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_EXPIRED',
])
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(10) # Wait for 10 seconds before polling again
batch_job = client.batches.get(name=job_name)
print(f"Job finished with state: {batch_job.state.name}")
# 3. Retrieve results
if batch_job.state.name == 'JOB_STATE_SUCCEEDED':
print("Results are inline:")
for i, inline_response in enumerate(batch_job.dest.inlined_responses):
print(f"Response {i+1}:")
if inline_response.response:
for part in inline_response.response.candidates[0].content.parts:
if part.text:
print(part.text)
elif part.inline_data:
print(f"Image mime type: {part.inline_data.mime_type}")
image = part.as_image()
image.save(f"image_{i+1}.png")
elif inline_response.error:
print(f"Error: {inline_response.error}")
elif batch_job.state.name == 'JOB_STATE_FAILED':
print(f"Error: {batch_job.error}")
JavaScript
import {GoogleGenAI} from '@google/genai';
const ai = new GoogleGenAI({});
async function run() {
// 1. Create batch job with inline requests
const inlinedRequests = [
{
contents: [{parts: [{text: 'A big letter A surrounded by animals starting with the A letter'}]}],
config: {responseModalities: ['TEXT', 'IMAGE']}
},
{
contents: [{parts: [{text: 'A big letter B surrounded by animals starting with the B letter'}]}],
config: {responseModalities: ['TEXT', 'IMAGE']}
}
]
const inlineBatchJob = await ai.batches.create({
model: 'gemini-3-pro-image-preview',
src: inlinedRequests,
config: {
displayName: 'inlined-image-requests-job-1',
}
});
console.log(inlineBatchJob);
// 2. Monitor job status
let batchJob;
const completedStates = new Set([
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_EXPIRED',
]);
try {
batchJob = await ai.batches.get({name: inlineBatchJob.name});
while (!completedStates.has(batchJob.state)) {
console.log(`Current state: ${batchJob.state}`);
// Wait for 10 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 10000));
batchJob = await ai.batches.get({ name: batchJob.name });
}
console.log(`Job finished with state: ${batchJob.state}`);
} catch (error) {
console.error(`An error occurred while polling job ${inlineBatchJob.name}:`, error);
return;
}
// 3. Retrieve results
if (batchJob.state === 'JOB_STATE_SUCCEEDED') {
if (batchJob.dest?.inlinedResponses) {
console.log("Results are inline:");
for (let i = 0; i < batchJob.dest.inlinedResponses.length; i++) {
const inlineResponse = batchJob.dest.inlinedResponses[i];
console.log(`Response ${i + 1}:`);
if (inlineResponse.response) {
for (const part of inlineResponse.response.candidates[0].content.parts) {
if (part.text) {
console.log(part.text);
} else if (part.inlineData) {
console.log(`Image mime type: ${part.inlineData.mimeType}`);
}
}
} else if (inlineResponse.error) {
console.error(`Error: ${inlineResponse.error}`);
}
}
} else {
console.log("No inline results found.");
}
} else if (batchJob.state === 'JOB_STATE_FAILED') {
console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);
}
}
run();
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
# 1. Create batch job
printf -v request_data '{
"batch": {
"display_name": "my-batch-image-requests",
"input_config": {
"requests": {
"requests": [
{
"request": {
"contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}],
"generation_config": {"responseModalities": ["TEXT", "IMAGE"]}
},
"metadata": { "key": "request-1" }
},
{
"request": {
"contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}],
"generation_config": {"responseModalities": ["TEXT", "IMAGE"]}
},
"metadata": { "key": "request-2" }
}
]
}
}
}
}'
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:batchGenerateContent \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-X POST \
-H "Content-Type:application/json" \
-d "$request_data" > created_batch.json
BATCH_NAME=$(jq -r '.name' created_batch.json)
echo "Created batch job: $BATCH_NAME"
# 2. Poll job status until completion by repeating the following command
# Replace $BATCH_NAME with the name returned above.
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" > batch_status.json
echo "Current status:"
jq '.' batch_status.json
# 3. If state is JOB_STATE_SUCCEEDED, retrieve results from batch_status.json
batch_state=$(jq -r '.state' batch_status.json)
if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then
echo "Job succeeded. Results:"
jq -r '.dest.inlinedResponses' batch_status.json
fi
Plik wejściowy dla obrazów
Python
import json
import time
import base64
from google import genai
from google.genai import types
from PIL import Image
client = genai.Client()
# 1. Create and upload file
file_name = "my-batch-image-requests.jsonl"
with open(file_name, "w") as f:
requests = [
{"key": "request-1", "request": {"contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}},
{"key": "request-2", "request": {"contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}
]
for req in requests:
f.write(json.dumps(req) + "\n")
uploaded_file = client.files.upload(
file=file_name,
config=types.UploadFileConfig(display_name='my-batch-image-requests', mime_type='jsonl')
)
print(f"Uploaded file: {uploaded_file.name}")
# 2. Create batch job
file_batch_job = client.batches.create(
model="gemini-3-pro-image-preview",
src=uploaded_file.name,
config={
'display_name': "file-image-upload-job-1",
},
)
print(f"Created batch job: {file_batch_job.name}")
# 3. Monitor job status
job_name = file_batch_job.name
print(f"Polling status for job: {job_name}")
completed_states = set([
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_EXPIRED',
])
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(10) # Wait for 10 seconds before polling again
batch_job = client.batches.get(name=job_name)
print(f"Job finished with state: {batch_job.state.name}")
# 4. Retrieve results
if batch_job.state.name == 'JOB_STATE_SUCCEEDED':
result_file_name = batch_job.dest.file_name
print(f"Results are in file: {result_file_name}")
print("Downloading result file content...")
file_content_bytes = client.files.download(file=result_file_name)
file_content = file_content_bytes.decode('utf-8')
# The result file is also a JSONL file. Parse and print each line.
for line in file_content.splitlines():
if line:
parsed_response = json.loads(line)
if 'response' in parsed_response and parsed_response['response']:
for part in parsed_response['response']['candidates'][0]['content']['parts']:
if part.get('text'):
print(part['text'])
elif part.get('inlineData'):
print(f"Image mime type: {part['inlineData']['mimeType']}")
data = base64.b64decode(part['inlineData']['data'])
elif 'error' in parsed_response:
print(f"Error: {parsed_response['error']}")
elif batch_job.state.name == 'JOB_STATE_FAILED':
print(f"Error: {batch_job.error}")
JavaScript
import {GoogleGenAI} from '@google/genai';
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from 'url';
const ai = new GoogleGenAI({});
async function run() {
// 1. Create and upload file
const fileName = "my-batch-image-requests.jsonl";
const requests = [
{ "key": "request-1", "request": { "contents": [{ "parts": [{ "text": "A big letter A surrounded by animals starting with the A letter" }] }], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]} } },
{ "key": "request-2", "request": { "contents": [{ "parts": [{ "text": "A big letter B surrounded by animals starting with the B letter" }] }], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]} } }
];
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const filePath = path.join(__dirname, fileName);
try {
const writeStream = fs.createWriteStream(filePath, { flags: 'w' });
for (const req of requests) {
writeStream.write(JSON.stringify(req) + '\n');
}
writeStream.end();
console.log(`Successfully wrote batch requests to ${filePath}`);
} catch (error) {
console.error(`An unexpected error occurred writing file:`, error);
return;
}
const uploadedFile = await ai.files.upload({file: fileName, config: { mimeType: 'jsonl' }});
console.log(`Uploaded file: ${uploadedFile.name}`);
// 2. Create batch job
const fileBatchJob = await ai.batches.create({
model: 'gemini-3-pro-image-preview',
src: uploadedFile.name,
config: {
displayName: 'file-image-upload-job-1',
}
});
console.log(fileBatchJob);
// 3. Monitor job status
let batchJob;
const completedStates = new Set([
'JOB_STATE_SUCCEEDED',
'JOB_STATE_FAILED',
'JOB_STATE_CANCELLED',
'JOB_STATE_EXPIRED',
]);
try {
batchJob = await ai.batches.get({name: fileBatchJob.name});
while (!completedStates.has(batchJob.state)) {
console.log(`Current state: ${batchJob.state}`);
// Wait for 10 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 10000));
batchJob = await ai.batches.get({ name: batchJob.name });
}
console.log(`Job finished with state: ${batchJob.state}`);
} catch (error) {
console.error(`An error occurred while polling job ${fileBatchJob.name}:`, error);
return;
}
// 4. Retrieve results
if (batchJob.state === 'JOB_STATE_SUCCEEDED') {
if (batchJob.dest?.fileName) {
const resultFileName = batchJob.dest.fileName;
console.log(`Results are in file: ${resultFileName}`);
console.log("Downloading result file content...");
const fileContentBuffer = await ai.files.download({ file: resultFileName });
const fileContent = fileContentBuffer.toString('utf-8');
for (const line of fileContent.split('\n')) {
if (line) {
const parsedResponse = JSON.parse(line);
if (parsedResponse.response) {
for (const part of parsedResponse.response.candidates[0].content.parts) {
if (part.text) {
console.log(part.text);
} else if (part.inlineData) {
console.log(`Image mime type: ${part.inlineData.mimeType}`);
}
}
} else if (parsedResponse.error) {
console.error(`Error: ${parsedResponse.error}`);
}
}
}
} else {
console.log("No result file found.");
}
} else if (batchJob.state === 'JOB_STATE_FAILED') {
console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);
}
}
run();
Java
import com.google.genai.Client;
import com.google.genai.types.BatchJob;
import com.google.genai.types.BatchJobSource;
Client client = new Client();
BatchJobSource batchJobSource =
BatchJobSource.builder()
.gcsUri("gs://unified-genai-tests/batches/input/generate_content_requests.jsonl")
.format("jsonl")
.build();
BatchJob batchJob = client.batches.create("gemini-3.8-flash", batchJobSource, null);
System.out.println("Batch Job Name: " + batchJob.name().orElse(""));
REST
# 1. Create and upload file
echo '{"key": "request-1", "request": {"contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}' > my-batch-image-requests.jsonl
echo '{"key": "request-2", "request": {"contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}' >> my-batch-image-requests.jsonl
# Follow File API guide to upload: https://ai.google.dev/gemini-api/docs/files#upload_a_file
# This example assumes you have uploaded the file and set BATCH_INPUT_FILE to its name (e.g., files/abcdef123)
BATCH_INPUT_FILE="files/your-uploaded-file-name"
# 2. Create batch job
printf -v request_data '{
"batch": {
"display_name": "my-batch-file-image-requests",
"input_config": { "file_name": "%s" }
}
}' "$BATCH_INPUT_FILE"
curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:batchGenerateContent \
-X POST \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" \
-d "$request_data" > created_batch.json
BATCH_NAME=$(jq -r '.name' created_batch.json)
echo "Created batch job: $BATCH_NAME"
# 3. Poll job status until completion by repeating the following command:
curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type:application/json" > batch_status.json
echo "Current status:"
jq '.' batch_status.json
# 4. If state is JOB_STATE_SUCCEEDED, download results file
batch_state=$(jq -r '.state' batch_status.json)
if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then
responses_file_name=$(jq -r '.dest.fileName' batch_status.json)
echo "Job succeeded. Downloading results from $responses_file_name..."
curl https://generativelanguage.googleapis.com/download/v1beta/$responses_file_name:download?alt=media \
-H "x-goog-api-key: $GEMINI_API_KEY" > batch_results.jsonl
echo "Results saved to batch_results.jsonl"
fi
Szczegóły techniczne
- Obsługiwane modele: wsadowy interfejs API obsługuje różne modele Gemini. Informacje o tym, które modele obsługują wsadowy interfejs API, znajdziesz na stronie Modele. Obsługiwane modalności w przypadku wsadowego interfejsu API są takie same jak w przypadku interaktywnego (lub bezwsadowego) interfejsu API.
- Ceny: korzystanie z wsadowego interfejsu API jest rozliczane według 50% standardowego kosztu interaktywnego interfejsu API dla odpowiedniego modelu. Więcej informacji znajdziesz na stronie cennika. Szczegółowe informacje o limitach liczby żądań dla tej funkcji znajdziesz na stronie Limity liczby żądań.
- Docelowy poziom usług: zadania wsadowe powinny zostać ukończone w ciągu 24 godzin. Wiele zadań może zostać ukończonych znacznie szybciej w zależności od ich rozmiaru i bieżącego obciążenia systemu.
- Pamięć podręczna: Buforowanie kontekstu jest obsługiwane
w przypadku żądań wsadowych. Aby ponownie użyć treści z pamięci podręcznej, w konfiguracji poszczególnych żądań w zadaniu wsadowym określ nazwę zasobu
cached_content. Jeśli żądanie w zadaniu wsadowym spowoduje trafienie w pamięci podręcznej, zapłacisz standardowe stawki za buforowanie kontekstu.
Sprawdzone metody
- Używaj plików wejściowych w przypadku dużych żądań: w przypadku dużej liczby żądań,
zawsze używaj metody przesyłania plików,
aby ułatwić zarządzanie i uniknąć przekroczenia limitów rozmiaru żądań dla
samego wywołania
BatchGenerateContent. Pamiętaj, że maksymalny rozmiar pliku wejściowego to 2 GB. - Obsługa błędów: po zakończeniu zadania sprawdź
batchStatspod kątemfailedRequestCount. Jeśli używasz danych wyjściowych w pliku, przeanalizuj każdy wiersz, aby sprawdzić, czy jest to obiektGenerateContentResponse, czy obiekt stanu wskazujący błąd w przypadku konkretnego żądania. Pełny zestaw kodów błędów znajdziesz w przewodniku rozwiązywaniaproblemów. - Przesyłaj zadania tylko raz: tworzenie zadania wsadowego nie jest idempotentne. Jeśli 2 razy wyślesz to samo żądanie utworzenia, zostaną utworzone 2 osobne zadania wsadowe.
- Dziel bardzo duże zadania wsadowe: docelowy czas realizacji to 24 godziny, ale rzeczywisty czas przetwarzania może się różnić w zależności od obciążenia systemu i rozmiaru zadania. W przypadku dużych zadań rozważ podzielenie ich na mniejsze zadania wsadowe, jeśli wyniki pośrednie są potrzebne wcześniej.
Co dalej?
- Więcej przykładów znajdziesz w notatniku wsadowego interfejsu API.
- Warstwa zgodności z OpenAI obsługuje wsadowy interfejs API. Przykłady znajdziesz na stronie Zgodność z OpenAI.