Spaces:
Running
Running
feat: analysis jobs timeline scanning inference xai ve corresponding tests eklendi
Browse files
app/routes/analyze_schemas.py
CHANGED
|
@@ -126,6 +126,61 @@ class MetaClassifierExplanation(BaseModel):
|
|
| 126 |
topFeatures: List[MetaFeatureImportance] = Field(default_factory=list)
|
| 127 |
|
| 128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
class AnalysisResult(BaseModel):
|
| 130 |
"""Platform/hooks/analysisTypes.ts uyumlu."""
|
| 131 |
|
|
@@ -142,6 +197,8 @@ class AnalysisResult(BaseModel):
|
|
| 142 |
xai: Optional[XAIExplanation] = None
|
| 143 |
towerScores: Dict[str, float] = Field(default_factory=dict)
|
| 144 |
metaClassifier: Optional[MetaClassifierExplanation] = None
|
|
|
|
|
|
|
| 145 |
# Per-layer status: which model actually ran and how (e.g. CLAP embedding
|
| 146 |
# vs. its spectral heuristic fallback), so the UI can label each score.
|
| 147 |
layers: Dict[str, Dict[str, Any]] = Field(default_factory=dict)
|
|
|
|
| 126 |
topFeatures: List[MetaFeatureImportance] = Field(default_factory=list)
|
| 127 |
|
| 128 |
|
| 129 |
+
class SegmentReason(BaseModel):
|
| 130 |
+
"""One feature that pushed a window's score, from SHAP."""
|
| 131 |
+
|
| 132 |
+
name: str
|
| 133 |
+
label: str
|
| 134 |
+
labelEn: str
|
| 135 |
+
direction: Literal["towards_ai", "towards_human"]
|
| 136 |
+
shapValue: float
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
class TimelineSegment(BaseModel):
|
| 140 |
+
"""One window of the whole-track scan. Only `ok` windows carry a score."""
|
| 141 |
+
|
| 142 |
+
index: int
|
| 143 |
+
start: float
|
| 144 |
+
end: float
|
| 145 |
+
state: Literal["ok", "silent", "skipped", "failed"] = "ok"
|
| 146 |
+
probability: Optional[float] = None
|
| 147 |
+
isAi: Optional[bool] = None
|
| 148 |
+
# 0 at the decision threshold, 1 at the far end of the window's side.
|
| 149 |
+
margin: Optional[float] = None
|
| 150 |
+
hasVocals: Optional[bool] = None
|
| 151 |
+
reasons: List[SegmentReason] = Field(default_factory=list)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
class TimelineSummary(BaseModel):
|
| 155 |
+
scoredCount: int = 0
|
| 156 |
+
flaggedCount: int = 0
|
| 157 |
+
scoredSec: float = 0.0
|
| 158 |
+
# Share of the scored time whose windows lean AI.
|
| 159 |
+
aiShare: float = 0.0
|
| 160 |
+
meanProbability: float = 0.0
|
| 161 |
+
maxProbability: float = 0.0
|
| 162 |
+
peakIndex: Optional[int] = None
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
class Timeline(BaseModel):
|
| 166 |
+
"""The track read window by window with the primary classifier.
|
| 167 |
+
|
| 168 |
+
Window scores come from a model trained on 60 s clips that were wholly AI
|
| 169 |
+
or wholly human, so they show where the music reads AI-like rather than
|
| 170 |
+
proving where an AI was used.
|
| 171 |
+
"""
|
| 172 |
+
|
| 173 |
+
# Seconds the scan covered (at most the first six minutes) and the full track length.
|
| 174 |
+
durationSec: float
|
| 175 |
+
totalSec: float
|
| 176 |
+
truncated: bool = False
|
| 177 |
+
threshold: float
|
| 178 |
+
# Peak level per slice of the covered part, 0 to 1, for drawing the waveform.
|
| 179 |
+
peaks: List[float] = Field(default_factory=list)
|
| 180 |
+
segments: List[TimelineSegment] = Field(default_factory=list)
|
| 181 |
+
summary: TimelineSummary = Field(default_factory=TimelineSummary)
|
| 182 |
+
|
| 183 |
+
|
| 184 |
class AnalysisResult(BaseModel):
|
| 185 |
"""Platform/hooks/analysisTypes.ts uyumlu."""
|
| 186 |
|
|
|
|
| 197 |
xai: Optional[XAIExplanation] = None
|
| 198 |
towerScores: Dict[str, float] = Field(default_factory=dict)
|
| 199 |
metaClassifier: Optional[MetaClassifierExplanation] = None
|
| 200 |
+
# Whole-track scan; absent when the classifier or the decode was unavailable.
|
| 201 |
+
timeline: Optional[Timeline] = None
|
| 202 |
# Per-layer status: which model actually ran and how (e.g. CLAP embedding
|
| 203 |
# vs. its spectral heuristic fallback), so the UI can label each score.
|
| 204 |
layers: Dict[str, Dict[str, Any]] = Field(default_factory=dict)
|