XiaoBai1221 commited on
Commit
b0d8d63
·
1 Parent(s): f998449

進一步修復和優化

Browse files

- 修復 app.py 中的額外問題
- 優化 services/ai_service.py 的功能

Files changed (2) hide show
  1. app.py +64 -64
  2. services/ai_service.py +13 -3
app.py CHANGED
@@ -832,6 +832,70 @@ async def websocket_endpoint_with_jwt(websocket: WebSocket, token: str = Query(N
832
  import asyncio as _asyncio
833
  _asyncio.create_task(_do_process_and_send())
834
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
835
  elif message_type == "chat_focus":
836
  try:
837
  cid = message_data.get("chat_id")
@@ -1209,70 +1273,6 @@ async def websocket_endpoint_with_jwt(websocket: WebSocket, token: str = Query(N
1209
  "timestamp": time.time()
1210
  })
1211
 
1212
- finally:
1213
- pass
1214
- # ===== 環境快照上報 =====
1215
- if message_type == "env_snapshot":
1216
- try:
1217
- lat = float(message_data.get("lat")) if message_data.get("lat") is not None else None
1218
- lon = float(message_data.get("lon")) if message_data.get("lon") is not None else None
1219
- acc = message_data.get("accuracy_m")
1220
- acc = float(acc) if acc is not None else None
1221
- heading_deg = message_data.get("heading_deg")
1222
- heading_deg = float(heading_deg) if heading_deg is not None else None
1223
- tz = message_data.get("tz")
1224
- locale = message_data.get("locale")
1225
- device = message_data.get("device")
1226
-
1227
- # 後端節流:距離<100m且方位差<25度則忽略
1228
- do_write_snapshot = False
1229
- last = manager.last_env.get(user_id)
1230
- if last and lat is not None and lon is not None and last.get("lat") is not None:
1231
- dist = _haversine_m(last.get("lat",0), last.get("lon",0), lat, lon)
1232
- deg_diff = abs((heading_deg or 0) - (last.get("heading_deg") or 0))
1233
- if dist >= 100 or deg_diff >= 25:
1234
- do_write_snapshot = True
1235
- else:
1236
- do_write_snapshot = True
1237
-
1238
- from geohash2 import encode as gh_encode
1239
- geohash7 = gh_encode(lat, lon, precision=7) if (lat is not None and lon is not None) else None
1240
- heading_cardinal = _heading_to_cardinal(heading_deg) if heading_deg is not None else None
1241
- env_payload = {
1242
- "lat": lat,
1243
- "lon": lon,
1244
- "accuracy_m": acc,
1245
- "heading_deg": heading_deg,
1246
- "heading_cardinal": heading_cardinal,
1247
- "tz": tz,
1248
- "locale": locale,
1249
- "device": device,
1250
- "geohash_7": geohash7,
1251
- }
1252
-
1253
- # 更新會話暫存
1254
- manager.last_env[user_id] = env_payload
1255
- info = manager.get_client_info(user_id) or {}
1256
- info['env_context'] = env_payload
1257
- manager.set_client_info(user_id, info)
1258
-
1259
- try:
1260
- await set_user_env_current(user_id, env_payload)
1261
- except Exception as e:
1262
- logger.warning(f"寫入環境現況失敗: {e}")
1263
-
1264
- if do_write_snapshot:
1265
- try:
1266
- snap = env_payload.copy()
1267
- snap['reason'] = 'threshold'
1268
- await add_user_env_snapshot(user_id, snap)
1269
- except Exception as e:
1270
- logger.warning(f"寫入環境快照失敗: {e}")
1271
-
1272
- await websocket.send_json({"type": "env_ack", "success": True, "geohash_7": geohash7, "heading_cardinal": heading_cardinal})
1273
- except Exception as e:
1274
- logger.error(f"處理 env_snapshot 失敗: {e}")
1275
- await websocket.send_json({"type": "env_ack", "success": False, "error": str(e)})
1276
  except json.JSONDecodeError:
1277
  await manager.send_message("消息格式錯誤,無法解析", user_id, "error")
1278
  except Exception as e:
 
832
  import asyncio as _asyncio
833
  _asyncio.create_task(_do_process_and_send())
834
 
835
+ elif message_type == "env_snapshot":
836
+ try:
837
+ lat = float(message_data.get("lat")) if message_data.get("lat") is not None else None
838
+ lon = float(message_data.get("lon")) if message_data.get("lon") is not None else None
839
+ acc = message_data.get("accuracy_m")
840
+ acc = float(acc) if acc is not None else None
841
+ heading_deg = message_data.get("heading_deg")
842
+ heading_deg = float(heading_deg) if heading_deg is not None else None
843
+ tz = message_data.get("tz")
844
+ locale = message_data.get("locale")
845
+ device = message_data.get("device")
846
+
847
+ # 後端節流:距離<100m且方位差<25度則忽略
848
+ do_write_snapshot = False
849
+ last = manager.last_env.get(user_id)
850
+ if last and lat is not None and lon is not None and last.get("lat") is not None:
851
+ dist = _haversine_m(last.get("lat", 0), last.get("lon", 0), lat, lon)
852
+ deg_diff = abs((heading_deg or 0) - (last.get("heading_deg") or 0))
853
+ if dist >= 100 or deg_diff >= 25:
854
+ do_write_snapshot = True
855
+ else:
856
+ do_write_snapshot = True
857
+
858
+ from geohash2 import encode as gh_encode
859
+ geohash7 = gh_encode(lat, lon, precision=7) if (lat is not None and lon is not None) else None
860
+ heading_cardinal = _heading_to_cardinal(heading_deg) if heading_deg is not None else None
861
+ env_payload = {
862
+ "lat": lat,
863
+ "lon": lon,
864
+ "accuracy_m": acc,
865
+ "heading_deg": heading_deg,
866
+ "heading_cardinal": heading_cardinal,
867
+ "tz": tz,
868
+ "locale": locale,
869
+ "device": device,
870
+ "geohash_7": geohash7,
871
+ }
872
+
873
+ # 更新會話暫存
874
+ manager.last_env[user_id] = env_payload
875
+ info = manager.get_client_info(user_id) or {}
876
+ info["env_context"] = env_payload
877
+ manager.set_client_info(user_id, info)
878
+
879
+ try:
880
+ await set_user_env_current(user_id, env_payload)
881
+ except Exception as e:
882
+ logger.warning(f"寫入環境現況失敗: {e}")
883
+
884
+ if do_write_snapshot:
885
+ try:
886
+ snap = env_payload.copy()
887
+ snap["reason"] = "threshold"
888
+ await add_user_env_snapshot(user_id, snap)
889
+ except Exception as e:
890
+ logger.warning(f"寫入環境快照失敗: {e}")
891
+
892
+ await websocket.send_json(
893
+ {"type": "env_ack", "success": True, "geohash_7": geohash7, "heading_cardinal": heading_cardinal}
894
+ )
895
+ except Exception as e:
896
+ logger.error(f"處理 env_snapshot 失敗: {e}")
897
+ await websocket.send_json({"type": "env_ack", "success": False, "error": str(e)})
898
+
899
  elif message_type == "chat_focus":
900
  try:
901
  cid = message_data.get("chat_id")
 
1273
  "timestamp": time.time()
1274
  })
