Use the new google-genai SDK
(from google import genai) for Gemini 2.x and beyond.
The older google-generativeai package
(import google.generativeai as genai) is
Legacy — new features (Live API, batch, Files v2) only ship on
google-genai. The same SDK calls AI Studio (GEMINI_API_KEY)
and Vertex AI (ADC + project/location) — switched by env var.
Install · envSetup
bash
# Python SDK — the modern one (Gemini 2.x era)
pip install google-genai # ≥ 1.0
# Node / TS SDK
npm install @google/genai
# env — picked up automatically by Client()
export GEMINI_API_KEY=AIza...
# or, equivalently, for AI Studio keys:
export GOOGLE_API_KEY=AIza...
# Vertex AI mode uses ADC instead of an API key:
export GOOGLE_GENAI_USE_VERTEXAI=true
export GOOGLE_CLOUD_PROJECT=my-project
export GOOGLE_CLOUD_LOCATION=us-central1
Where things liveCommon imports
Two top-level imports cover the surface: the genai package for clients and the
types module for config + content objects.
Video generation. Async via long-running operations.
gemini-2.5-flash-preview-tts
Text-to-speech.
gemini-1.5-pro, gemini-1.0-pro
Legacy Outdated. Migrate to 2.5.
List live IDs with client.models.list(). Pin the exact ID in production —
Google rotates -latest aliases without notice and previews graduate to stable under new names.
The single endpointgenerate_content
Basic call
client.models.generate_content(model, contents)
The everyday call. Contents = string, Part, or list of either.
resp.text
Concatenated text across all parts. The shortcut.
resp.parsed
Pydantic instance when response_schema was set.
resp.candidates[0].content.parts
Full content tree (text, function_call, inline_data…).
from google import genai
from google.genai import types
client = genai.Client()
# Plain Python function — schema inferred from type hints + docstring
def get_weather(city: str) -> dict:
"""Current weather for a city."""
return {"temp_c": 31, "city": city}
# Automatic function calling: SDK executes the call and feeds the result back
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="Weather in Mumbai?",
config=types.GenerateContentConfig(
tools=[get_weather],
),
)
print(resp.text)
# Manual mode — disable auto-execution and inspect the call
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents="Weather in Mumbai?",
config=types.GenerateContentConfig(
tools=[get_weather],
automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),
),
)
for call in resp.function_calls:
print(call.name, call.args)
Token-by-tokenStreaming
client.models.generate_content_stream(…)
Streaming variant. Same args, returns an iterator.
for chunk in stream: chunk.text
Each chunk is a partial GenerateContentResponse.
chunk.candidates[0].content.parts
Streamed parts — including function calls.
final_chunk.usage_metadata
Usage lands on the final chunk. Save the last one.
await aio.models.generate_content_stream(…)
Async streaming. Iterate with async for.
chat.send_message_stream(…)
Streaming for multi-turn chats.
Worked example
python
from google import genai
client = genai.Client()
# Streaming variant — same call, _stream suffix, chunk iterator
stream = client.models.generate_content_stream(
model="gemini-2.5-flash",
contents="Write a haiku about Mumbai monsoons.",
)
for chunk in stream:
if chunk.text:
print(chunk.text, end="", flush=True)
# Final usage is on the last chunk's usage_metadata
print(f"\n[done · {chunk.usage_metadata.total_token_count} tokens]")
Multi-turn chat with Google Search grounding, system prompt, and citation extraction. No vector DB — the search tool does the retrieval.
python
from google import genai
from google.genai import types
client = genai.Client()
# Multi-turn chat with grounding via Google Search
chat = client.chats.create(
model="gemini-2.5-flash",
config=types.GenerateContentConfig(
system_instruction="You are a concise travel assistant.",
tools=[types.Tool(google_search=types.GoogleSearch())],
temperature=0.3,
),
)
for question in [
"What's the weather like in Mumbai in July?",
"And how does that compare to Goa?",
]:
resp = chat.send_message(question)
print(f"Q: {question}\nA: {resp.text}\n")
# Citations from grounded search live in candidate metadata
candidate = resp.candidates[0]
if candidate.grounding_metadata:
for chunk in candidate.grounding_metadata.grounding_chunks:
print(f" - {chunk.web.title}: {chunk.web.uri}")
Best practiceGood to know
Use google-genai, not google-generativeai.
The old SDK only covers Gemini 1.5; new APIs (Live, batch, caches v2) land on the new SDK first. Same imports differ —
pay attention to docs versions.
Set response_mime_type AND response_schema together.
Schema alone gives you freeform text that tends to match the schema. The MIME type is what forces strict JSON output.
Use Flash for everything except hard reasoning. Gemini 2.5 Flash has the same 1M-token context as Pro and handles 95% of workloads at a fraction of the cost.
Common trapsWatch out for
Roles are user / model.
Not assistant. Copy-paste an OpenAI-style messages array and Gemini rejects it.
Safety filters can return an empty response.
If resp.text is empty, check resp.prompt_feedback.block_reason and
candidate.finish_reason — SAFETY is silent unless you look.
Context cache minimums are large.
Flash needs 4k tokens, Pro needs 32k. Cache anything smaller and the create call errors. For shorter prefixes, just resend.
The Gemini API gives developers programmatic access to Google's Gemini family of multimodal LLMs. You can generate text, analyze images and video, call tools, stream responses, and build multi-turn chat sessions. It is accessible via AI Studio (API key) or Vertex AI (Google Cloud credentials).
What is the difference between google-genai and google-generativeai?
google-genai (from google import genai) is the current SDK targeting Gemini 2.x and all new features including the Live API, Files v2, and batch inference. google-generativeai (import google.generativeai as genai) is the legacy SDK for Gemini 1.x — it still works but new features will not be added to it. New projects should use google-genai.
How do I use function calling with the Gemini API?
Define your function with a standard Python signature and pass it in the tools parameter: client.models.generate_content(model, contents, config=GenerateContentConfig(tools=[my_func])). The model will emit a function call part when it wants to invoke the tool; you execute it and return the result as a function response in the next turn.
Does the Gemini API support streaming?
Yes. Call generate_content_stream instead of generate_content to receive an iterator of response chunks as they are generated. Each chunk has a text property. This is useful for showing progressively generated output in a UI without waiting for the full response.
Can the Gemini API process images and video?
Yes. Pass a PIL image, raw bytes, or a Google Cloud Storage URI in the contents list alongside the text prompt to analyze images. For video, upload the file via the Files API first (client.files.upload), then reference the returned file URI in your contents. Supported formats include JPEG, PNG, MP4, and MOV.
Is the Gemini API free to use?
There is a free tier with rate limits (requests per minute and per day) accessible through AI Studio with a GEMINI_API_KEY. Production workloads or higher-volume usage are billed per token. Vertex AI access uses Google Cloud pricing with committed-use discounts available.