Pedrinho-Dev01 commited on
Commit
c7d60e2
·
1 Parent(s): a1de573

API DeBERTa Update

Browse files
Files changed (1) hide show
  1. api.py +24 -7
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 both models' probabilities and apply per-class thresholds."""
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
- avg_prob = round((r_prob + e_prob) / 2, 4)
 
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": roberta_emotion_bundle is not None and electra_emotion_bundle is not None,
 
 
 
 
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 (both models share the same config structure)
349
  detected, all_scores = ensemble_emotions(
350
- roberta_probas, electra_probas, roberta_emotion_bundle.threshold_per_class
 
 
 
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