Tortyfishguy commited on
Commit
96c717f
·
verified ·
1 Parent(s): 46c2cbe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -42
app.py CHANGED
@@ -6,89 +6,151 @@ from fastapi import FastAPI, Request, HTTPException, Header
6
  from linebot import LineBotApi, WebhookHandler
7
  from linebot.exceptions import InvalidSignatureError
8
  from linebot.models import MessageEvent, TextMessage, TextSendMessage
9
- from model import classify_esi # นำเข้าโมเดลที่โหลดไว้แล้ว
 
10
 
11
- # ตั้งค่า Logging
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
- # โหลด Environment Variables
16
  LINE_ACCESS_TOKEN = os.getenv("LINE_ACCESS_TOKEN")
17
  LINE_CHANNEL_SECRET = os.getenv("LINE_CHANNEL_SECRET")
18
 
19
- # Initialize FastAPI
20
  app = FastAPI()
21
-
22
- # Initialize LINE SDK
23
  line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
24
  handler = WebhookHandler(LINE_CHANNEL_SECRET)
25
 
26
  @app.get("/")
27
  async def root():
28
- return {"message": "Triage Bot is running for the ER of San Pa Tong Hospital!"}
29
 
30
  @app.post("/webhook")
31
  async def webhook(request: Request, x_line_signature: str = Header(None)):
32
  if not x_line_signature:
33
  raise HTTPException(status_code=400, detail="Missing X-Line-Signature")
34
-
35
  body = await request.body()
36
  body_text = body.decode("utf-8")
37
-
38
- # Log ข้อความที่ได้รับจาก LINE
39
- logger.info(f"Received webhook event: {body_text}")
40
-
41
  try:
42
- # ✅ ตอบกลับ LINE ทันที เพื่อป้องกัน Timeout
43
  threading.Thread(target=handle_webhook, args=(body_text, x_line_signature)).start()
44
  return {"status": "OK"}
45
  except Exception as e:
46
- logger.error(f"Error processing webhook: {e}")
47
  return {"status": "Error"}, 500
48
 
49
  def handle_webhook(body_text, x_line_signature):
50
- """ ฟังก์ชันประมวลผล Webhook แยกต่างหาก """
51
  try:
52
  handler.handle(body_text, x_line_signature)
53
  except InvalidSignatureError:
54
- logger.error("Invalid signature error")
55
  except Exception as e:
56
- logger.error(f"Error handling webhook: {e}")
57
 
58
- # Event handler สำหรับข้อความที่ได้รับ
59
  @handler.add(MessageEvent, message=TextMessage)
60
  def handle_message(event):
61
  user_message = event.message.text
62
- logger.info(f"User message: {user_message}") # Log ข้อความจากผู้ใช้
63
-
64
- esi_level = classify_esi(user_message) # ใช้โมเดล AI วิเคราะห์ ESI
65
- response_text = get_triage_response(esi_level)
66
-
67
- logger.info(f"Bot response: {response_text}") # Log ข้อความที่บอทจะส่ง
68
-
69
- # ใช้ threading เพื่อให้ bot ตอบกลับเร็วขึ้น
70
  threading.Thread(target=reply_message, args=(event.reply_token, response_text)).start()
71
 
72
  def reply_message(reply_token, message):
73
- """ ส่งข้อความตอบกลับผู้ใช้ """
74
  try:
75
  line_bot_api.reply_message(reply_token, TextSendMessage(text=message))
76
- logger.info("Reply sent successfully") # Log เมื่อส่งสำเร็จ
77
  except Exception as e:
78
- logger.error(f"Error sending reply: {e}")
79
-
80
- def get_triage_response(esi_level):
81
- """
82
- รับค่า ESI (1-5) และแปลงเป็นข้อความแนะนำให้ผู้ป่วย
83
- """
84
- if esi_level in [1, 2]:
85
- return "🚑 อาการของคุณรุนแรง ควรรีบไปห้องฉุกเฉินทันที!"
86
- elif esi_level == 3:
87
- return "🏥 คุณควรพบแพทย์เร็วที่สุดเพื่อตรวจสอบเพิ่มเติม"
88
- elif esi_level in [4, 5]:
89
- return "😊 อาการของคุณสามารถรอพบแพทย์ที่ OPD ในวันพรุ่งนี้เช้าได้"
90
- else:
91
- return " ไม่สามารถประเมินได้ กรุณาลองอธิบายอาการให้ละเอียดขึ้น"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  if __name__ == "__main__":
94
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
6
  from linebot import LineBotApi, WebhookHandler
7
  from linebot.exceptions import InvalidSignatureError
8
  from linebot.models import MessageEvent, TextMessage, TextSendMessage
9
+ from pythainlp.tokenize import word_tokenize
10
+ from rapidfuzz import fuzz
11
 
