Spaces:
Build error
Build error
feat: adjust confidence range in analysis result and optimize parallel processing for feature extraction, vocal analysis, and CLAP detection
Browse files- app/routes/analyze.py +32 -40
- app/training/wav2vec2_classifier.py +1 -1
app/routes/analyze.py
CHANGED
|
@@ -174,7 +174,7 @@ class AnalysisResult(BaseModel):
|
|
| 174 |
"""Platform/hooks/analysisTypes.ts uyumlu."""
|
| 175 |
|
| 176 |
isAIGenerated: bool
|
| 177 |
-
confidence: float = Field(..., ge=0.
|
| 178 |
processingTime: float
|
| 179 |
modelVersion: str
|
| 180 |
decisionSource: str
|
|
@@ -333,11 +333,25 @@ async def _analyze_file(
|
|
| 333 |
)
|
| 334 |
|
| 335 |
warnings: List[str] = []
|
|
|
|
| 336 |
|
| 337 |
-
# ──
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 338 |
try:
|
| 339 |
-
|
| 340 |
-
features: AudioFeatures = extract_features(audio_bytes)
|
| 341 |
logger.info(
|
| 342 |
f"[{request_id}] Features: "
|
| 343 |
f"S={features.spectral_regularity:.3f} "
|
|
@@ -345,30 +359,20 @@ async def _analyze_file(
|
|
| 345 |
f"H={features.harmonic_structure:.3f}"
|
| 346 |
)
|
| 347 |
except ValueError as e:
|
| 348 |
-
logger.warning(
|
| 349 |
-
f"[{request_id}] Feature extraction "
|
| 350 |
-
f"failed: {e}"
|
| 351 |
-
)
|
| 352 |
return _fallback_analysis(
|
| 353 |
-
request_id, file, content,
|
| 354 |
-
file_size, start_time, str(e),
|
| 355 |
)
|
| 356 |
except Exception as e:
|
| 357 |
-
logger.error(
|
| 358 |
-
f"[{request_id}] Feature extraction "
|
| 359 |
-
f"error: {e}", exc_info=True,
|
| 360 |
-
)
|
| 361 |
-
warnings.append("feature_extraction_partial")
|
| 362 |
return _fallback_analysis(
|
| 363 |
-
request_id, file, content,
|
| 364 |
-
file_size, start_time, str(e),
|
| 365 |
)
|
| 366 |
|
| 367 |
-
#
|
| 368 |
vocals: Optional[VocalFeatures] = None
|
| 369 |
try:
|
| 370 |
-
|
| 371 |
-
vocals = analyze_vocals(audio_bytes_vocal)
|
| 372 |
if vocals.has_vocals:
|
| 373 |
logger.info(
|
| 374 |
f"[{request_id}] Vocals: "
|
|
@@ -381,11 +385,10 @@ async def _analyze_file(
|
|
| 381 |
logger.warning(f"[{request_id}] Vocal analysis failed: {e}")
|
| 382 |
warnings.append("vocal_analysis_unavailable")
|
| 383 |
|
| 384 |
-
#
|
| 385 |
clap_result = None
|
| 386 |
try:
|
| 387 |
-
|
| 388 |
-
clap_result = clap_service.predict(audio_bytes_clap)
|
| 389 |
if clap_result.available:
|
| 390 |
logger.info(
|
| 391 |
f"[{request_id}] CLAP: "
|
|
@@ -393,21 +396,15 @@ async def _analyze_file(
|
|
| 393 |
f"conf={clap_result.confidence:.3f}"
|
| 394 |
)
|
| 395 |
else:
|
| 396 |
-
logger.info(
|
| 397 |
-
f"[{request_id}] CLAP unavailable: "
|
| 398 |
-
f"{clap_result.error}"
|
| 399 |
-
)
|
| 400 |
except Exception as e:
|
| 401 |
-
logger.warning(
|
| 402 |
-
f"[{request_id}] CLAP failed: {e}"
|
| 403 |
-
)
|
| 404 |
warnings.append("clap_analysis_unavailable")
|
| 405 |
|
| 406 |
-
#
|
| 407 |
fst_result = None
|
| 408 |
try:
|
| 409 |
-
|
| 410 |
-
fst_result = await fst_service.predict(audio_bytes_fst)
|
| 411 |
if fst_result.available:
|
| 412 |
logger.info(
|
| 413 |
f"[{request_id}] FST: "
|
|
@@ -416,14 +413,9 @@ async def _analyze_file(
|
|
| 416 |
f"label={fst_result.label}"
|
| 417 |
)
|
| 418 |
else:
|
| 419 |
-
logger.info(
|
| 420 |
-
f"[{request_id}] FST unavailable: "
|
| 421 |
-
f"{fst_result.error}"
|
| 422 |
-
)
|
| 423 |
except Exception as e:
|
| 424 |
-
logger.warning(
|
| 425 |
-
f"[{request_id}] FST failed: {e}"
|
| 426 |
-
)
|
| 427 |
warnings.append("fst_analysis_unavailable")
|
| 428 |
|
| 429 |
# ── Step 5: Score fusion ───────────────
|
|
|
|
| 174 |
"""Platform/hooks/analysisTypes.ts uyumlu."""
|
| 175 |
|
| 176 |
isAIGenerated: bool
|
| 177 |
+
confidence: float = Field(..., ge=0.03, le=0.97)
|
| 178 |
processingTime: float
|
| 179 |
modelVersion: str
|
| 180 |
decisionSource: str
|
|
|
|
| 333 |
)
|
| 334 |
|
| 335 |
warnings: List[str] = []
|
| 336 |
+
loop = asyncio.get_event_loop()
|
| 337 |
|
| 338 |
+
# ── Run feature extraction + vocal analysis + CLAP in parallel ────
|
| 339 |
+
def _extract_features_sync():
|
| 340 |
+
return extract_features(io.BytesIO(content))
|
| 341 |
+
|
| 342 |
+
def _analyze_vocals_sync():
|
| 343 |
+
return analyze_vocals(io.BytesIO(content))
|
| 344 |
+
|
| 345 |
+
def _clap_predict_sync():
|
| 346 |
+
return clap_service.predict(io.BytesIO(content))
|
| 347 |
+
|
| 348 |
+
feat_future = loop.run_in_executor(_analysis_pool, _extract_features_sync)
|
| 349 |
+
vocal_future = loop.run_in_executor(_analysis_pool, _analyze_vocals_sync)
|
| 350 |
+
clap_future = loop.run_in_executor(_analysis_pool, _clap_predict_sync)
|
| 351 |
+
|
| 352 |
+
# Await feature extraction first (required for fusion)
|
| 353 |
try:
|
| 354 |
+
features: AudioFeatures = await feat_future
|
|
|
|
| 355 |
logger.info(
|
| 356 |
f"[{request_id}] Features: "
|
| 357 |
f"S={features.spectral_regularity:.3f} "
|
|
|
|
| 359 |
f"H={features.harmonic_structure:.3f}"
|
| 360 |
)
|
| 361 |
except ValueError as e:
|
| 362 |
+
logger.warning(f"[{request_id}] Feature extraction failed: {e}")
|
|
|
|
|
|
|
|
|
|
| 363 |
return _fallback_analysis(
|
| 364 |
+
request_id, file, content, file_size, start_time, str(e),
|
|
|
|
| 365 |
)
|
| 366 |
except Exception as e:
|
| 367 |
+
logger.error(f"[{request_id}] Feature extraction error: {e}", exc_info=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 368 |
return _fallback_analysis(
|
| 369 |
+
request_id, file, content, file_size, start_time, str(e),
|
|
|
|
| 370 |
)
|
| 371 |
|
| 372 |
+
# Await vocal analysis (ran in parallel)
|
| 373 |
vocals: Optional[VocalFeatures] = None
|
| 374 |
try:
|
| 375 |
+
vocals = await vocal_future
|
|
|
|
| 376 |
if vocals.has_vocals:
|
| 377 |
logger.info(
|
| 378 |
f"[{request_id}] Vocals: "
|
|
|
|
| 385 |
logger.warning(f"[{request_id}] Vocal analysis failed: {e}")
|
| 386 |
warnings.append("vocal_analysis_unavailable")
|
| 387 |
|
| 388 |
+
# Await CLAP (ran in parallel)
|
| 389 |
clap_result = None
|
| 390 |
try:
|
| 391 |
+
clap_result = await clap_future
|
|
|
|
| 392 |
if clap_result.available:
|
| 393 |
logger.info(
|
| 394 |
f"[{request_id}] CLAP: "
|
|
|
|
| 396 |
f"conf={clap_result.confidence:.3f}"
|
| 397 |
)
|
| 398 |
else:
|
| 399 |
+
logger.info(f"[{request_id}] CLAP unavailable: {clap_result.error}")
|
|
|
|
|
|
|
|
|
|
| 400 |
except Exception as e:
|
| 401 |
+
logger.warning(f"[{request_id}] CLAP failed: {e}")
|
|
|
|
|
|
|
| 402 |
warnings.append("clap_analysis_unavailable")
|
| 403 |
|
| 404 |
+
# FST detection (Layer 3) — async native
|
| 405 |
fst_result = None
|
| 406 |
try:
|
| 407 |
+
fst_result = await fst_service.predict(io.BytesIO(content))
|
|
|
|
| 408 |
if fst_result.available:
|
| 409 |
logger.info(
|
| 410 |
f"[{request_id}] FST: "
|
|
|
|
| 413 |
f"label={fst_result.label}"
|
| 414 |
)
|
| 415 |
else:
|
| 416 |
+
logger.info(f"[{request_id}] FST unavailable: {fst_result.error}")
|
|
|
|
|
|
|
|
|
|
| 417 |
except Exception as e:
|
| 418 |
+
logger.warning(f"[{request_id}] FST failed: {e}")
|
|
|
|
|
|
|
| 419 |
warnings.append("fst_analysis_unavailable")
|
| 420 |
|
| 421 |
# ── Step 5: Score fusion ───────────────
|
app/training/wav2vec2_classifier.py
CHANGED
|
@@ -38,7 +38,7 @@ class Wav2Vec2Config:
|
|
| 38 |
learning_rate_head: float = 1e-3
|
| 39 |
learning_rate_encoder: float = 1e-5
|
| 40 |
weight_decay: float = 0.01
|
| 41 |
-
batch_size: int =
|
| 42 |
epochs: int = 10
|
| 43 |
patience: int = 3
|
| 44 |
device: str = "auto"
|
|
|
|
| 38 |
learning_rate_head: float = 1e-3
|
| 39 |
learning_rate_encoder: float = 1e-5
|
| 40 |
weight_decay: float = 0.01
|
| 41 |
+
batch_size: int = 2
|
| 42 |
epochs: int = 10
|
| 43 |
patience: int = 3
|
| 44 |
device: str = "auto"
|