# Streaming responses met de Gemini API [[TOC]] ## Waarom streaming Bij een standaard API-call wacht je tot het model het volledige antwoord heeft gegenereerd. Voor lange antwoorden (samenvatten, schrijven, analyseren) kan dat enkele seconden tot meer dan een halve minuut duren. Met streaming ontvang je de tokens zodra ze beschikbaar zijn, vergelijkbaar met hoe een chatinterface het antwoord live laat verschijnen. Streaming is vooral waardevol voor conversatie-interfaces, live dashboards en elke toepassing waar wachttijd de gebruikerservaring schaadt. De totale verwerkingstijd verandert niet, maar de waargenomen snelheid wel. :::warn title="Gebruik de unified Google Gen AI SDK" De oude SDK's `google-generativeai` (Python) en `@google/generative-ai` (JavaScript) zijn uitgefaseerd; de ondersteuning eindigde op 30 november 2025. Werk je nog met `import google.generativeai as genai`, migreer dan naar de unified Google Gen AI SDK: `google-genai` voor Python en `@google/genai` voor JavaScript. De voorbeelden hieronder gebruiken die nieuwe SDK. ::: ## Streaming in Python Installeer eerst de SDK met `pip install google-genai`. De client leest je sleutel automatisch uit de omgevingsvariabele `GEMINI_API_KEY` (of `GOOGLE_API_KEY`). ```python from google import genai client = genai.Client() response_stream = client.models.generate_content_stream( model="gemini-2.5-flash", contents="Schrijf een gedetailleerde uitleg over hoe zonnepanelen werken.", ) for chunk in response_stream: if chunk.text: print(chunk.text, end="", flush=True) print() ``` De `flush=True` is belangrijk: zonder deze parameter buffert Python de output en zie je toch batches in plaats van een continue stroom. :::tip title="Asynchroon streamen" Heb je een async applicatie, gebruik dan `client.aio.models.generate_content_stream(...)` en loop met `async for chunk in await ...`. De rest van de logica blijft identiek. ::: ## Streaming in JavaScript (Node.js) Installeer de SDK met `npm install @google/genai`. ```javascript import { GoogleGenAI } from "@google/genai"; const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY }); const response = await ai.models.generateContentStream({ model: "gemini-2.5-flash", contents: "Schrijf een recept voor erwtensoep met stap-voor-stap instructies.", }); for await (const chunk of response) { if (chunk.text) { process.stdout.write(chunk.text); } } console.log(); ``` Let op dat `chunk.text` in de nieuwe JavaScript-SDK een property is en geen functie-aanroep meer (`chunk.text()`), zoals in de oude SDK. ## Streaming in een webapplicatie (Server-Sent Events) Voor een browser-frontend stuur je de chunks door via Server-Sent Events (SSE). Onderstaand voorbeeld gebruikt Flask. ```python import os from flask import Flask, Response, request, stream_with_context from google import genai app = Flask(__name__) client = genai.Client() @app.route("/stream") def stream_response(): prompt = request.args.get("prompt", "Vertel iets interessants.") def generate(): response_stream = client.models.generate_content_stream( model="gemini-2.5-flash", contents=prompt, ) for chunk in response_stream: if chunk.text: yield f"data: {chunk.text} " yield "data: [DONE] " return Response( stream_with_context(generate()), mimetype="text/event-stream", headers={ "Cache-Control": "no-cache", "X-Accel-Buffering": "no", }, ) ``` Frontend JavaScript: ```javascript const eventSource = new EventSource(`/stream?prompt=${encodeURIComponent(prompt)}`); const output = document.getElementById("output"); eventSource.onmessage = (event) => { if (event.data === "[DONE]") { eventSource.close(); return; } output.textContent += event.data; }; ``` :::warn title="Pas op met newlines in je SSE-payload" Een SSE-bericht eindigt bij een lege regel. Bevat een tekst-chunk zelf een newline, dan kan dat de berichtgrenzen verstoren. Voor robuuste streams verpak je elke chunk in JSON (bijvoorbeeld `data: {"text": "..."}`) en parse je dat aan de clientkant, in plaats van de rauwe tekst door te sturen. ::: :::tip title="Schakel buffering uit achter Nginx" Voeg de header `X-Accel-Buffering: no` toe als je achter Nginx draait. Zonder deze header buffert Nginx de SSE-stream en verlies je het streaming-effect. ::: ## Streaming met chatsessies Voor een gesprek met geschiedenis gebruik je `client.chats.create(...)`. De sessie houdt de history automatisch bij. ```python chat = client.chats.create(model="gemini-2.5-flash") full_response = "" for chunk in chat.send_message_stream("Leg uit hoe quantumcomputers werken."): if chunk.text: print(chunk.text, end="", flush=True) full_response += chunk.text print() ``` ## Volledige respons en tokengebruik na streaming Elke chunk draagt zijn eigen `usage_metadata`; de laatste chunk bevat de geaggregeerde totalen. Verzamel de chunks om er na afloop bij te kunnen. ```python response_stream = client.models.generate_content_stream( model="gemini-2.5-flash", contents="Schrijf een lang essay over de geschiedenis van de boekdrukkunst.", ) chunks = [] for chunk in response_stream: chunks.append(chunk) if chunk.text: print(chunk.text, end="", flush=True) usage = chunks[-1].usage_metadata print(f" Tokens gebruikt: {usage.total_token_count}") ``` ## Streaming met multimodale invoer Streaming werkt ook met afbeeldingen, audio of andere bestanden in dezelfde call. Bouw de invoer op als een lijst met tekst en een `Part`. ```python from google import genai from google.genai import types client = genai.Client() with open("diagram.png", "rb") as f: image_bytes = f.read() response_stream = client.models.generate_content_stream( model="gemini-2.5-flash", contents=[ "Geef een gedetailleerde technische analyse van dit architectuurdiagram.", types.Part.from_bytes(data=image_bytes, mime_type="image/png"), ], ) for chunk in response_stream: if chunk.text: print(chunk.text, end="", flush=True) ``` ## Foutafhandeling bij streaming Fouten kunnen optreden bij het opzetten van de stream of tijdens het itereren. Vang ze af met `errors.APIError`, de basisklasse voor API-fouten in de nieuwe SDK. ```python from google.genai import errors def stream_with_error_handling(prompt: str): try: response_stream = client.models.generate_content_stream( model="gemini-2.5-flash", contents=prompt, ) for chunk in response_stream: if chunk.text: yield chunk.text except errors.APIError as e: yield f"[API-fout {e.code}: {e.message}]" except Exception as e: yield f"[Onverwachte fout: {e}]" ``` Wil je weten waarom een antwoord stopte (bijvoorbeeld door een veiligheidsfilter), controleer dan `chunk.candidates[0].finish_reason` en `chunk.prompt_feedback` op de chunks die binnenkomen. :::faq ### Is streaming goedkoper dan een standaard call? Nee, de tokenkosten zijn identiek. Streaming verbetert alleen de waargenomen latency, niet de daadwerkelijke verwerkingstijd of de prijs. ### Kan ik een streaming-antwoord annuleren? Ja, stop met itereren over de stream en sluit de onderliggende verbinding (bijvoorbeeld via een `break`, of door je async task te cancelen). Je betaalt alleen voor de tokens die al gegenereerd zijn. ### Werkt streaming samen met structured output (JSON-modus)? Ja, maar het JSON-object is pas volledig en parseerbaar aan het einde van de stream. Je kunt de chunks tonen terwijl ze binnenkomen, maar wacht tot de stream klaar is voordat je de samengevoegde tekst als JSON parseert. ### Welk model gebruik ik in juni 2026? Gebruik `gemini-2.5-flash` voor een snelle, voordelige optie of `gemini-2.5-pro` voor complexere taken. De oudere 2.0 Flash-modellen zijn op 1 juni 2026 uitgefaseerd. Controleer de officiele modeloverzichten van Google voor de actuele lijst, want het aanbod verandert regelmatig. ### Waarom werkt mijn oude code met `import google.generativeai` niet meer? Die SDK is uitgefaseerd en wordt sinds 30 november 2025 niet meer ondersteund. Migreer naar de unified Google Gen AI SDK: `pip install google-genai` voor Python en `npm install @google/genai` voor JavaScript. ### Waarom zie ik de chunks niet live binnenkomen? Meestal door buffering. Gebruik in Python `flush=True` bij het printen, schakel proxy-buffering uit (`X-Accel-Buffering: no` bij Nginx) en zet `Cache-Control: no-cache` op je SSE-respons. :::