Build an AI Quiz Generator with OpenAI: Step-by-Step Tutorial Part 2
Brief recap of Part 1
In the first part of this tutorial series, we created the foundation of an AI-powered Quiz Generator using OpenAI and Next.js. Here’s what we accomplished:
- The Project set up with Next.js and essential libraries like OpenAI API, DaisyUI, and react-hot-toast for notifications.
- Educator interface allowing users to upload PDF content.
- File upload handling that stores files on OpenAI’s platform.
- Prompt engineering to generate multiple-choice quiz questions in a structured JSON format based on uploaded content.
- Dynamic quiz rendering for students, displaying generated questions and options interactively.
This setup allows educators to upload documents and automatically generate quizzes, while students can view and select answers for the generated questions.
What We’re Building in Part 2
Now that we have the quiz questions generated and displayed, it’s time to close the learning loop by adding:
- Interactive User Feedback: Immediate, personalized feedback after students select their answers to help reinforce learning and clarify misunderstandings.
- Automated Grading: Real-time scoring of student responses with a clear grade summary at the end of the quiz.
Interactive feedback
To implement this feature, we add an event listener to each question. When the user picks an answer, we provide the question, the correct answer, and the Content source, which is our file in the OpenAI storage, and ask LLM to provide feedback for the user to show it in the UI. The Feedback should be in Markdown format.
Pass the file ID
Let's pass the file ID down from the Dashboard to the Quizzes component so we can use it in the LLM prompt.
In the Dashboard.tsx
, where you render the Quizzes, add fileId as props
In the Quizzes.tsx
make sure you are getting that prop
Implementing the Event Listener
What we want to do here is, when a user clicks on a choice, we grab the question, the correct answer, and the user's answer.
Open the Quizzes.tsx
file and add an event handler to the Quizzes component like the following
For each Input radio add this event handler, onChange
Your file should look like the following
Now, when you interact with a question, you should see userAnswer printed in the browser console:
Feedback API Endpoint
We are going to create an endpoint that receives userAnswer
via a POST call and passes it to the LLM to get feedback. In the api
directory, create a new folder called feedback
and create a route.tsx
file in it.
We create a simple POST API that checks if we are receiving all the necessary data, and when all checks pass, we return feedback to the UI. We will implement the util function next, so we can provide real feedback.
Let's change our Quizzes component
- Converting it to a client component so it can save all the answers with their feedback in the component state
- Instead of printing the
userAnswer
Make a POST call to the endpoint and send the userAnswer
- Upsert
userAnswer
for that question, with the feedback LLM generates for us - Make the
handleOptionChange
async function so it can handle the fetch call - Make the message green if the answer is correct and orange if the answer is incorrect
- Parse feedback Markdown
Let's first install the Markdown parser libraries we need npm i react-markdown remark-gfm
Now open the Quizzes.tsx and change its content to the following
Generate LLM feedback
In the utils directory, create a new file called feedback.tsx
to
- Pass the user's answer and file ID to it
- Create a prompt and ask to generate feedback for the answer.
- Return the feedback in markdown format
Now let's change our feedback route to return the LLM feedback instead of hardcoded text
Grading
For this section, we are not going to use AI for grading since we have multiple-choice questions, and we know the correct answer and the user's response. Let's define 3 as the total score for our question, and when the user clicks on submit, we show a modal with a breakdown of the grade per question and total score. Open the Quizzes.tsx
file and change it to the following to show a modal when the user clicks on the submit button. This modal shows the total grade and breakdown of each question's score in the table
With the interactive feedback and grading system now in place, your AI Quiz Generator has become a much more engaging and effective learning tool. Students receive immediate, personalized insights on their answers, and the grading breakdown helps them understand their overall performance clearly.
However, there are still areas we can improve to enhance the user experience further. For example, the current feedback generation depends on calls to the language model, which can introduce some latency, meaning students might wait a bit before seeing their feedback. Also, managing multiple attempts or allowing users to reset their answers and try again will make the quiz more flexible and learner-friendly.
Conclusion
Congratulations! 🎉 In this second part of our tutorial, you successfully implemented:
- Interactive user feedback powered by OpenAI’s language model, providing helpful, encouraging responses based on student answers.
- Real-time grading with a clear breakdown of scores per question and total quiz score.
- A dynamic UI that updates feedback instantly and visually distinguishes correct and incorrect answers.
These features significantly improve the learning experience by closing the feedback loop and motivating students to engage deeply with the material.
You can find the Github Repo here
What’s Next?
In the upcoming Part 3, we’ll focus on:
- Reducing feedback latency using streaming.
- Adding a reset button and answering logic to allow students multiple attempts.