yiming-0120 commited on
Commit
8fee980
·
verified ·
1 Parent(s): 8fac0d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -44
app.py CHANGED
@@ -115,7 +115,7 @@ def debate_turn(topic, user_stance, user_input_text, user_input_audio, history):
115
  # 將用戶原始語音(路徑)加入歷史
116
  history.append(((processed_audio_path,), None)) # 用戶音訊路徑作為輸入顯示
117
  if user_text and not user_text.startswith("["):
118
- # 成功辨識,在下面會統一加入 history
119
  pass
120
  elif user_text.startswith("["): # 辨識失敗
121
  history.append((user_text, None)) # 顯示錯誤訊息
@@ -127,66 +127,73 @@ def debate_turn(topic, user_stance, user_input_text, user_input_audio, history):
127
  if user_input_text:
128
  user_text = user_input_text
129
  # 將用戶文字輸入加入 history,這會是這一輪的開始
130
- history.append((user_text, None))
 
 
 
 
 
 
 
 
 
 
131
  else:
132
- # 如果兩者都無效 (沒有輸入文字,且語音無效/未提供)
133
  if not processed_audio_path: # 僅當連音訊都沒嘗試時才報錯
134
  history.append(("[錯誤:請提供文字或語音論點]", None))
135
- return history, None, ""
136
- # 如果是語音辨識失敗導致的 user_text 為空,前面已記錄錯誤,這裡不用重複加
137
 
138
  # 確保 user_text 是有效的字串才繼續
139
  if not isinstance(user_text, str) or user_text.startswith("["):
140
  print("Invalid user text, stopping turn.")
141
- return history, None, "" # 可能前面語音辨識失敗,終止這輪
 
 
 
142
 
143
  # --- 準備呼叫 LLM ---
144
- # 從 history 整理出 LLM 需要的 messages 格式
145
  llm_messages = []
 
146
  for i, turn in enumerate(history):
147
  user_msg, ai_msg = turn
148
-
149
- # --- 處理用戶訊息 ---
150
  user_content = None
151
- if isinstance(user_msg, str): # 純文字輸入 或 之前的錯誤/辨識訊息
152
  if not user_msg.startswith("[") and not user_msg.startswith("(語音辨識結果:"):
153
  user_content = user_msg
154
- elif isinstance(user_msg, tuple): # 音訊輸入元組 (路徑,)
155
- # 需要找到對應的辨識結果 (如果有的話)
156
- # 簡單處理:如果這是最新一輪的音訊,user_text 應該已經包含辨識結果
157
- if i == len(history) - 1 and not user_text.startswith("["):
158
  user_content = user_text
159
- # (更健壯的作法是檢查 history[i+1] 是否為辨識結果,但目前結構下直接用 user_text 更直接)
160
 
161
  if user_content:
162
  llm_messages.append({"role": "user", "content": user_content})
163
 
164
-
165
- # --- 處理 AI 訊息 ---
166
  ai_content = None
167
- if isinstance(ai_msg, str): # 純文字回應 或 之前的錯誤訊息
168
  if not ai_msg.startswith("["):
169
  ai_content = ai_msg
170
- elif isinstance(ai_msg, tuple) and len(ai_msg) > 0: # (文字, (音訊路徑,))
171
- if isinstance(ai_msg[0], str) and not ai_msg[0].startswith("["):
172
- ai_content = ai_msg[0] # 取元組中的文字部分
 
 
 
 
173
 
174
  if ai_content:
175
  llm_messages.append({"role": "assistant", "content": ai_content})
176
 
177
-
178
- # 確保最後一條訊息是 user 的輸入 (如果 llm_messages 非空)
179
- if llm_messages and llm_messages[-1]["role"] != "user":
180
- # 這種情況理論上不應發生在正確流程中,但以防萬一
181
- print("Warning: Last message before LLM call is not from user. Appending current user text.")
182
- if not user_text.startswith("["):
183
- llm_messages.append({"role": "user", "content": user_text})
184
- else:
185
- print("Skipping LLM call due to invalid user text.")
186
- return history, None, "" # 無法呼叫 LLM
187
- elif not llm_messages and not user_text.startswith("["):
188
- # 如果是第一輪
189
- llm_messages.append({"role": "user", "content": user_text})
190
 
191
  # --- 呼叫 LLM ---
192
  ai_response_text = call_llm(topic, user_stance, llm_messages)
@@ -198,21 +205,27 @@ def debate_turn(topic, user_stance, user_input_text, user_input_audio, history):
198
  # 找到用戶最新輸入的那一條記錄(它還沒有 AI 回應)
199
  last_user_turn_index = -1
200
  for i in range(len(history) - 1, -1, -1):
201
- if history[i][1] is None: # 找到最後一個 AI 回應為 None 的地方
202
  last_user_turn_index = i
203
  break
204
 
205
  if last_user_turn_index != -1:
206
- if ai_response_audio_path:
207
- # 如果 TTS 成功,組合文字和 Audio 元件
208
- history[last_user_turn_index] = (history[last_user_turn_index][0], (ai_response_text, (ai_response_audio_path,)))
209
- else:
210
- # 如果 TTS 失敗,只顯示文字
211
- history[last_user_turn_index] = (history[last_user_turn_index][0], ai_response_text)
 
 
 
212
  else:
213
- # 理論上不應該發生,表示找不到用戶的輸入回合
214
- print("Error: Could not find user's turn in history to append AI response.")
215
- history.append(("[內部錯誤]", ai_response_text)) # 至少顯示 AI 回應
 
 
 
216
 
217
  # 清空輸入框
218
  return history, None, ""
 
115
  # 將用戶原始語音(路徑)加入歷史
116
  history.append(((processed_audio_path,), None)) # 用戶音訊路徑作為輸入顯示
