KrizTech100 commited on
Commit
92972fa
Β·
verified Β·
1 Parent(s): c420504

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -24
app.py CHANGED
@@ -36,14 +36,25 @@ aai.settings.api_key = os.getenv("ASSEMBLYAI_API_KEY")
36
  device = "cuda" if torch.cuda.is_available() else "cpu"
37
 
38
  tokenizer = AutoTokenizer.from_pretrained(
39
- "nlptown/bert-base-multilingual-uncased-sentiment"
40
  )
41
  sentiment_model = AutoModelForSequenceClassification.from_pretrained(
42
- "nlptown/bert-base-multilingual-uncased-sentiment"
43
  )
44
  sentiment_model.to(device)
45
  sentiment_model.eval()
46
 
 
 
 
 
 
 
 
 
 
 
 
47
  # =========================
48
  # HELPERS
49
  # =========================
@@ -52,12 +63,41 @@ def format_time(ms):
52
  return f"{int(s // 60):02d}:{int(s % 60):02d}"
53
 
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  def analyze_sentiment(text):
56
- inputs = tokenizer(text[:512], return_tensors="pt", truncation=True).to(device)
 
 
 
 
 
 
57
  with torch.no_grad():
58
  logits = sentiment_model(**inputs).logits
59
  probs = F.softmax(logits, dim=-1)[0]
60
- return torch.argmax(probs).item() + 1
61
 
62
 
63
  def build_segments(transcript):
@@ -96,6 +136,7 @@ def process_audio(file, speakers, language, state):
96
  speaker_labels=True,
97
  speakers_expected=int(speakers) if speakers > 0 else None,
98
  language_code=None if language == "auto" else language,
 
99
  )
100
  transcript = aai.Transcriber().transcribe(temp_wav, config)
101
 
@@ -105,26 +146,34 @@ def process_audio(file, speakers, language, state):
105
  segments = build_segments(transcript)
106
  speaker_count = len(set(s["speaker"] for s in segments))
107
 
108
- label_map = {
109
- 1: ("πŸ”΄", "Very Negative"),
110
- 2: ("🟠", "Negative"),
111
- 3: ("🟑", "Neutral"),
112
- 4: ("🟒", "Positive"),
113
- 5: ("🟒", "Very Positive"),
114
- }
115
-
116
  conversation = ""
117
- for i, seg in enumerate(segments, start=1):
118
- score = analyze_sentiment(seg["text"])
119
- emoji, label = label_map.get(score, ("βšͺ", "Unknown"))
120
- seg["sentiment"] = label
121
- conversation += (
122
- f"Speaker {seg['speaker']} | Utterance {i}\n"
123
- f"({seg['start']} - {seg['end']})\n"
124
- f"{emoji} {label}: {seg['text']}\n\n"
125
- )
126
 
