PsalmsJava commited on
Commit
b03eb12
·
1 Parent(s): 28a1786

Fixing Logs

Browse files
Files changed (1) hide show
  1. main.py +11 -145
main.py CHANGED
@@ -1,149 +1,15 @@
1
- import os
2
- import tempfile
3
- import subprocess
4
- from fastapi import FastAPI, File, UploadFile, HTTPException
5
- from fastapi.responses import JSONResponse
6
- import aiohttp
7
- import numpy as np
8
- from datetime import datetime
9
- import logging
10
-
11
- # Setup
12
- logging.basicConfig(level=logging.INFO)
13
- logger = logging.getLogger(__name__)
14
- app = FastAPI(title="Emotion Detection API", docs_url="/docs")
15
-
16
- # Config - get from environment
17
- HF_TOKEN = os.getenv("HF_TOKEN", "")
18
- API_TOKEN = os.getenv("API_TOKEN", "test123")
19
 
20
- # Models - using only 2 for reliability
21
- MODELS = {
22
- "wav2vec2_english": {
23
- "url": "https://api-inference.huggingface.co/models/ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition",
24
- "weight": 0.7,
25
- },
26
- "gigam_emo": {
27
- "url": "https://api-inference.huggingface.co/models/salute-developers/GigaAM-emo",
28
- "weight": 0.3,
29
- }
30
- }
31
-
32
- # Emotion mapping
33
- EMOTION_MAPPING = {
34
- "angry": ["angry", "ang"],
35
- "happy": ["happy", "hap"],
36
- "sad": ["sad"],
37
- "fear": ["fear"],
38
- "surprise": ["surprise"],
39
- "disgust": ["disgust"],
40
- "neutral": ["neutral", "neu"]
41
- }
42
-
43
- @app.get("/health")
44
- async def health():
45
- return {"status": "ok", "hf_token": bool(HF_TOKEN)}
46
 
47
- @app.get("/")
48
- async def root():
49
- return {
50
- "message": "Emotion Detection API",
51
- "docs": "/docs",
52
- "endpoints": ["POST /analyze"]
53
- }
54
 
55
- @app.post("/analyze")
56
- async def analyze(file: UploadFile = File(...)):
57
- """Analyze emotion from audio file"""
58
-
59
- # Check auth header
60
- auth = file.headers.get("authorization", "")
61
- if not auth or auth.replace("Bearer ", "") != API_TOKEN:
62
- return JSONResponse(
63
- status_code=401,
64
- content={"error": "Invalid or missing Authorization header"}
65
- )
66
-
67
- # Save uploaded file
68
- with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmp:
69
- content = await file.read()
70
- tmp.write(content)
71
- input_path = tmp.name
72
-
73
- try:
74
- # Convert to proper format
75
- with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as out:
76
- output_path = out.name
77
-
78
- subprocess.run([
79
- "ffmpeg", "-i", input_path,
80
- "-ar", "16000", "-ac", "1",
81
- "-y", output_path
82
- ], check=True, capture_output=True)
83
-
84
- # Read converted file
85
- with open(output_path, "rb") as f:
86
- audio_bytes = f.read()
87
-
88
- # Query models
89
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
90
- results = {}
91
-
92
- async with aiohttp.ClientSession() as session:
93
- for name, config in MODELS.items():
94
- try:
95
- async with session.post(
96
- config["url"],
97
- headers=headers,
98
- data=audio_bytes,
99
- timeout=10
100
- ) as resp:
101
- if resp.status == 200:
102
- results[name] = await resp.json()
103
- except Exception as e:
104
- logger.warning(f"{name} failed: {e}")
105
-
106
- # Simple ensemble
107
- emotion_scores = {}
108
- total_weight = 0
109
-
110
- for name, predictions in results.items():
111
- weight = MODELS[name]["weight"]
112
- total_weight += weight
113
-
114
- for pred in predictions:
115
- label = pred.get("label", "").lower()
116
- score = pred.get("score", 0)
117
-
118
- # Map to standard emotions
119
- for std_emo, variations in EMOTION_MAPPING.items():
120
- if any(v in label for v in variations):
121
- emotion_scores[std_emo] = emotion_scores.get(std_emo, 0) + score * weight
122
- break
123
-
124
- # Normalize
125
- if total_weight > 0:
126
- emotion_scores = {k: v/total_weight for k, v in emotion_scores.items()}
127
-
128
- # Get primary emotion
129
- primary = max(emotion_scores.items(), key=lambda x: x[1]) if emotion_scores else ("unknown", 0)
130
-
131
- return {
132
- "primary_emotion": primary[0],
133
- "confidence": round(primary[1], 3),
134
- "all_emotions": {k: round(v, 3) for k, v in emotion_scores.items()},
135
- "models_used": list(results.keys())
136
- }
137
-
138
- except Exception as e:
139
- logger.error(f"Error: {e}")
140
- return JSONResponse(status_code=500, content={"error": str(e)})
141
- finally:
142
- # Cleanup
143
- for path in [input_path, output_path]:
144
- if os.path.exists(path):
145
- os.unlink(path)
146
 
147
- # For Hugging Face
148
- from fastapi.middleware.cors import CORSMiddleware
149
- app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
 
1
+ """
2
+ Entry point for Hugging Face Spaces
3
+ This file imports the FastAPI app from the app package
4
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
+ import os
7
+ import sys
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ # Add the current directory to Python path
10
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
 
 
 
 
 
11
 
12
+ # Import the FastAPI app from your app module
13
+ from app.main import app
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ # This file exists only to give Hugging Face a clear entry point