117
  if user_text and not user_text.startswith("["):
118
+ # 成功辨識,在下面會統一處理
119
  pass
120
  elif user_text.startswith("["): # 辨識失敗
121
  history.append((user_text, None)) # 顯示錯誤訊息
 
127
  if user_input_text:
128
  user_text = user_input_text
129
  # 將用戶文字輸入加入 history,這會是這一輪的開始
130
+ # 如果前面已經因為 audio 加入了 history,這裡就不重複加
131
+ if not processed_audio_path:
132
+ history.append((user_text, None))
133
+ # 如果 audio 辨識失敗,且有文字輸入,用文字覆蓋辨識結果 (或者提示用戶?)
134
+ # 這裡選擇使用文字輸入(如果有的話)
135
+ elif user_input_text:
136
+ user_text = user_input_text
137
+ # 替換掉 history 中 audio 辨識失敗的訊息,或者追加? 這裡選擇追加文字輸入
138
+ history.append((user_text, None))
139
+
140
+
141
  else:
142
+ # 如果兩者都無效 (沒有輸入文字,且音訊無效/未提供/辨識失敗)
143
  if not processed_audio_path: # 僅當連音訊都沒嘗試時才報錯
144
  history.append(("[錯誤:請提供文字或語音論點]", None))
145
+ # 如果是語音辨識失敗,前面已加入錯誤訊息
146
+ return history, None, ""
147
 
148
  # 確保 user_text 是有效的字串才繼續
149
  if not isinstance(user_text, str) or user_text.startswith("["):
150
  print("Invalid user text, stopping turn.")
151
+ # 如果 history 最後一筆是 audio tuple,且辨識失敗,避免錯誤繼續
152
+ if history and isinstance(history[-1][0], tuple) and history[-1][1] is None:
153
+ history.append((f"[無法處理用戶輸入: {user_text}]", None))
154
+ return history, None, ""
155
 
156
  # --- 準備呼叫 LLM ---
 
157
  llm_messages = []
158
+ # 從 history 整理出 LLM 需要的 messages 格式 (保持不變)
159
  for i, turn in enumerate(history):
160
  user_msg, ai_msg = turn
 
 
161
  user_content = None
162
+ if isinstance(user_msg, str):
163
  if not user_msg.startswith("[") and not user_msg.startswith("(語音辨識結果:"):
164
  user_content = user_msg
165
+ elif isinstance(user_msg, tuple):
166
+ # 如果是最新一輪的音訊,用 call_asr 的結果
167
+ # 這裡需要更可靠的方式找到辨識結果,但為了簡化,先假設 user_text 是對的
168
+ if i == len(history) - 1 and not user_text.startswith("["): # 假設 user_text 是剛辨識的
169
  user_content = user_text
170
+ # 注意:如果歷史中有多次語音,這裡的邏輯需要加強才能正確配對
171
 
172
  if user_content:
173
  llm_messages.append({"role": "user", "content": user_content})
174
 
 
 
175
  ai_content = None
176
+ if isinstance(ai_msg, str):
177
  if not ai_msg.startswith("["):
178
  ai_content = ai_msg
179
+ elif isinstance(ai_msg, tuple) and len(ai_msg) > 0:
180
+ # 之前的結構是 (文字, (音訊,)),現在已修改,但先保留兼容舊結構的解析
181
+ if isinstance(ai_msg[0], str) and not ai_msg[0].startswith("["):
182
+ ai_content = ai_msg[0]
183
+ # 新結構是 (音訊路徑,)
184
+ elif isinstance(ai_msg[0], str) and ai_msg[0].endswith(".mp3"):
185
+ pass # 這是音訊,不是文本內容
186
 
187
  if ai_content:
188
  llm_messages.append({"role": "assistant", "content": ai_content})
189
 
190
+ # 確保最後是 user message
191
+ if not llm_messages or llm_messages[-1]["role"] == "assistant":
192
+ if not user_text.startswith("["):
193
+ llm_messages.append({"role": "user", "content": user_text})
194
+ else:
195
+ print("Skipping LLM call due to invalid final user text.")
196
+ return history, None, ""
 
 
 
 
 
 
197
 
198
  # --- 呼叫 LLM ---
199
  ai_response_text = call_llm(topic, user_stance, llm_messages)
 
205
  # 找到用戶最新輸入的那一條記錄(它還沒有 AI 回應)
206
  last_user_turn_index = -1
207
  for i in range(len(history) - 1, -1, -1):
208
+ if history[i][1] is None and not history[i][0] is None: # 找到最後一個用戶有輸入但AI無回應的地方
209
  last_user_turn_index = i
210
  break
211
 
212
  if last_user_turn_index != -1:
213
+ # ****** 修改核心 ******
214
+ # 1. 更新找到的那一回合,填入 AI 的文字回應
215
+ history[last_user_turn_index] = (history[last_user_turn_index][0], ai_response_text)
216
+
217
+ # 2. 如果 TTS 成功,*追加*一個新的回合,只包含 AI 的音訊
218
+ if ai_response_audio_path and not ai_response_text.startswith("["):
219
+ # AI 的音訊回應格式應該是 (filepath,)
220
+ history.append((None, (ai_response_audio_path,))) # User 設為 None, AI 設為音訊元組
221
+ # ****** 修改結束 ******
222
  else:
223
+ # 如果找不到用戶回合(理論上不該發生),直接追加
224
+ print("Warning: Could not find user's turn. Appending AI response.")
225
+ history.append(("[用戶回合丟失?]", ai_response_text))
226
+ if ai_response_audio_path and not ai_response_text.startswith("["):
227
+ history.append((None, (ai_response_audio_path,)))
228
+
229
 
230
  # 清空輸入框
231
  return history, None, ""