GCLing commited on
Commit
2a89f5d
·
verified ·
1 Parent(s): 82dd2b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -16
app.py CHANGED
@@ -17,58 +17,102 @@ svm_model = joblib.load(model_path)
17
  print("SVM model loaded.")
18
 
19
  # --- 2. 文本情绪分析:规则+zero-shot ---
20
- zero_shot = pipeline("zero-shot-classification", model="joeddav/xlm-roberta-large-xnli")
 
 
 
 
 
21
  candidate_labels = ["joy", "sadness", "anger", "fear", "surprise", "disgust"]
22
  label_map_en2cn = {
23
  "joy": "高興", "sadness": "悲傷", "anger": "憤怒",
24
  "fear": "恐懼", "surprise": "驚訝", "disgust": "厭惡"
25
  }
 
 
26
  emo_keywords = {
27
  "happy": ["開心","快樂","愉快","喜悦","喜悅","歡喜","興奮","高興"],
28
  "angry": ["生氣","憤怒","不爽","發火","火大","氣憤"],
29
  "sad": ["傷心","難過","哭","難受","心酸","憂","悲","哀","痛苦","慘","愁"],
30
  "surprise": ["驚訝","意外","嚇","驚詫","詫異","訝異","好奇"],
31
- "fear": ["怕","恐懼","緊張","懼","膽怯","畏"]
 
32
  }
 
33
  negations = ["不","沒","沒有","別","勿","非"]
34
 
35
  def keyword_emotion(text: str):
 
 
 
 
 
 
 
36
  counts = {emo: 0 for emo in emo_keywords}
37
  for emo, kws in emo_keywords.items():
38
  for w in kws:
39
- idx = text.find(w)
40
  if idx != -1:
41
- # 简单否定检测
42
  neg = False
43
  for neg_word in negations:
44
  plen = len(neg_word)
45
- if idx - plen >= 0 and text[idx-plen:idx] == neg_word:
46
  neg = True
47
  break
48
  if not neg:
49
  counts[emo] += 1
 
 
 
50
  total = sum(counts.values())
51
  if total > 0:
52
- return {emo: counts[emo]/total for emo in counts}
 
53
  else:
54
  return None
55
 
56
  def predict_text_mixed(text: str):
 
 
 
 
 
57
  if not text or text.strip() == "":
 
58
  return {}
 
59
  res = keyword_emotion(text)
 
60
  if res:
61
- top_emo = max(res, key=res.get)
62
- mapping = {"happy":"高兴","angry":"愤怒","sad":"悲伤","surprise":"惊讶","fear":"恐惧"}
 
 
 
 
 
 
 
 
63
  cn = mapping.get(top_emo, top_emo)
64
- return {cn: res[top_emo]}
 
 
 
 
 
 
65
  try:
66
  out = zero_shot(text, candidate_labels=candidate_labels,
67
- hypothesis_template="這句話表達了{}情緒")
 
68
  result = {}
69
  for lab, sc in zip(out["labels"], out["scores"]):
70
  cn = label_map_en2cn.get(lab.lower(), lab)
71
  result[cn] = float(sc)
 
72
  return result
73
  except Exception as e:
74
  print("zero-shot error:", e)
@@ -133,12 +177,15 @@ with gr.Blocks() as demo:
133
  voice_out = gr.Label(label="語音情緒結果")
134
  audio.change(fn=predict_voice, inputs=audio, outputs=voice_out)
135
  # 文字情緒 Tab
136
- with gr.TabItem("文字情緒"):
137
- gr.Markdown("### 文字情緒 分析 (规则+zero-shot)")
138
- with gr.Row():
139
- text = gr.Textbox(lines=3, placeholder="請輸入中文文字…")
140
- text_out = gr.Label(label="文字情緒結果")
141
- text.submit(fn=predict_text_mixed, inputs=text, outputs=text_out)
 
 
 
142
 
143
  if __name__ == "__main__":
144
  demo.launch()
 
17
  print("SVM model loaded.")
18
 
19
  # --- 2. 文本情绪分析:规则+zero-shot ---
20
+ try:
21
+ zero_shot = pipeline("zero-shot-classification", model="joeddav/xlm-roberta-large-xnli")
22
+ except Exception as e:
23
+ print("加载 zero-shot pipeline 失败:", e)
24
+ zero_shot = None
25
+
26
  candidate_labels = ["joy", "sadness", "anger", "fear", "surprise", "disgust"]
27
  label_map_en2cn = {
28
  "joy": "高興", "sadness": "悲傷", "anger": "憤怒",
29
  "fear": "恐懼", "surprise": "驚訝", "disgust": "厭惡"
30
  }
