Spaces:
Runtime error
Runtime error
Pedrinho-Dev01 commited on
Commit ·
c7d60e2
1
Parent(s): a1de573
API DeBERTa Update
Browse files
api.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
"""
|
| 2 |
Spam Detection + Emotion Analysis API
|
| 3 |
-
Ensemble of RoBERTa-Large + ELECTRA-Large classifiers
|
|
|
|
| 4 |
Run with: uvicorn api:app --reload
|
| 5 |
"""
|
| 6 |
|
|
@@ -15,6 +16,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
|
| 15 |
from pydantic import BaseModel
|
| 16 |
from transformers import (
|
| 17 |
AutoTokenizer,
|
|
|
|
| 18 |
ElectraForSequenceClassification,
|
| 19 |
RobertaForSequenceClassification,
|
| 20 |
)
|
|
@@ -25,6 +27,7 @@ ROBERTA_SPAM_REPO = "Dpedrinho01/trained_roberta_large"
|
|
| 25 |
ELECTRA_SPAM_REPO = "Dpedrinho01/trained_electra_large"
|
| 26 |
ROBERTA_EMOTION_REPO = "Dpedrinho01/trained_roberta_emotion"
|
| 27 |
ELECTRA_EMOTION_REPO = "Dpedrinho01/trained_electra_emotion"
|
|
|
|
| 28 |
|
| 29 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 30 |
|
|
@@ -124,17 +127,19 @@ roberta_spam_bundle: Optional[SpamModelBundle] = None
|
|
| 124 |
electra_spam_bundle: Optional[SpamModelBundle] = None
|
| 125 |
roberta_emotion_bundle: Optional[EmotionModelBundle] = None
|
| 126 |
electra_emotion_bundle: Optional[EmotionModelBundle] = None
|
|
|
|
| 127 |
|
| 128 |
|
| 129 |
@app.on_event("startup")
|
| 130 |
def load_models():
|
| 131 |
global roberta_spam_bundle, electra_spam_bundle
|
| 132 |
-
global roberta_emotion_bundle, electra_emotion_bundle
|
| 133 |
|
| 134 |
roberta_spam_bundle = SpamModelBundle(ROBERTA_SPAM_REPO, RobertaForSequenceClassification)
|
| 135 |
electra_spam_bundle = SpamModelBundle(ELECTRA_SPAM_REPO, ElectraForSequenceClassification)
|
| 136 |
roberta_emotion_bundle = EmotionModelBundle(ROBERTA_EMOTION_REPO, RobertaForSequenceClassification)
|
| 137 |
electra_emotion_bundle = EmotionModelBundle(ELECTRA_EMOTION_REPO, ElectraForSequenceClassification)
|
|
|
|
| 138 |
print(f"All models ready on {DEVICE}.")
|
| 139 |
|
| 140 |
|
|
@@ -179,6 +184,7 @@ class EmotionPredictResponse(BaseModel):
|
|
| 179 |
all_scores: list[EmotionScore] # ensemble averaged, sorted by probability
|
| 180 |
roberta: Optional[EmotionModelResult] = None
|
| 181 |
electra: Optional[EmotionModelResult] = None
|
|
|
|
| 182 |
|
| 183 |
|
| 184 |
class EmlRequest(BaseModel):
|
|
@@ -201,15 +207,17 @@ def classify_spam(proba: float, threshold: float) -> dict:
|
|
| 201 |
def ensemble_emotions(
|
| 202 |
roberta_probas: dict[str, float],
|
| 203 |
electra_probas: dict[str, float],
|
|
|
|
| 204 |
threshold_per_class: dict[str, float],
|
| 205 |
) -> tuple[list[str], list[EmotionScore]]:
|
| 206 |
-
"""Average
|
| 207 |
all_scores: list[EmotionScore] = []
|
| 208 |
detected: list[str] = []
|
| 209 |
|
| 210 |
for emotion, r_prob in roberta_probas.items():
|
| 211 |
e_prob = electra_probas.get(emotion, 0.0)
|
| 212 |
-
|
|
|
|
| 213 |
threshold = threshold_per_class.get(emotion, 0.4)
|
| 214 |
is_detected = avg_prob >= threshold
|
| 215 |
all_scores.append(EmotionScore(
|
|
@@ -285,7 +293,11 @@ def health():
|
|
| 285 |
"status": "healthy",
|
| 286 |
"device": DEVICE,
|
| 287 |
"spam_models_loaded": roberta_spam_bundle is not None and electra_spam_bundle is not None,
|
| 288 |
-
"emotion_models_loaded":
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
}
|
| 290 |
|
| 291 |
|
|
@@ -344,10 +356,14 @@ def predict_emotion(req: EmotionPredictRequest):
|
|
| 344 |
|
| 345 |
roberta_probas = roberta_emotion_bundle.predict_proba(req.text)
|
| 346 |
electra_probas = electra_emotion_bundle.predict_proba(req.text)
|
|
|
|
| 347 |
|
| 348 |
-
# Use roberta's per-class thresholds (
|
| 349 |
detected, all_scores = ensemble_emotions(
|
| 350 |
-
roberta_probas,
|
|
|
|
|
|
|
|
|
|
| 351 |
)
|
| 352 |
|
| 353 |
return EmotionPredictResponse(
|
|
@@ -356,6 +372,7 @@ def predict_emotion(req: EmotionPredictRequest):
|
|
| 356 |
all_scores=all_scores,
|
| 357 |
roberta=_emotion_model_result(roberta_emotion_bundle, roberta_probas),
|
| 358 |
electra=_emotion_model_result(electra_emotion_bundle, electra_probas),
|
|
|
|
| 359 |
)
|
| 360 |
|
| 361 |
|
|
|
|
| 1 |
"""
|
| 2 |
Spam Detection + Emotion Analysis API
|
| 3 |
+
Ensemble of RoBERTa-Large + ELECTRA-Large classifiers for spam,
|
| 4 |
+
and RoBERTa-Large + ELECTRA-Large + DeBERTa-v3-Large for emotion.
|
| 5 |
Run with: uvicorn api:app --reload
|
| 6 |
"""
|
| 7 |
|
|
|
|
| 16 |
from pydantic import BaseModel
|
| 17 |
from transformers import (
|
| 18 |
AutoTokenizer,
|
| 19 |
+
DebertaV2ForSequenceClassification,
|
| 20 |
ElectraForSequenceClassification,
|
| 21 |
RobertaForSequenceClassification,
|
| 22 |
)
|
|
|
|
| 27 |
ELECTRA_SPAM_REPO = "Dpedrinho01/trained_electra_large"
|
| 28 |
ROBERTA_EMOTION_REPO = "Dpedrinho01/trained_roberta_emotion"
|
| 29 |
ELECTRA_EMOTION_REPO = "Dpedrinho01/trained_electra_emotion"
|
| 30 |
+
DEBERTA_EMOTION_REPO = "Dpedrinho01/trained_deberta_v3_large_emotion"
|
| 31 |
|
| 32 |
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
| 33 |
|
|
|
|
| 127 |
electra_spam_bundle: Optional[SpamModelBundle] = None
|
| 128 |
roberta_emotion_bundle: Optional[EmotionModelBundle] = None
|
| 129 |
electra_emotion_bundle: Optional[EmotionModelBundle] = None
|
| 130 |
+
deberta_emotion_bundle: Optional[EmotionModelBundle] = None
|
| 131 |
|
| 132 |
|
| 133 |
@app.on_event("startup")
|
| 134 |
def load_models():
|
| 135 |
global roberta_spam_bundle, electra_spam_bundle
|
| 136 |
+
global roberta_emotion_bundle, electra_emotion_bundle, deberta_emotion_bundle
|
| 137 |
|
| 138 |
roberta_spam_bundle = SpamModelBundle(ROBERTA_SPAM_REPO, RobertaForSequenceClassification)
|
| 139 |
electra_spam_bundle = SpamModelBundle(ELECTRA_SPAM_REPO, ElectraForSequenceClassification)
|
| 140 |
roberta_emotion_bundle = EmotionModelBundle(ROBERTA_EMOTION_REPO, RobertaForSequenceClassification)
|
| 141 |
electra_emotion_bundle = EmotionModelBundle(ELECTRA_EMOTION_REPO, ElectraForSequenceClassification)
|
| 142 |
+
deberta_emotion_bundle = EmotionModelBundle(DEBERTA_EMOTION_REPO, DebertaV2ForSequenceClassification)
|
| 143 |
print(f"All models ready on {DEVICE}.")
|
| 144 |
|
| 145 |
|
|
|
|
| 184 |
all_scores: list[EmotionScore] # ensemble averaged, sorted by probability
|
| 185 |
roberta: Optional[EmotionModelResult] = None
|
| 186 |
electra: Optional[EmotionModelResult] = None
|
| 187 |
+
deberta: Optional[EmotionModelResult] = None
|
| 188 |
|
| 189 |
|
| 190 |
class EmlRequest(BaseModel):
|
|
|
|
| 207 |
def ensemble_emotions(
|
| 208 |
roberta_probas: dict[str, float],
|
| 209 |
electra_probas: dict[str, float],
|
| 210 |
+
deberta_probas: dict[str, float],
|
| 211 |
threshold_per_class: dict[str, float],
|
| 212 |
) -> tuple[list[str], list[EmotionScore]]:
|
| 213 |
+
"""Average all three models' probabilities and apply per-class thresholds."""
|
| 214 |
all_scores: list[EmotionScore] = []
|
| 215 |
detected: list[str] = []
|
| 216 |
|
| 217 |
for emotion, r_prob in roberta_probas.items():
|
| 218 |
e_prob = electra_probas.get(emotion, 0.0)
|
| 219 |
+
d_prob = deberta_probas.get(emotion, 0.0)
|
| 220 |
+
avg_prob = round((r_prob + e_prob + d_prob) / 3, 4)
|
| 221 |
threshold = threshold_per_class.get(emotion, 0.4)
|
| 222 |
is_detected = avg_prob >= threshold
|
| 223 |
all_scores.append(EmotionScore(
|
|
|
|
| 293 |
"status": "healthy",
|
| 294 |
"device": DEVICE,
|
| 295 |
"spam_models_loaded": roberta_spam_bundle is not None and electra_spam_bundle is not None,
|
| 296 |
+
"emotion_models_loaded": (
|
| 297 |
+
roberta_emotion_bundle is not None
|
| 298 |
+
and electra_emotion_bundle is not None
|
| 299 |
+
and deberta_emotion_bundle is not None
|
| 300 |
+
),
|
| 301 |
}
|
| 302 |
|
| 303 |
|
|
|
|
| 356 |
|
| 357 |
roberta_probas = roberta_emotion_bundle.predict_proba(req.text)
|
| 358 |
electra_probas = electra_emotion_bundle.predict_proba(req.text)
|
| 359 |
+
deberta_probas = deberta_emotion_bundle.predict_proba(req.text)
|
| 360 |
|
| 361 |
+
# Use roberta's per-class thresholds (all models share the same config structure)
|
| 362 |
detected, all_scores = ensemble_emotions(
|
| 363 |
+
roberta_probas,
|
| 364 |
+
electra_probas,
|
| 365 |
+
deberta_probas,
|
| 366 |
+
roberta_emotion_bundle.threshold_per_class,
|
| 367 |
)
|
| 368 |
|
| 369 |
return EmotionPredictResponse(
|
|
|
|
| 372 |
all_scores=all_scores,
|
| 373 |
roberta=_emotion_model_result(roberta_emotion_bundle, roberta_probas),
|
| 374 |
electra=_emotion_model_result(electra_emotion_bundle, electra_probas),
|
| 375 |
+
deberta=_emotion_model_result(deberta_emotion_bundle, deberta_probas),
|
| 376 |
)
|
| 377 |
|
| 378 |
|