|
import typing |
|
|
|
from django.contrib.postgres import fields |
|
from django.db import models |
|
|
|
|
|
class Quiz(models.Model): |
|
name = models.CharField(max_length=100) |
|
|
|
def __str__(self): |
|
return self.name |
|
|
|
|
|
class Question(models.Model): |
|
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE) |
|
prompt = models.CharField(max_length=200) |
|
|
|
def __str__(self): |
|
return self.prompt |
|
|
|
def get_answer(self) -> typing.Union["Answer", None]: |
|
return ( |
|
getattr(self, "multiplechoiceanswer", None) |
|
or getattr(self, "freetextanswer", None) |
|
or getattr(self, "llmgradedanswer", None) |
|
) |
|
|
|
|
|
class Answer(models.Model): |
|
question = models.OneToOneField(Question, on_delete=models.CASCADE) |
|
correct_answer = models.CharField(max_length=200, default="") |
|
rubrics = models.TextField( |
|
blank=True, null=True, verbose_name="Grading Rubrics - For LLM-graded questions only. You can leave this empty." |
|
) |
|
|
|
class Meta: |
|
abstract = True |
|
|
|
def __str__(self) -> str: |
|
return self.correct_answer or self.rubrics or "No answer or rubrics provided" |
|
|
|
def is_correct(self, user_answer) -> bool: |
|
return user_answer == self.correct_answer |
|
|
|
|
|
class FreeTextAnswer(Answer): |
|
case_sensitive = models.BooleanField(default=False) |
|
|
|
def is_correct(self, user_answer) -> bool: |
|
if not self.case_sensitive: |
|
return user_answer.lower() == self.correct_answer.lower() |
|
return user_answer == self.correct_answer |
|
|
|
|
|
class LLMGradedAnswer(Answer): |
|
def grade(self, user_answer, rubrics) -> dict: |
|
import requests |
|
|
|
""" |
|
Grades the user's answer by calling the grading API. |
|
|
|
Args: |
|
user_answer (str): The answer provided by the user. |
|
rubrics (str): The grading rubrics. |
|
|
|
Returns: |
|
bool: True if the user's answer is correct, False otherwise. |
|
""" |
|
api_url = "http://localhost/api/grade" |
|
payload = {"user_answer": user_answer, "rubrics": rubrics} |
|
|
|
try: |
|
response = requests.post(api_url, json=payload) |
|
response.raise_for_status() |
|
result = response.json() |
|
|
|
|
|
return result |
|
except requests.RequestException as e: |
|
|
|
print(f"An error occurred: {e}") |
|
return {"result": "error", "message": str(e)} |
|
|
|
|
|
class MultipleChoiceAnswer(Answer): |
|
choices = fields.ArrayField(models.CharField(max_length=200, blank=True)) |
|
|
|
def __str__(self) -> str: |
|
return f"{self.correct_answer} from {self.choices}" |
|
|