31
+
32
+ # 关键词列表:注意繁简体一致,或可添加两种形式
33
  emo_keywords = {
34
  "happy": ["開心","快樂","愉快","喜悦","喜悅","歡喜","興奮","高興"],
35
  "angry": ["生氣","憤怒","不爽","發火","火大","氣憤"],
36
  "sad": ["傷心","難過","哭","難受","心酸","憂","悲","哀","痛苦","慘","愁"],
37
  "surprise": ["驚訝","意外","嚇","驚詫","詫異","訝異","好奇"],
38
+ "fear": ["怕","恐懼","緊張","懼","膽怯","畏"],
39
+ "disgust": ["噁心","厭惡","反感"] # 如需“厭惡”等
40
  }
41
+ # 否定词列表
42
  negations = ["不","沒","沒有","別","勿","非"]
43
 
44
  def keyword_emotion(text: str):
45
+ """
46
+ 规则方法:扫描 emo_keywords,处理前置否定词。
47
+ 返回 None 或 {} 表示规则未命中;否则返回非空 dict,例如 {'angry': 2, 'sad':1} 或归一化 {'angry':0.67,'sad':0.33}。
48
+ """
49
+ if not text or text.strip() == "":
50
+ return None
51
+ text_proc = text.strip() # 中文不需要 lower
52
  counts = {emo: 0 for emo in emo_keywords}
53
  for emo, kws in emo_keywords.items():
54
  for w in kws:
55
+ idx = text_proc.find(w)
56
  if idx != -1:
57
+ # 检查前一到两字符是否否定词
58
  neg = False
59
  for neg_word in negations:
60
  plen = len(neg_word)
61
+ if idx - plen >= 0 and text_proc[idx-plen:idx] == neg_word:
62
  neg = True
63
  break
64
  if not neg:
65
  counts[emo] += 1
66
+ else:
67
+ # 若否定,可选择减分或忽略;这里忽略
68
+ pass
69
  total = sum(counts.values())
70
  if total > 0:
71
+ # 归一化
72
+ return {emo: counts[emo] / total for emo in counts if counts[emo] > 0}
73
  else:
74
  return None
75
 
76
  def predict_text_mixed(text: str):
77
+ """
78
+ 文本情绪分析:先规则,若规则命中返回最高情绪及其比例;否则fallback zero-shot返回多类别分布。
79
+ 返回 dict[str, float],供 Gradio Label 显示。
80
+ """
81
+ print("predict_text_mixed called, text:", repr(text))
82
  if not text or text.strip() == "":
83
+ print("輸入為空,返回空")
84
  return {}
85
+ # 规则优先
86
  res = keyword_emotion(text)
87
+ print("keyword_emotion result:", res)
88
  if res:
89
+ # 只返回最高项:也可返回完整分布 res
90
+ top_emo = max(res, key=res.get) # 例如 "angry"
91
+ mapping = {
92
+ "happy": "高興",
93
+ "angry": "憤怒",
94
+ "sad": "悲傷",
95
+ "surprise": "驚訝",
96
+ "fear": "恐懼",
97
+ "disgust": "厭惡"
98
+ }
99
  cn = mapping.get(top_emo, top_emo)
100
+ prob = float(res[top_emo])
101
+ print(f"使用規則方法,返回: {{'{cn}': {prob}}}")
102
+ return {cn: prob}
103
+ # 规则未命中,zero-shot fallback
104
+ if zero_shot is None:
105
+ print("zero_shot pipeline 未加载,返回中性")
106
+ return {"中性": 1.0}
107
  try:
108
  out = zero_shot(text, candidate_labels=candidate_labels,
109
+ hypothesis_template="这句話表達了{}情緒")
110
+ print("zero-shot 返回:", out)
111
  result = {}
112
  for lab, sc in zip(out["labels"], out["scores"]):
113
  cn = label_map_en2cn.get(lab.lower(), lab)
114
  result[cn] = float(sc)
115
+ print("zero-shot 结果映射中文:", result)
116
  return result
117
  except Exception as e:
118
  print("zero-shot error:", e)
 
177
  voice_out = gr.Label(label="語音情緒結果")
178
  audio.change(fn=predict_voice, inputs=audio, outputs=voice_out)
179
  # 文字情緒 Tab
180
+ with gr.Blocks() as demo:
181
+ with gr.TabItem("文字情緒"):
182
+ gr.Markdown("### 文字情緒 分析 (规则+zero-shot)")
183
+ with gr.Row():
184
+ text = gr.Textbox(lines=3, placeholder="請輸入中文文字…")
185
+ text_out = gr.Label(label="文字情緒結果")
186
+ btn = gr.Button("分析")
187
+ btn.click(fn=predict_text_mixed, inputs=text, outputs=text_out)
188
+ )
189
 
190
  if __name__ == "__main__":
191
  demo.launch()