1275
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1276
  except json.JSONDecodeError:
1277
  await manager.send_message("消息格式錯誤,無法解析", user_id, "error")
1278
  except Exception as e:
services/ai_service.py CHANGED
@@ -32,7 +32,7 @@ from core.config import settings
32
  OPENAI_TIMEOUT = settings.OPENAI_TIMEOUT # 關懷模式 reasoning model 需要更長時間
33
 
34
  # 情緒關懷模式 System Prompt(新增)
35
- CARE_MODE_SYSTEM_PROMPT = """你是富有同理心的 AI 助手,用戶情緒不佳需要支持。
36
 
37
  **極簡短回應規則(必須嚴格遵守)**:
38
  - 最多 1-2 句話(總共不超過 30 字)
@@ -99,6 +99,8 @@ def _build_base_system_prompt(
99
  base_prompt = f"用戶情緒:{care_emotion}\n{base_prompt}"
100
  else:
101
  base_prompt = (
 
 
102
  "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。"
103
  "請使用繁體中文回覆,保持簡潔清晰的表達。"
104
  )
@@ -693,7 +695,11 @@ async def _generate_response_with_chat_db(
693
  system_prompt = f"{CARE_MODE_SYSTEM_PROMPT}\n\n{emotion_text}"
694
  logger.info(f"💙 使用關懷模式 System Prompt,情緒:{care_emotion}")
695
  else:
696
- system_prompt = "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。請使用繁體中文回覆,保持簡潔清晰的表達。"
 
 
 
 
697
 
698
  # 在系統提示前加上用戶名稱
699
  if user_name:
@@ -890,7 +896,11 @@ async def _generate_response_with_global_history(
890
  system_prompt = f"{CARE_MODE_SYSTEM_PROMPT}\n\n{emotion_text}"
891
  logger.info(f"💙 使用關懷模式 System Prompt(全局歷史),情緒:{care_emotion}")
892
  else:
893
- system_prompt = "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。請使用繁體中文回覆,保持簡潔清晰的表達。"
 
 
 
 
894
 
895
  # 在系統提示前加上用戶名稱
896
  if user_name:
 
32
  OPENAI_TIMEOUT = settings.OPENAI_TIMEOUT # 關懷模式 reasoning model 需要更長時間
33
 
34
  # 情緒關懷模式 System Prompt(新增)
35
+ CARE_MODE_SYSTEM_PROMPT = """你是 BloomWare 情緒關懷助手,由銘傳大學人工智慧應用學系 BloomWare 團隊開發。你不是 GPT,也不要自稱 GPT。你是富有同理心的 AI 助手,用戶情緒不佳需要支持。
36
 
