Rthur2003 commited on
Commit
e6d2d3e
·
1 Parent(s): 26c0314

refactor: extract Pydantic modelleri üzerinden analyze.py into analyze_schemas.py ve the core api/analyze route ile rate limiting eklendi

Browse files
Files changed (1) hide show
  1. app/routes/analyze_schemas.py +141 -0
app/routes/analyze_schemas.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Response models for the /api/analyze endpoint.
3
+
4
+ Split out from analyze.py — that file was mixing 11 Pydantic response
5
+ models with the route handlers and service-orchestration logic in one
6
+ 693-line file. This module holds only the response shape (kept in exact
7
+ sync with platform/hooks/analysisTypes.ts); analyze.py imports from here.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import Any, Dict, List, Literal, Optional
13
+
14
+ from pydantic import BaseModel, Field
15
+
16
+
17
+ class VocalAnalysis(BaseModel):
18
+ """Vocal analysis results for the response."""
19
+
20
+ hasVocals: bool = False
21
+ vocalConfidence: float = 0.0
22
+ vocalAiScore: float = 0.0
23
+ pitchStabilityScore: float = 0.0
24
+ vibratoRegularityScore: float = 0.0
25
+ formantConsistencyScore: float = 0.0
26
+ breathPatternScore: float = 0.0
27
+ vocalTextureScore: float = 0.0
28
+ pitchMeanHz: float = 0.0
29
+ pitchStdCents: float = 0.0
30
+ vibratoRateHz: float = 0.0
31
+ vibratoExtentCents: float = 0.0
32
+ indicators: List[str] = Field(default_factory=list)
33
+
34
+
35
+ class AnalysisFeatures(BaseModel):
36
+ """Audio feature analysis results."""
37
+
38
+ spectralRegularity: float = 0.5
39
+ temporalPatterns: float = 0.5
40
+ harmonicStructure: float = 0.5
41
+ artificialIndicators: List[str] = Field(default_factory=list)
42
+
43
+
44
+ class AudioInfo(BaseModel):
45
+ """Audio file information."""
46
+
47
+ duration: float = 0.0
48
+ sampleRate: int = 44100
49
+ bitrate: int = 128
50
+ format: str = "unknown"
51
+ channels: int = 2
52
+
53
+
54
+ class ConfidenceBandModel(BaseModel):
55
+ tier: str
56
+ labelTr: str
57
+ labelEn: str
58
+ lowerBound: float
59
+ upperBound: float
60
+
61
+
62
+ class ModelVoteModel(BaseModel):
63
+ name: str
64
+ probability: float
65
+ vote: str
66
+
67
+
68
+ class FeatureContributionModel(BaseModel):
69
+ name: str
70
+ label: str
71
+ labelEn: str
72
+ category: str
73
+ value: float
74
+ zScore: float
75
+ shapValue: float
76
+ direction: str
77
+ description: str
78
+
79
+
80
+ class XAIExplanation(BaseModel):
81
+ """Rich explainable analysis payload."""
82
+
83
+ probability: float
84
+ threshold: float
85
+ baseProbability: float
86
+ confidenceBand: ConfidenceBandModel
87
+ modelVotes: List[ModelVoteModel] = Field(default_factory=list)
88
+ bestModel: str = "XGBoost"
89
+ topContributions: List[FeatureContributionModel] = Field(default_factory=list)
90
+ allFeatures: Dict[str, FeatureContributionModel] = Field(default_factory=dict)
91
+ featureCount: int = 0
92
+
93
+
94
+ class MetaFeatureImportance(BaseModel):
95
+ """One feature's contribution to the meta-classifier's prediction."""
96
+
97
+ feature: str
98
+ importance: float
99
+ value: float
100
+
101
+
102
+ class MetaClassifierExplanation(BaseModel):
103
+ """
104
+ Trained stacking ensemble result — a second, independent opinion
105
+ (LightGBM over all tower outputs) shown alongside the primary XAI
106
+ verdict for transparency, not used to override it. Present only when
107
+ the trained model artifacts are available; absent (not error) otherwise.
108
+ """
109
+
110
+ isAIGenerated: bool
111
+ confidence: float
112
+ modelVersion: str
113
+ towerScores: Dict[str, float] = Field(default_factory=dict)
114
+ indicators: List[str] = Field(default_factory=list)
115
+ topFeatures: List[MetaFeatureImportance] = Field(default_factory=list)
116
+
117
+
118
+ class AnalysisResult(BaseModel):
119
+ """Platform/hooks/analysisTypes.ts uyumlu."""
120
+
121
+ isAIGenerated: bool
122
+ confidence: float = Field(..., ge=0.03, le=0.97)
123
+ processingTime: float
124
+ modelVersion: str
125
+ decisionSource: str
126
+ analysisMode: Literal["production", "preview"]
127
+ source: Dict[str, Any]
128
+ features: AnalysisFeatures
129
+ audioInfo: AudioInfo
130
+ vocalAnalysis: Optional[VocalAnalysis] = None
131
+ xai: Optional[XAIExplanation] = None
132
+ towerScores: Dict[str, float] = Field(default_factory=dict)
133
+ metaClassifier: Optional[MetaClassifierExplanation] = None
134
+
135
+
136
+ class AnalyzeResponse(BaseModel):
137
+ """Response model for analysis endpoint."""
138
+
139
+ result: Optional[AnalysisResult] = None
140
+ warnings: List[str] = Field(default_factory=list)
141
+ errors: List[str] = Field(default_factory=list)