File size: 4,676 Bytes
4d67ec7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"""
schemas.py — Pydantic models for FastAPI request/response validation

Defines the complete API contract for the NEET Biology Q&A system.
"""

from pydantic import BaseModel, Field
from typing import Optional


# ==============================
# REQUEST MODELS
# ==============================

class QuestionRequest(BaseModel):
    """Request body for the /qa endpoint."""
    question: str = Field(
        ...,
        min_length=5,
        max_length=500,
        description="The NEET Biology question to answer.",
        examples=["What is the role of cofactors in enzyme activity?"],
    )
    chapter_filter: Optional[str] = Field(
        default=None,
        description="Optional: manually specify a chapter to filter retrieval. "
                    "If omitted, BERT classifier auto-detects the chapter.",
        examples=["Biomolecules"],
    )
    top_k: int = Field(
        default=5,
        ge=1,
        le=20,
        description="Number of NCERT chunks to retrieve for context.",
    )
    use_classifier: bool = Field(
        default=True,
        description="Whether to use the BERT classifier for auto chapter detection.",
    )


# ==============================
# RESPONSE MODELS
# ==============================

class TopicInfo(BaseModel):
    """A predicted topic/subtopic from the NCERT syllabus."""
    section_code: str = Field(..., description="Section code (e.g., '9.8')")
    section_title: str = Field(..., description="Section title (e.g., 'Enzymes')")
    similarity: float = Field(..., description="Cosine similarity score (0-1)")


class ClassificationResult(BaseModel):
    """BERT classification output for the question."""
    chapter: str = Field(..., description="Predicted NCERT chapter name")
    chapter_id: int = Field(..., description="Chapter ID (0-30)")
    chapter_confidence: float = Field(..., description="BERT confidence score (0-1)")
    topics: list[TopicInfo] = Field(
        default=[],
        description="Top 1-3 relevant topics/subtopics within the chapter",
    )
    rejected: bool = Field(default=False, description="True if rejected by OOD gating")
    rejection_reason: str = Field(default="", description="Reason for rejection")
    entropy: float = Field(default=0.0, description="Normalized entropy of prediction")
    margin: float = Field(default=0.0, description="Confidence margin between top-1 and top-2")


class IsNeetBioRequest(BaseModel):
    """Request body for the /is-neet-bio validation endpoint."""
    question: str = Field(
        ...,
        min_length=3,
        max_length=500,
        description="The question to validate."
    )

class IsNeetBioResponse(BaseModel):
    """Response indicating whether the query is valid NEET biology."""
    is_valid: bool
    rejected: bool
    reason: str


class SourceChunk(BaseModel):
    """A retrieved NCERT text chunk used as context."""
    chapter: Optional[str] = None
    section: Optional[str] = None
    section_title: Optional[str] = None
    text_content: Optional[str] = None
    similarity: float = 0.0


class QAResponse(BaseModel):
    """Full response from the Q&A pipeline."""
    question: str = Field(..., description="The original question")
    classification: Optional[ClassificationResult] = Field(
        default=None,
        description="BERT classification result (chapter + topics)",
    )
    answer: str = Field(..., description="Generated answer from NCERT context")
    justification: list[str] = Field(
        default=[],
        description="Step-by-step justification of the answer",
    )
    sources: list[SourceChunk] = Field(
        default=[],
        description="Retrieved NCERT chunks used as evidence",
    )
    confidence: float = Field(
        ...,
        ge=0.0,
        le=1.0,
        description="Overall confidence score (0-1)",
    )
    verified: bool = Field(..., description="Whether the answer passed verification")
    verifier_note: str = Field(
        default="",
        description="Explanation from the verifier",
    )


class ClassifyOnlyRequest(BaseModel):
    """Request body for the /classify endpoint (no RAG, just classification)."""
    question: str = Field(
        ...,
        min_length=5,
        max_length=500,
        description="The NEET Biology question to classify.",
        examples=["What is the role of mitochondria in ATP synthesis?"],
    )


class ClassifyOnlyResponse(BaseModel):
    """Response from the /classify endpoint."""
    question: str
    classification: ClassificationResult


class HealthResponse(BaseModel):
    """Health check response."""
    status: str = "ok"
    version: str = "1.0.0"
    components: dict = {}