127
- new_state = {"segments": segments, "conversation": conversation}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  return (
129
  "βœ… Done",
130
  conversation,
@@ -163,7 +212,7 @@ def export_file(format_type, state):
163
  path = f"/tmp/conversation_{timestamp}.csv"
164
  with open(path, "w", newline="", encoding="utf-8") as f:
165
  writer = csv.DictWriter(
166
- f, fieldnames=["speaker", "start", "end", "text", "sentiment"]
167
  )
168
  writer.writeheader()
169
  writer.writerows(segments)
@@ -235,4 +284,4 @@ with gr.Blocks(title="AI Conversation Sentiment Analyzer", theme=gr.themes.Soft(
235
  )
236
 
237
  if __name__ == "__main__":
238
- app.launch(server_name="0.0.0.0", server_port=7860)
 
36
  device = "cuda" if torch.cuda.is_available() else "cpu"
37
 
38
  tokenizer = AutoTokenizer.from_pretrained(
39
+ "j-hartmann/emotion-english-distilroberta-base"
40
  )
41
  sentiment_model = AutoModelForSequenceClassification.from_pretrained(
42
+ "j-hartmann/emotion-english-distilroberta-base"
43
  )
44
  sentiment_model.to(device)
45
  sentiment_model.eval()
46
 
47
+ # Maps model's 7 emotion classes to business-friendly labels
48
+ EMOTION_LABELS = {
49
+ 0: ("πŸ”΄", "Negative"), # Anger
50
+ 1: ("πŸ”΄", "Negative"), # Disgust
51
+ 2: ("πŸ”΄", "Negative"), # Fear
52
+ 3: ("🟒", "Positive"), # Joy
53
+ 4: ("🟑", "Neutral"), # Neutral
54
+ 5: ("πŸ”΄", "Negative"), # Sadness
55
+ 6: ("🟒", "Positive"), # Surprise
56
+ }
57
+
58
  # =========================
59
  # HELPERS
60
  # =========================
 
63
  return f"{int(s // 60):02d}:{int(s % 60):02d}"
64
 
65
 
66
+ def split_into_chunks(text, chunk_size=200):
67
+ """
68
+ Split text into equal fixed-character chunks.
69
+ Breaks at the nearest space to avoid cutting mid-word.
70
+ """
71
+ text = text.strip()
72
+ if len(text) <= chunk_size:
73
+ return [text]
74
+
75
+ chunks = []
76
+ while len(text) > chunk_size:
77
+ split_at = text.rfind(" ", 0, chunk_size)
78
+ if split_at == -1:
79
+ split_at = chunk_size
80
+ chunks.append(text[:split_at].strip())
81
+ text = text[split_at:].strip()
82
+
83
+ if text:
84
+ chunks.append(text)
85
+
86
+ return chunks
87
+
88
+
89
  def analyze_sentiment(text):
90
+ inputs = tokenizer(
91
+ text,
92
+ return_tensors="pt",
93
+ truncation=True,
94
+ max_length=512,
95
+ padding=True
96
+ ).to(device)
97
  with torch.no_grad():
98
  logits = sentiment_model(**inputs).logits
99
  probs = F.softmax(logits, dim=-1)[0]
100
+ return torch.argmax(probs).item()
101
 
102
 
103
  def build_segments(transcript):
 
136
  speaker_labels=True,
137
  speakers_expected=int(speakers) if speakers > 0 else None,
138
  language_code=None if language == "auto" else language,
139
+ speech_model=aai.SpeechModel.best
140
  )
141
  transcript = aai.Transcriber().transcribe(temp_wav, config)
142
 
 
146
  segments = build_segments(transcript)
147
  speaker_count = len(set(s["speaker"] for s in segments))
148
 
 
 
 
 
 
 
 
 
149
  conversation = ""
150
+ export_segments = []
 
 
 
 
 
 
 
 
151
 
152
+ for i, seg in enumerate(segments, start=1):
153
+ chunks = split_into_chunks(seg["text"])
154
+
155
+ for c_idx, chunk in enumerate(chunks, start=1):
156
+ emotion_idx = analyze_sentiment(chunk)
157
+ emoji, label = EMOTION_LABELS.get(emotion_idx, ("βšͺ", "Unknown"))
158
+
159
+ chunk_label = f" | Chunk {c_idx}" if len(chunks) > 1 else ""
160
+
161
+ conversation += (
162
+ f"Speaker {seg['speaker']} | Utterance {i}{chunk_label}\n"
163
+ f"({seg['start']} - {seg['end']})\n"
164
+ f"{emoji} {label}: {chunk}\n\n"
165
+ )
166
+
167
+ export_segments.append({
168
+ "speaker": seg["speaker"],
169
+ "start": seg["start"],
170
+ "end": seg["end"],
171
+ "chunk": c_idx,
172
+ "text": chunk,
173
+ "sentiment": label,
174
+ })
175
+
176
+ new_state = {"segments": export_segments, "conversation": conversation}
177
  return (
178
  "βœ… Done",
179
  conversation,
 
212
  path = f"/tmp/conversation_{timestamp}.csv"
213
  with open(path, "w", newline="", encoding="utf-8") as f:
214
  writer = csv.DictWriter(
215
+ f, fieldnames=["speaker", "start", "end", "chunk", "text", "sentiment"]
216
  )
217
  writer.writeheader()
218
  writer.writerows(segments)
 
284
  )
285
 
286
  if __name__ == "__main__":
287
+ app.launch(server_name="0.0.0.0", server_port=7860)