Build an AI Quiz Generator with Gemini
Use Google Gemini AI to build a CLI quiz app with structured JSON output.
Introduction
30 Second Summary
Quizzes are one of the best ways to learn something new. What if you could instantly generate a quiz on any topic, powered by AI?
In this project, you will build a command-line quiz generator that uses Google's Gemini AI to create multiple-choice questions on any topic you choose.
What You'll Build
A Python script that connects to the Gemini API, generates structured quiz questions, and runs an interactive quiz loop with grading and personalised feedback.
By the end of this project, you'll have:
- A working Python script that connects to Google's Gemini API and generates quiz questions on any topic.
- Hands-on experience with core AI patterns: prompt engineering, system instructions, and structured output.
- A multi-turn conversation where the AI gives you personalised study recommendations based on your quiz results.
- Secret Mission: Add difficulty levels, scoring, and a colourful report card to your quiz app.
Are there any prerequisites?
You need basic Python knowledge (variables, functions, loops, if/else). No AI or machine learning experience is needed.
Set Up Your Environment
Before you can build a quiz generator, you need to connect to the AI that powers it.
In this step, you'll install the Python packages that talk to Google's Gemini AI, grab a free API key, and set up your project folder.
In this step, get ready to:
- Install the google-genai and pydantic packages.
- Get a free API key from Google AI Studio.
- Create your project folder and verify the connection works.
Install the Google GenAI SDK and Pydantic
Your quiz generator needs two Python packages to work. google-genai connects your code to Gemini AI, and pydantic helps you define the structure of quiz questions so the AI returns predictable data.
- Open a terminal in VS Code by pressing Cmd+` (macOS) or Ctrl+` (Windows).
- Install both packages by running this command:
pip install google-genai pydantic
What are these packages?
google-genai is Google's official SDK for the Gemini API. It handles authentication, sends your prompts to the AI, and returns responses.
pydantic is a data validation library. You'll use it to define the exact shape of a quiz question so the AI always returns consistent JSON.
- Verify the installation worked by running:
python -c "from google import genai; print('SDK ready!')"
✔️ I see SDK ready!
The package installed correctly. You're ready to move on.
ⓧ I see an error
If you see a ModuleNotFoundError, the package didn't install into the Python that ran the command.
- Try running pip3 install google-genai pydantic instead.
- If that doesn't work, try python3 -c "from google import genai; print('SDK ready!')" to confirm you're using the same Python version.
- Make sure your Python version is 3.10 or higher by running python --version.
Get your free Gemini API key
An API key is like a password that identifies your app to Google's servers. Without one, Gemini won't respond to your requests.
- Open your browser and go to Google AI Studio.
- Sign in with your Google account.
- Click Get API key on the landing page.
- Click Create API key to generate a new key.
- Copy the key and save it somewhere temporarily (you'll need it in a moment).
Is this really free?
Yes. The Gemini API free tier includes free input and output tokens with no credit card required. This project stays well within those limits.
Keep your API key private
Treat your API key like a password. Never paste it into code you share publicly, and never commit it to a Git repository.
Set your API key and create the project
Now you'll create a project folder, tell your terminal where to find the API key, and create the file you'll write your quiz code in.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir quiz-generator
cd quiz-generator
- Open this folder in a new VS Code window by running:
code .
Getting 'command not found' for code?
On macOS, you need to install the shell command first. Open VS Code, press Cmd+Shift+P to open the Command Palette, type shell command, and select Shell Command: Install 'code' command in PATH. Restart your terminal and try again.
On Windows, the VS Code installer adds code to your PATH automatically. If it's not working, restart your terminal or reinstall VS Code and make sure Add to PATH is checked during installation.
Help me fix the 'code' command not working in my terminal.
- In the new VS Code window, open a terminal by pressing Cmd+` (macOS) or Ctrl+` (Windows).
Now set your API key as an environment variable so the SDK can find it automatically.
macOS
- Set the environment variable by running:
export GEMINI_API_KEY="your-api-key-here"
- Replace your-api-key-here with the API key you copied from Google AI Studio.
Windows
- Set the environment variable by running:
$env:GEMINI_API_KEY = "your-api-key-here"
- Replace your-api-key-here with the API key you copied from Google AI Studio.
Why an environment variable?
The google-genai SDK automatically reads your API key from the GEMINI_API_KEY environment variable. This keeps the key out of your code so you never accidentally share it.
- Create the quiz file by clicking the New File icon at the top of the VS Code Explorer sidebar.
- Type quiz.py as the filename and press Enter.
You should see quiz.py appear in the Explorer sidebar and open as an empty file in the editor.
Finally, verify that your API key works by making a quick test call to Gemini.
- Test your connection by running this in the terminal:
python -c "from google import genai; client = genai.Client(); r = client.interactions.create(model='gemini-2.5-flash', input='Say hello in one sentence'); print(r.output_text)"
You should see a short greeting from Gemini printed in your terminal.
Not seeing a response?
If you see an authentication error, double-check that you pasted your API key correctly in the export or $env: command. Make sure there are no extra spaces or missing quotes.
If you see a ModuleNotFoundError, the new VS Code terminal may be using a different Python than the one you installed the package with. Try running pip install google-genai pydantic again in this terminal.
Help me troubleshoot my Gemini API connection.
✔️ Awesome, I've got everything!
Great. Double check you have quiz.py visible in the VS Code Explorer sidebar and that the file is empty.
ⓧ I'd like to double check the full code
Your quiz.py file should be completely empty at this point. You haven't written any code in it yet. If you see anything inside it, select all the text and delete it, then save the file.
Your environment is ready. Next up, you'll make your first AI call and see Gemini respond to a prompt you design.
Make Your First AI Call
Your environment is ready. Now it's time to make your first call to Google Gemini.
An AI API works like a conversation. You send a message (called a prompt), and the AI sends a response back. In this step, you'll send your first prompt to Gemini and then shape its personality using system instructions.
In this step, get ready to:
- Write a basic Gemini API call that sends a prompt and prints a response.
- Add a system instruction to shape the AI into a quiz master.
Write a basic Gemini API call
The Interactions API is Gemini's recommended interface for sending prompts and receiving responses. You create an interaction, pass in your prompt, and get text back.
- In VS Code, open quiz.py and add the following code:
import json
import os
from google import genai
# --- Gemini Client Setup ---
client = genai.Client()
interaction = client.interactions.create(
model="gemini-2.5-flash",
input="Generate a sample quiz question about Python programming.",
)
print(interaction.output_text)
What does this code do?
- from google import genai imports the Google GenAI SDK, which handles all communication with the Gemini API.
- client = genai.Client() creates a client that automatically reads your GEMINI_API_KEY environment variable. No need to pass the key manually.
- client.interactions.create() sends your prompt to the gemini-2.5-flash model and returns the AI's response.
- interaction.output_text contains the text the AI generated.
- Save quiz.py.
- Run the script in your terminal by running:
python quiz.py
You should see a quiz question generated by Gemini printed in your terminal. The exact text will vary each time you run it.
Seeing an error instead of a response?
- If you see an error mentioning an invalid or missing API key, your GEMINI_API_KEY environment variable may not be set in this terminal session. Re-run the export command from Step 1 in the same terminal window.
- If you see ModuleNotFoundError: No module named 'google', the SDK is not installed in the Python environment this terminal is using. Run pip install google-genai again.
- Make sure you are running the command from the folder that contains quiz.py.
Still stuck? Help me debug my first Gemini API call.
Add a system instruction
Your first response was probably generic text. System instructions let you define a persona for the AI before it ever sees the user's prompt. This is a core prompt engineering technique.
- In quiz.py, find this line:
client = genai.Client()
- Add the following SYSTEM_INSTRUCTION variable below it:
SYSTEM_INSTRUCTION = """You are a quiz master. Your job is to generate engaging,
educational multiple-choice quiz questions. Each question should have exactly
4 options with only one correct answer. Make questions clear and unambiguous.
Provide a brief, informative explanation for the correct answer."""
What is a system instruction?
A system instruction is a behind-the-scenes message that tells the AI how to behave. The user never sees it, but it shapes every response the AI gives.
Here, you're telling Gemini to act as a quiz master. Every response it generates will now follow these rules: exactly 4 options, one correct answer, and an explanation.
- Now find your client.interactions.create() call. It currently looks like this:
interaction = client.interactions.create(
model="gemini-2.5-flash",
input="Generate a sample quiz question about Python programming.",
)
- Add system_instruction=SYSTEM_INSTRUCTION, as a new line between model and input, so it looks like this:
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input="Generate a sample quiz question about Python programming.",
)
- Save quiz.py and run the script again:
python quiz.py
This time, the response should look like a structured quiz question with four numbered options and an explanation. The system instruction shaped the AI's output format.
Experiment with temperature
You can add a generation_config parameter to control how creative the AI gets. A temperature of 0.2 gives consistent, predictable responses. A temperature of 1.5 makes them more varied and surprising.
Try adding generation_config={"temperature": 1.0} to your interactions.create() call and running the script a few times to see the difference. Remove it when you're done experimenting.
Response doesn't look like a quiz question?
- Check that SYSTEM_INSTRUCTION is defined between client = genai.Client() and the interaction = ... call.
- Make sure system_instruction=SYSTEM_INSTRUCTION is inside the client.interactions.create() parentheses, not after them.
- Verify you used triple quotes """ to open and close the system instruction string.
Still stuck? Help me debug my system instruction.
✔️ Awesome, I've got everything!
Great. Double check you've saved quiz.py and that your script prints a quiz-style response when you run it.
ⓧ I'd like to double check the full code
Here is what your quiz.py should look like at this point:
import json
import os
from google import genai
# --- Gemini Client Setup ---
client = genai.Client()
SYSTEM_INSTRUCTION = """You are a quiz master. Your job is to generate engaging,
educational multiple-choice quiz questions. Each question should have exactly
4 options with only one correct answer. Make questions clear and unambiguous.
Provide a brief, informative explanation for the correct answer."""
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input="Generate a sample quiz question about Python programming.",
)
print(interaction.output_text)
You just made your first AI call and shaped its behaviour with a system instruction. Next up, you'll get the AI to return structured JSON data so your Python code can reliably parse every quiz question.
Get Structured Quiz Questions
Your script can talk to Gemini and get a response. That response comes back as free-form text, which is great for chatting but tricky to work with in code.
In this step, you'll teach Gemini to respond in a predictable structure. Instead of messy paragraphs, you'll get clean JSON that your Python code can parse into real objects with Pydantic.
In this step, get ready to:
- Define Pydantic models that describe the shape of a quiz question.
- Request structured JSON output from the Gemini API.
- Test that your quiz generator works with different topics.
Define your Pydantic models
Right now, Gemini returns whatever text format it wants. You have no control over whether it gives you bullet points, numbered lists, or a paragraph of prose. To use AI responses in a real application, you need a guaranteed structure.
Pydantic models let you define exactly what shape you expect the data to arrive in. You'll create two models: one for a single question, and one for the full quiz.
- In quiz.py, add these two import lines directly below the existing from google import genai line. Then add the Pydantic model classes between the imports and the # --- Gemini Client Setup --- comment. Copy this code:
from pydantic import BaseModel, Field
from typing import List
# --- Pydantic Models ---
class Question(BaseModel):
question: str = Field(description="The quiz question text")
options: List[str] = Field(description="Four possible answer choices")
correct_answer: int = Field(description="Index (0-3) of the correct option")
explanation: str = Field(description="Brief explanation of why the answer is correct")
class Quiz(BaseModel):
topic: str = Field(description="The quiz topic")
questions: List[Question] = Field(description="List of quiz questions")
What does this code do?
- BaseModel is the Pydantic base class that gives your models automatic validation and JSON parsing.
- Field(description=...) adds metadata that tells Gemini what each field should contain. The AI reads these descriptions when generating its response.
- Question defines one quiz question: the question text, four answer options, which option is correct (as an index), and an explanation.
- Quiz wraps multiple Question objects together with the topic name.
- Save quiz.py and run it in your terminal:
python quiz.py
- You should still see the same AI text response from before. The models are defined but not used yet, so nothing changes visually. The important thing is no import errors appear.
Seeing ModuleNotFoundError: No module named 'pydantic'?
- Make sure you installed pydantic in Step 1. Run pip install pydantic again to confirm it's installed in your active Python environment.
- Check that your terminal is using the same Python interpreter where you installed the package. Running pip show pydantic should display the package info.
- Make sure you don't have a file called pydantic.py in your project folder. That would shadow the real package.
Why can't Python find my pydantic package?
Request structured JSON output from Gemini
Now you'll build a function that asks Gemini to respond using your Pydantic schema. The key is the response_format parameter, which tells Gemini exactly what JSON structure to produce.
- In quiz.py, find these lines at the bottom of the file:
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input="Generate a sample quiz question about Python programming.",
)
print(interaction.output_text)
- Delete those lines entirely. Replace them with the generate_quiz function and test code below:
def generate_quiz(topic: str, num_questions: int = 5) -> Quiz:
"""Generate a quiz on the given topic using Gemini AI."""
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input=f"Generate a quiz with {num_questions} multiple-choice questions about: {topic}",
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Quiz.model_json_schema(),
},
)
return Quiz.model_validate_json(interaction.output_text)
# Test
quiz = generate_quiz("Python programming")
for q in quiz.questions:
print(q.question)
for i, opt in enumerate(q.options):
print(f" {i+1}. {opt}")
print(f"Answer: {q.options[q.correct_answer]}")
print()
What does this code do?
- response_format tells Gemini to return JSON matching your Quiz schema. The mime_type declares the format, and schema provides the exact structure via Quiz.model_json_schema().
- Quiz.model_validate_json() parses the raw JSON string from the AI into a real Python Quiz object. If the AI returns malformed data, Pydantic raises an error instead of silently passing bad data through.
- The test loop at the bottom calls the function, then prints each question with its numbered options and the correct answer.
- Save quiz.py and run it:
python quiz.py
- You should see 5 quiz questions about Python programming printed with numbered options and the correct answer for each. Every run produces real, structured questions.
Seeing a JSON parsing error?
- Make sure your response_format dictionary matches exactly: "type": "text", "mime_type": "application/json", and "schema": Quiz.model_json_schema().
- Confirm that your Question and Quiz classes are defined above the generate_quiz function. Python reads top to bottom, so the models must exist before the function references them.
- If you see a timeout, try running the script again. The first API call can occasionally take a few extra seconds.
Why is my structured output not parsing correctly?
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here's what your complete quiz.py should look like at this point:
import json
import os
from google import genai
from pydantic import BaseModel, Field
from typing import List
# --- Pydantic Models ---
class Question(BaseModel):
question: str = Field(description="The quiz question text")
options: List[str] = Field(description="Four possible answer choices")
correct_answer: int = Field(description="Index (0-3) of the correct option")
explanation: str = Field(description="Brief explanation of why the answer is correct")
class Quiz(BaseModel):
topic: str = Field(description="The quiz topic")
questions: List[Question] = Field(description="List of quiz questions")
# --- Gemini Client Setup ---
client = genai.Client()
SYSTEM_INSTRUCTION = """You are a quiz master. Your job is to generate engaging,
educational multiple-choice quiz questions. Each question should have exactly
4 options with only one correct answer. Make questions clear and unambiguous.
Provide a brief, informative explanation for the correct answer."""
def generate_quiz(topic: str, num_questions: int = 5) -> Quiz:
"""Generate a quiz on the given topic using Gemini AI."""
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input=f"Generate a quiz with {num_questions} multiple-choice questions about: {topic}",
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Quiz.model_json_schema(),
},
)
return Quiz.model_validate_json(interaction.output_text)
# Test
quiz = generate_quiz("Python programming")
for q in quiz.questions:
print(q.question)
for i, opt in enumerate(q.options):
print(f" {i+1}. {opt}")
print(f"Answer: {q.options[q.correct_answer]}")
print()
Test with different topics
The beauty of structured output is that no matter what topic you request, the response always arrives in the same predictable format. Your code never has to guess how to parse it.
- In quiz.py, find this line:
quiz = generate_quiz("Python programming")
- Change "Python programming" to a different topic, like "World War 2" or "Solar system". The line should look like this:
quiz = generate_quiz("Solar system")
- Save quiz.py and run it again:
python quiz.py
- You should see 5 new questions about your chosen topic. The format is identical to before: numbered options, a correct answer, and the same clean structure.
- Change the topic back to "Python programming" before moving to the next step.
Why is consistent structure important?
Without structured output, you'd need to write fragile text-parsing logic that breaks whenever the AI decides to format things differently. With the response_format parameter and Pydantic validation, your code can trust that quiz.questions[0].correct_answer will always be an integer between 0 and 3.
This is the pattern every production AI application uses to bridge the gap between unpredictable AI output and reliable software.
Your quiz generator now produces clean, structured data every time. Next up, you'll turn this into an interactive quiz where you actually answer the questions and get graded.
Build the Interactive Quiz Loop
You have structured quiz data flowing from Gemini. The questions are parsed, the options are clean, and everything sits in a predictable Pydantic model.
Now it is time to make the quiz come alive. In this step, you will build an interactive loop that presents questions, collects answers, grades them, and then asks Gemini for personalised study advice based on the results.
In this step, get ready to:
- Build an interactive quiz loop that displays questions and collects answers.
- Grade answers with feedback and explanations.
- Add an AI-powered study recommendation after the quiz ends.
Create the quiz flow
The quiz needs a function that loops through each question, displays the options with numbers, and waits for the learner to type an answer. It also needs to handle bad input gracefully so the quiz does not crash if someone types a letter instead of a number.
- In quiz.py, find the test code at the bottom of your file:
# Test
quiz = generate_quiz("Python programming")
for q in quiz.questions:
print(q.question)
for i, opt in enumerate(q.options):
print(f" {i+1}. {opt}")
print(f"Answer: {q.options[q.correct_answer]}")
print()
- Delete the entire test block above (everything from # Test to the end of the file).
- Replace it with the run_quiz() function by copying the following code below your generate_quiz() function:
def run_quiz(quiz: Quiz) -> int:
"""Run the quiz interactively and return the score."""
score = 0
total = len(quiz.questions)
print(f"\n{'='*50}")
print(f" QUIZ: {quiz.topic}")
print(f" {total} questions")
print(f"{'='*50}\n")
for i, q in enumerate(quiz.questions, 1):
print(f"Question {i}/{total}: {q.question}\n")
for j, option in enumerate(q.options):
print(f" {j + 1}. {option}")
while True:
try:
answer = int(input("\nYour answer (1-4): ")) - 1
if 0 <= answer <= 3:
break
print("Please enter a number between 1 and 4.")
except ValueError:
print("Please enter a number between 1 and 4.")
if answer == q.correct_answer:
print("\nCorrect!")
score += 1
else:
print(f"\nWrong! The correct answer was: {q.options[q.correct_answer]}")
print(f"Explanation: {q.explanation}\n")
print("-" * 40 + "\n")
return score
What does this code do?
This function handles the entire interactive quiz experience in one loop.
- It prints a header banner showing the topic and question count.
- The for loop iterates through each question, printing numbered options (1-4) for the learner to choose from.
- The while True block validates input. It keeps asking until the learner types a valid number between 1 and 4. The try/except ValueError catches non-numeric input like letters.
- After collecting an answer, it compares against q.correct_answer and prints whether the learner got it right or wrong, plus the explanation.
- The function returns the total score as an integer for use later.
- Save quiz.py.
You will not see a change yet because there is no main() function to call run_quiz(). The next substep adds that.
Seeing a syntax error on save?
- Make sure you deleted the entire test block. Leftover lines from the test code can conflict with the new function.
- Check that the def run_quiz line starts at column 0 (no extra indentation). It should be at the same level as def generate_quiz above it.
Help me debug a syntax error in my quiz.py file after adding the run_quiz function.
Grade answers and show explanations
The run_quiz() function handles grading internally. Now you need a main() function that orchestrates the full flow: asking for a topic, generating the quiz, running it, and showing the final score.
- Add the main() function and the if __name__ guard below run_quiz() by copying this code:
def main():
"""Main function to run the quiz application."""
print("\n" + "=" * 50)
print(" AI QUIZ GENERATOR")
print(" Powered by Google Gemini")
print("=" * 50)
topic = input("\nWhat topic would you like to be quizzed on? ")
print(f"\nGenerating quiz about '{topic}'...")
quiz = generate_quiz(topic)
score = run_quiz(quiz)
total = len(quiz.questions)
percentage = (score / total) * 100
print(f"\n{'='*50}")
print(f" FINAL SCORE: {score}/{total} ({percentage:.0f}%)")
print(f"{'='*50}")
if __name__ == "__main__":
main()
What does this code do?
- main() prints a welcome banner, asks the user what topic they want to be quizzed on, then calls generate_quiz() and run_quiz() in sequence.
- After the quiz ends, it calculates a percentage score and prints a final summary.
- The if __name__ == "__main__": guard ensures main() only runs when you execute the script directly, not when importing it as a module.
- Save quiz.py.
- Run your quiz app by running this command in your terminal:
python quiz.py
You should see the welcome banner, a topic prompt, and then AI-generated quiz questions. Answer each one and you will see whether you got it right or wrong, along with an explanation.
Quiz not starting or crashing immediately?
- If you see an error about GEMINI_API_KEY, make sure your environment variable is still set in this terminal session. PowerShell variables reset when you close the window.
- If the script hangs after printing the topic, the AI is generating questions. This can take a few seconds on the first call.
- If you see an import error, confirm you are running python quiz.py from the same folder where quiz.py lives.
My quiz app is crashing when I try to run it. Help me debug the issue.
Add a multi-turn follow-up
A good quiz does not just show a score. It tells you what to study next. You will add a second AI call that takes your quiz results and generates a personalised study recommendation.
Why a separate AI call instead of multi-turn chaining?
The Interactions API supports multi-turn conversations via previous_interaction_id. For this project, a standalone call with context in the prompt is simpler and avoids managing server-side state.
Both approaches give you a "context-aware" follow-up. The standalone approach works well when you only need one follow-up question and can summarise the context in a sentence or two.
- In quiz.py, find the main() function. Add the get_study_recommendation() function directly above it (between run_quiz() and main()):
def get_study_recommendation(quiz: Quiz, score: int) -> str:
"""Ask Gemini for a personalised study recommendation."""
total = len(quiz.questions)
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction="You are a helpful study coach. Give brief, actionable study advice.",
input=f"A student just took a quiz on '{quiz.topic}' and scored {score}/{total}. "
f"Give them a short, encouraging study recommendation (2-3 sentences).",
)
return interaction.output_text
What does this code do?
- This function makes a second call to Gemini with a different system_instruction that frames the AI as a study coach.
- It passes the quiz topic and score directly in the input prompt so the AI has full context to give relevant advice.
- The response comes back as plain text (no structured output needed here), so you just return interaction.output_text directly.
Now update main() to call this function after showing the final score.
- In main(), find the last print statement that shows the final score:
print(f"{'='*50}")
- Add these lines directly below it, inside main() (indented with 4 spaces):
print("\nGetting study recommendation...")
recommendation = get_study_recommendation(quiz, score)
print(f"\nStudy Coach says: {recommendation}")
- Save quiz.py and run it again:
python quiz.py
After completing the quiz and seeing your final score, you should now see a personalised study recommendation from the AI study coach.
Not seeing the study recommendation?
- Make sure the three new lines are inside main() (indented with 4 spaces), not at the top level of the file.
- Check that get_study_recommendation() is defined above main(). Python reads top to bottom, so the function must exist before main() calls it.
My study recommendation is not appearing after the quiz finishes. Help me figure out why.
✔️ Awesome, I've got everything!
Great. Double check you have saved quiz.py and that your quiz runs end-to-end with a study recommendation at the end.
ⓧ I'd like to double check the full code
import json
import os
from google import genai
from pydantic import BaseModel, Field
from typing import List
# --- Pydantic Models ---
class Question(BaseModel):
question: str = Field(description="The quiz question text")
options: List[str] = Field(description="Four possible answer choices")
correct_answer: int = Field(description="Index (0-3) of the correct option")
explanation: str = Field(description="Brief explanation of why the answer is correct")
class Quiz(BaseModel):
topic: str = Field(description="The quiz topic")
questions: List[Question] = Field(description="List of quiz questions")
# --- Gemini Client Setup ---
client = genai.Client()
SYSTEM_INSTRUCTION = """You are a quiz master. Your job is to generate engaging,
educational multiple-choice quiz questions. Each question should have exactly
4 options with only one correct answer. Make questions clear and unambiguous.
Provide a brief, informative explanation for the correct answer."""
def generate_quiz(topic: str, num_questions: int = 5) -> Quiz:
"""Generate a quiz on the given topic using Gemini AI."""
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction=SYSTEM_INSTRUCTION,
input=f"Generate a quiz with {num_questions} multiple-choice questions about: {topic}",
response_format={
"type": "text",
"mime_type": "application/json",
"schema": Quiz.model_json_schema(),
},
)
return Quiz.model_validate_json(interaction.output_text)
def run_quiz(quiz: Quiz) -> int:
"""Run the quiz interactively and return the score."""
score = 0
total = len(quiz.questions)
print(f"\n{'='*50}")
print(f" QUIZ: {quiz.topic}")
print(f" {total} questions")
print(f"{'='*50}\n")
for i, q in enumerate(quiz.questions, 1):
print(f"Question {i}/{total}: {q.question}\n")
for j, option in enumerate(q.options):
print(f" {j + 1}. {option}")
while True:
try:
answer = int(input("\nYour answer (1-4): ")) - 1
if 0 <= answer <= 3:
break
print("Please enter a number between 1 and 4.")
except ValueError:
print("Please enter a number between 1 and 4.")
if answer == q.correct_answer:
print("\nCorrect!")
score += 1
else:
print(f"\nWrong! The correct answer was: {q.options[q.correct_answer]}")
print(f"Explanation: {q.explanation}\n")
print("-" * 40 + "\n")
return score
def get_study_recommendation(quiz: Quiz, score: int) -> str:
"""Ask Gemini for a personalised study recommendation."""
total = len(quiz.questions)
interaction = client.interactions.create(
model="gemini-2.5-flash",
system_instruction="You are a helpful study coach. Give brief, actionable study advice.",
input=f"A student just took a quiz on '{quiz.topic}' and scored {score}/{total}. "
f"Give them a short, encouraging study recommendation (2-3 sentences).",
)
return interaction.output_text
def main():
"""Main function to run the quiz application."""
print("\n" + "=" * 50)
print(" AI QUIZ GENERATOR")
print(" Powered by Google Gemini")
print("=" * 50)
topic = input("\nWhat topic would you like to be quizzed on? ")
print(f"\nGenerating quiz about '{topic}'...")
quiz = generate_quiz(topic)
score = run_quiz(quiz)
total = len(quiz.questions)
percentage = (score / total) * 100
print(f"\n{'='*50}")
print(f" FINAL SCORE: {score}/{total} ({percentage:.0f}%)")
print(f"{'='*50}")
print("\nGetting study recommendation...")
recommendation = get_study_recommendation(quiz, score)
print(f"\nStudy Coach says: {recommendation}")
if __name__ == "__main__":
main()
Your quiz app is fully functional. You can generate quizzes on any topic, answer questions interactively, see your score, and get AI-powered study advice. Next up, the Secret Mission will challenge you to add difficulty levels and a colourful report card.
Secret mission
Add Difficulty Levels and a Score Report
Your quiz works, but every question hits the same difficulty. What if the learner could choose easy, medium, or hard? And what if the app printed a colourful report card at the end with a grade and personalised study tip?
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs on the Gemini free tier, so there are no ongoing costs.
Resources you used:
- Gemini API key (free tier, no charges for normal usage).
- Local project folder with quiz.py.
- Installed Python packages (google-genai and pydantic).
Keep everything running
No action needed. Choose this if you plan to keep experimenting with your quiz generator or building more AI projects.
- Your API key stays active on the free tier with no charges for normal usage.
- Your project folder and installed packages remain on your machine ready to use.
Pause - I'll come back to this later
No action needed for this project. The Gemini free tier has no ongoing costs, so nothing is accumulating charges while you are away.
- Your API key remains valid and ready whenever you return.
- Your local files stay on disk until you decide to remove them.
Delete - I don't want to use this again
Remove all project resources and revoke API access. Follow each step below.
- Delete your Gemini API key by opening the Google Cloud API Credentials page at https://console.cloud.google.com/apis/credentials.
- Find the API key you created for this project and click the Actions icon next to it.
- Select Delete API key, then click Delete in the confirmation modal.
- Delete your project folder by running this command in your terminal:
cd ~/Desktop
rm -rf ai-quiz-generator
Windows users
If you are on Windows, run this in PowerShell instead:
cd ~\Desktop
Remove-Item -Recurse -Force ai-quiz-generator
- Uninstall the Python packages by running:
pip uninstall google-genai pydantic -y
That's a Wrap!
That's a Wrap!
Nice work! You just built a fully interactive, AI-powered quiz generator from scratch using Python and Google Gemini.
You've learned how to:
- Connect to an AI API and send prompts to Google Gemini using the Interactions API.
- Shape AI behaviour with system instructions to turn a general-purpose model into a focused quiz master.
- Get predictable, parseable responses from AI using structured JSON output and Pydantic models.
- Secret Mission: Added difficulty levels, a scoring system, and a colourful report card with ANSI escape codes.
Ready to quiz yourself?