12
+ # Logging
13
  logging.basicConfig(level=logging.INFO)
14
  logger = logging.getLogger(__name__)
15
 
16
+ # LINE Credentials
17
  LINE_ACCESS_TOKEN = os.getenv("LINE_ACCESS_TOKEN")
18
  LINE_CHANNEL_SECRET = os.getenv("LINE_CHANNEL_SECRET")
19
 
20
+ # Initialize
21
  app = FastAPI()
 
 
22
  line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
23
  handler = WebhookHandler(LINE_CHANNEL_SECRET)
24
 
25
  @app.get("/")
26
  async def root():
27
+ return {"message": "Triage Bot is running (Thai NLP + fuzzy + triage level)"}
28
 
29
  @app.post("/webhook")
30
  async def webhook(request: Request, x_line_signature: str = Header(None)):
31
  if not x_line_signature:
32
  raise HTTPException(status_code=400, detail="Missing X-Line-Signature")
 
33
  body = await request.body()
34
  body_text = body.decode("utf-8")
35
+ logger.info(f"Received webhook: {body_text}")
 
 
 
36
  try:
 
37
  threading.Thread(target=handle_webhook, args=(body_text, x_line_signature)).start()
38
  return {"status": "OK"}
39
  except Exception as e:
40
+ logger.error(f"Webhook error: {e}")
41
  return {"status": "Error"}, 500
42
 
43
  def handle_webhook(body_text, x_line_signature):
 
44
  try:
45
  handler.handle(body_text, x_line_signature)
46
  except InvalidSignatureError:
47
+ logger.error("Invalid signature")
48
  except Exception as e:
49
+ logger.error(f"Handle webhook error: {e}")
50
 
 
51
  @handler.add(MessageEvent, message=TextMessage)
52
  def handle_message(event):
53
  user_message = event.message.text
54
+ logger.info(f"User message: {user_message}")
55
+ response_text = check_emergency(user_message)
56
+ logger.info(f"Bot response: {response_text}")
 
 
 
 
 
57
  threading.Thread(target=reply_message, args=(event.reply_token, response_text)).start()
58
 
59
  def reply_message(reply_token, message):
 
60
  try:
61
  line_bot_api.reply_message(reply_token, TextSendMessage(text=message))
62
+ logger.info("Reply sent")
63
  except Exception as e:
