from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field
from typing import List, Optional
from llama_index.llms.ollama import Ollama
from llama_index.core import PromptTemplate
from llama_index.llms.groq import Groq
import os
import dotenv
from enum import Enum
dotenv.load_dotenv()
app = FastAPI()
# Enable CORS for all origins (for development purposes)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Load LLM model
# llm = Ollama(model="llama3", request_timeout=120.0)
# llama3-70b-8192
llm = Groq(model="llama-3.3-70b-versatile",
api_key="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",
)
class Options(BaseModel):
"""A quiz with a title and a list of questions."""
questions: List[str] = Field(..., description="List of questions in the quiz")
class Quiz(BaseModel):
"""An album inspired by a movie, containing an artist and a list of songs."""
question: str = Field(..., description="The question to be answered")
correct_answer: str = Field(..., description="The correct answer to the question")
options: List[Options] = Field(..., description="List of options for the question")
class Difficulty(str, Enum):
easy = "Easy"
medium = "Medium"
hard = "Hard"
class QuizFormat(str, Enum):
multiple_choice = "Multiple Choice"
open_ended = "Open ended"
true_false = "True/False"
class QuizRequest(BaseModel):
topic: str = Field(..., description="Topic of the quiz")
subject: str = Field(..., description="Subject of the quiz")
grade_level: str = Field(..., description="Grade level (e.g., Primary 3, JSS 1)")
description: Optional[str] = Field(None, description="Brief description of the quiz (optional)")
difficulty: Difficulty = Field(..., description="Difficulty level")
format: QuizFormat = Field(..., description="Format of the quiz")
num_questions: int = Field(..., gt=0, le=50, description="Number of questions (1-50)")
language: str = Field(..., description="Language to translate the quiz into")
# Define the prompt template for quiz generation
PROMPT_TEMPLATE = """
Generate a set of quizzes that align with the given requirements:
Topic: {topic}
Subject: {subject}
Grade Level: {grade_level}
{description_part}
Difficulty: {difficulty}
Format: {format}
Number of Questions: {num_questions}
Ensure the format follows and ensure its in json format. No extra information just your response please and make it well formatted:
[
{{
"question": "Question text here?",
"correct_answer": "Correct answer",
"options": ["Option 1", "Option 2", "Option 3", "Option 4"]
}},
]
"""
FORMAT_PROMPT_TEMPLATE = """
You are a formatting assistant. Your ONLY job is to format quizzes into a structured, teacher-friendly format.
STRICT INSTRUCTIONS:
1. Do NOT include any explanations, introductions, or thought processes. Output ONLY the formatted quiz.
2. Do NOT add or remove content from questions, answers, or options.
3. Format each quiz as follows:
- Start with the question number (e.g., "1. Question text here?").
- On the next line, write "Answer: " followed by the correct answer.
- On the next line, write "Options: " followed by the list of options, each on a new line with a bullet point.
4. Separate each quiz with two blank lines for clarity.
5. Use STRICTLY these HTML tags for proper formatting:
- `
` for line breaks.
- `
` for paragraphs. - `