File size: 2,595 Bytes
5c095ca
 
 
 
 
 
 
 
 
 
 
 
 
5951bbe
 
 
 
 
 
 
5c095ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5951bbe
 
 
 
5c095ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Pydantic schemas for API request and response validation.

WHY PYDANTIC SCHEMAS IN THE API LAYER:
    FastAPI uses these to:
    1. Validate incoming requests (wrong types -> automatic 422 error)
    2. Serialize outgoing responses (Python objects -> JSON)
    3. Generate automatic API documentation (OpenAPI/Swagger)
    
    You get input validation AND documentation for free.
"""

from pydantic import BaseModel, Field
from typing import Optional, List


class ConversationTurnSchema(BaseModel):
    role:     str
    content:  str
    citations: list = []



class QueryRequest(BaseModel):
    """
    Schema for POST /query request body.
    
    Field() lets us add validation constraints and documentation.
    """
    question: str = Field(
        ...,                    # ... means required
        min_length      = 3,
        max_length      = 500,
        description     = "Research question to answer",
        examples        = ["How does LoRA reduce trainable parameters?"]
    )
    history: List[ConversationTurnSchema] = Field(
        default=[],
        description="Conversation history for context"
    )
    top_k: int = Field(
        default     = 5,
        ge          = 1,                 # ge = greater than or equal
        le          = 20,
        description = "Number of chunks to retrieve"
    )
    filter_category: Optional[str] = Field(
        default     = None,
        description = "ArXiv category filter, e.g. 'cs.LG'",
        example     = ["cs.LG"]
    )
    filter_year_gte: Optional[int] = Field(
        default     = None,
        ge          = 2020,
        le          = 2030,
        description = "Only include papers from this year onwards",
        example     = [2024]
    )


class CitationSchema(BaseModel):
    """A single cited paper."""
    paper_id:       str
    title:          str
    authors:        list[str]
    published_date: str
    arxiv_url:      str


class QueryResponse(BaseModel):
    """Schema for POST /query response."""
    answer:             str
    citations:          list[CitationSchema]
    query:              str
    chunks_used:        int
    retrieval_time_ms:  float
    generation_time_ms: float
    total_time_ms:      float
    has_context:        bool


class HealthResponse(BaseModel):
    """Schema for GET /health response."""
    status:          str
    model:           str
    vector_db_size:  int
    bm25_index_size: int
    version:         str = "1.0.0"


class ErrorResponse(BaseModel):
    """Schema for error responses."""
    error:   str
    detail:  str
    code:    int