Build an AI Study Buddy with Python
Call the Gemini API to build a quiz app with structured JSON output.
Introduction
30 Second Summary
Studying for a test or picking up a new skill usually means hunting for practice questions online and hoping they cover what you actually need. What if you could generate custom quiz questions on any topic, instantly?
In this project, you will build an AI Study Buddy using Python and Google's Gemini API. You'll create a terminal app that generates quiz questions on any topic, lets you answer them interactively, and scores your answers with detailed explanations.
What You'll Build
You'll type a topic like "Python decorators" into your terminal, answer AI-generated multiple-choice questions one by one, and see your score alongside detailed explanations for every answer.
By the end of this project, you'll have:
- A working quiz generator where you type any topic and get AI-created multiple-choice questions in seconds.
- An interactive quiz loop that collects your answers, scores them, and sends the results back to the AI for detailed explanations of every answer.
- Hands-on experience with prompt engineering and structured JSON output, turning messy AI text into clean data your code can parse automatically.
- Secret Mission: Add a difficulty selector and a running score tracker across multiple quiz rounds.
Do I need AI or machine learning experience?
Not at all. This project assumes basic Python knowledge like variables, functions, and loops. You'll learn AI engineering concepts as you build.
Before We Start
Before diving into code, let's lock in what you're about to build and why it matters for your journey into AI engineering.
Set Up Python and the Gemini SDK
Every AI-powered app starts with a connection to an AI model. Before your Study Buddy can generate a single quiz question, it needs a way to talk to the Gemini model from Python and a credential that proves you are allowed to use it.
In this step, you will grab a free API key from Google, install the Python SDK that handles Gemini API communication, and write a short script that proves everything is connected.
In this step, get ready to:
- Get a free Gemini API key from Google AI Studio.
- Install the google-genai SDK and create your project file.
- Write and run your first API call to verify the connection works.
Get your free Gemini API key
An API key is a unique string that identifies your code when it talks to the Gemini API. Google provides these for free with no credit card required.
- Open your browser and go to aistudio.google.com.
- Sign in with your Google account.
- Click Get API key in the left sidebar.
- Click Create API key.
- Copy the key that appears. You will need it in a later substep.
What is an API key?
An API key is like a password that lets your Python script access the Gemini API. It tells Google who is making the request so it can track your free-tier usage.
Never share your API key publicly or commit it to version control. Treat it like a password.
Can't create an API key?
Make sure you are signed into a personal Google account. Some school or work accounts restrict API key creation.
Help me troubleshoot my Gemini API key creation issue.
Install the SDK and create your project file
The google-genai SDK is the Python library that handles all communication with the Gemini API for you.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or Command Prompt (Windows) and press Enter to open it.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir ai-study-buddy
cd ai-study-buddy
- Install the Google GenAI SDK by running:
pip install google-genai
You should see output showing packages being downloaded and installed. The last few lines confirm a successful install.
Having trouble with pip?
On some systems, the command is pip3 instead of pip. Try pip3 install google-genai if the first command did not work.
Help me fix my pip installation issue.
Now open the project folder in VS Code so you can create your Python file.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code and press Enter to open it.
- In VS Code, click File in the top menu bar.
- Click Open Folder.
- Select the ai-study-buddy folder on your Desktop, then click Open.
- In the Explorer sidebar on the left, hover over the folder name and click the New File icon.
- Type study_buddy.py and press Enter.
Your new file opens in the editor, ready for code.
Write and run your first API call
With the SDK installed and your file created, you can now write a minimal script that sends a prompt to Gemini and prints the response.
- In study_buddy.py, paste the following code:
# Import the Google GenAI SDK
from google import genai
# Create a client that reads your GEMINI_API_KEY automatically
client = genai.Client()
# Send a simple prompt to the Gemini model and print the response
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="What is Python?",
)
print(response.text)
What does this code do?
from google import genai loads the SDK you just installed. This gives your script access to the Gemini API.
genai.Client() creates a client that automatically reads a GEMINI_API_KEY environment variable. No need to paste your key into the code.
client.models.generate_content() sends your prompt to the gemini-2.5-flash model and returns the AI's response. response.text extracts just the text portion.
- Save study_buddy.py by pressing Cmd+S (macOS) or Ctrl+S (Windows).
Before you can run the script, you need to set your API key as an environment variable. The SDK reads it automatically so your key stays out of the code.
- Open the VS Code integrated terminal by pressing Ctrl+` (backtick key, located above Tab) on both macOS and Windows.
- Set your API key by running this command. Replace your-api-key-here with the key you copied from Google AI Studio.
macOS
export GEMINI_API_KEY=your-api-key-here
Windows
set GEMINI_API_KEY=your-api-key-here
Environment variables are temporary
This environment variable only lasts for the current terminal session. If you close the terminal, you will need to set it again before running your script.
Before you run this, take a guess. What do you think will happen when you send the prompt "What is Python?" to the Gemini API?
- Run your script:
python study_buddy.py
You should see a paragraph or two from the AI explaining what Python is, printed directly in your terminal. The exact wording varies each time because the model generates a fresh response.
Seeing an error instead of a response?
- If you see an authentication or invalid key error, double-check that you ran the export or set command in the same terminal where you are running the script.
- If you see an error about a missing module, make sure you installed the SDK with pip install google-genai (not pip install google).
- On macOS, try python3 study_buddy.py if python does not work.
Help me fix my first Gemini API call.
✔️ Awesome, I've got everything!
Great. Double check you have saved study_buddy.py and your script printed an AI-generated response about Python.
ⓧ I'd like to double check the full code
Here is the complete study_buddy.py file at this point. Make sure yours matches:
from google import genai
client = genai.Client()
response = client.models.generate_content(
model="gemini-2.5-flash",
contents="What is Python?",
)
print(response.text)
Your connection to the Gemini API is live. Next up, you will use prompt engineering to turn this basic connection into a quiz question generator.
Generate Quiz Questions with Prompt Engineering
Your connection to the Gemini API is working. Right now the script asks a hardcoded question and prints whatever the AI says back.
To turn this into a quiz generator, you need to tell the AI exactly what to produce. This is prompt engineering: crafting the input so the AI returns the output you want.
In this step, get ready to:
- Ask the user for a quiz topic and craft a prompt that generates questions.
- Add a system instruction to control the AI's behavior.
- Observe the limitation of unstructured text output.
Ask the user for a topic and craft the quiz prompt
Instead of a hardcoded question, the script should ask the user what they want to study. The user's answer then gets inserted into a detailed prompt that tells the AI what kind of output to generate.
- In study_buddy.py, find the existing response = client.models.generate_content( block.
- Select everything from response = down to the closing ) and replace it with the following code:
# Ask the user what they want to study
topic = input("What topic do you want to study? ")
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Generate 3 multiple-choice quiz questions about: {topic}",
)
What does this code do?
- input() pauses the script and waits for the user to type something. Whatever they type gets stored in the topic variable.
- The f in f"Generate 3..." makes this an f-string. Python replaces {topic} with whatever the user typed.
- The prompt is specific and detailed. Instead of asking "What is Python?", it tells the AI exactly what format to produce: 3 multiple-choice questions with 4 options each.
- Save study_buddy.py.
- Run the script by entering this command in your terminal:
python study_buddy.py
- When the script asks for a topic, type something like the solar system and press Enter.
You should see quiz questions about your topic printed in the terminal. The AI is already generating questions based on your prompt.
Not seeing quiz questions?
- Make sure you saved study_buddy.py before running the command.
- Check that the f is present before the opening quote in f"Generate 3...". Without it, Python treats {topic} as literal text instead of inserting your variable.
- Confirm your GEMINI_API_KEY environment variable is still set in the same terminal session. If you closed and reopened the terminal, you need to set it again.
Why aren't my quiz questions generating when I run the script?
Add a system instruction to control the AI
The quiz questions work, but the AI is acting as a general assistant. A system instruction sets a persistent role for the AI that shapes every response it generates.
- In study_buddy.py, add this import below the existing from google import genai line:
from google.genai import types
- Now find your response = client.models.generate_content( call.
- Replace the entire call with the following version, which adds a config parameter containing the system instruction:
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Generate 3 multiple-choice quiz questions about: {topic}",
config=types.GenerateContentConfig(
system_instruction="You are a quiz generator. Create clear, educational multiple-choice questions. Each question must have exactly 4 options labeled A through D. Make the questions test understanding, not just memorization.",
),
)
What does this code do?
- types.GenerateContentConfig lets you pass extra settings to the API call alongside the main prompt.
- system_instruction tells the AI what role to play before it reads your prompt. It shapes every response the AI generates, like giving a briefing before the task.
- Here, the system instruction tells the AI to be a quiz generator that creates questions with exactly 4 options labeled A through D and tests understanding rather than memorization.
Why use a system instruction instead of putting everything in the prompt?
You could stuff the role and rules into the contents prompt, but system instructions are treated differently by the model. They carry more weight and are applied consistently across every response.
Separating the role from the task also keeps your code cleaner. The system instruction stays constant while the contents changes with each user request.
- Save study_buddy.py.
Seeing a NameError for types?
Make sure the from google.genai import types import is on its own line directly below from google import genai. Both lines must be at the very top of the file.
Why am I getting a NameError when I try to use types.GenerateContentConfig?
Run the improved quiz generator
Before you run this, think about what the output will look like. The AI now has a detailed prompt and a system instruction telling it exactly how to format quiz questions. Will the output be easy for your Python code to work with?
- Run the script by entering this command in your terminal:
python study_buddy.py
- Type a topic like Python decorators and press Enter.
You should see three quiz questions printed in your terminal, each with options labeled A through D. The system instruction is doing its job.
Now look at the output from your code's perspective. The AI returned a wall of plain text. Try to imagine writing Python code to reliably extract each question, its four options, and the correct answer from this string.
Why is this output a problem?
The output looks great for a human to read. But every time you run the script, the AI might format things slightly differently. Sometimes it uses bold text, sometimes numbered lists, sometimes dashes.
Any code you write to parse this text would be fragile. A small change in the AI's phrasing or layout would break your parsing logic. You need the AI to return data in a predictable, structured format that your code can always rely on.
✔️ Awesome, I've got everything!
Great. Double check you've saved study_buddy.py.
ⓧ I'd like to double check the full code
Here is the complete study_buddy.py file at the end of this step. Compare it with yours line by line.
from google import genai
from google.genai import types
client = genai.Client()
topic = input("What topic do you want to study? ")
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Generate 3 multiple-choice quiz questions about: {topic}",
config=types.GenerateContentConfig(
system_instruction="You are a quiz generator. Create clear, educational multiple-choice questions. Each question must have exactly 4 options labeled A through D. Make the questions test understanding, not just memorization.",
),
)
print(response.text)
Your quiz prompt generates great questions, but the output is raw text your code cannot reliably parse. Next up, you will force the AI to return clean, structured JSON that your Python code can work with every time.
Get Clean JSON with Structured Output
In the last step, you saw what happens when you ask the AI for quiz questions without any structure. The output came back as a wall of plain text. It looked fine for reading, but imagine trying to write Python code that reliably picks out each question, its four options, and the correct answer from that free-form string.
In this step, you'll fix that by defining the exact shape of data you want back using Pydantic models. Then you'll tell the Gemini API to return structured JSON matching that shape, turning messy text into clean, parseable Python objects.
In this step, get ready to:
- Define Pydantic data models that describe quiz questions.
- Force the AI to return structured JSON matching your models.
- Parse AI responses into clean Python objects and display formatted questions.
Define Pydantic models for your quiz data
Pydantic is a Python data validation library that lets you define the exact shape of data using Python classes. The google-genai SDK already includes Pydantic as a dependency, so there is nothing new to install.
- In study_buddy.py, replace the import lines at the top of your file with the following updated imports, and add the model definitions right below them:
import json
from google import genai
from google.genai import types
from pydantic import BaseModel, Field
# Define the structure for a single quiz question
class Question(BaseModel):
question: str = Field(description="The quiz question text")
options: list[str] = Field(description="Four possible answer choices")
correct_answer: str = Field(description="The correct answer, must be one of the options")
# Define the structure for a complete quiz
class Quiz(BaseModel):
questions: list[Question] = Field(description="A list of quiz questions")
What do these models do?
Each Question has three fields: the question text, a list of four answer options, and the correct answer. The Quiz model wraps a list of Question objects.
The Field(description=...) values tell the AI what each field represents, so it fills them in correctly. Think of these models as a contract between your code and the AI.
- Save study_buddy.py.
- Confirm the new imports work by running:
python study_buddy.py
- Type any topic when prompted. The output is still plain text for now. The important thing is that the script runs without any import errors.
Seeing an import error?
- Make sure import json is on its own line at the very top of the file, before the from google import genai line.
- Check that from pydantic import BaseModel, Field appears after the google imports. Pydantic was installed automatically with google-genai, so you should not need to install it separately.
- Verify that the class definitions (Question and Quiz) appear below all the import lines but above the client = genai.Client() line.
Still stuck? Help me fix my Pydantic import error in study_buddy.py
Force the AI to return structured JSON
Now you'll put those models to work. Two new configuration options will force the API to return valid JSON matching your Quiz schema instead of free-form text.
- In study_buddy.py, find the config=types.GenerateContentConfig( section.
- Find this closing part of the config:
config=types.GenerateContentConfig(
system_instruction="You are a quiz generator. Create clear, educational multiple-choice questions. Each question must have exactly 4 options labeled A through D. Make the questions test understanding, not just memorization.",
),
- Add response_mime_type and response_json_schema after the system_instruction line, so the config looks like this:
config=types.GenerateContentConfig(
system_instruction="You are a quiz generator. Create clear, educational multiple-choice questions. Each question must have exactly 4 options labeled A through D. Make the questions test understanding, not just memorization.",
response_mime_type="application/json",
response_json_schema=Quiz.model_json_schema(),
),
What do these new settings do?
response_mime_type="application/json" tells the API to return JSON instead of plain text.
response_json_schema=Quiz.model_json_schema() provides the exact JSON structure the API must follow, generated automatically from your Pydantic Quiz model. Together, these two settings guarantee you get back parseable data instead of a wall of text.
Parse the response and display formatted questions
The API now returns JSON, but your script still prints it as raw text. Let's replace that with code that parses the JSON into Python objects and displays each question cleanly.
- In study_buddy.py, find this line at the bottom of your file:
print(response.text)
- Replace it with the following code:
# Parse the JSON response into a Quiz object
quiz = Quiz.model_validate_json(response.text)
# Display each question with numbered format and lettered options
for i, q in enumerate(quiz.questions, 1):
print(f"\nQuestion {i}: {q.question}")
for j, option in enumerate(q.options):
label = chr(65 + j)
print(f" {label}. {option}")
What does this code do?
Quiz.model_validate_json(response.text) takes the raw JSON string from the API and converts it into a Quiz Python object with proper Question objects inside. No manual JSON parsing needed.
The outer loop prints each question with a number. chr(65 + j) converts 0, 1, 2, 3 into the letters A, B, C, D to label each option.
Before you run this, think about what you expect to see. Will the output look different from the plain-text wall you saw in the last step?
- Save study_buddy.py and run it:
python study_buddy.py
- Type a topic when prompted.
You'll see each question on its own numbered line, followed by four neatly labeled options (A through D). Compare this to the unstructured text wall from the last step. Same AI, same topic, but now your code is in full control of the format.
Seeing an error when you run the script?
- If you see a NameError mentioning Quiz, make sure your Quiz class definition appears above the client = genai.Client() line, not below it.
- If you see a validation error from Pydantic, double-check that response_mime_type="application/json" and response_json_schema=Quiz.model_json_schema() are both inside your GenerateContentConfig. Both are required for structured output to work.
- If the script hangs or returns nothing, check that your GEMINI_API_KEY environment variable is still set in this terminal session.
Still stuck? Help me fix my structured output error in study_buddy.py
\u2714\ufe0f Awesome, I've got everything!
Great. Double check that you have saved study_buddy.py and that your output shows cleanly formatted, numbered questions with lettered options.
\u24e7 I'd like to double check the full code
Your study_buddy.py should have four sections built across the chunks above. Scroll up and confirm each is present in this order:
- Imports: import json, from google import genai, from google.genai import types, and from pydantic import BaseModel, Field.
- The Question and Quiz class definitions, before client = genai.Client().
- The generate_content call with response_mime_type and response_json_schema inside the config.
- The parsing and display loop using Quiz.model_validate_json() and the nested for loops at the bottom.
You just solved the messy-text problem. Your quiz questions now come back as clean, structured data that your code can work with. Next up, you'll build an interactive quiz loop so the user can actually answer questions and get scored.
Build the Interactive Quiz Loop
You now have structured quiz data flowing from the Gemini API. Each question arrives as a clean Python object with named fields you can access directly.
But right now, the quiz just prints questions to the screen and exits. There is no way to answer them, no scoring, and no feedback. This step turns your quiz generator into a fully interactive study tool that scores your answers and explains what you got right.
In this step, get ready to:
- Restructure your script into reusable functions.
- Build a run_quiz function that lets users answer questions interactively.
- Add AI-powered scoring that explains why each answer is correct.
Wrap your existing code in a generate_quiz function
Before adding interactivity, your code needs a cleaner structure. Right now, the API call and quiz logic sit as loose statements at the top level of the script. Wrapping them in functions makes the code reusable and sets you up to add the interactive quiz loop.
- In study_buddy.py, select everything from client = genai.Client() all the way to the end of the file.
- Delete all of it. You will replace this inline code with two functions.
- Below the Quiz class, add the following generate_quiz function:
def generate_quiz(client, topic):
# Send a structured-output request and return a Quiz object
response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Generate 3 multiple-choice quiz questions about: {topic}",
config=types.GenerateContentConfig(
system_instruction="You are a quiz generator. Create clear, educational multiple-choice questions. Each question must have exactly 4 options labeled A through D. Make the questions test understanding, not just memorization.",
response_mime_type="application/json",
response_json_schema=Quiz.model_json_schema(),
),
)
return Quiz.model_validate_json(response.text)
What does this function do?
This is the same API call you had before, wrapped in a function that takes client and topic as parameters. It sends the structured-output request to Gemini and returns a fully parsed Quiz object.
Making it a function means you can call generate_quiz(client, topic) from anywhere in your code without duplicating the API logic.
- Below generate_quiz, add a main function that creates the client and kicks off the quiz flow:
def main():
# Create the API client and start the quiz flow
client = genai.Client()
print("=== AI Study Buddy ===")
print("I'll generate quiz questions on any topic you choose!\n")
topic = input("What topic do you want to study? ")
print(f"\nGenerating quiz questions about '{topic}'...")
quiz = generate_quiz(client, topic)
if __name__ == "__main__":
main()
What does this code do?
The main function is the entry point of your script. It creates the genai.Client(), prints a welcome banner, asks the user for a topic, and calls generate_quiz to get the questions.
The if __name__ == "__main__": block at the bottom is a Python convention. It means "only run main() when this file is executed directly, not when it is imported as a module."
- Save study_buddy.py.
- Run your script to confirm the refactor works:
python study_buddy.py
You should see the welcome banner, a prompt asking for a topic, and the "Generating quiz questions" message. The script then exits after generating the quiz, because main does not do anything with the quiz yet.
Seeing a NameError or IndentationError?
- Make sure you deleted all the old inline code from client = genai.Client() to the end of the file. Leftover lines will conflict with the new functions.
- Check that generate_quiz and main are both at the top level of the file (no extra indentation), below the Quiz class.
- Confirm the if __name__ block is at the very bottom of the file with no indentation.
Still stuck? Why is my refactored study_buddy.py throwing an error when I run it?
Build the answer collection loop
Your script generates questions but the user cannot interact with them. The run_quiz function will display each question with lettered options, collect the user's answer, validate it, and track whether it was correct.
- In study_buddy.py, add the following run_quiz function between generate_quiz and main:
def run_quiz(client, quiz):
score = 0
results = []
# Loop through each question in the quiz
for i, q in enumerate(quiz.questions, 1):
print(f"\nQuestion {i}: {q.question}")
for j, option in enumerate(q.options):
label = chr(65 + j)
print(f" {label}. {option}")
answer = input("\nYour answer (A/B/C/D): ").strip().upper()
while answer not in ["A", "B", "C", "D"]:
answer = input("Please enter A, B, C, or D: ").strip().upper()
# Convert letter to option text and check if correct
answer_index = ord(answer) - 65
user_answer = q.options[answer_index] if answer_index < len(q.options) else ""
is_correct = user_answer == q.correct_answer
if is_correct:
score += 1
results.append({
"question": q.question,
"user_answer": user_answer,
"correct_answer": q.correct_answer,
"is_correct": is_correct,
})
print(f"\n--- You got {score}/{len(quiz.questions)} correct! ---")
What does this code do?
- The for loop iterates through each Question object, printing the question text and four options labeled A through D.
- chr(65 + j) converts the index 0, 1, 2, 3 into the letters A, B, C, D (65 is the ASCII code for the letter A).
- The while loop keeps prompting until the user enters a valid letter. This prevents the quiz from crashing on bad input.
- ord(answer) - 65 reverses the conversion, turning the letter back into an index so you can look up the actual option text and compare it to correct_answer.
- Each result is stored in a dictionary with the question, the user's answer, the correct answer, and whether they got it right.
- In your main function, find the line quiz = generate_quiz(client, topic). Add the following code below it:
run_quiz(client, quiz)
print("\nThanks for studying! Keep learning!")
- Save study_buddy.py.
- Run your script to test the interactive quiz:
python study_buddy.py
Type a topic, then answer all 3 questions by typing A, B, C, or D. After you answer the last question, you should see your score printed (for example, "You got 2/3 correct!").
Script crashes when you type an answer?
- Make sure run_quiz is defined between generate_quiz and main. Python reads the file top to bottom, so main must be below the functions it calls.
- Check that the run_quiz(client, quiz) line you added is indented inside main, not at the top level.
Need a hand? My run_quiz function is crashing when I type an answer. Help me figure out what went wrong.
Add AI-powered explanations
Seeing a score is useful, but knowing why each answer is correct turns a quiz into a real learning tool. You will send the results back to the Gemini API and ask it to explain each answer.
- In your run_quiz function, find the line that prints the score:
print(f"\n--- You got {score}/{len(quiz.questions)} correct! ---")
- Add the following code directly below that line, still inside run_quiz:
# Build a summary of all results for the AI to explain
results_text = "\n".join(
f"Q: {r['question']}\nUser answered: {r['user_answer']}\nCorrect answer: {r['correct_answer']}\nWas correct: {r['is_correct']}"
for r in results
)
# Send results to the AI for educational explanations
explanation_response = client.models.generate_content(
model="gemini-2.5-flash",
contents=f"Here are quiz results. For each question, briefly explain why the correct answer is correct.\n\n{results_text}",
config=types.GenerateContentConfig(
system_instruction="You are a helpful tutor. Give brief, clear explanations for each answer. Be encouraging.",
),
)
print("\n--- Explanations ---")
print(explanation_response.text)
return score, len(quiz.questions)
What does this code do?
- results_text joins all the question results into a single formatted string. This gives the AI the full context of what the user answered and what was correct.
- A second generate_content call sends the results to Gemini with a tutor-style system_instruction. The AI reads the results and generates a personalized explanation for each question.
- The function returns score and len(quiz.questions) as a tuple, which you will use in the Secret Mission to track scores across rounds.
- Save study_buddy.py.
Before you run this, think about what you expect to see after answering all 3 questions. Will the output look any different from the last run?
- Run your script one more time:
python study_buddy.py
After answering all 3 questions, you should see your score (for example, "You got 2/3 correct!") followed by an "Explanations" section where the AI walks through each question and explains why the correct answer is correct.
Score prints but no explanations appear?
- Make sure the explanation code is indented inside run_quiz, at the same level as the print(f"\n--- You got... line. If it is outside the function, it will not run.
- Check that you have return score, len(quiz.questions) as the very last line of run_quiz. If it appears before the explanation code, the function exits too early.
Still stuck? My quiz shows the score but the AI explanations are missing. Help me debug why the explanation code is not running.
✔️ Awesome, I've got everything!
Great. Double check you have saved study_buddy.py and that your last run showed both the score and the AI explanations.
ⓧ I'd like to double check the full code
Your study_buddy.py should now contain these sections, in this order. Scroll through your file and confirm each one is present:
- Imports: json, genai, types, BaseModel, Field.
- Question class with question, options, and correct_answer fields.
- Quiz class with a questions list.
- generate_quiz(client, topic) function that sends the structured-output API call and returns a Quiz object.
- run_quiz(client, quiz) function that displays questions, collects answers, prints the score, sends results for AI explanations, and returns score, len(quiz.questions).
- main() function that creates the client, prompts for a topic, calls generate_quiz, then calls run_quiz, then prints the farewell message.
- if __name__ == "__main__": block at the very bottom.
Your AI Study Buddy is fully functional. You can pick any topic, answer quiz questions, and get AI-powered explanations for every answer. That is a complete study loop built entirely from Python and the Gemini API.
Next up is the Secret Mission, where you will add a difficulty selector and track your scores across multiple quiz rounds.
Secret mission
Add Difficulty and Score Tracking
Your quiz works for a single round on one difficulty level. A real study tool would let you adjust difficulty based on your confidence and track your progress across multiple rounds. Ready to add both?
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. The Gemini API free tier has no expiration and requires no credit card.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- study_buddy.py file (local).
- google-genai Python package (installed via pip).
- Gemini API key (stored in Google AI Studio).
Keep everything running
No action needed. Choose this if you plan to keep building on this project or want your API key ready for future experiments.
- Your study_buddy.py file stays on your machine, ready to run anytime.
- Your Gemini API key stays active in Google AI Studio. Store it securely and never commit it to version control.
- The GEMINI_API_KEY environment variable only lasts for your current terminal session. You will need to set it again the next time you open a new terminal.
Pause - I'll come back to this later
There are no running processes to shut down. This project is a script you run manually, so there is nothing to pause.
- Your study_buddy.py file stays on your machine for when you are ready to come back.
- Your API key remains active in Google AI Studio at no cost. No action needed there.
- When you return, open a new terminal and set the GEMINI_API_KEY environment variable again before running the script.
Delete - I don't want to use this again
Remove all project files, the installed package, and your API key to start fresh.
- Delete your project file by running this command in the folder where study_buddy.py is saved:
macOS
rm study_buddy.py
Windows
del study_buddy.py
- Uninstall the google-genai package by running:
pip uninstall google-genai
- Type y when prompted to confirm the uninstall.
- Delete your Gemini API key from Google AI Studio. Open aistudio.google.com in your browser.
- Navigate to the API Keys page, find the key you created for this project, and delete it.
That's a Wrap!
That's a Wrap!
Nice work! You just built a fully interactive AI Study Buddy that generates quiz questions on any topic, scores your answers, and explains the results.
You've learned how to:
- Connected to the Gemini API from Python using the google-genai SDK and made your first LLM API call.
- Engineered prompts with system instructions to control AI behavior, then solved the unstructured text problem with structured JSON output using Pydantic models and response schemas.
- Built a complete interactive quiz loop with AI-powered scoring and explanations that turn wrong answers into learning moments.
- Secret Mission: Added difficulty levels and cumulative score tracking across multiple quiz rounds.
Ready to quiz yourself?