File size: 2,769 Bytes
cdb73a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from typing import Dict, List, Optional, Annotated

from pydantic import BaseModel, Field, BeforeValidator


def _strip_whitespace(v: Optional[str]) -> Optional[str]:
    return v.strip() if v else v


StrippedString = Annotated[str, BeforeValidator(_strip_whitespace)]
OptionalStrippedString = Annotated[Optional[str], BeforeValidator(_strip_whitespace)]


class RecommendByQueryRequest(BaseModel):
    query: StrippedString = Field(
        ...,
        min_length=1,
        max_length=255,
        json_schema_extra={"example": "science fiction about space travel"},
    )
    top_k: int = Field(5, gt=0, le=100, json_schema_extra={"example": 5})


class RecommendByTitleRequest(BaseModel):
    title: StrippedString = Field(
        ...,
        min_length=1,
        max_length=255,
        json_schema_extra={"example": "Dune"},
    )
    top_k: int = Field(5, gt=0, le=100, json_schema_extra={"example": 5})


class Book(BaseModel):
    id: str
    title: str
    authors: List[str]
    description: Optional[str] = None
    genres: List[str]
    cover_image_url: Optional[str] = None


class RecommendationResult(BaseModel):
    book: Book
    similarity_score: float


class BookStats(BaseModel):
    total_books: int
    genres_count: dict
    authors_count: dict


class BookSearchResult(BaseModel):
    books: List[Book]
    total: int
    page: int
    page_size: int


class BookCluster(BaseModel):
    id: int
    name: str
    size: int
    top_books: List[Book]


class ExplainRecommendationRequest(BaseModel):
    query_text: str = Field(..., json_schema_extra={"example": "A fantasy novel with dragons"})
    recommended_book: Book
    similarity_score: float = Field(..., ge=0.0, le=1.0)


class ExplanationResponse(BaseModel):
    match_score: int
    confidence: str
    summary: str
    details: Dict[str, int]


class FeedbackRequest(BaseModel):
    query: StrippedString = Field(
        ...,
        min_length=1,
        max_length=255,
        json_schema_extra={"example": "books about dragons"},
    )
    book_id: StrippedString = Field(
        ...,
        min_length=1,
        max_length=36,
        json_schema_extra={"example": "b1b2b3b4-b5b6-b7b8-b9b0-b1b2b3b4b5b6"},
    )
    feedback_type: str = Field(..., pattern="^(positive|negative)$")
    session_id: OptionalStrippedString = Field(
        None,
        min_length=1,
        max_length=128,
        json_schema_extra={"example": "user-session-12345"},
    )


class FeedbackStatsResponse(BaseModel):
    total_feedback: int
    positive_feedback: int
    negative_feedback: int
    feedback_by_book_title: Dict[str, Dict[str, int]]
    feedback_by_query: Dict[str, Dict[str, int]]

class RecommendByHistoryRequest(BaseModel):
   user_history: List[str]
   top_k: int = 5