37
  **極簡短回應規則(必須嚴格遵守)**:
38
  - 最多 1-2 句話(總共不超過 30 字)
 
99
  base_prompt = f"用戶情緒:{care_emotion}\n{base_prompt}"
100
  else:
101
  base_prompt = (
102
+ "你是 BloomWare 助理,由銘傳大學人工智慧應用學系 BloomWare 團隊開發。"
103
+ "你不是 GPT,也不要自稱 GPT。"
104
  "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。"
105
  "請使用繁體中文回覆,保持簡潔清晰的表達。"
106
  )
 
695
  system_prompt = f"{CARE_MODE_SYSTEM_PROMPT}\n\n{emotion_text}"
696
  logger.info(f"💙 使用關懷模式 System Prompt,情緒:{care_emotion}")
697
  else:
698
+ system_prompt = (
699
+ "你是 BloomWare 助理,由銘傳大學人工智慧應用學系 BloomWare 團隊開發。"
700
+ "你不是 GPT,也不要自稱 GPT。"
701
+ "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。請使用繁體中文回覆,保持簡潔清晰的表達。"
702
+ )
703
 
704
  # 在系統提示前加上用戶名稱
705
  if user_name:
 
896
  system_prompt = f"{CARE_MODE_SYSTEM_PROMPT}\n\n{emotion_text}"
897
  logger.info(f"💙 使用關懷模式 System Prompt(全局歷史),情緒:{care_emotion}")
898
  else:
899
+ system_prompt = (
900
+ "你是 BloomWare 助理,由銘傳大學人工智慧應用學系 BloomWare 團隊開發。"
901
+ "你不是 GPT,也不要自稱 GPT。"
902
+ "你是一個友善、有禮、幽默且能夠提供幫助的AI助手。請使用繁體中文回覆,保持簡潔清晰的表達。"
903
+ )
904
 
905
  # 在系統提示前加上用戶名稱
906
  if user_name: