Abhirudraa commited on
Commit
605c6bb
·
verified ·
1 Parent(s): 297fc2c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -63
app.py CHANGED
@@ -1,91 +1,100 @@
1
- import json
2
- from pathlib import Path
3
- from typing import Dict, Tuple, List
4
-
5
  import gradio as gr
6
  import torch
7
  import torch.nn as nn
 
8
  from transformers import AutoTokenizer, AutoConfig, AutoModel
9
 
 
 
 
10
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
11
- META_PATH = "meta.json"
12
- WEIGHTS_PATH = "best_model.pth"
13
  TOKENIZER_PATH = "tokenizer"
 
14
 
 
 
 
 
 
 
15
 
16
- def load_meta(path: str) -> Dict:
17
- p = Path(path)
18
- if not p.exists():
19
- return {"target_cols": ["anger", "fear", "joy", "sadness", "surprise"], "max_length": 256, "backbone": "microsoft/deberta-v3-base"}
20
- with p.open("r", encoding="utf8") as f:
21
- return json.load(f)
22
-
23
-
24
- meta = load_meta(META_PATH)
25
- TARGET_COLS: List[str] = meta.get("target_cols", ["anger", "fear", "joy", "sadness", "surprise"])
26
- MAX_LENGTH: int = meta.get("max_length", 256)
27
- BACKBONE: str = meta.get("backbone", "microsoft/deberta-v3-base")
28
-
29
  tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH)
30
 
31
-
 
 
32
  class EmotionClassifier(nn.Module):
33
- def __init__(self, model_name: str, num_labels: int, dropout_rate: float = 0.3):
34
  super().__init__()
35
  self.config = AutoConfig.from_pretrained(model_name)
36
  self.transformer = AutoModel.from_pretrained(model_name)
37
  self.dropout = nn.Dropout(dropout_rate)
38
  self.classifier = nn.Linear(self.config.hidden_size, num_labels)
39
 
40
- def forward(self, input_ids: torch.Tensor, attention_mask: torch.Tensor) -> torch.Tensor:
41
  outputs = self.transformer(input_ids=input_ids, attention_mask=attention_mask)
42
  cls = outputs.last_hidden_state[:, 0, :]
43
  cls = self.dropout(cls)
44
- return self.classifier(cls)
45
-
46
-
47
- def build_and_load_model(backbone: str, weights_path: str, num_labels: int) -> nn.Module:
48
- model = EmotionClassifier(backbone, num_labels=num_labels)
49
- device = DEVICE
50
- if Path(weights_path).exists():
51
- state = torch.load(weights_path, map_location=device)
52
- if isinstance(state, dict) and "state_dict" in state:
53
- state = state["state_dict"]
54
- cleaned = {k.replace("module.", ""): v for k, v in state.items()}
55
- model.load_state_dict(cleaned, strict=False)
56
- model.to(device)
57
- model.eval()
58
- return model
59
-
60
-
61
- model = build_and_load_model(BACKBONE, WEIGHTS_PATH, num_labels=len(TARGET_COLS))
62
-
63
-
64
- def predict_text(text: str, threshold: float = 0.5) -> Tuple[Dict[str, float], Dict[str, int]]:
65
- inputs = tokenizer(text, truncation=True, padding=True, max_length=MAX_LENGTH, return_tensors="pt")
66
- inputs = {k: v.to(DEVICE) for k, v in inputs.items()}
 
 
 
 
67
  with torch.no_grad():
68
  logits = model(**inputs)
69
- probs = torch.sigmoid(logits).cpu().numpy().ravel()
70
- percentages = {label: round(float(p) * 100.0, 2) for label, p in zip(TARGET_COLS, probs)}
71
- binary = {label: int(p > threshold) for label, p in zip(TARGET_COLS, probs)}
 
 
 
 
 
 
 
72
  percentages_sorted = dict(sorted(percentages.items(), key=lambda x: x[1], reverse=True))
 
73
  return percentages_sorted, binary
74
 
75
-
76
- def create_gradio_app():
77
- demo = gr.Blocks()
78
- with demo:
79
- gr.Markdown("# Multi-label Emotion Classifier")
80
- txt = gr.Textbox(lines=4, placeholder="Enter text here...", label="Input Text")
81
- thresh = gr.Slider(minimum=0.1, maximum=0.9, value=0.5, step=0.01, label="Threshold")
82
- btn = gr.Button("Predict")
83
- probs_out = gr.Label(label="Emotion Probabilities (%)")
84
- binary_out = gr.JSON(label="Binary Predictions (0/1)")
85
- btn.click(predict_text, inputs=[txt, thresh], outputs=[probs_out, binary_out])
86
- return demo
87
-
88
 
89
  if __name__ == "__main__":
90
- app = create_gradio_app()
91
- app.launch()
 
 
 
 
 
1
  import gradio as gr
2
  import torch
3
  import torch.nn as nn
4
+ import json
5
  from transformers import AutoTokenizer, AutoConfig, AutoModel
6
 
7
+ # ----------------------------
8
+ # Configuration / Meta
9
+ # ----------------------------
10
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
11
+ MAX_LENGTH = 256
12
+ WEIGHTS_PATH = "best_model.pth" # your model file
13
  TOKENIZER_PATH = "tokenizer"
14
+ META_PATH = "meta.json"
15
 
16
+ # Load meta.json
17
+ with open(META_PATH, "r") as f:
18
+ meta = json.load(f)
19
+ TARGET_COLS = meta.get("target_cols", ["anger","fear","joy","sadness","surprise"])
20
+ MAX_LENGTH = meta.get("max_length", MAX_LENGTH)
21
+ BACKBONE = meta.get("backbone", "microsoft/deberta-v3-base")
22
 
23
+ # ----------------------------
24
+ # Load tokenizer
25
+ # ----------------------------
 
 
 
 
 
 
 
 
 
 
26
  tokenizer = AutoTokenizer.from_pretrained(TOKENIZER_PATH)
27
 
28
+ # ----------------------------
29
+ # Define model class
30
+ # ----------------------------
31
  class EmotionClassifier(nn.Module):
32
+ def __init__(self, model_name, num_labels=5, dropout_rate=0.3):
33
  super().__init__()
34
  self.config = AutoConfig.from_pretrained(model_name)
35
  self.transformer = AutoModel.from_pretrained(model_name)
36
  self.dropout = nn.Dropout(dropout_rate)
37
  self.classifier = nn.Linear(self.config.hidden_size, num_labels)
38
 
39
+ def forward(self, input_ids, attention_mask):
40
  outputs = self.transformer(input_ids=input_ids, attention_mask=attention_mask)
41
  cls = outputs.last_hidden_state[:, 0, :]
42
  cls = self.dropout(cls)
43
+ logits = self.classifier(cls)
44
+ return logits
45
+
46
+ # ----------------------------
47
+ # Load model
48
+ # ----------------------------
49
+ model = EmotionClassifier(BACKBONE, num_labels=len(TARGET_COLS))
50
+ state = torch.load(WEIGHTS_PATH, map_location=DEVICE)
51
+ # Strip 'module.' prefix if present
52
+ new_state = {k.replace("module.", ""): v for k,v in state.items()}
53
+ model.load_state_dict(new_state, strict=False)
54
+ model.to(DEVICE)
55
+ model.eval()
56
+
57
+ # ----------------------------
58
+ # Prediction function
59
+ # ----------------------------
60
+ def predict_text(text, threshold=0.5):
61
+ inputs = tokenizer(
62
+ text,
63
+ truncation=True,
64
+ padding=True,
65
+ max_length=MAX_LENGTH,
66
+ return_tensors="pt"
67
+ )
68
+ inputs = {k:v.to(DEVICE) for k,v in inputs.items()}
69
+
70
  with torch.no_grad():
71
  logits = model(**inputs)
72
+
73
+ probs = torch.sigmoid(logits).cpu().numpy()[0]
74
+
75
+ # Percentages
76
+ percentages = {label: round(float(p)*100,2) for label,p in zip(TARGET_COLS, probs)}
77
+
78
+ # Binary predictions
79
+ binary = {label: int(p>threshold) for label,p in zip(TARGET_COLS, probs)}
80
+
81
+ # Sort probabilities descending for display
82
  percentages_sorted = dict(sorted(percentages.items(), key=lambda x: x[1], reverse=True))
83
+
84
  return percentages_sorted, binary
85
 
86
+ # ----------------------------
87
+ # Gradio Interface
88
+ # ----------------------------
89
+ with gr.Blocks() as demo:
90
+ gr.Markdown("# Multi-label Emotion Classifier")
91
+ txt = gr.Textbox(lines=4, placeholder="Enter text here...", label="Input Text")
92
+ thresh = gr.Slider(minimum=0.1, maximum=0.9, value=0.5, step=0.01, label="Threshold")
93
+ btn = gr.Button("Predict")
94
+ probs_out = gr.Label(label="Emotion Probabilities (%)")
95
+ binary_out = gr.JSON(label="Binary Predictions (0/1)")
96
+
97
+ btn.click(predict_text, inputs=[txt, thresh], outputs=[probs_out, binary_out])
 
98
 
99
  if __name__ == "__main__":
100
+ demo.launch()