PhilipL commited on
Commit
ec0fbd4
·
verified ·
1 Parent(s): 7c6ecc9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -82
app.py CHANGED
@@ -25,18 +25,13 @@ HF_TOKEN = os.getenv("HF_TOKEN")
25
  # --- 1. 資料讀取 (主要資料庫) ---
26
  df = pd.DataFrame()
27
  try:
28
- # engine='python' 可以避免 Invalid file descriptor 錯誤
29
  df = pd.read_csv('google_maps_rag_data.csv', engine='python')
30
-
31
- # 清理欄位名稱 (移除前後空白)
32
- df.columns = df.columns.str.strip()
33
 
34
  def classify_mood(row):
35
- # 確保轉成字串以免報錯
36
  name_str = str(row.get('Name', ''))
37
  rag_str = str(row.get('RAG_Content', ''))
38
  text = (name_str + " " + rag_str).lower()
39
-
40
  tags = []
41
  rules = {
42
  "開心/慶祝": ["牛排", "steak", "pizza", "炸", "雞排", "甜點", "蛋糕", "cake", "冰", "waffle", "吃到飽", "buffet", "burger", "bistro", "餐酒館"],
@@ -55,33 +50,27 @@ try:
55
  df['Mood_Tags'] = df.apply(classify_mood, axis=1)
56
  except Exception as e:
57
  print(f"⚠️ 讀取 google_maps_rag_data.csv 失敗: {e}")
58
- print("RAG 功能將受限")
59
 
60
- # --- 2. 資料讀取 (Prompt 資料庫) [修正重點] ---
61
  df_prompts = pd.DataFrame()
62
- PROMPT_COL_NAME = 'Image_Prompt' # 設定目標欄位名稱
63
 
64
  try:
65
- # 使用 engine='python' 避免 file descriptor 錯誤
66
  df_prompts = pd.read_csv('restaurants_prompts_v6.csv', engine='python')
67
-
68
- # 自動清除欄位名稱的前後空白 (解決 ' Image_Prompt' 抓不到的問題)
69
  df_prompts.columns = df_prompts.columns.str.strip()
70
 
71
- # 檢查並設定 Index
72
  if 'Name' in df_prompts.columns:
73
  df_prompts.set_index('Name', inplace=True)
74
  else:
75
- print(f"⚠️ Prompts CSV 警告: 找不到 'Name' 欄位,現有欄位: {df_prompts.columns.tolist()}")
76
 
77
- # 檢查目標欄位是否存在
78
  if PROMPT_COL_NAME not in df_prompts.columns:
79
- print(f"⚠️ Prompts CSV 警告: 找不到 '{PROMPT_COL_NAME}' 欄位。現有欄位: {df_prompts.columns.tolist()}")
80
 
81
  except FileNotFoundError:
82
- print("⚠️ 找不到 restaurants_prompts_v6.csv,將使用預設 Prompt")
83
  except Exception as e:
84
- print(f"⚠️ 讀取 Prompt CSV 發生未預期錯誤: {e}")
85
 
86
 
87
  # --- RAG 建置 ---
@@ -115,19 +104,14 @@ custom_css = """
115
  }
116
  """
117
 
118
- # 圖片路徑
119
  img_path_1 = "images/image_0.png"
120
  img_path_2 = "images/image_1.png"
121
-
122
- # 自動產生替代圖片
123
  if not os.path.exists("images"): os.makedirs("images")
124
  try:
125
  if not os.path.exists(img_path_1): Image.new('RGB', (400, 300), color='gray').save(img_path_1)
126
  if not os.path.exists(img_path_2): Image.new('RGB', (400, 300), color='lightblue').save(img_path_2)
127
- except Exception:
128
- pass # 忽略圖片建立錯誤
129
 
130
- # 選項對照表
131
  q1_options_map = {
132
  "不​要​再​問白癡​問題​了​我​只​想​吃飯​": "現實主義者 (只想吃飯)",
133
  "去​過隱​居​生活": "隱士 (嚮往平靜)",
@@ -161,10 +145,7 @@ def get_restaurant_data(mood_score_str, food_choice):
161
  elif food_choice == "吃麵": food_keyword = "麵"
162
 
163
  candidates = df.copy()
164
-
165
- # 確保必要欄位存在
166
- if 'Mood_Tags' not in candidates.columns:
167
- return df.sample(1).iloc[0], True
168
 
169
  if target_moods:
170
  pattern = "|".join(target_moods)
@@ -181,37 +162,29 @@ def get_restaurant_data(mood_score_str, food_choice):
181
 
182
  def generate_content_with_groq(restaurant_name, restaurant_detail, user_diary, mood_score, quiz_result):
183
  if not GROQ_API_KEY: return "⚠️ 請設定 GROQ_API_KEY (系統變數)"
184
-
185
  client = OpenAI(api_key=GROQ_API_KEY, base_url="https://api.groq.com/openai/v1")
186
-
187
  system_prompt = "你是一個幽默、懂吃且善解人意的 AI 朋友。請根據使用者的日記、心情以及「中二病測驗結果」來推薦餐廳。"
188
-
189
  user_msg = f"""
190
  【使用者狀態】
191
  心情分數:{mood_score}
192
  心情日記:{user_diary}
193
-
194
- 【前測小遊戲結果 (參考用)】
195
- 使用者的隱藏人設:{quiz_result.get('q1', '未知')}
196
- 使用者選擇的魔法:{quiz_result.get('q2', '未知')}
197
-
198
- 【推薦餐廳資訊 (RAG)】
199
- 餐廳名稱:{restaurant_name}
200
- 詳細資料:{restaurant_detail}
201
-
202
  請完成任務:
203
  【回應內容】:用繁體中文寫一段溫暖有趣的回覆。
204
  - 結合「日記」與「前測人設」給予回應。
205
  - 推薦上述餐廳,說明為��麼這家店適合他。
206
- - 語氣自然,像朋友一樣。
207
  """
208
  try:
209
  response = client.chat.completions.create(
210
  model="llama-3.3-70b-versatile",
211
  messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": user_msg}]
212
  )
213
- content = response.choices[0].message.content
214
- return content
215
  except Exception as e:
216
  return f"Groq Error: {str(e)}"
217
 
@@ -222,8 +195,8 @@ def generate_image_huggingface(prompt):
222
  return hf_client.text_to_image(prompt=prompt, model="stabilityai/stable-diffusion-xl-base-1.0")
223
  except: return None
224
 
225
- # --- 主邏輯 Agent ---
226
- def mood_agent_logic(score_input, food_input, diary_input, quiz_state):
227
  restaurant, is_random = get_restaurant_data(score_input, food_input)
228
  if restaurant is None:
229
  yield "資料庫讀取錯誤或為空", None, ""
@@ -234,49 +207,58 @@ def mood_agent_logic(score_input, food_input, diary_input, quiz_state):
234
  url = str(restaurant.get('URL', f'https://www.google.com/maps/search/?api=1&query={urllib.parse.quote(name)}'))
235
  note = "(隨機推薦)" if is_random else ""
236
 
237
- # 1. 處理 RAG 內容
238
  rag_info = str(restaurant.get('RAG_Content', ''))
239
  if retriever:
240
  try:
241
  docs = retriever.invoke(name)
242
  if docs: rag_info = "\n".join([d.page_content for d in docs])
243
- except Exception:
244
- pass
245
 
246
- # 2. 呼叫 LLM 產生文字回應
247
- ai_text = generate_content_with_groq(name, rag_info, diary_input, score_input, quiz_state)
248
-
249
- final_response = f"### 🍽️ 推薦:{name} {note}\n\n{ai_text}"
250
- map_html = f'<div style="text-align:center"><a href="{url}" target="_blank" style="background:#4CAF50;color:white;padding:8px 16px;border-radius:20px;text-decoration:none">🗺️ Google Map 導航</a></div>'
251
-
252
- # 3. 先回傳文字與地圖
253
- yield final_response, None, map_html
254
-
255
- # 4. 查找 CSV 獲取 Prompt 並生成圖片 [安全讀取版]
256
  img_prompt = f"Delicious food from {name}, cinematic lighting, 8k, photorealistic" # 預設值
257
-
258
- # 檢查 df_prompts 是否有資料且目標欄位存在
259
  if not df_prompts.empty and PROMPT_COL_NAME in df_prompts.columns:
260
  if name in df_prompts.index:
261
  try:
262
  csv_prompt = df_prompts.loc[name, PROMPT_COL_NAME]
 
263
 
264
- # 處理重複名稱 (如果是 Series 取第一個)
265
- if isinstance(csv_prompt, pd.Series):
266
- csv_prompt = csv_prompt.iloc[0]
267
-
268
- # 檢查是否為 NaN 或空字串
269
  if pd.notna(csv_prompt) and str(csv_prompt).strip() != "":
270
  img_prompt = str(csv_prompt)
271
- # print(f"✅ 使用 CSV Prompt ({name}): {img_prompt[:20]}...")
272
  else:
273
- print(f"⚠️ 餐廳 {name} 在 CSV 中,但 Prompt 為空,使用預設值。")
274
  except Exception as e:
275
- print(f"⚠️ 取用 Prompt 時發生錯誤: {e}")
276
  else:
277
- print(f"ℹ️ 餐廳 '{name}' 不在 Prompts CSV 索引中,使用預設生成規則")
 
 
 
278
 
279
- # 5. 生成圖片
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  image_output = generate_image_huggingface(img_prompt)
281
  yield final_response, image_output, map_html
282
 
@@ -294,22 +276,18 @@ def handle_q2_change(selected_label, current_state):
294
  current_state["q2"] = q2_options_map.get(selected_label, selected_label)
295
  return current_state, gr.Button(interactive=True, variant="primary", value="完成測驗 (前往點餐) ➔")
296
 
297
- def go_to_page_2():
298
- return gr.update(visible=False), gr.update(visible=True)
299
-
300
- def go_to_main_app():
301
- return gr.update(visible=False), gr.update(visible=True)
302
 
303
  # ==========================================
304
  # 4. Gradio 介面建構
305
  # ==========================================
306
 
307
  with gr.Blocks(title="AI 心情食堂") as demo:
308
-
309
  gr.HTML(f"<style>{custom_css}</style>")
310
  quiz_state = gr.State(value={})
311
 
312
- # ------ Page 1: 測驗第一題 ------
313
  with gr.Column(visible=True) as page_1_col:
314
  gr.Markdown("### 🔮 第一題:直覺測試")
315
  gr.Image(value=img_path_1, type="filepath", label="請觀察圖片", height=300)
@@ -317,7 +295,7 @@ with gr.Blocks(title="AI 心情食堂") as demo:
317
  radio_q1 = gr.Radio(choices=list(q1_options_map.keys()), label="請選擇", elem_classes="vertical-radio")
318
  btn_q1_next = gr.Button("下一頁 ➔", interactive=False)
319
 
320
- # ------ Page 2: 測驗第二題 ------
321
  with gr.Column(visible=False) as page_2_col:
322
  gr.Markdown("### 🔮 第二題:魔法適性")
323
  gr.Image(value=img_path_2, type="filepath", label="請觀察圖片", height=300)
@@ -325,7 +303,7 @@ with gr.Blocks(title="AI 心情食堂") as demo:
325
  radio_q2 = gr.Radio(choices=list(q2_options_map.keys()), label="請選擇", elem_classes="vertical-radio")
326
  btn_q2_finish = gr.Button("完成測驗 ➔", interactive=False)
327
 
328
- # ------ Page 3: 主功能 ------
329
  with gr.Column(visible=False) as main_app_col:
330
  gr.Markdown(f"## 🍱 AI 心情食堂導航")
331
  gr.Markdown("測驗結束!現在,告訴我你真正想吃什麼吧!")
@@ -334,7 +312,11 @@ with gr.Blocks(title="AI 心情食堂") as demo:
334
  with gr.Column(scale=1):
335
  score_input = gr.Radio(["1 (心情差)", "2 (不太好)", "3 (普通)", "4 (不錯)", "5 (超棒)"], label="1. 心情分數", value="3 (普通)")
336
  food_input = gr.Radio(["吃飯", "吃麵", "隨便"], label="2. 想吃什麼", value="隨便")
337
- diary_input = gr.Textbox(lines=4, label="3. 心情日記", placeholder="寫下今天發生的事... (AI 會參考你的測驗結果喔!)")
 
 
 
 
338
  submit_btn = gr.Button("送出給 Agent", variant="primary")
339
 
340
  with gr.Column(scale=1):
@@ -342,15 +324,16 @@ with gr.Blocks(title="AI 心情食堂") as demo:
342
  image_output = gr.Image(label="AI 推薦美食圖", type="pil", width=400)
343
  map_output = gr.HTML(label="地圖導航")
344
 
345
- # ------ 事件綁定 ------
346
  radio_q1.change(fn=handle_q1_change, inputs=[radio_q1, quiz_state], outputs=[quiz_state, btn_q1_next])
347
  btn_q1_next.click(fn=go_to_page_2, outputs=[page_1_col, page_2_col])
348
  radio_q2.change(fn=handle_q2_change, inputs=[radio_q2, quiz_state], outputs=[quiz_state, btn_q2_finish])
349
  btn_q2_finish.click(fn=go_to_main_app, outputs=[page_2_col, main_app_col])
350
 
 
351
  submit_btn.click(
352
  fn=mood_agent_logic,
353
- inputs=[score_input, food_input, diary_input, quiz_state],
354
  outputs=[agent_output, image_output, map_output]
355
  )
356
 
 
25
  # --- 1. 資料讀取 (主要資料庫) ---
26
  df = pd.DataFrame()
27
  try:
 
28
  df = pd.read_csv('google_maps_rag_data.csv', engine='python')
29
+ df.columns = df.columns.str.strip() # 清理欄位空白
 
 
30
 
31
  def classify_mood(row):
 
32
  name_str = str(row.get('Name', ''))
33
  rag_str = str(row.get('RAG_Content', ''))
34
  text = (name_str + " " + rag_str).lower()
 
35
  tags = []
36
  rules = {
37
  "開心/慶祝": ["牛排", "steak", "pizza", "炸", "雞排", "甜點", "蛋糕", "cake", "冰", "waffle", "吃到飽", "buffet", "burger", "bistro", "餐酒館"],
 
50
  df['Mood_Tags'] = df.apply(classify_mood, axis=1)
51
  except Exception as e:
52
  print(f"⚠️ 讀取 google_maps_rag_data.csv 失敗: {e}")
 
53
 
54
+ # --- 2. 資料讀取 (Prompt 資料庫) ---
55
  df_prompts = pd.DataFrame()
56
+ PROMPT_COL_NAME = 'Image_Prompt'
57
 
58
  try:
 
59
  df_prompts = pd.read_csv('restaurants_prompts_v6.csv', engine='python')
 
 
60
  df_prompts.columns = df_prompts.columns.str.strip()
61
 
 
62
  if 'Name' in df_prompts.columns:
63
  df_prompts.set_index('Name', inplace=True)
64
  else:
65
+ print(f"⚠️ Prompts CSV 警告: 找不到 'Name' 欄位")
66
 
 
67
  if PROMPT_COL_NAME not in df_prompts.columns:
68
+ print(f"⚠️ Prompts CSV 警告: 找不到 '{PROMPT_COL_NAME}' 欄位")
69
 
70
  except FileNotFoundError:
71
+ print("⚠️ 找不到 restaurants_prompts_v6.csv")
72
  except Exception as e:
73
+ print(f"⚠️ 讀取 Prompt CSV 發生錯誤: {e}")
74
 
75
 
76
  # --- RAG 建置 ---
 
104
  }
105
  """
106
 
 
107
  img_path_1 = "images/image_0.png"
108
  img_path_2 = "images/image_1.png"
 
 
109
  if not os.path.exists("images"): os.makedirs("images")
110
  try:
111
  if not os.path.exists(img_path_1): Image.new('RGB', (400, 300), color='gray').save(img_path_1)
112
  if not os.path.exists(img_path_2): Image.new('RGB', (400, 300), color='lightblue').save(img_path_2)
113
+ except: pass
 
114
 
 
115
  q1_options_map = {
116
  "不​要​再​問白癡​問題​了​我​只​想​吃飯​": "現實主義者 (只想吃飯)",
117
  "去​過隱​居​生活": "隱士 (嚮往平靜)",
 
145
  elif food_choice == "吃麵": food_keyword = "麵"
146
 
147
  candidates = df.copy()
148
+ if 'Mood_Tags' not in candidates.columns: return df.sample(1).iloc[0], True
 
 
 
149
 
150
  if target_moods:
151
  pattern = "|".join(target_moods)
 
162
 
163
  def generate_content_with_groq(restaurant_name, restaurant_detail, user_diary, mood_score, quiz_result):
164
  if not GROQ_API_KEY: return "⚠️ 請設定 GROQ_API_KEY (系統變數)"
 
165
  client = OpenAI(api_key=GROQ_API_KEY, base_url="https://api.groq.com/openai/v1")
 
166
  system_prompt = "你是一個幽默、懂吃且善解人意的 AI 朋友。請根據使用者的日記、心情以及「中二病測驗結果」來推薦餐廳。"
 
167
  user_msg = f"""
168
  【使用者狀態】
169
  心情分數:{mood_score}
170
  心情日記:{user_diary}
171
+ 【前測小遊戲結果】
172
+ 隱藏人設:{quiz_result.get('q1', '未知')}
173
+ 魔法:{quiz_result.get('q2', '未知')}
174
+ 【推薦餐廳】
175
+ 名稱:{restaurant_name}
176
+ 資料:{restaurant_detail}
 
 
 
177
  請完成任務:
178
  【回應內容】:用繁體中文寫一段溫暖有趣的回覆。
179
  - 結合「日記」與「前測人設」給予回應。
180
  - 推薦上述餐廳,說明為��麼這家店適合他。
 
181
  """
182
  try:
183
  response = client.chat.completions.create(
184
  model="llama-3.3-70b-versatile",
185
  messages=[{"role": "system", "content": system_prompt}, {"role": "user", "content": user_msg}]
186
  )
187
+ return response.choices[0].message.content
 
188
  except Exception as e:
189
  return f"Groq Error: {str(e)}"
190
 
 
195
  return hf_client.text_to_image(prompt=prompt, model="stabilityai/stable-diffusion-xl-base-1.0")
196
  except: return None
197
 
198
+ # --- 主邏輯 Agent (新增 debug_mode 參數) ---
199
+ def mood_agent_logic(score_input, food_input, diary_input, quiz_state, debug_mode):
200
  restaurant, is_random = get_restaurant_data(score_input, food_input)
201
  if restaurant is None:
202
  yield "資料庫讀取錯誤或為空", None, ""
 
207
  url = str(restaurant.get('URL', f'https://www.google.com/maps/search/?api=1&query={urllib.parse.quote(name)}'))
208
  note = "(隨機推薦)" if is_random else ""
209
 
210
+ # 1. 處理 RAG
211
  rag_info = str(restaurant.get('RAG_Content', ''))
212
  if retriever:
213
  try:
214
  docs = retriever.invoke(name)
215
  if docs: rag_info = "\n".join([d.page_content for d in docs])
216
+ except: pass
 
217
 
218
+ # 2. 準備圖片 Prompt (提前執行以便顯示除錯資訊)
 
 
 
 
 
 
 
 
 
219
  img_prompt = f"Delicious food from {name}, cinematic lighting, 8k, photorealistic" # 預設值
220
+ prompt_source = "⚠️ 預設生成 (未找到 CSV 對應)"
221
+
222
  if not df_prompts.empty and PROMPT_COL_NAME in df_prompts.columns:
223
  if name in df_prompts.index:
224
  try:
225
  csv_prompt = df_prompts.loc[name, PROMPT_COL_NAME]
226
+ if isinstance(csv_prompt, pd.Series): csv_prompt = csv_prompt.iloc[0]
227
 
 
 
 
 
 
228
  if pd.notna(csv_prompt) and str(csv_prompt).strip() != "":
229
  img_prompt = str(csv_prompt)
230
+ prompt_source = "✅ CSV 檔案 (restaurants_prompts_v6.csv)"
231
  else:
232
+ prompt_source = "⚠️ CSV 有此餐廳但 Prompt 空白"
233
  except Exception as e:
234
+ prompt_source = f"❌ 讀取錯誤: {e}"
235
  else:
236
+ prompt_source = "ℹ️ CSV 中無此餐廳"
237
+
238
+ # 3. 呼叫 LLM
239
+ ai_text = generate_content_with_groq(name, rag_info, diary_input, score_input, quiz_state)
240
 
241
+ # 4. 組合回應 (包含除錯資訊)
242
+ debug_text = ""
243
+ if debug_mode:
244
+ debug_text = f"""
245
+ \n\n---
246
+ **🛠️ Prompt 除錯模式**
247
+ * **餐廳名稱**: `{name}`
248
+ * **Prompt 來源**: {prompt_source}
249
+ * **實際使用 Prompt**:
250
+ ```
251
+ {img_prompt}
252
+ ```
253
+ """
254
+
255
+ final_response = f"### 🍽️ 推薦:{name} {note}\n\n{ai_text}{debug_text}"
256
+ map_html = f'<div style="text-align:center"><a href="{url}" target="_blank" style="background:#4CAF50;color:white;padding:8px 16px;border-radius:20px;text-decoration:none">🗺️ Google Map 導航</a></div>'
257
+
258
+ # 5. 先回傳文字
259
+ yield final_response, None, map_html
260
+
261
+ # 6. 生成圖片
262
  image_output = generate_image_huggingface(img_prompt)
263
  yield final_response, image_output, map_html
264
 
 
276
  current_state["q2"] = q2_options_map.get(selected_label, selected_label)
277
  return current_state, gr.Button(interactive=True, variant="primary", value="完成測驗 (前往點餐) ➔")
278
 
279
+ def go_to_page_2(): return gr.update(visible=False), gr.update(visible=True)
280
+ def go_to_main_app(): return gr.update(visible=False), gr.update(visible=True)
 
 
 
281
 
282
  # ==========================================
283
  # 4. Gradio 介面建構
284
  # ==========================================
285
 
286
  with gr.Blocks(title="AI 心情食堂") as demo:
 
287
  gr.HTML(f"<style>{custom_css}</style>")
288
  quiz_state = gr.State(value={})
289
 
290
+ # Page 1
291
  with gr.Column(visible=True) as page_1_col:
292
  gr.Markdown("### 🔮 第一題:直覺測試")
293
  gr.Image(value=img_path_1, type="filepath", label="請觀察圖片", height=300)
 
295
  radio_q1 = gr.Radio(choices=list(q1_options_map.keys()), label="請選擇", elem_classes="vertical-radio")
296
  btn_q1_next = gr.Button("下一頁 ➔", interactive=False)
297
 
298
+ # Page 2
299
  with gr.Column(visible=False) as page_2_col:
300
  gr.Markdown("### 🔮 第二題:魔法適性")
301
  gr.Image(value=img_path_2, type="filepath", label="請觀察圖片", height=300)
 
303
  radio_q2 = gr.Radio(choices=list(q2_options_map.keys()), label="請選擇", elem_classes="vertical-radio")
304
  btn_q2_finish = gr.Button("完成測驗 ➔", interactive=False)
305
 
306
+ # Page 3 (Main)
307
  with gr.Column(visible=False) as main_app_col:
308
  gr.Markdown(f"## 🍱 AI 心情食堂導航")
309
  gr.Markdown("測驗結束!現在,告訴我你真正想吃什麼吧!")
 
312
  with gr.Column(scale=1):
313
  score_input = gr.Radio(["1 (心情差)", "2 (不太好)", "3 (普通)", "4 (不錯)", "5 (超棒)"], label="1. 心情分數", value="3 (普通)")
314
  food_input = gr.Radio(["吃飯", "吃麵", "隨便"], label="2. 想吃什麼", value="隨便")
315
+ diary_input = gr.Textbox(lines=4, label="3. 心情日記", placeholder="寫下今天發生的事...")
316
+
317
+ # [新增] 除錯模式開關
318
+ debug_mode_btn = gr.Checkbox(label="🔧 顯示 Prompt 除錯資訊", value=False)
319
+
320
  submit_btn = gr.Button("送出給 Agent", variant="primary")
321
 
322
  with gr.Column(scale=1):
 
324
  image_output = gr.Image(label="AI 推薦美食圖", type="pil", width=400)
325
  map_output = gr.HTML(label="地圖導航")
326
 
327
+ # Events
328
  radio_q1.change(fn=handle_q1_change, inputs=[radio_q1, quiz_state], outputs=[quiz_state, btn_q1_next])
329
  btn_q1_next.click(fn=go_to_page_2, outputs=[page_1_col, page_2_col])
330
  radio_q2.change(fn=handle_q2_change, inputs=[radio_q2, quiz_state], outputs=[quiz_state, btn_q2_finish])
331
  btn_q2_finish.click(fn=go_to_main_app, outputs=[page_2_col, main_app_col])
332
 
333
+ # [修改] 加入 debug_mode_btn 到 inputs
334
  submit_btn.click(
335
  fn=mood_agent_logic,
336
+ inputs=[score_input, food_input, diary_input, quiz_state, debug_mode_btn],
337
  outputs=[agent_output, image_output, map_output]
338
  )
339