AI group · Hands-on

Gemini API playground

Chat is only the start. These live demos show what Google's Gemini API can do for real community tasks: match people to events, read photos and PDFs, turn messy text into clean data, call your own tools, run code and speak.

Structured output · real data

Match my situation to upcoming events

Describe your situation in a sentence, in English or Chinese. Gemini reads the G8 list of upcoming Triangle events and picks the 3 to 5 that fit you best, with a reason for each. It can only choose real events from the list; the server checks every pick.

Or try a sample:

We don't store what you type or upload. It goes to the Gemini API to produce the answer and is not saved on G8.

Show the code
from google import genai
from google.genai import types

client = genai.Client()  # reads GEMINI_API_KEY from the environment
events = open("events.txt").read()  # one line per event: "id | start | town | category | cost | title | summary"
ids = [line.split(" | ")[0] for line in events.splitlines()]

schema = {
    "type": "object",
    "properties": {"matches": {"type": "array", "maxItems": 5, "items": {
        "type": "object",
        "properties": {
            "id": {"type": "string", "enum": ids},     # can only pick real events
            "reason": {"type": "string"},
            "score": {"type": "integer", "minimum": 0, "maximum": 100}},
        "required": ["id", "reason", "score"]}}},
    "required": ["matches"],
}

resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=f"EVENTS:\n{events}\n\nVISITOR: We just moved to Cary with two kids...",
    config=types.GenerateContentConfig(
        system_instruction="Recommend 3-5 events ONLY from the EVENTS list, by exact id. "
                           "Never invent events. One-sentence reason in the visitor's language.",
        response_mime_type="application/json",
        response_json_schema=schema,
    ),
)
print(resp.text)  # {"matches": [{"id": "...", "reason": "...", "score": 92}, ...]}

Structured output (JSON schema)

Messy flyer text to clean data

Paste the text of an event flyer or a group-chat post. Gemini fills in a fixed JSON schema and leaves unknown fields empty instead of guessing.

Show the code
from google import genai
from google.genai import types
from pydantic import BaseModel

class Event(BaseModel):
    title: str
    date: str | None          # YYYY-MM-DD
    start_time: str | None
    end_time: str | None
    venue: str | None
    town: str | None
    cost: str | None          # None if not stated: never assume free
    organizer: str | None
    registration_url: str | None
    languages: list[str]

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=open("flyer.txt").read(),
    config=types.GenerateContentConfig(
        system_instruction="Extract the event. Use null for anything not stated.",
        response_mime_type="application/json",
        response_json_schema=Event.model_json_schema(),
    ),
)
event = Event.model_validate_json(resp.text)
print(event)

Function calling

Let Gemini call your own tool

We give Gemini one tool, get_events, that reads this site's events data. Gemini decides when to call it and with which filters, then answers from the real results.

Show the code
from google import genai
from google.genai import types

def get_events(town: str = "", start_date: str = "", end_date: str = "",
               free_only: bool = False) -> dict:
    """List upcoming Triangle events from the G8 site's events data."""
    ...  # filter your own events.json and return {"events": [...]}

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="What's on in Cary this weekend that's free for families?",
    config=types.GenerateContentConfig(
        system_instruction="Today is Tuesday, October 20, 2026. Use get_events; never invent events.",
        tools=[get_events],   # the Python SDK calls the function for you, then Gemini answers
    ),
)
print(resp.text)

Image understanding

Understand a photo

Pick a sample photo or upload your own, then ask a question about it.

Sample photos (AI-generated images)

Show the code
from google import genai
from google.genai import types

client = genai.Client()
image = open("photo.jpg", "rb").read()

resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        types.Part.from_bytes(data=image, mime_type="image/jpeg"),
        "What is happening in this photo? List three details.",
    ],
)
print(resp.text)

Document understanding

Ask a PDF

Gemini reads a whole PDF, including tables, and answers questions about it. The sample is a fictional neighborhood newsletter.

· Open the sample PDF

Show the code
from google import genai
from google.genai import types

client = genai.Client()
pdf = open("newsletter.pdf", "rb").read()

resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents=[
        types.Part.from_bytes(data=pdf, mime_type="application/pdf"),
        "Summarize in 5 bullet points, then list every date and deadline in a table.",
    ],
)
print(resp.text)

Code execution

Write and run Python

Gemini writes Python, runs it in Google's sandbox, and uses the real output, including charts.

Show the code
from google import genai
from google.genai import types

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="Family budget: rent 1850, groceries 720, car 410 ... "
             "Make a sorted bar chart and give each item's percent of the total.",
    config=types.GenerateContentConfig(
        tools=[types.Tool(code_execution=types.ToolCodeExecution())],
    ),
)
for part in resp.candidates[0].content.parts:
    if part.executable_code:       print(part.executable_code.code)
    if part.code_execution_result: print(part.code_execution_result.output)
    if part.inline_data:           open("chart.png", "wb").write(part.inline_data.data)
    if part.text:                  print(part.text)

URL context

Summarize a web page

Give Gemini a public web address. It fetches the page itself and answers from what's on it.

Show the code
from google import genai
from google.genai import types

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="What can a new Cary resident do on this website? "
             "https://www.townofcary.org/",
    config=types.GenerateContentConfig(
        tools=[types.Tool(url_context=types.UrlContext())],
    ),
)
print(resp.text)
print(resp.candidates[0].url_context_metadata)  # which URLs were fetched

Speech generation

Text to speech

Turn short text into natural speech, in English or Chinese, with a choice of voices.

Show the code
from google import genai
from google.genai import types

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.8-flash-tts",
    contents="Welcome to the Triangle! The English conversation group meets every Tuesday.",
    config=types.GenerateContentConfig(
        response_modalities=["AUDIO"],
        speech_config=types.SpeechConfig(
            voice_config=types.VoiceConfig(
                prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Kore"))),
    ),
)
audio = resp.candidates[0].content.parts[0].inline_data
open("welcome.wav", "wb").write(audio.data)  # 3.8 TTS models return WAV

How it works

Your browser sends the demo request to a small G8 server function. The function adds the API key (kept secret on the server), calls the Gemini API with a Flash model, and sends back the answer. Every card has a 'Show the code' button with the same call in Python.

Not included, and why

  • Grounding with Google Search: Search grounding is not available on the free tier for current Gemini Flash models (Google's pricing page lists it as paid only).
  • Embeddings / semantic search: The free embedding model can only embed one item per call here, so searching all events would use dozens of requests per visitor. The event matcher above covers the same idea.
  • Image generation: Google's Flash image models (Nano Banana) are not available on the free tier.

Have a demo passcode?

Presenters can unlock a higher limit. Signed-in G8 editors get it automatically.