Free lesson · GenAI Application Engineering
థింకింగ్ బడ్జెట్తో Gemini 2.5 Flash స్ట్రీమింగ్ అడాప్టర్ను అమలు చేయండి
మీరు adapters/gemini_stream.py లో google.genai.Client (కొత్త ఏకీకృత SDK, డిప్రికేట్ అయిన google-generativeai కాదు) ను ర్యాప్ చేసే GeminiStreamAdapter క్లాస్ను సృష్టిస్తారు. ఈ అడాప్టర్ client.aio.models.generate_content_stream() ను కాల్ చేసే stream_chat(messages, model, temperature, thinking_enabled) -> AsyncGenerator[StreamChunk, None] ను అందిస్తుంది. thinking_enabled True అయినప్పుడు, విస్తృత రీజనింగ్ కోసం config=GenerateContentConfig(thinking_config=ThinkingConfig(thinking_budget=1024)) ను పాస్ చేయండి; False అయినప్పుడు, thinking_budget=0 గా సెట్ చేయండి. ప్రతి GenerateContentResponse చంక్ కోసం, chunk.candidates[0].content.parts[0].text ను వెలికితీసి StreamChunk కు మ్యాప్ చేయండి. candidate.finish_reason ను FinishReason.SAFETY తో పోల్చి తనిఖీ చేయడం ద్వారా సేఫ్టీ బ్లాక్లను నిర్వహించి, StreamError ను ఎమిట్ చేయండి. ఈ అడాప్టర్ Gemini రోల్ 'model' ను 'assistant' గా నార్మలైజ్ చేస్తుంది. కాన్ఫిగరేషన్ Settings నుండి GEMINI_API_KEY ను చదువుతుంది.
Course: Full-Stack GenAI Applications · Chapter 1 · Chat Completion API with Streaming
Free to read — no subscription required.
పరిచయం
మీరు Gemini 2.5 Flash ను ఒక streaming chat endpoint లో ఇంటిగ్రేట్ చేసినప్పుడు, కేవలం ఒక stream=True ఫ్లాగ్ సరిపోదు: Gemini రెండు వేర్వేరు టోకెన్ స్ట్రీమ్లను తిరిగి ఇస్తుంది — thought టోకెన్లు మరియు text టోకెన్లు — వాటిని ఒకేలా పరిగణిస్తే, రీజనింగ్ యూజర్కు కనిపించే chat bubble లలోకి లీక్ అవుతుంది లేదా అసలు రీజనింగ్ అవసరమే లేని క్వెరీలపై మీ టోకెన్ బిల్లు నిశ్శబ్దంగా 2–3× పెరుగుతుంది. ఇంజనీర్లు దీన్ని తరచుగా డిప్లాయ్ చేసిన తర్వాతే గుర్తిస్తారు — యూజర్లు గందరగోళంగా ఉన్న అవుట్పుట్ గురించి రిపోర్ట్ చేసినప్పుడు లేదా బిల్లింగ్ అలర్ట్లు అనుకోకుండా ట్రిగ్గర్ అయినప్పుడు. ఈ పాఠం ముగిసే సమయానికి, మీరు ప్రతి రిక్వెస్ట్కు ఒక ThinkingConfig ను నిర్మించగలరు, part.thought ఫ్లాగ్ ఉపయోగించి thought మరియు text టోకెన్ల మధ్య ఫేజ్ సరిహద్దును గుర్తించగలరు, మరియు వర్గీకరించిన అవుట్పుట్ను FastAPI SSE endpoint ద్వారా బ్రౌజర్ EventSource క్లయింట్కు స్ట్రీమ్ చేయగలరు.
ముఖ్య పదజాలం
- ThinkingConfig: Gemini 2.5 Flash యొక్క extended reasoning ప్రవర్తనను ప్రతి రిక్వెస్ట్ ప్రాతిపదికన కాన్ఫిగర్ చేసే ఒక
google.genai.typesడేటాక్లాస్; దీనిthinking_budgetఫీల్డ్, మోడల్ కనిపించే టెక్స్ట్ను ఎమిట్ చేయడానికి ముందు రీజనింగ్ కోసం ఎన్ని టోకెన్లు ఖర్చు చేయవచ్చో నియంత్రిస్తుంది. - thinking_budget:
ThinkingConfigలోపల పాస్ చేసే ఒక పూర్ణాంకం (0–24576), ఇది రీజనింగ్ టోకెన్లకు పరిమితి విధిస్తుంది.0thinking ను పూర్తిగా నిలిపివేస్తుంది (అత్యంత వేగంగా, అత్యంత చౌకగా); ఎక్కువ విలువలు బహుళ-దశల సమస్యలపై ఖచ్చితత్వం కోసం latency మరియు ఖర్చును త్యాగం చేస్తాయి. - SSE (Server-Sent Events): సర్వర్ దీర్ఘకాలం ఉండే HTTP రెస్పాన్స్ ద్వారా
data: <json>\n\nఫ్రేమ్లను ఎమిట్ చేసే W3C-ప్రామాణిక ఏకదిశ streaming ప్రోటోకాల్.media_type="text/event-stream"తో FastAPI యొక్కStreamingResponseఅనేది Gemini యొక్క రెండు-ఫేజ్ టోకెన్ స్ట్రీమ్ను బ్రౌజర్EventSourceక్లయింట్కు అందించడానికి ప్రామాణిక మార్గం.
భావనలు
Gemini 2.5 Flash streaming అడాప్టర్లో ప్రతి నిర్ణయాన్ని రెండు ఆలోచనలు నడిపిస్తాయి: thinking_budget విలువ ప్రతి రిక్వెస్ట్కు latency–ఖర్చు–ఖచ్చితత్వం ట్రేడ్-ఆఫ్ను నిర్ణయిస్తుంది, మరియు వచ్చే రెస్పాన్స్ ఒక రెండు-ఫేజ్ స్ట్రీమ్ (ముందు thought టోకెన్లు, తర్వాత text టోకెన్లు), దీన్ని మీ సర్వర్ SSE ఫ్రేమ్లను ఎమిట్ చేయడానికి ముందు వర్గీకరించాలి. కింది ఉపవిభాగం బడ్జెట్ను ఎలా ఎంచుకోవాలో వివరిస్తుంది; ఆ తర్వాత Code Walkthrough ఫేజ్ మార్పును ఎలా గుర్తించాలో మరియు ప్రతి chunk ను సరైన SSE ఈవెంట్ రకంలోకి ఎలా రూట్ చేయాలో చూపిస్తుంది.
Thinking Budget ఎంపిక కోసం ఆచరణాత్మక పరిగణనలు
సరైన thinking budget ఎంచుకోవడంలో latency, ఖర్చు మరియు సమాధాన నాణ్యతను సమతుల్యం చేయడం ఉంటుంది. thinking_budget 0 అయినప్పుడు, Gemini 2.5 Flash దాని non-thinking పూర్వీకుడితో పోల్చదగిన latency తో స్పందిస్తుంది — చిన్న ప్రాంప్ట్లకు సాధారణంగా 150–300ms time-to-first-token. thinking_budget=1024 వద్ద, మొదటి కనిపించే టోకెన్ రావడానికి ముందు మోడల్ కొన్ని వందల మిల్లీసెకన్లు రీజనింగ్ కోసం ఖర్చు చేస్తుంది, ఇది గుర్తించదగిన ఆలస్యాన్ని జోడిస్తుంది కానీ బహుళ-దశల సమస్యలపై ఖచ్చితత్వాన్ని అర్థవంతంగా మెరుగుపరుస్తుంది. thinking_budget=8192 లేదా అంతకంటే ఎక్కువ వద్ద, text టోకెన్లు ప్రవహించడం ప్రారంభించే ముందు మీరు 2–5 సెకన్ల "thinking" నిశ్శబ్దాన్ని గమనించవచ్చు, దీనికి యూజర్లను గందరగోళపరచకుండా ఉండటానికి మీ ఫ్రంటెండ్ ఒక "reasoning..." సూచికను ప్రదర్శించాల్సి ఉంటుంది.
Thinking budget టోకెన్ బిల్లింగ్ను కూడా ప్రభావితం చేస్తుంది. Thought టోకెన్లు మీ అవుట్పుట్ టోకెన్ వినియోగంలో లెక్కించబడతాయి, కాబట్టి thinking_budget=8192 తో తన బడ్జెట్ను పూర్తిగా వినియోగించుకునే రిక్వెస్ట్, thinking నిలిపివేసిన అదే రిక్వెస్ట్ కంటే సుమారు 2–3x ఎక్కువ ఖర్చు అవుతుంది. అందుకే ప్రతి రిక్వెస్ట్ స్థాయి నియంత్రణ ముఖ్యం: మీ అప్లికేషన్ సాధారణ క్వెరీలను (గ్రీటింగ్లు, వాస్తవ సమాచార శోధనలు) thinking_budget=0 తో అడాప్టర్ ద్వారా రూట్ చేయగలదు మరియు సంక్లిష్ట క్వెరీలను (కోడ్ డీబగ్గింగ్, బహుళ-దశల గణితం, ప్లానింగ్ టాస్క్లు) డైనమిక్గా ఎక్కువ బడ్జెట్లకు పెంచగలదు.
Thinking ఎనేబుల్ అయినప్పుడు, Gemini API ఏ స్పష్టమైన temperature విలువనైనా తిరస్కరిస్తుంది: మీరు సున్నా కాని thinking budget తో పాటు temperature=0.3 పాస్ చేస్తే, API మీ విలువను వర్తింపజేయకుండా ఒక validation error ను తిరిగి ఇస్తుంది. అందుకే thinking_budget సున్నా కంటే ఎక్కువగా ఉన్నప్పుడల్లా అడాప్టర్ temperature ఫీల్డ్ను వదిలివేస్తుంది, మరియు thinking_budget=0 ఉన్న non-thinking మార్గంలో మాత్రమే temperature=1.0 సెట్ చేస్తుంది. ఈ విధంగా temperature ను షరతుతో సెట్ చేయడం రెండు కోడ్ మార్గాలనూ చెల్లుబాటులో ఉంచుతుంది మరియు రిక్వెస్ట్ విఫలం కాకుండా నివారిస్తుంది.
Code Walkthrough
thinking_budget latency–ఖర్చు–ఖచ్చితత్వం ట్రేడ్-ఆఫ్ను ఎలా నియంత్రిస్తుందో ఇప్పుడు మీకు అర్థమైంది కాబట్టి, అమలు రెండు పనులకు తగ్గుతుంది: ప్రతి chunk యొక్క part.thought ఫ్లాగ్ను పరిశీలించి దాన్ని thought టోకెన్ లేదా కనిపించే టోకెన్గా వర్గీకరించే ఒక అడాప్టర్ను నిర్మించడం, ఆపై ఆ అడాప్టర్ను media_type="text/event-stream" తో ఒక FastAPI StreamingResponse లోకి వైర్ చేయడం.
అడాప్టర్: adapters/gemini_stream.py
GeminiStreamAdapter క్లాస్ ఒక google.genai.Client ను సృష్టించి ఒక stream_chat జనరేటర్ను అందిస్తుంది. దాని లోపల, అభ్యర్థించిన బడ్జెట్కు సెట్ చేసిన ThinkingConfig తో ఒక GenerateContentConfig నిర్మించబడుతుంది. ఒక ముఖ్యమైన పరిమితి: thinking_budget సున్నా కంటే ఎక్కువగా ఉన్నప్పుడు temperature ఫీల్డ్ను తప్పనిసరిగా వదిలివేయాలి — రెండూ సెట్ చేస్తే API ఒక validation error ను తిరిగి ఇస్తుంది. thinking_budget 0 అయినప్పుడు, temperature=1.0 ను స్పష్టంగా సెట్ చేయడం రెస్పాన్స్ శైలిని non-thinking మార్గంతో స్థిరంగా ఉంచుతుంది. ఇటరేషన్ లూప్ లోపల, part.thought అనేది ఫేజ్ సరిహద్దును గుర్తించే ఫ్లాగ్: రీజనింగ్ ఫేజ్లో True, కనిపించే టెక్స్ట్ ప్రారంభమైన తర్వాత False.
Code snippetpython
1from google import genai 2from google.genai import types 3 4class GeminiStreamAdapter: 5 def __init__(self, api_key: str, model: str = "gemini-2.5-flash"): 6 self.client = genai.Client(api_key=api_key) 7 self.model = model 8 9 def stream_chat(self, message: str, thinking_budget: int = 0): 10 """Yields SSE-ready dicts: type='thinking'|'token'|'done'.""" 11 config_kwargs: dict = { 12 "thinking_config": types.ThinkingConfig(thinking_budget=thinking_budget), 13 } 14 if thinking_budget == 0: 15 config_kwargs["temperature"] = 1.0 16 config = types.GenerateContentConfig(**config_kwargs) 17 for chunk in self.client.models.generate_content_stream( 18 model=self.model, contents=message, config=config 19 ): 20 for part in chunk.candidates[0].content.parts: 21 if part.thought: 22 yield {"type": "thinking", "token": part.text} 23 else: 24 yield {"type": "token", "token": part.text} 25 yield {"type": "done"}
FastAPI SSE endpoint
ఈ endpoint stream_chat ను ఒక async జనరేటర్లో చుట్టి దాన్ని StreamingResponse కు పాస్ చేస్తుంది. ప్రతి yield చేసిన dict ఒక data: …\n\n ఫ్రేమ్గా సీరియలైజ్ చేయబడుతుంది — ఇది బ్రౌజర్ EventSource క్లయింట్ స్థానికంగా చదివే W3C SSE వైర్ ఫార్మాట్. thinking_budget క్వెరీ పారామీటర్ నేరుగా రిక్వెస్ట్ నుండి ప్రవహిస్తుంది, కాబట్టి కాలర్లు రూట్ను మార్చకుండానే రీజనింగ్ను ఆన్ లేదా ఆఫ్ చేయవచ్చు.
Code snippetpython
1import json 2from fastapi import FastAPI 3from fastapi.responses import StreamingResponse 4from adapters.gemini_stream import GeminiStreamAdapter 5 6app = FastAPI() 7adapter = GeminiStreamAdapter(api_key="your-api-key") 8 9@app.post("/chat/stream") 10async def chat_stream(message: str, thinking_budget: int = 0): 11 async def event_generator(): 12 for event in adapter.stream_chat(message, thinking_budget): 13 yield f"data: {json.dumps(event)}\n\n" 14 15 return StreamingResponse(event_generator(), media_type="text/event-stream")
POST /chat/stream?message=hello&thinking_budget=0 పంపడం వల్ల, కనీసం ఒక {"type":"token","token":"..."} ఈవెంట్ను కలిగి ఉండి, చివరి {"type":"done"} ఫ్రేమ్తో ముగిసే ఫ్రేమ్లు ఉన్న text/event-stream రెస్పాన్స్ తిరిగి వస్తుందని నిర్ధారించుకోండి.
విభాగ అనువర్తనం
చేయవలసినవి మరియు చేయకూడనివి
చేయవలసినవి
thinking_budget > 0ఉన్నప్పుడల్లాGenerateContentConfigనుండిtemperatureను వదిలివేయండి — ఒకే రిక్వెస్ట్లోThinkingConfigమరియు temperature విలువ రెండూ ఉంటే Gemini API ఒక validation error ను తిరిగి ఇస్తుంది; non-thinking రిక్వెస్ట్లు స్థిరంగా ప్రవర్తించేలా స్పష్టమైనtemperature=1.0అసైన్మెంట్నుthinking_budget == 0మార్గానికి మాత్రమే కేటాయించండి.- yield చేయడానికి ముందు టోకెన్లను వర్గీకరించడానికి ప్రతి chunk లోని ప్రతి part పై
part.thoughtను పరిశీలించండి — Gemini 2.5 Flash ఒకే స్ట్రీమ్లో thought టోకెన్లను మరియు కనిపించే text టోకెన్లను కలగలిపి పంపుతుంది, మరియు వాటిని వేర్వేరు SSE ఈవెంట్ రకాలకు ("thinking"vs"token") రూట్ చేయడమే ముడి రీజనింగ్ యూజర్కు కనిపించే chat bubble లో కనిపించకుండా నివారించే ఏకైక మార్గం. StreamingResponseపైmedia_type="text/event-stream"సెట్ చేయండి మరియు ప్రతి yield చేసిన dict నుdata: …\n\nఫ్రేమ్గా సీరియలైజ్ చేయండి — content-type ను లేదా డబుల్-న్యూలైన్ ఫ్రేమ్ డీలిమిటర్ను వదిలివేస్తే W3C SSE ఒప్పందం విచ్ఛిన్నమవుతుంది మరియు బ్రౌజర్EventSourceక్లయింట్ ప్రతి టోకెన్కు ఈవెంట్లను ఫైర్ చేయడానికి బదులు నిరవధికంగా బఫర్ చేస్తుంది.
చేయకూడనివి
- Gemini స్ట్రీమ్ను ఒకే తేడా లేని టోకెన్ క్రమంగా పరిగణించవద్దు —
part.thoughtను తనిఖీ చేయకుండాchunk.candidates[0].content.partsను ఇటరేట్ చేయడం thought టోకెన్లను మరియు కనిపించే టోకెన్లను ఒకే స్ట్రీమ్లోకి కుదిస్తుంది, బహుళ-వాక్య రీజనింగ్ చైన్లను నిశ్శబ్దంగా UI లోకి లీక్ చేస్తుంది మరియు రీజనింగ్-ఎనేబుల్డ్ రిక్వెస్ట్లపై యూజర్కు కనిపించే అవుట్పుట్ను 2–3× పెంచుతుంది. - రిక్వెస్ట్ల మధ్య ఒకే హార్డ్కోడ్ చేసిన
GenerateContentConfigను పంచుకోవద్దు — స్టార్టప్లోconfig_kwargsను ఒకసారి నిర్మించడం, కాలర్లు రన్టైమ్లో క్వెరీ పారామీటర్ ద్వారాthinking_budgetను టోగుల్ చేయకుండా నిరోధిస్తుంది; ప్రతి రిక్వెస్ట్ స్వతంత్రంగా రీజనింగ్ ఫేజ్ను ఎనేబుల్ లేదా డిసేబుల్ చేయగలిగేలాThinkingConfigను ప్రతి కాల్కుstream_chatలోపలే నిర్మించాలి. - SSE జనరేటర్ నుండి చివరి
{"type": "done"}ఫ్రేమ్ను విస్మరించవద్దు — స్ట్రీమ్ శుభ్రంగా ముగిసిందని తెలుసుకోవడానికి బ్రౌజర్EventSourceక్లయింట్ ఈ సెంటినల్పై ఆధారపడుతుంది; దాన్ని వదిలివేస్తే క్లయింట్ ఇప్పటికే మూసివేసిన కనెక్షన్ను పోల్ చేస్తూనే ఉంటుంది మరియు error స్థితులను నెమ్మదిగా వచ్చే రెస్పాన్స్ నుండి వేరు చేయలేని స్థితి ఏర్పడుతుంది.
3 hands-on labs come with this lesson — real code, in a cloud IDE. Create a free account to run them. No card.
Free account · no card · straight to the labs
Or get the full path — from
Listen to this lesson
Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.
More free lessons in Full-Stack GenAI Applications
- Ch 1Build a FastAPI SSE streaming response endpoint
- Ch 1Implement an OpenAI GPT-4o streaming adapter
- Ch 1Implement a Gemini 2.5 Flash streaming adapter with thinking budgetYou are here
- Ch 1Implement an Anthropic Claude streaming adapter
- Ch 1Build a Llama 4 Maverick streaming adapter via Together.ai
- Ch 2Extract structured output with Instructor + Pydantic
- Ch 2Build a usage logging system with token + cost capture