Feat: Complete CBT PDF upload, AI parsing, and MinIO storage integration

This commit is contained in:
2026-07-07 15:56:44 +05:30
parent c5260eec2e
commit b6ebb9d9c3
8 changed files with 476 additions and 8 deletions

View File

@@ -4,9 +4,12 @@ from celery import Celery
from celery.schedules import crontab
from sqlmodel import Session, select
import json
import asyncio
from database import engine
import models
import storage
from pdf_parser import parse_pdf_to_questions
REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379/0")
@@ -75,6 +78,76 @@ def generate_daily_study_plans(self):
print(f"Database error during study plan generation: {exc}")
raise self.retry(exc=exc)
@celery_app.task(name="process_pdf_test", bind=True, max_retries=1)
def process_pdf_test(self, test_id_str: str, object_name: str, admin_id_str: str, exam_pattern: str):
"""
Background task to download PDF from MinIO, extract text,
use LLM to generate questions, and attach them to a Test record.
"""
try:
print(f"Starting PDF processing for test {test_id_str}")
# 1. Download PDF from MinIO
pdf_bytes = storage.get_file(object_name)
if not pdf_bytes:
print("Failed to download PDF from MinIO")
return
# 2. Extract Questions using LLM (Async)
questions_data = asyncio.run(parse_pdf_to_questions(pdf_bytes, exam_pattern))
if not questions_data:
print("LLM parsing returned empty data")
return
import uuid
test_id = uuid.UUID(test_id_str)
admin_id = uuid.UUID(admin_id_str)
with Session(engine) as session:
test_obj = session.get(models.Test, test_id)
if not test_obj:
print("Test record not found in DB")
return
question_ids = []
for q_data in questions_data:
# Create a Question DB object
new_q = models.Question(
subject=q_data.get("subject", "Physics"),
topic=q_data.get("topic", "General"),
subtopic=q_data.get("subtopic", "General"),
difficulty=q_data.get("difficulty", "Medium"),
type=q_data.get("type", models.QuestionTypeEnum.MCQ_SINGLE),
question_text=q_data.get("question_text", ""),
options=q_data.get("options", {}),
correct_answer=q_data.get("correct_answer", {}),
solution_text=q_data.get("solution_text", ""),
language=models.MediumEnum.ENGLISH,
exam=models.ExamEnum(exam_pattern),
created_by=admin_id
)
session.add(new_q)
session.flush() # To get the ID
question_ids.append(str(new_q.id))
# Update Test record with the new sections
test_obj.sections = {
"Section 1": {
"questions": question_ids,
"time_limit": test_obj.total_time
}
}
# Automatically activate it when done processing
test_obj.is_active = True
session.commit()
print(f"Successfully processed PDF and created {len(question_ids)} questions for test {test_id_str}")
return f"Processed {len(question_ids)} questions"
except Exception as exc:
print(f"Error processing PDF test: {exc}")
# Mark test as failed if we had a status field, for now just log it
raise self.retry(exc=exc)
# Schedule the tasks using Celery Beat
celery_app.conf.beat_schedule = {
'generate-study-plans-every-morning': {