Teddy Xinyuan Chen commited on
Commit
07bbfbd
Β·
1 Parent(s): c02439d

2024-10-08T17-12-41Z

Browse files
.gitignore CHANGED
@@ -7,3 +7,4 @@ staticfiles/
7
  pytest.xml
8
  pytest-coverage.txt
9
  coverage.xml
 
 
7
  pytest.xml
8
  pytest-coverage.txt
9
  coverage.xml
10
+ .vercel
src/quizzes/admin.py CHANGED
@@ -1,6 +1,6 @@
1
  from django.contrib import admin
2
 
3
- from .models import FreeTextAnswer, MultipleChoiceAnswer, Question, Quiz
4
 
5
  admin.site.register(Quiz)
6
 
@@ -13,8 +13,12 @@ class MultipleChoiceAnswerInline(admin.StackedInline):
13
  model = MultipleChoiceAnswer
14
 
15
 
 
 
 
 
16
  class QuestionAdmin(admin.ModelAdmin):
17
- inlines = [FreeTextAnswerInline, MultipleChoiceAnswerInline]
18
 
19
 
20
  admin.site.register(Question, QuestionAdmin)
 
1
  from django.contrib import admin
2
 
3
+ from .models import FreeTextAnswer, MultipleChoiceAnswer, Question, Quiz, LLMGradedAnswer
4
 
5
  admin.site.register(Quiz)
6
 
 
13
  model = MultipleChoiceAnswer
14
 
15
 
16
+ class LLMGradedAnswerInline(admin.StackedInline):
17
+ model = LLMGradedAnswer
18
+
19
+
20
  class QuestionAdmin(admin.ModelAdmin):
21
+ inlines = [FreeTextAnswerInline, MultipleChoiceAnswerInline, LLMGradedAnswerInline]
22
 
23
 
24
  admin.site.register(Question, QuestionAdmin)
src/quizzes/models.py CHANGED
@@ -19,18 +19,25 @@ class Question(models.Model):
19
  return self.prompt
20
 
21
  def get_answer(self) -> typing.Union["Answer", None]:
22
- return getattr(self, "multiplechoiceanswer", None) or getattr(self, "freetextanswer", None)
 
 
 
 
23
 
24
 
25
  class Answer(models.Model):
26
  question = models.OneToOneField(Question, on_delete=models.CASCADE)
27
- correct_answer = models.CharField(max_length=200)
 
 
 
28
 
29
  class Meta:
30
  abstract = True
31
 
32
  def __str__(self) -> str:
33
- return self.correct_answer
34
 
35
  def is_correct(self, user_answer) -> bool:
36
  return user_answer == self.correct_answer
@@ -45,6 +52,36 @@ class FreeTextAnswer(Answer):
45
  return user_answer == self.correct_answer
46
 
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  class MultipleChoiceAnswer(Answer):
49
  choices = fields.ArrayField(models.CharField(max_length=200, blank=True))
50
 
 
19
  return self.prompt
20
 
21
  def get_answer(self) -> typing.Union["Answer", None]:
22
+ return (
23
+ getattr(self, "multiplechoiceanswer", None)
24
+ or getattr(self, "freetextanswer", None)
25
+ or getattr(self, "llmgradedanswer", None)
26
+ )
27
 
28
 
29
  class Answer(models.Model):
30
  question = models.OneToOneField(Question, on_delete=models.CASCADE)
31
+ correct_answer = models.CharField(max_length=200, default="")
32
+ rubrics = models.TextField(
33
+ blank=True, null=True, verbose_name="Grading Rubrics - For LLM-graded questions only. You can leave this empty."
34
+ )
35
 
36
  class Meta:
37
  abstract = True
38
 
39
  def __str__(self) -> str:
40
+ return self.correct_answer or self.rubrics or "No answer or rubrics provided"
41
 
42
  def is_correct(self, user_answer) -> bool:
43
  return user_answer == self.correct_answer
 
52
  return user_answer == self.correct_answer
53
 
54
 
55
+ class LLMGradedAnswer(Answer):
56
+ def grade(self, user_answer, rubrics) -> dict:
57
+ import requests
58
+
59
+ """
60
+ Grades the user's answer by calling the grading API.
61
+
62
+ Args:
63
+ user_answer (str): The answer provided by the user.
64
+ rubrics (str): The grading rubrics.
65
+
66
+ Returns:
67
+ bool: True if the user's answer is correct, False otherwise.
68
+ """
69
+ api_url = "http://localhost/api/grade"
70
+ payload = {"user_answer": user_answer, "rubrics": rubrics}
71
+
72
+ try:
73
+ response = requests.post(api_url, json=payload)
74
+ response.raise_for_status() # Raise an error for bad status codes
75
+ result = response.json()
76
+
77
+ # Assuming the API returns a JSON object with a 'correct' field
78
+ return result
79
+ except requests.RequestException as e:
80
+ # Handle any errors that occur during the request
81
+ print(f"An error occurred: {e}")
82
+ return {"result": "error", "message": str(e)}
83
+
84
+
85
  class MultipleChoiceAnswer(Answer):
86
  choices = fields.ArrayField(models.CharField(max_length=200, blank=True))
87
 
src/quizzes/templates/quizzes/partial.html CHANGED
@@ -6,6 +6,14 @@
6
 
7
  {% if is_correct %}
8
  βœ… You got it!
 
 
 
 
 
 
 
 
9
  {% else %}
10
  ❌ Sorry! The correct answer is {{ correct_answer }}
11
  {% endif %}
 
6
 
7
  {% if is_correct %}
8
  βœ… You got it!
9
+ {% elif llm_answer %}
10
+ βœ… LLM's results based on rubrics:
11
+
12
+ {{ correct_answer|markdown }}
13
+
14
+ <br/>
15
+
16
+ The rubrics: {{ rubrics }}
17
  {% else %}
18
  ❌ Sorry! The correct answer is {{ correct_answer }}
19
  {% endif %}
src/requirements.txt CHANGED
@@ -1,3 +1,4 @@
 
1
  Django==4.2.7
2
  psycopg2==2.9.9
3
  python-dotenv==1.0.1
 
1
+ requests
2
  Django==4.2.7
3
  psycopg2==2.9.9
4
  python-dotenv==1.0.1