Lab Guide — Google Gemini
Three exercises covering the Gemini SDK, multimodal inputs, and cross-provider comparison with Claude.
lab.pdf in Jupyter. You need a GOOGLE_API_KEY (from Google AI Studio) and an ANTHROPIC_API_KEY in your .env file. Install the SDKs: pip install google-generativeai anthropic.
Exercise 1 — Your First Gemini Call
Set up the Gemini SDK and generate text
Configure the google-generativeai SDK, create a model instance, and make your first API call.
- Import the SDK and configure it with your API key:
import google.generativeai as genai from dotenv import load_dotenv import os load_dotenv() genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) - Create a
GenerativeModelinstance forgemini-2.5-flash:model = genai.GenerativeModel("gemini-2.5-flash") - Send a simple text generation request:
response = model.generate_content("Explain the difference between TCP and UDP in 3 sentences.") print(response.text) - Inspect the token usage metadata:
print(f"Input tokens: {response.usage_metadata.prompt_token_count}") print(f"Output tokens: {response.usage_metadata.candidates_token_count}") print(f"Total tokens: {response.usage_metadata.total_token_count}") - Try passing
generation_configto control temperature and max output tokens:response = model.generate_content( "Write a haiku about machine learning.", generation_config=genai.GenerationConfig( temperature=0.9, max_output_tokens=100, ), ) print(response.text)
GenerativeModel object that you create once, then call generate_content() on repeatedly. Claude and OpenAI pass the model name to each API call instead.
Checkpoint: You can make a successful Gemini API call, print the response text, and view token usage metadata.
Exercise 2 — Multimodal Input (Image + Text)
Analyse an image using Gemini’s vision capabilities
Use Gemini’s native multimodal support to describe and analyse an image alongside a text prompt.
- Download or use a sample image. You can use any JPEG/PNG file or load one from a URL:
import urllib.request # Download a sample image url = "https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/280px-PNG_transparency_demonstration_1.png" urllib.request.urlretrieve(url, "sample_image.png") - Upload the file and send it with a text prompt:
uploaded_file = genai.upload_file("sample_image.png") response = model.generate_content([ "Describe what you see in this image in detail. " "Include colours, objects, and any text visible.", uploaded_file, ]) print(response.text) - Try different analysis prompts on the same image:
"What text is visible in this image?""If this image were used in a presentation, what topic would it illustrate?""Describe the mood or emotion this image conveys."
- Compare token usage for image inputs versus text-only inputs. Note how many tokens the image consumes:
print(f"Tokens used for image prompt: {response.usage_metadata.prompt_token_count}") # Compare with a text-only prompt of similar complexity - (Optional) Try loading an image directly from bytes using
PIL:from PIL import Image img = Image.open("sample_image.png") response = model.generate_content([ "What colours dominate this image?", img, ]) print(response.text)
Checkpoint: Gemini accurately describes your image content. You can see the token cost of image inputs in the usage metadata.
Exercise 3 — Cross-Provider Comparison (Gemini vs Claude)
Run the same prompts on Gemini and Claude, compare results
Build a comparison harness that sends identical prompts to both Gemini Flash and Claude Sonnet, then evaluates the results side by side.
- Set up both clients:
import google.generativeai as genai import anthropic import time genai.configure(api_key=os.getenv("GOOGLE_API_KEY")) gemini_model = genai.GenerativeModel("gemini-2.5-flash") claude_client = anthropic.Anthropic() - Define 5 test prompts covering different capabilities:
prompts = [ "Write a Python function that checks if a string is a valid IPv4 address.", "Explain quantum entanglement to a 10-year-old.", "Summarise the pros and cons of microservices vs monoliths.", "Write a short poem about a lonely lighthouse.", "What are the three most important factors when choosing a database?", ] - Write a comparison function that records response text, token usage, and latency for each provider:
def compare_models(prompt): # Gemini call t0 = time.time() g_resp = gemini_model.generate_content(prompt) g_time = time.time() - t0 # Claude call t0 = time.time() c_resp = claude_client.messages.create( model="claude-sonnet-4-20250514", max_tokens=1024, messages=[{"role": "user", "content": prompt}], ) c_time = time.time() - t0 return { "prompt": prompt, "gemini_text": g_resp.text, "gemini_tokens": g_resp.usage_metadata.total_token_count, "gemini_time": round(g_time, 2), "claude_text": c_resp.content[0].text, "claude_tokens": c_resp.usage.input_tokens + c_resp.usage.output_tokens, "claude_time": round(c_time, 2), } - Run all 5 prompts and display the results in a formatted comparison
- Add streaming support for Gemini and observe the output arriving in chunks:
# Gemini streaming response = gemini_model.generate_content( "Explain recursion step by step.", stream=True, ) for chunk in response: print(chunk.text, end="", flush=True) print() # newline after streaming completes
Checkpoint: A table or formatted output showing side-by-side results for all 5 prompts with token counts and response times for both providers.