64
+ logger.error(f"Send reply error: {e}")
65
+
66
+ # ----------------- Emergency Symptom and Levels ------------------
67
+
68
+ EMERGENCY_SYMPTOMS = {
69
+ "หมดสติ / ไม่รู้สึกตัว": [
70
+ "หมดสติ", "ไม่รู้สึกตัว", "เป็นลม", "ล้มแล้วไม่ตื��น", "ไม่ตอบสนอง",
71
+ "หลับไม่รู้เรื่อง", "ไม่ขยับ", "ปลุกไม่ตื่น", "เหม่อลอย", "สลบ"
72
+ ],
73
+ "หายใจผิดปกติ": [
74
+ "หายใจเร็ว", "หายใจเหนื่อย", "หายใจลำบาก", "หายใจติดขัด", "หอบ",
75
+ "หายใจเสียงดัง", "แน่นหน้าอก", "หายใจไม่ทัน", "อึดอัด", "หายใจถี่"
76
+ ],
77
+ "เจ็บหน้าอก": [
78
+ "เจ็บหน้าอก", "แน่นหน้าอก", "จุกหน้าอก", "เสียวหน้าอก", "ปวดอก",
79
+ "บีบหน้าอก", "เจ็บลึกๆในอก", "อกแน่น", "อกอึดอัด", "หน้าอกปวดจี๊ด"
80
+ ],
81
+ "ชัก / หยุดหายใจ": [
82
+ "ชัก", "เกร็ง", "หยุดหายใจ", "หมดลม", "ตัวสั่น",
83
+ "ชักกระตุก", "หมดแรง", "ดิ้น", "ลืมตาไม่ขึ้น", "ตัวแข็ง"
84
+ ],
85
+ "อัมพฤกษ์ / พูดไม่ชัด": [
86
+ "อัมพฤกษ์", "อัมพาต", "พูดไม่ชัด", "หน้าเบี้ยว", "แขนขาอ่อนแรง",
87
+ "ยิ้มไม่เท่ากัน", "ยกแขนไม่ขึ้น", "เดินเซ", "ลิ้นแข็ง", "แขนขาไม่มีแรง"
88
+ ],
89
+ "เลือดออก / บาดแผล": [
90
+ "เลือดออก", "เลือดไม่หยุด", "เลือดไหล", "แผลฉกรรจ์", "แผลลึก",
91
+ "เลือดพุ่ง", "เลือดเปื้อนตัว", "แผลเปิด", "เลือดซึมตลอด", "แผลทะลุ"
92
+ ],
93
+ "กระดูกหัก": [
94
+ "กระดูกหัก", "แขนหัก", "ขาหัก", "นิ้วหัก", "บวมผิดรูป",
95
+ "ขางอผิดรูป", "ขาใช้การไม่ได้", "ขยับแล้วเจ็บมาก", "ปูด", "โค้งผิดปกติ"
96
+ ],
97
+ "อุบัติเหตุรุนแรง": [
98
+ "รถชน", "รถล้ม", "ตกจากที่สูง", "หัวฟาด", "อุบัติเหตุแรง",
99
+ "รถคว่ำ", "ล้มแรง", "โดนกระแทกแรง", "ลื่นหัวฟาด", "โดนรถชน"
100
+ ],
101
+ "เด็กมีไข้ / ชัก": [
102
+ "ไข้สูง", "เด็กชัก", "ลูกชัก", "ชักตอนมีไข้", "ตัวร้อนจัด",
103
+ "ไข้ขึ้นสูง", "ตาค้าง", "เด็กไม่ตอบสนอง", "มือแข็ง", "สั่นทั้งตัว"
104
+ ],
105
+ "ภาวะช็อก / หัวใจเต้นผิดจังหวะ": [
106
+ "ช็อก", "ความดันต่ำ", "ใจสั่น", "หัวใจเต้นผิดจังหวะ", "ชีพจรเร็ว",
107
+ "หมดแรงกะทันหัน", "ตัวเย็น", "เหงื่อแตก", "ใจเต้นแรง", "แน่นท้องหายใจไม่ออก"
108
+ ],
109
+ "ได้รับสารพิษ / ยาเกินขนาด / สัตว์มีพิษกัด": [
110
+ "สารพิษ", "กินยาเกิน", "ยาเกินขนาด", "พิษ", "ถูกงูกัด",
111
+ "แมงป่องต่อย", "แมลงกัด", "แพ้ยา", "แพ้อาหารรุนแรง", "คลื่นไส้อาเจียนมาก"
112
+ ],
113
+ "ผู้ป่วยตั้งครรภ์ใกล้คลอด": [
114
+ "ตั้งครรภ์", "เจ็บท้องคลอด", "น้ำเดิน", "มูกเลือด", "ปวดท้องใกล้คลอด",
115
+ "ท้องแข็ง", "มดลูกบีบ", "ปวดหน่วง", "เจ็บท้องถี่", "ลูกดิ้นแรงผิดปกติ"
116
+ ]
117
+ }
118
+
119
+ EMERGENCY_LEVELS = {
120
+ "หมดสติ / ไม่รู้สึกตัว": 1,
121
+ "หายใจผิดปกติ": 1,
122
+ "เจ็บหน้าอก": 2,
123
+ "ชัก / หยุดหายใจ": 1,
124
+ "อัมพฤกษ์ / พูดไม่ชัด": 2,
125
+ "เลือดออก / บาดแผล": 2,
126
+ "กระดูกหัก": 2,
127
+ "อุบัติเหตุรุนแรง": 1,
128
+ "เด็กมีไข้ / ชัก": 2,
129
+ "ภาวะช็อก / หัวใจเต้นผิดจังหวะ": 1,
130
+ "ได้รับสารพิษ / ยาเกินขนาด / สัตว์มีพิษกัด": 1,
131
+ "ผู้ป่วยตั้งครรภ์ใกล้คลอด": 2
132
+ }
133
+
134
+ FUZZY_THRESHOLD = 85
135
+
136
+ def check_emergency(message):
137
+ tokens = word_tokenize(message.lower(), engine="newmm")
138
+ logger.info(f"Tokenized: {tokens}")
139
+
140
+ for label, keywords in EMERGENCY_SYMPTOMS.items():
141
+ for token in tokens:
142
+ for keyword in keywords:
143
+ score = fuzz.partial_ratio(token, keyword)
144
+ if score >= FUZZY_THRESHOLD:
145
+ level = EMERGENCY_LEVELS.get(label, 2)
146
+ if level == 1:
147
+ return f"🚨 อาการของคุณเข้าข่ายฉุกเฉินระดับ **1 (ด่วนมาก)**: {label}\nกรุณารีบไปห้องฉุกเฉินทันที!"
148
+ elif level == 2:
149
+ return f"⚠️ อาการของคุณเข้าข่ายฉุกเฉินระดับ **2 (เร่งด่วน)**: {label}\nควรไปโรงพยาบาลโดยเร็วที่สุด"
150
+
151
+ return "🟢 อาการของคุณไม่เข้าข่ายฉุกเฉิน สามารถเข้ารับบริการที่ห้องตรวจทั่วไปในวันถัดไปได้"
152
+
153
+ # ----------------------------------------------------------------
154
 
155
  if __name__ == "__main__":
156
  uvicorn.run(app, host="0.0.0.0", port=7860)