CadenShokat commited on
Commit
020a076
·
verified ·
1 Parent(s): 264c9fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +41 -26
app.py CHANGED
@@ -2,47 +2,62 @@ from fastapi import FastAPI
2
  from pydantic import BaseModel
3
  from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
4
 
5
- MODEL_ID = "cardiffnlp/twitter-roberta-base-sentiment-latest"
 
6
 
7
  app = FastAPI()
 
 
8
 
9
  @app.get("/")
10
  def root():
11
- return {"status": "ok"}
12
 
13
  @app.get("/healthz")
14
- def healthz():
15
- return {"status": "healthy"}
16
-
17
- tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
18
- model = AutoModelForSequenceClassification.from_pretrained(MODEL_ID)
19
- clf = pipeline(
20
- "text-classification",
21
- model=model,
22
- tokenizer=tokenizer,
23
- return_all_scores=True,
24
- truncation=True,
25
- )
26
 
27
  class Payload(BaseModel):
28
  sentences: list[str]
29
 
30
- def to_label(scores):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  m = {s["label"].lower(): s["score"] for s in scores}
32
- neg = m.get("negative", m.get("label_0", 0.0))
33
- neu = m.get("neutral", m.get("label_1", 0.0))
34
- pos = m.get("positive", m.get("label_2", 0.0))
35
- conf = max(neg, neu, pos)
36
- if conf < 0.55:
37
- final = "neutral"
38
  else:
39
- final = "positive" if pos >= max(neg, neu) else ("negative" if neg >= max(pos, neu) else "neutral")
40
- return {"label": final, "confidence": conf, "scores": {"positive": pos, "neutral": neu, "negative": neg}}
 
 
 
 
 
41
 
42
  @app.post("/predict")
43
  def predict(payload: Payload):
 
44
  if not payload.sentences:
45
  return {"results": []}
46
- outputs = clf(payload.sentences, top_k=None)
47
- results = [to_label(scores) for scores in outputs]
48
- return {"results": results}
 
 
2
  from pydantic import BaseModel
3
  from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
4
 
5
+ PRIMARY_MODEL = "cardiffnlp/twitter-roberta-base-sentiment-latest"
6
+ FALLBACK_MODEL = "distilbert-base-uncased-finetuned-sst-2-english"
7
 
8
  app = FastAPI()
9
+ clf = None
10
+ loaded_model_id = None
11
 
12
  @app.get("/")
13
  def root():
14
+ return {"status": "ok", "model": loaded_model_id}
15
 
16
  @app.get("/healthz")
17
+ def health():
18
+ return {"status": "healthy", "model": loaded_model_id}
 
 
 
 
 
 
 
 
 
 
19
 
20
  class Payload(BaseModel):
21
  sentences: list[str]
22
 
23
+ def load_pipeline():
24
+ global clf, loaded_model_id
25
+ if clf is not None:
26
+ return clf
27
+ # Try primary (3-class), then fallback (binary)
28
+ for model_id in (PRIMARY_MODEL, FALLBACK_MODEL):
29
+ try:
30
+ tok = AutoTokenizer.from_pretrained(model_id)
31
+ mdl = AutoModelForSequenceClassification.from_pretrained(model_id)
32
+ clf = pipeline("text-classification", model=mdl, tokenizer=tok, return_all_scores=True, truncation=True)
33
+ loaded_model_id = model_id
34
+ return clf
35
+ except Exception as e:
36
+ print(f"Failed to load {model_id}: {e}")
37
+ raise RuntimeError("No sentiment model could be loaded")
38
+
39
+ def scores_to_label(scores, binary=False):
40
  m = {s["label"].lower(): s["score"] for s in scores}
41
+ if binary or ("neutral" not in m):
42
+ neg, pos = m.get("negative", 0.0), m.get("positive", 0.0)
43
+ conf = max(neg, pos)
44
+ label = "positive" if pos >= neg else "negative"
45
+ return {"label": label, "confidence": conf, "scores": {"positive": pos, "neutral": 0.0, "negative": neg}}
 
46
  else:
47
+ neg, neu, pos = m.get("negative", 0.0), m.get("neutral", 0.0), m.get("positive", 0.0)
48
+ conf = max(neg, neu, pos)
49
+ # Optional neutral clamp for low confidence
50
+ label = "positive" if pos >= max(neg, neu) else ("negative" if neg >= max(pos, neu) else "neutral")
51
+ if conf < 0.55:
52
+ label = "neutral"
53
+ return {"label": label, "confidence": conf, "scores": {"positive": pos, "neutral": neu, "negative": neg}}
54
 
55
  @app.post("/predict")
56
  def predict(payload: Payload):
57
+ classifier = load_pipeline()
58
  if not payload.sentences:
59
  return {"results": []}
60
+ outputs = classifier(payload.sentences, top_k=None)
61
+ binary = (loaded_model_id == FALLBACK_MODEL)
62
+ results = [scores_to_label(scores, binary=binary) for scores in outputs]
63
+ return {"model": loaded_model_id, "results": results}