ningaraddi commited on
Commit
113c6bb
·
verified ·
1 Parent(s): 586a7fa

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -26
app.py CHANGED
@@ -1,8 +1,9 @@
1
  # app.py — HuggingFace Space (FastAPI)
2
- # Serves our fine-tuned sentiment model as a REST API
3
- # Deploy this to: huggingface.co/spaces/YOUR_USERNAME/creatorpulse-api
4
 
5
  from fastapi import FastAPI
 
6
  from pydantic import BaseModel
7
  from typing import List
8
  from transformers import pipeline
@@ -10,55 +11,67 @@ import os
10
 
11
  app = FastAPI(title="CreatorPulse Sentiment API")
12
 
 
 
 
 
 
 
 
 
13
  # ── Load model once on startup ─────────────────────────────────────────────────
14
- HF_USERNAME = os.getenv("HF_USERNAME", "ningaraddi")
15
- MODEL_REPO = f"{HF_USERNAME}/creatorpulse-sentiment"
16
 
17
- print(f"Loading model from {MODEL_REPO}...")
18
 
19
  classifier = pipeline(
20
- "sentiment-analysis",
21
  model=MODEL_REPO,
22
  tokenizer=MODEL_REPO,
23
  truncation=True,
24
  max_length=128,
25
- device=-1 # CPU on free tier — fast enough for our use case
 
26
  )
27
 
28
- print("Model loaded and ready.")
29
 
30
- # ── Request / Response schemas ──────────────────────────────────────────────────
31
  class ClassifyRequest(BaseModel):
32
- texts: List[str] # up to 100 comments at once
33
 
34
- class PredictionResult(BaseModel):
35
- text: str
36
- label: str # POSITIVE | NEUTRAL | NEGATIVE
37
  confidence: float
 
38
 
39
  class ClassifyResponse(BaseModel):
40
- predictions: List[PredictionResult]
41
 
42
- # ── Health check ───────────────────────────────────────────────────────────────
43
  @app.get("/")
44
  def health():
45
  return {"status": "ok", "model": MODEL_REPO}
46
 
47
- # ── Main classify endpoint ──────────────────────────────────────────────────────
48
  @app.post("/classify", response_model=ClassifyResponse)
49
  def classify(request: ClassifyRequest):
50
- # Limit to 100 texts per call to avoid timeout
51
- texts = request.texts[:100]
 
 
 
 
 
52
 
53
- results = classifier(texts, batch_size=16)
 
 
54
 
55
- predictions = [
56
- PredictionResult(
57
  text=text,
58
- label=result["label"], # POSITIVE / NEUTRAL / NEGATIVE
59
- confidence=round(result["score"], 4)
60
- )
61
- for text, result in zip(texts, results)
62
- ]
63
 
64
  return ClassifyResponse(predictions=predictions)
 
1
  # app.py — HuggingFace Space (FastAPI)
2
+ # FREE CPU tier hosting for CreatorPulse sentiment model
3
+ # Space URL: https://ningaraddi-creatorpulse-api.hf.space
4
 
5
  from fastapi import FastAPI
6
+ from fastapi.middleware.cors import CORSMiddleware
7
  from pydantic import BaseModel
8
  from typing import List
9
  from transformers import pipeline
 
11
 
12
  app = FastAPI(title="CreatorPulse Sentiment API")
13
 
14
+ # ── CORS — allow calls from any origin (our React app) ─────────────────────────
15
+ app.add_middleware(
16
+ CORSMiddleware,
17
+ allow_origins=["*"],
18
+ allow_methods=["POST", "GET"],
19
+ allow_headers=["*"],
20
+ )
21
+
22
  # ── Load model once on startup ─────────────────────────────────────────────────
23
+ MODEL_REPO = "ningaraddi/creatorpulse-sentiment"
 
24
 
25
+ print(f"Loading model: {MODEL_REPO}")
26
 
27
  classifier = pipeline(
28
+ "text-classification",
29
  model=MODEL_REPO,
30
  tokenizer=MODEL_REPO,
31
  truncation=True,
32
  max_length=128,
33
+ device=-1, # CPU free tier
34
+ top_k=None, # Return all labels with scores
35
  )
36
 
37
+ print("Model loaded!")
38
 
39
+ # ── Schemas ────────────────────────────────────────────────────────────────────
40
  class ClassifyRequest(BaseModel):
41
+ inputs: List[str]
42
 
43
+ class Prediction(BaseModel):
44
+ label: str
 
45
  confidence: float
46
+ text: str
47
 
48
  class ClassifyResponse(BaseModel):
49
+ predictions: List[Prediction]
50
 
51
+ # ── Health check ───────────────────────────────────────────────────────────────
52
  @app.get("/")
53
  def health():
54
  return {"status": "ok", "model": MODEL_REPO}
55
 
56
+ # ── Classify endpoint ──────────────────────────────────────────────────────────
57
  @app.post("/classify", response_model=ClassifyResponse)
58
  def classify(request: ClassifyRequest):
59
+ texts = request.inputs[:100] # Max 100 per call
60
+
61
+ results = classifier(texts, batch_size=8)
62
+
63
+ predictions = []
64
+ for text, label_list in zip(texts, results):
65
+ top = max(label_list, key=lambda x: x["score"])
66
 
67
+ # Normalize label names
68
+ label_map = {"LABEL_0": "NEGATIVE", "LABEL_1": "NEUTRAL", "LABEL_2": "POSITIVE"}
69
+ label = label_map.get(top["label"], top["label"])
70
 
71
+ predictions.append(Prediction(
 
72
  text=text,
73
+ label=label,
74
+ confidence=round(top["score"], 4),
75
+ ))
 
 
76
 
77
  return ClassifyResponse(predictions=predictions)