Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -212,15 +212,71 @@
|
|
| 212 |
|
| 213 |
# return "\n\n".join(results)
|
| 214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 215 |
# # ------------------------------
|
| 216 |
# # Chapter Detection (Using Actual Chapter Names)
|
| 217 |
# # ------------------------------
|
| 218 |
# def detect_chapter_from_list(context, topic, subject):
|
| 219 |
# """
|
| 220 |
# Detect chapter using the actual chapter list by matching keywords
|
|
|
|
| 221 |
# """
|
| 222 |
# if subject not in CHAPTER_NAMES:
|
| 223 |
-
# return
|
| 224 |
|
| 225 |
# chapters = CHAPTER_NAMES[subject]
|
| 226 |
# combined_text = (topic + " " + context[:1000]).lower()
|
|
@@ -258,32 +314,35 @@
|
|
| 258 |
# def detect_chapter_with_llm(context, topic, subject, chapters):
|
| 259 |
# """
|
| 260 |
# Use LLM to pick the correct chapter from the provided list
|
|
|
|
| 261 |
# """
|
| 262 |
# if not groq_client:
|
| 263 |
-
# return
|
| 264 |
|
| 265 |
# chapter_list = "\n".join([f"{i+1}. {ch}" for i, ch in enumerate(chapters)])
|
| 266 |
|
| 267 |
-
# detection_prompt = f"""Based on the following textbook content and topic, identify which chapter from the
|
| 268 |
|
| 269 |
# Topic: {topic}
|
| 270 |
|
| 271 |
# Content snippet:
|
| 272 |
# {context[:600]}
|
| 273 |
|
| 274 |
-
# Available chapters:
|
| 275 |
# {chapter_list}
|
| 276 |
|
| 277 |
-
#
|
|
|
|
|
|
|
| 278 |
|
| 279 |
-
#
|
| 280 |
|
| 281 |
# try:
|
| 282 |
# response = groq_client.chat.completions.create(
|
| 283 |
# messages=[
|
| 284 |
# {
|
| 285 |
# "role": "system",
|
| 286 |
-
# "content": "You are an expert at identifying which chapter textbook content belongs to.
|
| 287 |
# },
|
| 288 |
# {
|
| 289 |
# "role": "user",
|
|
@@ -297,6 +356,11 @@
|
|
| 297 |
|
| 298 |
# result = response.choices[0].message.content.strip()
|
| 299 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 300 |
# # Extract chapter name from response (remove number prefix if present)
|
| 301 |
# chapter = re.sub(r'^\d+\.\s*', '', result).strip()
|
| 302 |
|
|
@@ -307,11 +371,11 @@
|
|
| 307 |
# return ch
|
| 308 |
|
| 309 |
# print(f"β οΈ LLM response not in list: {result}")
|
| 310 |
-
# return
|
| 311 |
|
| 312 |
# except Exception as e:
|
| 313 |
# print(f"β οΈ Chapter detection failed: {e}")
|
| 314 |
-
# return
|
| 315 |
|
| 316 |
# # ------------------------------
|
| 317 |
# # MCQ Generation
|
|
@@ -325,7 +389,7 @@
|
|
| 325 |
# 2. API key is valid (get one from https://console.groq.com/keys)
|
| 326 |
# 3. Space has been restarted after adding the key
|
| 327 |
# Current status: API key not found or invalid."""
|
| 328 |
-
# return error_msg,
|
| 329 |
|
| 330 |
# # Check cache
|
| 331 |
# context_hash = hashlib.md5(context.encode()).hexdigest()[:8]
|
|
@@ -340,6 +404,12 @@
|
|
| 340 |
# # Detect the chapter from our actual chapter list
|
| 341 |
# chapter = detect_chapter_from_list(context, topic, subject)
|
| 342 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
# prompt = f"""You are a Class-12 {subject.title()} teacher creating MCQs.
|
| 344 |
# Topic: "{topic}"
|
| 345 |
# Chapter: "{chapter}"
|
|
@@ -723,8 +793,22 @@
|
|
| 723 |
# if subject not in SUBJECTS:
|
| 724 |
# return jsonify({"error": "Invalid subject"}), 400
|
| 725 |
|
| 726 |
-
# print(f"\nπ
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 727 |
|
|
|
|
| 728 |
# context = rag_search(topic, subject, k=5)
|
| 729 |
|
| 730 |
# if not context or len(context.strip()) < 50:
|
|
@@ -732,8 +816,13 @@
|
|
| 732 |
|
| 733 |
# print(f"β Context found ({len(context)} chars)")
|
| 734 |
|
|
|
|
| 735 |
# mcqs, chapter = generate_mcqs(context, topic, subject)
|
| 736 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 737 |
# return jsonify({
|
| 738 |
# "mcqs": mcqs,
|
| 739 |
# "subject": subject,
|
|
@@ -761,7 +850,6 @@
|
|
| 761 |
# port = int(os.environ.get("PORT", 7860))
|
| 762 |
# print(f"\nπ Starting server on port {port}...\n")
|
| 763 |
# app.run(host="0.0.0.0", port=port, debug=False)
|
| 764 |
-
|
| 765 |
import pickle
|
| 766 |
import faiss
|
| 767 |
from flask import Flask, request, jsonify, render_template_string
|
|
@@ -1144,7 +1232,7 @@ Response:"""
|
|
| 1144 |
# ------------------------------
|
| 1145 |
# MCQ Generation
|
| 1146 |
# ------------------------------
|
| 1147 |
-
def generate_mcqs(context, topic, subject):
|
| 1148 |
# Check if Groq is available
|
| 1149 |
if not groq_client:
|
| 1150 |
error_msg = """ERROR: Groq API not initialized!
|
|
@@ -1157,13 +1245,13 @@ Current status: API key not found or invalid."""
|
|
| 1157 |
|
| 1158 |
# Check cache
|
| 1159 |
context_hash = hashlib.md5(context.encode()).hexdigest()[:8]
|
| 1160 |
-
cache_key = get_cache_key(topic, subject, context_hash)
|
| 1161 |
|
| 1162 |
if cache_key in MCQ_CACHE:
|
| 1163 |
print("β Using cached MCQs")
|
| 1164 |
return MCQ_CACHE[cache_key]["mcqs"], MCQ_CACHE[cache_key]["chapter"]
|
| 1165 |
|
| 1166 |
-
print(f"π€ Generating MCQs for {subject} - {topic}")
|
| 1167 |
|
| 1168 |
# Detect the chapter from our actual chapter list
|
| 1169 |
chapter = detect_chapter_from_list(context, topic, subject)
|
|
@@ -1180,7 +1268,7 @@ Chapter: "{chapter}"
|
|
| 1180 |
Reference material from textbook:
|
| 1181 |
{context[:1500]}
|
| 1182 |
|
| 1183 |
-
Generate exactly
|
| 1184 |
|
| 1185 |
FORMAT (follow EXACTLY):
|
| 1186 |
Q1. [Question based on material]
|
|
@@ -1197,7 +1285,7 @@ C) [Option 3]
|
|
| 1197 |
D) [Option 4]
|
| 1198 |
Answer: [A/B/C/D] - [Brief explanation]
|
| 1199 |
|
| 1200 |
-
Continue for Q3, Q4, Q5.
|
| 1201 |
|
| 1202 |
REQUIREMENTS:
|
| 1203 |
- All questions must be answerable from the reference material
|
|
@@ -1205,9 +1293,12 @@ REQUIREMENTS:
|
|
| 1205 |
- Correct answer must be clearly supported by material
|
| 1206 |
- Keep explanations brief (1-2 sentences)
|
| 1207 |
|
| 1208 |
-
Generate
|
| 1209 |
|
| 1210 |
try:
|
|
|
|
|
|
|
|
|
|
| 1211 |
chat_completion = groq_client.chat.completions.create(
|
| 1212 |
messages=[
|
| 1213 |
{
|
|
@@ -1221,7 +1312,7 @@ Generate 5 MCQs now:"""
|
|
| 1221 |
],
|
| 1222 |
model="llama-3.3-70b-versatile",
|
| 1223 |
temperature=0.3,
|
| 1224 |
-
max_tokens=
|
| 1225 |
top_p=0.9
|
| 1226 |
)
|
| 1227 |
|
|
@@ -1449,7 +1540,33 @@ HTML_TEMPLATE = """
|
|
| 1449 |
<input type="text" id="topic" placeholder="e.g., Mitochondria, Chemical Bonding, Newton's Laws">
|
| 1450 |
</div>
|
| 1451 |
|
| 1452 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1453 |
|
| 1454 |
<div class="loading" id="loading">
|
| 1455 |
<div class="spinner"></div>
|
|
@@ -1479,6 +1596,7 @@ HTML_TEMPLATE = """
|
|
| 1479 |
async function generateMCQs() {
|
| 1480 |
const subject = document.getElementById('subject').value;
|
| 1481 |
const topic = document.getElementById('topic').value.trim();
|
|
|
|
| 1482 |
|
| 1483 |
if (!topic) {
|
| 1484 |
alert('β οΈ Please enter a topic!');
|
|
@@ -1500,7 +1618,7 @@ HTML_TEMPLATE = """
|
|
| 1500 |
const response = await fetch('/generate', {
|
| 1501 |
method: 'POST',
|
| 1502 |
headers: {'Content-Type': 'application/json'},
|
| 1503 |
-
body: JSON.stringify({subject, topic})
|
| 1504 |
});
|
| 1505 |
|
| 1506 |
const data = await response.json();
|
|
@@ -1523,7 +1641,7 @@ HTML_TEMPLATE = """
|
|
| 1523 |
} finally {
|
| 1524 |
loading.classList.remove('show');
|
| 1525 |
btn.disabled = false;
|
| 1526 |
-
btn.textContent = 'π Generate
|
| 1527 |
}
|
| 1528 |
}
|
| 1529 |
|
|
@@ -1550,6 +1668,15 @@ def generate():
|
|
| 1550 |
data = request.json
|
| 1551 |
subject = data.get("subject", "").lower()
|
| 1552 |
topic = data.get("topic", "")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1553 |
|
| 1554 |
if not topic:
|
| 1555 |
return jsonify({"error": "Topic is required"}), 400
|
|
@@ -1581,7 +1708,7 @@ def generate():
|
|
| 1581 |
print(f"β Context found ({len(context)} chars)")
|
| 1582 |
|
| 1583 |
# STEP 3: Generate MCQs
|
| 1584 |
-
mcqs, chapter = generate_mcqs(context, topic, subject)
|
| 1585 |
|
| 1586 |
# Check if there was a subject mismatch
|
| 1587 |
if chapter is None:
|
|
|
|
| 212 |
|
| 213 |
# return "\n\n".join(results)
|
| 214 |
|
| 215 |
+
# # ------------------------------
|
| 216 |
+
# # Topic Validation (Check if topic belongs to subject)
|
| 217 |
+
# # ------------------------------
|
| 218 |
+
# def validate_topic_subject(topic, subject):
|
| 219 |
+
# """
|
| 220 |
+
# Validate if the topic belongs to the selected subject using LLM
|
| 221 |
+
# Returns True if valid, False otherwise
|
| 222 |
+
# """
|
| 223 |
+
# if not groq_client:
|
| 224 |
+
# return True # Skip validation if API not available
|
| 225 |
+
|
| 226 |
+
# validation_prompt = f"""You are a Class 12 PCB subject expert. Determine if the following topic belongs to {subject.title()}.
|
| 227 |
+
|
| 228 |
+
# Topic: "{topic}"
|
| 229 |
+
# Subject: {subject.title()}
|
| 230 |
+
|
| 231 |
+
# Class 12 {subject.title()} covers:
|
| 232 |
+
# {"- Reproduction, Genetics, Evolution, Plant Physiology, Human Systems, Ecology, Biotechnology" if subject == "biology" else ""}
|
| 233 |
+
# {"- Solid State, Solutions, Thermodynamics, Electrochemistry, Organic Chemistry, Coordination Compounds" if subject == "chemistry" else ""}
|
| 234 |
+
# {"- Rotational Dynamics, Fluids, Thermodynamics, Waves, Optics, Electromagnetism, Modern Physics, Semiconductors" if subject == "physics" else ""}
|
| 235 |
+
|
| 236 |
+
# Answer ONLY with "YES" if the topic belongs to {subject.title()}, or "NO" if it belongs to a different subject.
|
| 237 |
+
|
| 238 |
+
# Answer:"""
|
| 239 |
+
|
| 240 |
+
# try:
|
| 241 |
+
# response = groq_client.chat.completions.create(
|
| 242 |
+
# messages=[
|
| 243 |
+
# {
|
| 244 |
+
# "role": "system",
|
| 245 |
+
# "content": f"You are an expert at identifying which subject a topic belongs to. Answer only YES or NO."
|
| 246 |
+
# },
|
| 247 |
+
# {
|
| 248 |
+
# "role": "user",
|
| 249 |
+
# "content": validation_prompt
|
| 250 |
+
# }
|
| 251 |
+
# ],
|
| 252 |
+
# model="llama-3.3-70b-versatile",
|
| 253 |
+
# temperature=0.1,
|
| 254 |
+
# max_tokens=10
|
| 255 |
+
# )
|
| 256 |
+
|
| 257 |
+
# result = response.choices[0].message.content.strip().upper()
|
| 258 |
+
|
| 259 |
+
# if "YES" in result:
|
| 260 |
+
# print(f"β Topic '{topic}' validated for {subject}")
|
| 261 |
+
# return True
|
| 262 |
+
# else:
|
| 263 |
+
# print(f"β Topic '{topic}' does NOT belong to {subject}")
|
| 264 |
+
# return False
|
| 265 |
+
|
| 266 |
+
# except Exception as e:
|
| 267 |
+
# print(f"β οΈ Validation failed: {e}")
|
| 268 |
+
# return True # Allow on error to avoid blocking
|
| 269 |
+
|
| 270 |
# # ------------------------------
|
| 271 |
# # Chapter Detection (Using Actual Chapter Names)
|
| 272 |
# # ------------------------------
|
| 273 |
# def detect_chapter_from_list(context, topic, subject):
|
| 274 |
# """
|
| 275 |
# Detect chapter using the actual chapter list by matching keywords
|
| 276 |
+
# Returns None if topic doesn't match the subject
|
| 277 |
# """
|
| 278 |
# if subject not in CHAPTER_NAMES:
|
| 279 |
+
# return None
|
| 280 |
|
| 281 |
# chapters = CHAPTER_NAMES[subject]
|
| 282 |
# combined_text = (topic + " " + context[:1000]).lower()
|
|
|
|
| 314 |
# def detect_chapter_with_llm(context, topic, subject, chapters):
|
| 315 |
# """
|
| 316 |
# Use LLM to pick the correct chapter from the provided list
|
| 317 |
+
# Also verifies if the topic belongs to the subject
|
| 318 |
# """
|
| 319 |
# if not groq_client:
|
| 320 |
+
# return None
|
| 321 |
|
| 322 |
# chapter_list = "\n".join([f"{i+1}. {ch}" for i, ch in enumerate(chapters)])
|
| 323 |
|
| 324 |
+
# detection_prompt = f"""Based on the following textbook content and topic, identify which chapter from the Class 12 {subject.title()} textbook this content belongs to.
|
| 325 |
|
| 326 |
# Topic: {topic}
|
| 327 |
|
| 328 |
# Content snippet:
|
| 329 |
# {context[:600]}
|
| 330 |
|
| 331 |
+
# Available {subject.title()} chapters:
|
| 332 |
# {chapter_list}
|
| 333 |
|
| 334 |
+
# IMPORTANT: If the topic and content do NOT belong to {subject.title()}, respond with "NOT_MATCHING".
|
| 335 |
+
|
| 336 |
+
# If it matches, respond with ONLY the chapter number and name exactly as listed (e.g., "5. Origin and Evolution of Life").
|
| 337 |
|
| 338 |
+
# Response:"""
|
| 339 |
|
| 340 |
# try:
|
| 341 |
# response = groq_client.chat.completions.create(
|
| 342 |
# messages=[
|
| 343 |
# {
|
| 344 |
# "role": "system",
|
| 345 |
+
# "content": f"You are an expert at identifying which chapter textbook content belongs to. You can recognize when content doesn't match the subject. If the topic is from a different subject than {subject.title()}, respond with 'NOT_MATCHING'."
|
| 346 |
# },
|
| 347 |
# {
|
| 348 |
# "role": "user",
|
|
|
|
| 356 |
|
| 357 |
# result = response.choices[0].message.content.strip()
|
| 358 |
|
| 359 |
+
# # Check if topic doesn't match the subject
|
| 360 |
+
# if "NOT_MATCHING" in result.upper() or "NOT MATCHING" in result.upper():
|
| 361 |
+
# print(f"β οΈ Topic '{topic}' doesn't belong to {subject}")
|
| 362 |
+
# return None
|
| 363 |
+
|
| 364 |
# # Extract chapter name from response (remove number prefix if present)
|
| 365 |
# chapter = re.sub(r'^\d+\.\s*', '', result).strip()
|
| 366 |
|
|
|
|
| 371 |
# return ch
|
| 372 |
|
| 373 |
# print(f"β οΈ LLM response not in list: {result}")
|
| 374 |
+
# return None
|
| 375 |
|
| 376 |
# except Exception as e:
|
| 377 |
# print(f"β οΈ Chapter detection failed: {e}")
|
| 378 |
+
# return None
|
| 379 |
|
| 380 |
# # ------------------------------
|
| 381 |
# # MCQ Generation
|
|
|
|
| 389 |
# 2. API key is valid (get one from https://console.groq.com/keys)
|
| 390 |
# 3. Space has been restarted after adding the key
|
| 391 |
# Current status: API key not found or invalid."""
|
| 392 |
+
# return error_msg, None
|
| 393 |
|
| 394 |
# # Check cache
|
| 395 |
# context_hash = hashlib.md5(context.encode()).hexdigest()[:8]
|
|
|
|
| 404 |
# # Detect the chapter from our actual chapter list
|
| 405 |
# chapter = detect_chapter_from_list(context, topic, subject)
|
| 406 |
|
| 407 |
+
# # If chapter is None, topic doesn't belong to this subject
|
| 408 |
+
# if chapter is None:
|
| 409 |
+
# error_msg = f"β The topic '{topic}' does not belong to {subject.title()}.\n\nPlease enter a topic related to {subject.title()} or select the correct subject."
|
| 410 |
+
# print(f"β οΈ Topic mismatch: '{topic}' not in {subject}")
|
| 411 |
+
# return error_msg, None
|
| 412 |
+
|
| 413 |
# prompt = f"""You are a Class-12 {subject.title()} teacher creating MCQs.
|
| 414 |
# Topic: "{topic}"
|
| 415 |
# Chapter: "{chapter}"
|
|
|
|
| 793 |
# if subject not in SUBJECTS:
|
| 794 |
# return jsonify({"error": "Invalid subject"}), 400
|
| 795 |
|
| 796 |
+
# print(f"\nπ Validating topic for {subject}...")
|
| 797 |
+
|
| 798 |
+
# # STEP 1: Validate if topic belongs to subject (BEFORE RAG search)
|
| 799 |
+
# if not validate_topic_subject(topic, subject):
|
| 800 |
+
# subject_names = {
|
| 801 |
+
# "biology": "Biology",
|
| 802 |
+
# "chemistry": "Chemistry",
|
| 803 |
+
# "physics": "Physics"
|
| 804 |
+
# }
|
| 805 |
+
# error_msg = f"The topic '{topic}' does not appear to be related to {subject_names[subject]}.\n\nPlease either:\nβ’ Enter a {subject_names[subject]}-related topic, or\nβ’ Select the correct subject for this topic"
|
| 806 |
+
# return jsonify({"error": error_msg}), 400
|
| 807 |
+
|
| 808 |
+
# print(f"β Topic validated for {subject}")
|
| 809 |
+
# print(f"π Searching {subject} for: {topic}")
|
| 810 |
|
| 811 |
+
# # STEP 2: RAG search
|
| 812 |
# context = rag_search(topic, subject, k=5)
|
| 813 |
|
| 814 |
# if not context or len(context.strip()) < 50:
|
|
|
|
| 816 |
|
| 817 |
# print(f"β Context found ({len(context)} chars)")
|
| 818 |
|
| 819 |
+
# # STEP 3: Generate MCQs
|
| 820 |
# mcqs, chapter = generate_mcqs(context, topic, subject)
|
| 821 |
|
| 822 |
+
# # Check if there was a subject mismatch
|
| 823 |
+
# if chapter is None:
|
| 824 |
+
# return jsonify({"error": mcqs}), 400
|
| 825 |
+
|
| 826 |
# return jsonify({
|
| 827 |
# "mcqs": mcqs,
|
| 828 |
# "subject": subject,
|
|
|
|
| 850 |
# port = int(os.environ.get("PORT", 7860))
|
| 851 |
# print(f"\nπ Starting server on port {port}...\n")
|
| 852 |
# app.run(host="0.0.0.0", port=port, debug=False)
|
|
|
|
| 853 |
import pickle
|
| 854 |
import faiss
|
| 855 |
from flask import Flask, request, jsonify, render_template_string
|
|
|
|
| 1232 |
# ------------------------------
|
| 1233 |
# MCQ Generation
|
| 1234 |
# ------------------------------
|
| 1235 |
+
def generate_mcqs(context, topic, subject, num_questions=5):
|
| 1236 |
# Check if Groq is available
|
| 1237 |
if not groq_client:
|
| 1238 |
error_msg = """ERROR: Groq API not initialized!
|
|
|
|
| 1245 |
|
| 1246 |
# Check cache
|
| 1247 |
context_hash = hashlib.md5(context.encode()).hexdigest()[:8]
|
| 1248 |
+
cache_key = get_cache_key(topic, subject, context_hash) + f":{num_questions}"
|
| 1249 |
|
| 1250 |
if cache_key in MCQ_CACHE:
|
| 1251 |
print("β Using cached MCQs")
|
| 1252 |
return MCQ_CACHE[cache_key]["mcqs"], MCQ_CACHE[cache_key]["chapter"]
|
| 1253 |
|
| 1254 |
+
print(f"π€ Generating {num_questions} MCQs for {subject} - {topic}")
|
| 1255 |
|
| 1256 |
# Detect the chapter from our actual chapter list
|
| 1257 |
chapter = detect_chapter_from_list(context, topic, subject)
|
|
|
|
| 1268 |
Reference material from textbook:
|
| 1269 |
{context[:1500]}
|
| 1270 |
|
| 1271 |
+
Generate exactly {num_questions} multiple-choice questions based on the reference material.
|
| 1272 |
|
| 1273 |
FORMAT (follow EXACTLY):
|
| 1274 |
Q1. [Question based on material]
|
|
|
|
| 1285 |
D) [Option 4]
|
| 1286 |
Answer: [A/B/C/D] - [Brief explanation]
|
| 1287 |
|
| 1288 |
+
Continue for Q3, Q4, Q5{"..." if num_questions > 5 else ""}.
|
| 1289 |
|
| 1290 |
REQUIREMENTS:
|
| 1291 |
- All questions must be answerable from the reference material
|
|
|
|
| 1293 |
- Correct answer must be clearly supported by material
|
| 1294 |
- Keep explanations brief (1-2 sentences)
|
| 1295 |
|
| 1296 |
+
Generate {num_questions} MCQs now:"""
|
| 1297 |
|
| 1298 |
try:
|
| 1299 |
+
# Adjust max_tokens based on number of questions
|
| 1300 |
+
max_tokens = min(3000, 300 * num_questions)
|
| 1301 |
+
|
| 1302 |
chat_completion = groq_client.chat.completions.create(
|
| 1303 |
messages=[
|
| 1304 |
{
|
|
|
|
| 1312 |
],
|
| 1313 |
model="llama-3.3-70b-versatile",
|
| 1314 |
temperature=0.3,
|
| 1315 |
+
max_tokens=max_tokens,
|
| 1316 |
top_p=0.9
|
| 1317 |
)
|
| 1318 |
|
|
|
|
| 1540 |
<input type="text" id="topic" placeholder="e.g., Mitochondria, Chemical Bonding, Newton's Laws">
|
| 1541 |
</div>
|
| 1542 |
|
| 1543 |
+
<div class="form-group">
|
| 1544 |
+
<label for="numQuestions">π’ Number of MCQs</label>
|
| 1545 |
+
<select id="numQuestions">
|
| 1546 |
+
<option value="1">1 MCQ</option>
|
| 1547 |
+
<option value="2">2 MCQs</option>
|
| 1548 |
+
<option value="3">3 MCQs</option>
|
| 1549 |
+
<option value="4">4 MCQs</option>
|
| 1550 |
+
<option value="5" selected>5 MCQs</option>
|
| 1551 |
+
<option value="6">6 MCQs</option>
|
| 1552 |
+
<option value="7">7 MCQs</option>
|
| 1553 |
+
<option value="8">8 MCQs</option>
|
| 1554 |
+
<option value="9">9 MCQs</option>
|
| 1555 |
+
<option value="10">10 MCQs</option>
|
| 1556 |
+
<option value="11">11 MCQs</option>
|
| 1557 |
+
<option value="12">12 MCQs</option>
|
| 1558 |
+
<option value="13">13 MCQs</option>
|
| 1559 |
+
<option value="14">14 MCQs</option>
|
| 1560 |
+
<option value="15">15 MCQs</option>
|
| 1561 |
+
<option value="16">16 MCQs</option>
|
| 1562 |
+
<option value="17">17 MCQs</option>
|
| 1563 |
+
<option value="18">18 MCQs</option>
|
| 1564 |
+
<option value="19">19 MCQs</option>
|
| 1565 |
+
<option value="20">20 MCQs</option>
|
| 1566 |
+
</select>
|
| 1567 |
+
</div>
|
| 1568 |
+
|
| 1569 |
+
<button onclick="generateMCQs()">π Generate MCQs</button>
|
| 1570 |
|
| 1571 |
<div class="loading" id="loading">
|
| 1572 |
<div class="spinner"></div>
|
|
|
|
| 1596 |
async function generateMCQs() {
|
| 1597 |
const subject = document.getElementById('subject').value;
|
| 1598 |
const topic = document.getElementById('topic').value.trim();
|
| 1599 |
+
const numQuestions = parseInt(document.getElementById('numQuestions').value);
|
| 1600 |
|
| 1601 |
if (!topic) {
|
| 1602 |
alert('β οΈ Please enter a topic!');
|
|
|
|
| 1618 |
const response = await fetch('/generate', {
|
| 1619 |
method: 'POST',
|
| 1620 |
headers: {'Content-Type': 'application/json'},
|
| 1621 |
+
body: JSON.stringify({subject, topic, num_questions: numQuestions})
|
| 1622 |
});
|
| 1623 |
|
| 1624 |
const data = await response.json();
|
|
|
|
| 1641 |
} finally {
|
| 1642 |
loading.classList.remove('show');
|
| 1643 |
btn.disabled = false;
|
| 1644 |
+
btn.textContent = 'π Generate MCQs';
|
| 1645 |
}
|
| 1646 |
}
|
| 1647 |
|
|
|
|
| 1668 |
data = request.json
|
| 1669 |
subject = data.get("subject", "").lower()
|
| 1670 |
topic = data.get("topic", "")
|
| 1671 |
+
num_questions = data.get("num_questions", 5)
|
| 1672 |
+
|
| 1673 |
+
# Validate num_questions
|
| 1674 |
+
try:
|
| 1675 |
+
num_questions = int(num_questions)
|
| 1676 |
+
if num_questions < 1 or num_questions > 20:
|
| 1677 |
+
num_questions = 5
|
| 1678 |
+
except:
|
| 1679 |
+
num_questions = 5
|
| 1680 |
|
| 1681 |
if not topic:
|
| 1682 |
return jsonify({"error": "Topic is required"}), 400
|
|
|
|
| 1708 |
print(f"β Context found ({len(context)} chars)")
|
| 1709 |
|
| 1710 |
# STEP 3: Generate MCQs
|
| 1711 |
+
mcqs, chapter = generate_mcqs(context, topic, subject, num_questions)
|
| 1712 |
|
| 1713 |
# Check if there was a subject mismatch
|
| 1714 |
if chapter is None:
|