C.W.K.
Stream
Lesson 02 of 05 · published

generate_content() & Response Structure

~14 min · python, generation, response, config

Level 0Spark
0 XP0/35 lessons0/10 achievements
0/140 XP to next level140 XP to go0% complete

The single call you'll write 10,000 times

client.models.generate_content(model=..., contents=..., config=...) is the heart of the SDK. contents can be a plain string (the SDK wraps it for you), a list of strings, a list of Content objects, or anything in between — the SDK normalizes.

Configuring with GenerateContentConfig

Every knob from the previous lesson (system_instruction, temperature, max_output_tokens, etc.) lives on types.GenerateContentConfig. You can also pass a plain dict — the SDK converts.

What the response actually is

The return value is a GenerateContentResponse. The fields you'll touch most often:

  • response.text — concatenated text across all parts. The 90% case.
  • response.parts — the raw list. Use this when you need non-text parts (images, function calls).
  • response.function_calls — populated when the model invoked a tool.
  • response.parsed — the deserialized object when you used JSON mode with a Pydantic schema.
  • response.candidates[0].finish_reason — the stop reason.
  • response.usage_metadata — token counts for billing.

The first thing to check

Whenever a Gemini call comes back, the first line of your handler should look at finish_reason. If it's not STOP, your response.text is unreliable — it might be empty (filtered) or truncated (max tokens hit) or recitation-blocked.

Code

Plain text in, text out·python
from google import genai
from google.genai import types

client = genai.Client()

response = client.models.generate_content(
    model='gemini-2.5-flash',
    contents='Why is the sky blue?',
)
print(response.text)
With config·python
response = client.models.generate_content(
    model='gemini-2.5-flash',
    contents='Explain quantum entanglement to a curious 10-year-old.',
    config=types.GenerateContentConfig(
        system_instruction='You are a warm, accurate physics tutor.',
        max_output_tokens=400,
        temperature=0.5,
        top_p=0.95,
        top_k=40,
        seed=42,
    ),
)

# Config can also be a dict — SDK converts
response = client.models.generate_content(
    model='gemini-2.5-flash',
    contents='Hello',
    config={'temperature': 0.0, 'max_output_tokens': 50},
)
Reading the response correctly·python
candidate = response.candidates[0]
reason = candidate.finish_reason

if reason.name != 'STOP':
    # MAX_TOKENS, SAFETY, RECITATION, OTHER
    raise RuntimeError(f'Generation did not finish cleanly: {reason.name}')

text = response.text
usage = response.usage_metadata

print(f'Reply ({usage.total_token_count} tokens):')
print(text)
print(f'  prompt={usage.prompt_token_count}  '
      f'completion={usage.candidates_token_count}')

External links

Exercise

Write a tiny safe_generate(prompt: str) -> str helper that: (1) calls generate_content on Flash with a 200-token cap, (2) checks finish_reason and raises a custom GenerationError if it isn't STOP, (3) returns the text on success. Test it on three prompts: a normal one, one that hits MAX_TOKENS (force it via a tiny limit), and one that requests something the safety classifier might filter. Verify each branch.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.