File size: 3,430 Bytes
cd5aabe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1605267
606732d
 
cd5aabe
 
 
 
 
 
 
 
606732d
75a5800
cd5aabe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
606732d
 
640e3c9
 
 
 
 
 
 
 
 
 
 
606732d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
787d6e0
 
 
 
 
 
 
 
 
 
 
 
 
46b1977
787d6e0
 
 
6507333
fcd684b
787d6e0
 
44d459b
2c9c1e9
787d6e0
 
 
 
 
 
46b1977
6507333
787d6e0
 
 
 
 
 
 
 
46b1977
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
145
146
147
148
149
from enum import Enum
from typing import List, Optional

from pydantic import BaseModel


class ModelType(str, Enum):
    """模型类型枚举"""

    HOWCUTEAMI = "howcuteami"
    DEEPFACE = "deepface"
    HYBRID = "hybrid"  # 混合模式:颜值性别用howcuteami,年龄情绪用deepface


class ImageScoreItem(BaseModel):
    file_path: str
    score: float
    is_cropped_face: bool = False
    size_bytes: int
    size_str: str
    last_modified: str
    nickname: Optional[str] = None
    hostname: Optional[str] = None
    region: Optional[str] = None
    region_country: Optional[str] = None


class SearchRequest(BaseModel):
    keyword: Optional[str] = ""
    searchType: Optional[str] = "face"
    top_k: Optional[int] = 5
    score_threshold: float = 0.0
    nickname: Optional[str] = None
    region: Optional[str] = None
    platform: Optional[str] = None


class ImageSearchRequest(BaseModel):
    image: Optional[str] = None  # base64编码的图片
    searchType: Optional[str] = "face"
    top_k: Optional[int] = 5
    score_threshold: float = 0.0
    nickname: Optional[str] = None


class ImageFileList(BaseModel):
    results: List[ImageScoreItem]
    count: int

class PagedImageFileList(BaseModel):
    results: List[ImageScoreItem]
    count: int
    page: int
    page_size: int
    total_pages: int

class CelebrityMatchResponse(BaseModel):
    filename: str
    display_name: Optional[str] = None
    distance: float
    similarity: float
    confidence: float
    face_filename: Optional[str] = None


class CategoryStatItem(BaseModel):
  category: str
  display_name: str
  count: int


class CategoryStatsResponse(BaseModel):
  stats: List[CategoryStatItem]
  total: int


class RegionStatItem(BaseModel):
    region: str
    region_country: str
    count: int


class RegionStatsResponse(BaseModel):
    stats: List[RegionStatItem]
    total: int


class UserDeviceItem(BaseModel):
    device_id: str
    device_type: Optional[str] = None
    device_model: Optional[str] = None
    os_version: Optional[str] = None
    app_version: Optional[str] = None
    timezone: Optional[str] = None
    region: Optional[str] = None
    region_country: Optional[str] = None
    language: Optional[str] = None
    detection_count: int = 0
    created_at: str
    updated_at: str


class UserDeviceListResponse(BaseModel):
    results: List[UserDeviceItem]
    count: int
    page: int
    page_size: int
    total_pages: int


class RankResponse(BaseModel):
    success: bool = True
    score: float
    region_code: Optional[str] = None
    region_name: Optional[str] = None
    region_rank: int
    region_total: int
    region_percentile: float
    global_rank: int
    global_total: int
    global_percentile: float
    days_limit: int = 90


class LeaderboardItem(BaseModel):
    record_id: int
    file_path: str = ""
    rank: int
    score: float
    nickname: Optional[str] = None
    display_name: str = ""
    region_code: Optional[str] = None
    region_name: Optional[str] = None
    gender: Optional[str] = None
    age: Optional[str] = None
    avatar_id: int
    created_at: Optional[str] = None
    updated_at: Optional[str] = None
    is_current_user: bool = False


class LeaderboardResponse(BaseModel):
    success: bool = True
    region_code: Optional[str] = None
    region_name: Optional[str] = None
    total_records: int
    items: List[LeaderboardItem]
    days_limit: int = 90