Quiz 생성 LLM API 제작

TIL Day 103

By polaris0208

LLM을 이용하여 퀴즈를 생성하는 API 제작

의존성

import json
from . import llm
from .models import *
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response

퀴즈 생성 API

  • Post 요청으로 퀴즈에 대한 설정값을 보내면 LLM으로 부터 결과를 받음
    • 퀴즈 개요 - 문제 - 선택지 구조로 나눠 DB에 저장
class QuizRequestView(APIView):
    def post(self, request):
        response = chain.invoke(request.data)
        response_dict = json.loads(response)
        quiz = Quiz.objects.create(
            title=response_dict["title"],
            description=response_dict["description"],
        )
        for question_data in response_dict["questions"]:
            question = Question.objects.create(
                quiz=quiz,
                number=question_data["id"],
                content=question_data["content"],
                answer_type=question_data["answer_type"],
            )
            for choice_data in question_data["choices"]:
                Choice.objects.create(
                    question=question,
                    number=choice_data["id"],
                    content=choice_data["content"],
                    is_correct=choice_data["is_correct"],
                )
        return Response(
            {"detail": "문제가 생성되었습니다."},
            status=status.HTTP_200_OK,
        )

퀴즈 API

  • class QuizAPIView(APIView):

조회

  • 생성된 퀴즈를 조회
    def get(self, request, quiz_id):
        try:
            quiz = Quiz.objects.prefetch_related("questions__choices").get(id=quiz_id)
            questions = [
                {
                    "number": question.number,
                    "content": question.content,
                    "answer_type": question.answer_type,
                    "choices": [
                        {"number": choice.number, "content": choice.content}
                        for choice in question.choices.all()
                    ],
                }
                for question in quiz.questions.all()
            ]
            return Response(
                {
                    "id": quiz.id,
                    "title": quiz.title,
                    "questions": questions,
                },
                status=status.HTTP_200_OK,
            )
        except Quiz.DoesNotExist:
            return Response(
                {"error": "Quiz not found"}, status=status.HTTP_404_NOT_FOUND
            )

답안 제출/채점

  • 답안 제출
    • 문제 번호 - 선택지 번호 제출
  • 채점
    • 선택지 데이터의 is_correct 옵션을 확인하여 채점
  • 결과
    • 전체 문제 중 맞힌 문제의 개수를 계산하여 점수 출력
    def post(self, request, quiz_id):
        try:
            quiz = Quiz.objects.get(id=quiz_id)
            answers = request.data.get("answers", [])
            total_questions = quiz.questions.count()
            correct_answers = 0
            details = []

            for answer in answers:
                question_number = answer.get("q_number")
                choice_number = answer.get("c_number")
                question = Question.objects.get(number=question_number, quiz=quiz)
                selected_choice = Choice.objects.get(
                    number=choice_number, question=question
                )

                is_correct = selected_choice.is_correct
                if is_correct:
                    correct_answers += 1

                details.append(
                    {"question_number": question_number, "is_correct": is_correct}
                )
            score = (correct_answers / total_questions) * 100
            report = {
                "quiz_id": quiz.id,
                "correct_answers": correct_answers,
                "total_questions": total_questions,
                "score": score,
                "details": details,
            }

            quiz_result = QuizResult.objects.create(
                title=quiz.title,
                description=quiz.description,
                result=report.pop("details", None),
            )

결과 저장

  • 채점 결과 / 문제 내용-제출한 답안 저장
            for answer in answers:
                question_number = answer.get("q_number")
                choice_number = answer.get("c_number")
                question = Question.objects.get(number=question_number, quiz=quiz)
                selected_choice = Choice.objects.get(
                    number=choice_number, question=question
                )
                questions_json = {
                    "id": question.id,
                    "number": question.number,
                    "content": question.content,
                    "answer_type": question.answer_type,
                    "quiz": question.quiz_id,
                }
                choice_json = {
                    "id": selected_choice.id,
                    "number": selected_choice.number,
                    "content": selected_choice.content,
                    "is_correct": selected_choice.is_correct,
                    "question": selected_choice.question_id,
                }
                QuizResultQuestion.objects.create(
                    quiz_result=quiz_result,
                    question=questions_json,
                    answer=choice_json,
                )
                
            return Response(
                report,
                status=status.HTTP_200_OK,
            )
        except (Quiz.DoesNotExist, Question.DoesNotExist, Choice.DoesNotExist):
            return Response(
                {"error": "Invalid data provided"}, status=status.HTTP_400_BAD_REQUEST
            )

퀴즈 삭제

  • 결과만 저장하고 DB부담을 줄이기 위해 퀴즈는 삭제
    def delete(self, request, quiz_id):
        quiz = Quiz.objects.get(id=quiz_id)
        quiz.delete()
        return Response(
            {"detail": "삭제되었습니다."},
            status=status.HTTP_204_NO_CONTENT,
        )
Tags: TIL LLM Tools