cwadayi commited on
Commit
f7db653
·
verified ·
1 Parent(s): 7363269

Update command_handler.py

Browse files
Files changed (1) hide show
  1. command_handler.py +50 -40
command_handler.py CHANGED
@@ -1,6 +1,7 @@
1
- # command_handler.py (Help message now includes English translations)
2
  import pandas as pd
3
  import re
 
4
  from linebot.v3.messaging import TextMessage, ImageMessage
5
 
6
  # 匯入所有服務函式
@@ -10,10 +11,7 @@ from ai_service import generate_ai_text
10
  from config import CURRENT_YEAR, MCP_SERVER_URL
11
 
12
  def get_help_message() -> TextMessage:
13
- """
14
- [核心修改]
15
- 產生並回傳包含所有指令的說明文字,並附上英文翻譯。
16
- """
17
  text = (
18
  "📖 指令列表 (Command List)\n"
19
  " (請直接輸入數字 / Please enter a number)\n\n"
@@ -33,7 +31,7 @@ def get_help_message() -> TextMessage:
33
  "【AI 與工具 (AI & Tools)】\n"
34
  "• 7 <問題> - 與 AI 助理對話\n"
35
  " (Chat with AI Assistant)\n"
36
- " (e.g., 7 2023年臺灣最大地震)\n\n"
37
  "【基本指令 (Basic Commands)】\n"
38
  "• 8 - 關於此機器人 (About this Bot)\n"
39
  "• 9 - 顯示此說明 (Show this Help Message)"
@@ -45,45 +43,32 @@ def get_info_message() -> TextMessage:
45
  text = (
46
  "🤖 關於我\n\n"
47
  "我是一個多功能助理機器人,提供地震查詢與 AI 對話功能。\n\n"
48
- "• 版本: 5.3 (Gemini Command-Only Edition)\n"
49
  "• 資料來源: CWA, USGS, Google Gemini\n"
50
  "• 開發者: dayichen"
51
  )
52
  return TextMessage(text=text)
53
 
54
  def get_taiwan_earthquake_list() -> TextMessage:
55
- """從 USGS 取得今年台灣的地震列表並格式化回覆。"""
56
  result = fetch_taiwan_df_this_year()
57
  if isinstance(result, pd.DataFrame):
58
  count = len(result)
59
  lines = [f"🇹🇼 今年 ({CURRENT_YEAR} 年) 台灣區域顯著地震 (M≥5.0),共 {count} 筆:", "-" * 20]
60
  for _, row in result.head(15).iterrows():
61
  t = row["time_utc"].strftime("%Y-%m-%d %H:%M")
62
- lines.append(
63
- f"規模: {row['magnitude']:.1f} | 日期時間: {t} (UTC)\n"
64
- f"地點: {row['place']}\n"
65
- f"報告連結: {row.get('url', '無')}"
66
- )
67
  if count > 15: lines.append(f"... (還有 {count-15} 筆資料)")
68
  reply_text = "\n\n".join(lines)
69
  else: reply_text = result
70
  return TextMessage(text=reply_text)
71
 
72
  def get_latest_earthquake_reply() -> list:
73
- """取得 CWA 最新一筆地震,並組合文字與圖片訊息。"""
74
  try:
75
  latest_eq = fetch_latest_significant_earthquake()
76
  if not latest_eq: return [TextMessage(text="✅ 近期無顯著有感地震報告。")]
77
  mag_str = f"{latest_eq['Magnitude']:.1f}" if latest_eq.get('Magnitude') is not None else "—"
78
  depth_str = f"{latest_eq['Depth']:.0f}" if latest_eq.get('Depth') is not None else "—"
79
- text_message_content = (
80
- f"🚨 CWA 最新顯著有感地震\n"
81
- f"----------------------------------\n"
82
- f"時間: {latest_eq.get('TimeStr', '—')}\n"
83
- f"地點: {latest_eq.get('Location', '—')}\n"
84
- f"規模: M{mag_str} | 深度: {depth_str} km\n"
85
- f"報告: {latest_eq.get('URL', '無')}"
86
- )
87
  reply_messages = [TextMessage(text=text_message_content)]
88
  if latest_eq.get("ImageURL"):
89
  image_url = latest_eq["ImageURL"]
@@ -92,26 +77,56 @@ def get_latest_earthquake_reply() -> list:
92
  except Exception as e: return [TextMessage(text=f"❌ 查詢最新地震失敗:{e}")]
93
 
94
  def preprocess_ai_prompt(prompt: str) -> str:
95
- """預處理使用者發給 AI 的問題。"""
 
 
 
 
96
  year_match = re.search(r"(\d{4})年", prompt)
97
- if year_match and "最大地震" in prompt:
98
- year = year_match.group(1)
99
- new_prompt = f"請幫我呼叫地震搜尋工具,找出{year}年1月1日至{year}年12月31日之間,規模最大的地震。"
100
- print(f"--- AI Prompt Rewritten ---\nOriginal: {prompt}\nNew: {new_prompt}\n---------------------------")
101
- return new_prompt
102
- return prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  def process_message(user_message_raw: str, request_base_url: str) -> list:
105
- """處理使用者輸入的主函式。"""
106
  user_message = (user_message_raw or "").strip()
107
- if not user_message:
108
- return [] # 如果是空訊息,不回應
109
-
110
  parts = user_message.split(' ', 1)
111
  command_key = parts[0]
112
  arg = parts[1].strip() if len(parts) > 1 else ""
113
 
114
- # 處理固定的數字指令
115
  if command_key == '1': return get_latest_earthquake_reply()
116
  if command_key == '2': return [TextMessage(text=fetch_global_last24h_text())]
117
  if command_key == '3': return [get_taiwan_earthquake_list()]
@@ -121,14 +136,9 @@ def process_message(user_message_raw: str, request_base_url: str) -> list:
121
  if command_key == '8': return [get_info_message()]
122
  if command_key == '9': return [get_help_message()]
123
 
124
- # 只有當指令是 '7' 時,才啟用 AI
125
  if command_key == '7':
126
- if not arg:
127
- return [TextMessage(text="請輸入問題,例如:7 台灣最高的山是哪座?")]
128
-
129
- # 將問題進行預處理,然後交給 AI
130
  processed_prompt = preprocess_ai_prompt(arg)
131
  return [TextMessage(text=generate_ai_text(processed_prompt))]
132
 
133
- # 對於所有其他無法識別的訊息 (一般對話),回傳說明指令
134
  return [get_help_message()]
 
1
+ # command_handler.py (Improved date keyword pre-processing for AI queries)
2
  import pandas as pd
3
  import re
4
+ from datetime import datetime, timedelta
5
  from linebot.v3.messaging import TextMessage, ImageMessage
6
 
7
  # 匯入所有服務函式
 
11
  from config import CURRENT_YEAR, MCP_SERVER_URL
12
 
13
  def get_help_message() -> TextMessage:
14
+ """產生並回傳包含所有指令的說明文字,並附上英文翻譯。"""
 
 
 
15
  text = (
16
  "📖 指令列表 (Command List)\n"
17
  " (請直接輸入數字 / Please enter a number)\n\n"
 
31
  "【AI 與工具 (AI & Tools)】\n"
32
  "• 7 <問題> - 與 AI 助理對話\n"
33
  " (Chat with AI Assistant)\n"
34
+ " (e.g., 7 顯示pws, 7 2024年最大的地震)\n\n"
35
  "【基本指令 (Basic Commands)】\n"
36
  "• 8 - 關於此機器人 (About this Bot)\n"
37
  "• 9 - 顯示此說明 (Show this Help Message)"
 
43
  text = (
44
  "🤖 關於我\n\n"
45
  "我是一個多功能助理機器人,提供地震查詢與 AI 對話功能。\n\n"
46
+ "• 版本: 5.4 (Gemini Pre-processor Edition)\n"
47
  "• 資料來源: CWA, USGS, Google Gemini\n"
48
  "• 開發者: dayichen"
49
  )
50
  return TextMessage(text=text)
51
 
52
  def get_taiwan_earthquake_list() -> TextMessage:
 
53
  result = fetch_taiwan_df_this_year()
54
  if isinstance(result, pd.DataFrame):
55
  count = len(result)
56
  lines = [f"🇹🇼 今年 ({CURRENT_YEAR} 年) 台灣區域顯著地震 (M≥5.0),共 {count} 筆:", "-" * 20]
57
  for _, row in result.head(15).iterrows():
58
  t = row["time_utc"].strftime("%Y-%m-%d %H:%M")
59
+ lines.append(f"規模: {row['magnitude']:.1f} | 日期時間: {t} (UTC)\n地點: {row['place']}\n報告連結: {row.get('url', '無')}")
 
 
 
 
60
  if count > 15: lines.append(f"... (還有 {count-15} 筆資料)")
61
  reply_text = "\n\n".join(lines)
62
  else: reply_text = result
63
  return TextMessage(text=reply_text)
64
 
65
  def get_latest_earthquake_reply() -> list:
 
66
  try:
67
  latest_eq = fetch_latest_significant_earthquake()
68
  if not latest_eq: return [TextMessage(text="✅ 近期無顯著有感地震報告。")]
69
  mag_str = f"{latest_eq['Magnitude']:.1f}" if latest_eq.get('Magnitude') is not None else "—"
70
  depth_str = f"{latest_eq['Depth']:.0f}" if latest_eq.get('Depth') is not None else "—"
71
+ text_message_content = (f"🚨 CWA 最新顯著有感地震\n----------------------------------\n時間: {latest_eq.get('TimeStr', '—')}\n地點: {latest_eq.get('Location', '—')}\n規模: M{mag_str} | 深度: {depth_str} km\n報告: {latest_eq.get('URL', '無')}")
 
 
 
 
 
 
 
72
  reply_messages = [TextMessage(text=text_message_content)]
73
  if latest_eq.get("ImageURL"):
74
  image_url = latest_eq["ImageURL"]
 
77
  except Exception as e: return [TextMessage(text=f"❌ 查詢最新地震失敗:{e}")]
78
 
79
  def preprocess_ai_prompt(prompt: str) -> str:
80
+ """
81
+ [核心修正]
82
+ 強化預處理:偵測多種時間關鍵字,並將問題改寫為更明確的指令。
83
+ """
84
+ today = datetime.now()
85
  year_match = re.search(r"(\d{4})年", prompt)
86
+
87
+ # 建立時間關鍵字與對應日期的字典
88
+ time_keywords = {
89
+ "昨天": (today - timedelta(days=1)).strftime("%Y-%m-%d"),
90
+ "今天": today.strftime("%Y-%m-%d"),
91
+ "今年": str(today.year),
92
+ "去年": str(today.year - 1),
93
+ }
94
+
95
+ # 如果找到 "YYYY年" 的格式,也加入字典
96
+ if year_match:
97
+ time_keywords[year_match.group(0)] = year_match.group(1)
98
+
99
+ # 如果訊息中包含 "地震"
100
+ if "地震" in prompt:
101
+ for keyword, date_val in time_keywords.items():
102
+ if keyword in prompt:
103
+ # 判斷是查詢特定一天還是一整年
104
+ if len(date_val) == 10: # YYYY-MM-DD 格式
105
+ start_date = end_date = date_val
106
+ date_range_str = date_val
107
+ else: # YYYY 格式
108
+ start_date = f"{date_val}-01-01"
109
+ end_date = f"{date_val}-12-31"
110
+ date_range_str = f"{date_val}年"
111
+
112
+ # 根據是否包含"最大"來決定指令內容
113
+ if "最大" in prompt:
114
+ new_prompt = f"請幫我呼叫地震搜尋工具,找出從 {start_date} 到 {end_date} 之間,規模最大的地震是哪一個。"
115
+ else:
116
+ new_prompt = f"請幫我呼叫地震搜尋工具,查詢從 {start_date} 到 {end_date} 之間發生的所有地震。"
117
+
118
+ print(f"--- AI Prompt Rewritten ---\nOriginal: {prompt}\nNew: {new_prompt}\n---------------------------")
119
+ return new_prompt
120
+
121
+ return prompt # 如果沒有匹配,回傳原始問題
122
 
123
  def process_message(user_message_raw: str, request_base_url: str) -> list:
 
124
  user_message = (user_message_raw or "").strip()
125
+ if not user_message: return []
 
 
126
  parts = user_message.split(' ', 1)
127
  command_key = parts[0]
128
  arg = parts[1].strip() if len(parts) > 1 else ""
129
 
 
130
  if command_key == '1': return get_latest_earthquake_reply()
131
  if command_key == '2': return [TextMessage(text=fetch_global_last24h_text())]
132
  if command_key == '3': return [get_taiwan_earthquake_list()]
 
136
  if command_key == '8': return [get_info_message()]
137
  if command_key == '9': return [get_help_message()]
138
 
 
139
  if command_key == '7':
140
+ if not arg: return [TextMessage(text="請輸入問題,例如:7 台灣最高的山是哪座?")]
 
 
 
141
  processed_prompt = preprocess_ai_prompt(arg)
142
  return [TextMessage(text=generate_ai_text(processed_prompt))]
143
 
 
144
  return [get_help_message()]