vikramvasudevan commited on
Commit
75c8d26
·
verified ·
1 Parent(s): 70f23d5

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. modules/quiz/answer_validator.py +19 -15
  2. server.py +87 -8
modules/quiz/answer_validator.py CHANGED
@@ -14,26 +14,30 @@ def validate_answer(
14
  """
15
  print("validating answer ...")
16
  prompt = f"""
17
- You are an answer validator for a scripture-based quiz.
18
 
19
- Question:
20
- {question.question}
21
 
22
- Choices (if any):
23
- {question.choices}
24
 
25
- Expected Answer:
26
- {question.expected_answer}
27
 
28
- User's Answer:
29
- {user_answer}
 
 
 
 
 
 
 
 
 
 
30
 
31
- Rules:
32
- - Compare strictly against expected_answer and choices.
33
- - Accept semantically equivalent answers (e.g., synonyms, transliterations).
34
- - Respond in {question.preferred_language}.
35
- - Do not invent a new correct answer. Only check against expected_answer.
36
- """
37
 
38
  response = client.chat.completions.parse(
39
  model="gpt-5-nano",
 
14
  """
15
  print("validating answer ...")
16
  prompt = f"""
17
+ You are an answer validator for a scripture-based quiz.
18
 
19
+ Question:
20
+ {question.question}
21
 
22
+ Choices (if any):
23
+ {question.choices}
24
 
25
+ Expected Answer:
26
+ {question.expected_answer}
27
 
28
+ User's Answer:
29
+ {user_answer}
30
+
31
+ Rules:
32
+ - Check strictly against the expected answer and choices.
33
+ - Accept semantically equivalent answers (e.g., synonyms, transliterations).
34
+ - Respond in {question.preferred_language}.
35
+ - Address the user directly, e.g., "You nailed it!" or "Not quite, here's why…".
36
+ - Do NOT repeat the user's answer verbatim.
37
+ - Give reasoning concisely, and optionally include the expected answer if user was wrong.
38
+ - Only validate correctness; do not invent new answers.
39
+ """
40
 
 
 
 
 
 
 
41
 
42
  response = client.chat.completions.parse(
43
  model="gpt-5-nano",
server.py CHANGED
@@ -1,6 +1,8 @@
1
  # server.py
2
  import json
 
3
  import traceback
 
4
  import uuid
5
  from fastapi import APIRouter, Request
6
  from fastapi.responses import JSONResponse
@@ -9,6 +11,9 @@ from pydantic import BaseModel
9
  from chat_utils import chat
10
  from config import SanatanConfig
11
  from db import SanatanDatabase
 
 
 
12
 
13
  router = APIRouter()
14
 
@@ -22,6 +27,22 @@ class Message(BaseModel):
22
  text: str
23
  session_id: str | None = None # Optional session ID from client
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  LANG_NATIVE_NAMES = {
26
  "en": "English",
27
  "fr": "Français",
@@ -42,25 +63,45 @@ LANG_NATIVE_NAMES = {
42
  "sat": "ᱥᱟᱱᱛᱟᱲᱤ",
43
  }
44
 
 
45
  @router.get("/languages")
46
  async def handle_fetch_languages():
47
  supported_lang_codes = [
48
- "en","fr","es","hi","bn","te","mr","ta","ur",
49
- "gu","kn","ml","pa","as","mai","sd","sat",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  ]
51
 
52
  languages = []
53
  for code in supported_lang_codes:
54
- lang = pycountry.languages.get(alpha_2=code) or pycountry.languages.get(alpha_3=code)
 
 
55
  if lang is None:
56
  continue # skip unknown codes
57
  english_name = lang.name
58
  native_name = LANG_NATIVE_NAMES.get(code, english_name)
59
- languages.append({
60
- "code": code,
61
- "name": english_name,
62
- "native_name": native_name,
63
- })
 
 
64
 
65
  languages.sort(key=lambda x: x["name"])
66
  return languages
@@ -109,3 +150,41 @@ async def handle_chat(msg: Message, request: Request):
109
  except Exception as e:
110
  traceback.print_exc()
111
  return JSONResponse(status_code=500, content={"reply": f"Error: {e}"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # server.py
2
  import json
3
+ import random
4
  import traceback
5
+ from typing import Optional
6
  import uuid
7
  from fastapi import APIRouter, Request
8
  from fastapi.responses import JSONResponse
 
11
  from chat_utils import chat
12
  from config import SanatanConfig
13
  from db import SanatanDatabase
14
+ from modules.quiz.answer_validator import validate_answer
15
+ from modules.quiz.models import Question
16
+ from modules.quiz.quiz_helper import generate_question
17
 
18
  router = APIRouter()
19
 
 
27
  text: str
28
  session_id: str | None = None # Optional session ID from client
29
 
30
+
31
+ class QuizGeneratePayload(BaseModel):
32
+ language: Optional[str] = "English"
33
+ scripture: Optional[str] = None
34
+ complexity: Optional[str] = None
35
+ mode: Optional[str] = None
36
+ session_id: Optional[str] = None # Optional session ID from client
37
+
38
+
39
+ class QuizEvalPayload(BaseModel):
40
+ language: Optional[str] = "English"
41
+ q: Question
42
+ answer: str
43
+ session_id: Optional[str] = None # Optional session ID from client
44
+
45
+
46
  LANG_NATIVE_NAMES = {
47
  "en": "English",
48
  "fr": "Français",
 
63
  "sat": "ᱥᱟᱱᱛᱟᱲᱤ",
64
  }
65
 
66
+
67
  @router.get("/languages")
68
  async def handle_fetch_languages():
69
  supported_lang_codes = [
70
+ "en",
71
+ "fr",
72
+ "es",
73
+ "hi",
74
+ "bn",
75
+ "te",
76
+ "mr",
77
+ "ta",
78
+ "ur",
79
+ "gu",
80
+ "kn",
81
+ "ml",
82
+ "pa",
83
+ "as",
84
+ "mai",
85
+ "sd",
86
+ "sat",
87
  ]
88
 
89
  languages = []
90
  for code in supported_lang_codes:
91
+ lang = pycountry.languages.get(alpha_2=code) or pycountry.languages.get(
92
+ alpha_3=code
93
+ )
94
  if lang is None:
95
  continue # skip unknown codes
96
  english_name = lang.name
97
  native_name = LANG_NATIVE_NAMES.get(code, english_name)
98
+ languages.append(
99
+ {
100
+ "code": code,
101
+ "name": english_name,
102
+ "native_name": native_name,
103
+ }
104
+ )
105
 
106
  languages.sort(key=lambda x: x["name"])
107
  return languages
 
150
  except Exception as e:
151
  traceback.print_exc()
152
  return JSONResponse(status_code=500, content={"reply": f"Error: {e}"})
153
+
154
+
155
+ @router.post("/quiz/generate")
156
+ async def handle_quiz_generate(payload: QuizGeneratePayload, request: Request):
157
+ q = generate_question(
158
+ collection=payload.scripture
159
+ or random.choice(
160
+ [
161
+ s["collection_name"]
162
+ for s in SanatanConfig.scriptures
163
+ if s["collection_name"] != "yt_metadata"
164
+ ]
165
+ ),
166
+ complexity=payload.complexity
167
+ or random.choice(["beginner", "intermediate", "advanced"]),
168
+ mode=payload.mode or random.choice(["mcq", "open"]),
169
+ preferred_lamguage=payload.language or "English",
170
+ )
171
+ print(q.model_dump_json(indent=1))
172
+ return q.model_dump()
173
+
174
+
175
+ @router.post("/quiz/eval")
176
+ async def handle_quiz_eval(payload: QuizEvalPayload, request: Request):
177
+ result = validate_answer(
178
+ payload.q, payload.answer, preferred_language=payload.language or "English"
179
+ )
180
+ return result
181
+
182
+ @router.get("/scriptures")
183
+ async def handle_get_scriptures():
184
+ return_values = {}
185
+ for scripture in SanatanConfig().scriptures:
186
+ num_units = SanatanDatabase().count(
187
+ collection_name=scripture["collection_name"]
188
+ )
189
+ return_values[scripture['title']] = scripture['collection_name']
190
+ return return_values