Wanneer gebruik je batch-verwerking
Batch-verwerking is de juiste keuze als je:
- Honderden tot miljoenen prompts wilt verwerken
- Geen real-time antwoord nodig hebt (resultaat mag tot 24 uur later komen)
- Kosten wilt minimaliseren (50 procent korting op input- en outputtokens)
- Rate limit-problemen wilt vermijden bij grote volumes
Typische use cases: een hele productcatalogus verrijken, samenvattingen genereren voor een archief, een kennisbank embedden, of classificaties draaien op grote datasets.
Sinds 2026 een native Batch API
Eerder had de Gemini Developer API geen eigen batch-endpoint voor tekstgeneratie en moest je parallelle calls bouwen. Sinds begin 2026 is er een echte Batch-modus via client.batches. Dit artikel gebruikt die native aanpak; de parallelle methode staat hieronder als alternatief voor wie wel real-time resultaten nodig heeft.
De juiste SDK en modellen
Gebruik de nieuwe, unified google-genai SDK (from google import genai). De oude google-generativeai SDK is gedeprec8 en krijgt geen nieuwe features meer.
pip install google-genai
Gangbare modellen in 2026 zijn gemini-2.5-flash (snel en goedkoop) en gemini-3.5-flash (nieuwer). Voor embeddings gebruik je gemini-embedding-001. Controleer de officiele modellenpagina van Google voor de actuele lijst, want modelnamen wisselen regelmatig.
Een batch-job aanmaken met inline requests
Voor kleinere batches (inputpayload onder 20 MB) geef je de requests direct mee:
from google import genai
client = genai.Client()
producten = [
{"id": "P001", "naam": "Draadloze muis"},
{"id": "P002", "naam": "Mechanisch toetsenbord"},
{"id": "P003", "naam": "4K monitor 27 inch"},
]
inline_requests = [
{
"contents": [
{"role": "user", "parts": [{"text": f"Schrijf een korte productomschrijving voor: {p['naam']}"}]}
]
}
for p in producten
]
batch_job = client.batches.create(
model="gemini-2.5-flash",
src=inline_requests,
config={"display_name": "productomschrijvingen"},
)
print(f"Aangemaakt: {batch_job.name}")
Een batch-job aanmaken met een JSONL-bestand
Voor grote batches (tot 2 GB inputbestand) upload je een JSON Lines-bestand. Elke regel is een volledige request met een eigen key, zodat je resultaten later kunt terugkoppelen aan je brondata:
import json
from google import genai
from google.genai import types
client = genai.Client()
producten = [
{"id": "P001", "naam": "Draadloze muis"},
{"id": "P002", "naam": "Mechanisch toetsenbord"},
]
with open("requests.jsonl", "w") as f:
for p in producten:
regel = {
"key": p["id"],
"request": {
"contents": [
{"role": "user", "parts": [{"text": f"Categoriseer dit product: {p['naam']}"}]}
]
},
}
f.write(json.dumps(regel) + "
")
uploaded = client.files.upload(
file="requests.jsonl",
config=types.UploadFileConfig(display_name="batch-requests", mime_type="jsonl"),
)
batch_job = client.batches.create(
model="gemini-2.5-flash",
src=uploaded.name,
config={"display_name": "product-classificatie"},
)
Voortgang monitoren
Een batch-job doorloopt verschillende statussen. Pollen doe je met client.batches.get():
import time
completed_states = {
"JOB_STATE_SUCCEEDED",
"JOB_STATE_FAILED",
"JOB_STATE_CANCELLED",
"JOB_STATE_EXPIRED",
}
job = client.batches.get(name=batch_job.name)
while job.state.name not in completed_states:
print(f"Status: {job.state.name}")
time.sleep(30)
job = client.batches.get(name=batch_job.name)
print(f"Eindstatus: {job.state.name}")
De belangrijkste statussen:
| Status | Betekenis |
|---|---|
JOB_STATE_PENDING |
Wacht om verwerkt te worden |
JOB_STATE_RUNNING |
Wordt verwerkt |
JOB_STATE_SUCCEEDED |
Succesvol afgerond |
JOB_STATE_FAILED |
Mislukt (bekijk de foutdetails) |
JOB_STATE_CANCELLED |
Door jou geannuleerd |
JOB_STATE_EXPIRED |
Liep langer dan 48 uur en is verlopen |
Resultaten ophalen
De uitvoer komt terug als inline responses (bij inline requests) of als bestand (bij JSONL-invoer):
job = client.batches.get(name=batch_job.name)
if job.state.name == "JOB_STATE_SUCCEEDED":
if job.dest and job.dest.file_name:
inhoud = client.files.download(file=job.dest.file_name)
for regel in inhoud.decode("utf-8").splitlines():
resultaat = json.loads(regel)
print(resultaat.get("key"), resultaat.get("response"))
elif job.dest and job.dest.inlined_responses:
for i, response in enumerate(job.dest.inlined_responses):
if response.response:
print(f"Antwoord {i + 1}: {response.response.text}")
Een job annuleren
Een lopende job stop je direct, al gegenereerde uitvoer blijft beschikbaar:
client.batches.cancel(name=batch_job.name)
Batch embeddings
Embeddings hebben hun eigen methode, create_embeddings, met hetzelfde job-model:
from google import genai
client = genai.Client()
teksten = [
"Artificiele intelligentie verandert de wereld",
"Machine learning is een onderdeel van AI",
"Neurale netwerken zijn geinspireerd op het menselijk brein",
]
inline_requests = [{"content": t} for t in teksten]
job = client.batches.create_embeddings(
model="gemini-embedding-001",
src={"inlined_requests": inline_requests},
config={"display_name": "kennisbank-embeddings"},
)
print(f"Embedding-job: {job.name}")
Begin klein
Test je request-formaat eerst met twee of drie inline requests voordat je een bestand van duizenden regels indient. Een verkeerd JSONL-schema laat de hele job falen en kost je een polling-ronde van soms uren.
Alternatief: parallelle calls voor real-time werk
Heb je toch synchrone resultaten nodig (bijvoorbeeld in een interactieve flow), dan zijn begrensde parallelle calls de beste keuze. Let op: dit valt onder de normale, niet-verlaagde tarieven en je raakt sneller rate limits.
import asyncio
from google import genai
client = genai.Client()
async def generate_for_item(item: dict, semaphore: asyncio.Semaphore) -> dict:
async with semaphore:
try:
response = await client.aio.models.generate_content(
model="gemini-2.5-flash",
contents=f"Schrijf een productomschrijving voor: {item['naam']}",
)
return {"id": item["id"], "tekst": response.text, "status": "ok"}
except Exception as e:
return {"id": item["id"], "tekst": None, "status": str(e)}
async def process_batch(items: list, concurrency: int = 5) -> list:
semaphore = asyncio.Semaphore(concurrency)
return await asyncio.gather(*(generate_for_item(i, semaphore) for i in items))
results = asyncio.run(process_batch(producten))
for r in results:
print(f"{r['id']}: {r['status']}")
Respecteer rate limits
Begrens gelijktijdige requests met een Semaphore. Vijf tot tien gelijktijdige requests is veilig op een gratis tier; meer is mogelijk met een betaald account. Bouw exponentiele back-off in voor RESOURCE_EXHAUSTED-fouten zodat je niet harder blijft proberen dan toegestaan.
Vertex AI Batch Prediction
Werk je binnen Google Cloud met grote, herhaalbare pipelines, dan biedt Vertex AI Batch Prediction dezelfde 50 procent korting met diepere integratie: input en output via Cloud Storage of BigQuery, IAM-rechten en monitoring binnen je project. De Gemini Batch API is doorgaans eenvoudiger om mee te starten; Vertex AI loont als je al in dat ecosysteem zit.
Heeft de Gemini API echt een native batch-endpoint?
Ja. Sinds begin 2026 maak je batch-jobs aan met client.batches.create() in de google-genai SDK. Een aparte parallelle-call-constructie is daarvoor niet meer nodig.
Hoeveel goedkoper is batch-verwerking?
Batch-jobs kosten 50 procent minder dan synchrone calls, voor zowel input- als outputtokens. De afspraak is dat resultaten binnen 24 uur klaar zijn, in de praktijk vaak veel sneller.
Welke SDK moet ik gebruiken?
De nieuwe unified google-genai SDK, geimporteerd als from google import genai. De oude google-generativeai SDK is gedeprec8; bestaande code migreer je via de officiele migratiegids van Google.
Werkt batch-modus ook voor embeddings?
Ja, via client.batches.create_embeddings() met een embeddingmodel zoals gemini-embedding-001. Je geeft inline requests of een geupload bestand mee, net als bij tekstgeneratie.
Hoe ga ik om met gedeeltelijk mislukte batches?
Geef elke request een unieke key mee. In de uitvoer koppel je per regel de status terug aan je brondata en dien je alleen de mislukte items opnieuw in.
Wanneer kies ik dan nog parallelle calls?
Alleen als je echt real-time antwoorden nodig hebt. Dat valt onder de normale tarieven en loopt sneller tegen rate limits aan, dus voor grote, niet-urgente volumes is de Batch API vrijwel altijd beter.