lauren-cw commited on
Commit
7cdf3eb
·
verified ·
1 Parent(s): 71ce824

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -402
app.py DELETED
@@ -1,402 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """DASS心理模型(Q12).ipynb
3
-
4
- Automatically generated by Colab.
5
-
6
- Original file is located at
7
- https://colab.research.google.com/drive/19ATyW5Lb692QV2Gk2I0rlsbeSQNwEDnQ
8
-
9
- 建立環境
10
- """
11
-
12
- import pandas as pd
13
- import matplotlib.pyplot as plt
14
- import numpy as np
15
- import gradio as gr
16
- import sklearn
17
- import pickle
18
- import joblib
19
- import time
20
- import os
21
- import json
22
- import gspread
23
-
24
-
25
- from sklearn.model_selection import train_test_split, RandomizedSearchCV
26
- from sklearn.compose import ColumnTransformer
27
- from sklearn.preprocessing import OneHotEncoder, StandardScaler
28
- from sklearn.pipeline import Pipeline
29
- from sklearn.linear_model import LogisticRegression
30
- from sklearn.metrics import classification_report, confusion_matrix, f1_score, accuracy_score, precision_score, balanced_accuracy_score
31
- from sklearn.ensemble import RandomForestClassifier
32
- from lightgbm import LGBMClassifier
33
- from AutoPreprocess import AutoPreprocess
34
- from google.oauth2.service_account import Credentials
35
- from datetime import datetime, timezone, timedelta
36
-
37
- """Gradio 使用者介面"""
38
-
39
- # 載入模型
40
- import pickle
41
- model_path = os.path.abspath("DASS_model.bin")
42
-
43
- with open(model_path, "rb") as f:
44
- model = pickle.load(f)
45
- model
46
-
47
- """定義歷史紀錄功能"""
48
-
49
- def update_history(current_result_1, current_result_2, history_list):
50
- """
51
- current_result_1 & 2: 來自 predict_risk 的兩個回傳值 (HTML 字串)
52
- history_list: 來自 gr.State 的現有紀錄列表
53
- """
54
-
55
- # 獲取當前時間,格式為:2023-10-27 14:30:05
56
- now = datetime.now(tw_timezone).strftime("%Y-%m-%d %H:%M:%S")
57
-
58
- # 組合這次的結果 (假設你想存這兩個 outputs 的組合)
59
- new_entry = f"""
60
- <div style="border-bottom: 2px solid #eee; padding-bottom: 20px; margin-bottom: 20px;">
61
- <div style="font-size: 18px; color: #666; margin-bottom: 10px; font-weight: bold;">
62
- 🕒 測驗時間:{now}
63
- </div>
64
-
65
- <div style="
66
- display: flex;
67
- flex-direction: row;
68
- justify-content: space-between;
69
- align-items: flex-start;
70
- gap: 20px;
71
- border-bottom: 1px dashed #ccc;
72
- padding-bottom: 15px;
73
- margin-bottom: 15px;
74
- width: 100%;">
75
-
76
- <div style="flex: 1;">{current_result_1}</div>
77
- <div style="flex: 1;">{current_result_2}</div>
78
-
79
- </div>
80
- </div>
81
- """
82
-
83
- # 將新紀錄放在最前面 (置頂)
84
- history_list.insert(0, new_entry)
85
-
86
- # 組合所有歷史紀錄,並整體縮小 80%
87
- # 使用 zoom: 0.8 或 transform 達到字體與版面同時縮小的效果
88
- combined_html = f"""
89
- <div style="zoom: 0.8; -moz-transform: scale(0.8); -moz-transform-origin: 0 0;">
90
- {"".join(history_list)}
91
- </div>
92
- """
93
-
94
- return combined_html, history_list
95
-
96
- """定義儲存測試資料的功能"""
97
-
98
- import os
99
- import json
100
- from datetime import datetime, timezone, timedelta
101
- import gspread
102
- from google.oauth2.service_account import Credentials
103
-
104
- # 設定台灣時區
105
- tw_timezone = timezone(timedelta(hours=8))
106
-
107
- def save_to_google_sheets(inputs, a_score, d_score, s_score, t_score, score):
108
-
109
- # 1. 設定 Google Sheets 存取權限
110
- scope = ['https://www.googleapis.com/auth/spreadsheets',
111
- 'https://www.googleapis.com/auth/drive']
112
-
113
- # 設定Secret Variables(藏金鑰)
114
- google_json = os.environ.get("DASS_JSON")
115
- info = json.loads(google_json)
116
- creds = Credentials.from_service_account_info(info, scopes=scope)
117
- client = gspread.authorize(creds)
118
-
119
- # 2. 開啟指定名稱的試算表 (確保已分享權限給 service account)
120
- sheet = client.open("DASS使用者測試資料").sheet1 # 存於檔案的第一張工作表
121
-
122
-
123
- # 1. 拆分資料:前 3 個是基本資料,後面剩下的 (*rest) 是 12 題答案
124
- user_info = inputs[:3] # 取得前三個:姓名, 年齡, 性別
125
- q_answers = inputs[3:] # 取得剩下的 12 題
126
- now = datetime.now(tw_timezone).strftime("%Y-%m-%d %H:%M:%S")
127
-
128
- # 2. 準備要儲存的資料字典
129
- row_to_add = [
130
- now, # 欄位 A: 測試時間
131
- user_info[0], # 欄位 B: 性別
132
- user_info[1], # 欄位 C: 年齡
133
- user_info[2], # 欄位 D: 家庭人數
134
- a_score, # 欄位 E: 焦慮分數
135
- d_score, # 欄位 F: 憂鬱分數
136
- s_score, # 欄位 G: 壓力分數
137
- t_score, # 欄位 H: 總體分數
138
- score # 欄位 I: 整體程度 (標籤)
139
- ]
140
-
141
- row_to_add.extend(q_answers) # 加入 Q1-Q12 (J欄以後)
142
-
143
- # 4. 追加到試算表最後一行
144
- sheet.append_row(row_to_add)
145
-
146
- """定義重新測驗功能"""
147
-
148
- # 清空函數:回傳與輸入組件數量相同的 None (15個:gen, age, family + 12個問題)
149
- def clear_all():
150
- # 15個輸入(gen, age, family, q1~q12) + 2個即時結果
151
- return [None] * 15 + ["", ""]
152
-
153
- """定義主要測試功能"""
154
-
155
- def predict_risk(gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12):
156
- inputs = [gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12]
157
-
158
- # 檢查是否有任何一個選項是 None (未按)
159
- if any(v is None or v == "" for v in inputs):
160
- # Return error message to a dedicated output component
161
- return "", "", "<div style=\"color: red; font-weight: bold;\">⚠️測驗載入有誤:請確保每一題都已填答或查看填答格式是否正確。</div>"
162
-
163
- # Clear any previous error message if inputs are valid
164
- error_message = ""
165
-
166
- # 1. 跑進度條 (需確保函式參數有 progress=gr.Progress())
167
- progress = gr.Progress()
168
- progress(0, desc="模型計算中...")
169
-
170
- # 2. 將 12 個輸入整理成模型認得的 DataFrame
171
- # 欄位名稱必須與訓練時完全相同
172
- cols = ["gender", "age", "familysize", "Q2A", "Q4A", "Q19A", "Q20A", "Q28A", "Q21A", "Q26A", "Q37A", "Q42A", "Q11A", "Q12A", "Q27A"]
173
- input_df = pd.DataFrame([[gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12]], columns=cols)
174
-
175
- progress(0.5, desc="正在分析數據...")
176
- time.sleep(0.5) # 模擬運算時間
177
-
178
- # 3. 使用模型 model 進行預測
179
- score = model.predict(input_df)[0]
180
- progress(1.0, desc="計算完成!")
181
-
182
-
183
- # 4. 定義風險標籤
184
- if score == 0:
185
- label = "低度風險"
186
- color = "#91cd92" # 綠色
187
- elif score == 1:
188
- label = "中度風險"
189
- color = "#f59e0b" # 橘色
190
- elif score == 2:
191
- label = "高度風險"
192
- color = "#ef4444" # 紅色
193
- else:
194
- label = "計算結果有誤,請重新測試。"
195
-
196
- # 定義類別分數條
197
- a_score = (q1 + q2 + q3 + q4 + q5)
198
- d_score = (q6 + q7 + q8 + q9)
199
- s_score = (q10 + q11 + q12)
200
- t_score = a_score + d_score + s_score
201
- max_val = 36
202
-
203
- def make_bar(label, score, max_val, color):
204
- percent = (score / max_val) * 100
205
- return f"""
206
- <div style="margin-bottom: 10px;">
207
- <div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
208
- <span style="font-weight: bold;">{label}</span>
209
- </div>
210
- <div style="background-color: #e0e0e0; border-radius: 10px; height: 12px; width: 100%;">
211
- <div style="background-color: {color}; width: {percent}%; height: 100%; border-radius: 10px;"></div>
212
- </div>
213
- </div>
214
- """
215
-
216
- # 5. 準備回傳內容
217
- # 總分與風險標籤
218
- result_score = f"""
219
- <div style="text-align: center; font-family: sans-serif;">
220
- <h2 style="color: #313230;">您的預測結果為</h2>
221
- <h1 style="font-size: 60px; color: {color}; margin: 0;">
222
- {label}
223
- </h1>
224
- <h1 style="font-size: 20px; color: #bbbbc2; margin: 0;">
225
- {t_score}/36
226
- </h1>
227
- </div>
228
- """
229
-
230
- # 類別分數條
231
- label_html = f"""
232
- <div style="padding: 20px; background: white; border-radius: 10px; border: 1px solid #ddd;">
233
- <h2 style="color: #313230;margin-top: 0; margin-bottom: 15px;">各面向之比重</h2>
234
- {make_bar("焦慮 (Anxiety)", a_score, max_val, "#fccb42")}
235
- {make_bar("憂鬱 (Depression)", d_score, max_val, "#6dc8fe")}
236
- {make_bar("壓力 (Stress)", s_score, max_val, "#fb6d6d")}
237
- </div>
238
- """
239
-
240
- # 儲存測試資料
241
- save_to_google_sheets(inputs, a_score, d_score, s_score, t_score, score)
242
-
243
-
244
- progress(1.0, desc="完成")
245
-
246
- return result_score, label_html, error_message
247
-
248
- # 設定主題色
249
-
250
- theme = gr.themes.Default(
251
- primary_hue="amber",
252
- secondary_hue="amber",
253
- ).set(
254
- body_background_fill="#fffbeb"
255
- )
256
-
257
- # 線上主題調色器
258
- # gr.themes.builder()
259
-
260
- # 介面編排
261
-
262
- #按鈕及面板格式設定
263
- custom_css = """
264
- #my_green_btn {
265
- background-color: #91cd92 !important;
266
- color: white !important;
267
- border: none;
268
- }
269
- #my_green_btn:hover {
270
- background-color: #72a473 !important; /* 滑鼠懸停時變深 */
271
- }
272
-
273
- #my_white_btn {
274
- background-color: #ffffff !important;
275
- color: black !important;
276
- border: 1px solid #e4e4e7;
277
- }
278
-
279
- #my_white_btn:hover {
280
- background-color: #e4e4e7 !important;
281
- color: black !important; /* 滑鼠懸停時變深 */
282
- }
283
-
284
-
285
- .my-custom-panel {
286
- background-color: #fffef8 !important;
287
- border: 2px solid #e4e4e7 !important;
288
- padding: 20px;
289
- border-radius: 15px;
290
- }
291
-
292
- #history_panel .label-wrap span {
293
- font-weight: bold !important;
294
- }
295
- """
296
-
297
- with gr.Blocks(theme=theme, css=custom_css) as demo:
298
-
299
- # 建立 Session 狀態 (開啟瀏覽器時初始化為空列表)
300
- history_state = gr.State([])
301
-
302
- # 標題及說明
303
- gr.Markdown("")
304
- gr.HTML(f"""
305
- <div style="text-align: center; font-family: sans-serif;">
306
- <h2 style="font-size: 32px; color: #313230; margin: 0;">🌿心理健康風險程度測試📝</h2>
307
- </div>
308
- """)
309
- gr.HTML(f"""
310
- <div style="text-align: center; font-family: sans-serif;">
311
- <h2 style="font-size: 18px; color: #313230; margin: 0;">歡迎來到心理健康風險程度測試環境!<br>
312
- 本測驗將透過12題問答,替您在5分鐘內簡單計算出潛在的心理健康風險程度。<br>
313
- 請輕鬆填答,無須思慮過度,測驗愉快!</h2>
314
- </div>
315
- """)
316
-
317
- with gr.Column(variant="panel", elem_classes="my-custom-panel"):
318
-
319
- # 輸入區塊1(人口靜態欄位)
320
- gr.Markdown("## Step 1. 請輸入基本資訊")
321
- with gr.Row():
322
- with gr.Column():
323
- name = gr.Textbox(label="暱稱")
324
- gen = gr.Dropdown(choices=["男", "女", "其他"],
325
- label="性別",
326
- value=[])
327
- with gr.Column():
328
- age = gr.Number(label="年齡 (僅限填寫數字)", value ="")
329
- family = gr.Number(label="家庭人數 (僅限填寫數字)", value ="")
330
-
331
-
332
- # 輸入區塊2(測驗題)
333
- gr.Markdown("")
334
- gr.Markdown("## Step 2. 請依自身狀態選擇符合的答案")
335
- q1 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
336
- label="Q1.我感覺到口乾舌燥。")
337
- q2 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
338
- label="Q2.我感到呼吸困難(例如:在沒有體力勞動的情況下,呼吸過度急促或喘不過氣)。")
339
- q3 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
340
- label="Q3.在氣溫不高或沒有體力勞動的情況下,我明顯地流汗(例如:手汗)。")
341
- q4 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
342
- label="Q4.我無緣無故地感到害怕。")
343
- q5 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
344
- label="Q5.我覺得自己接近恐慌發作的邊緣。")
345
- q6 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
346
- label="Q6.我覺得生命沒什麼意義/價值。")
347
- q7 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
348
- label="Q7.我感到垂頭喪氣、情緒低落。")
349
- q8 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
350
- label="Q8.我覺得未來毫無希望。")
351
- q9 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
352
- label="Q9.我發現自己很難打起精神主動去做事。")
353
- q10 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
354
- label="Q10.我發現自己很容易變得心煩意亂。")
355
- q11 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
356
- label="Q11.我覺得自己消耗了大量的神經能量(處於高度緊繃狀態)。")
357
- q12 = gr.Radio([("從不", 0), ("偶爾", 1), ("經常", 2), ("總是", 3)],
358
- label="Q12.我發現自己非常易怒(容易焦躁)。")
359
-
360
-
361
- # 確認送出按鈕
362
- sub_button = gr.Button("確認送出", elem_id="my_green_btn")
363
- # 重新測驗按鈕
364
- with gr.Row():
365
- btn_reset = gr.Button("重新測驗", elem_id="my_white_btn")
366
-
367
- # 輸出測試結果
368
- with gr.Row():
369
- out_html = gr.HTML()
370
- out_label = gr.HTML()
371
-
372
-
373
- # --- 新增:歷史紀錄呈現區域 ---
374
- with gr.Accordion("查看歷史紀錄", open=False, elem_id="history_panel"):
375
- history_display = gr.HTML(value="目前尚無測驗紀錄")
376
-
377
-
378
- # 按鈕設定
379
- # 1. 確認送出
380
- sub_button.click(fn=predict_risk,
381
- inputs= [gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12],
382
- outputs= [out_html, out_label]
383
- ).then(
384
- fn=update_history,
385
- inputs=[out_html, out_label, history_state],
386
- outputs=[history_display, history_state])
387
-
388
- # 2. 重新測驗 (清空所有輸入與輸出)
389
- # 注意:outputs 必須包含所有輸入的組件
390
- btn_reset.click(
391
- fn=lambda: [None]*15 + ["", ""],
392
- inputs=None,
393
- outputs=[gen, age, family, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, out_html , out_label]
394
- )
395
-
396
- gr.Markdown("## 免責聲明")
397
- gr.Markdown("""本測驗結果僅供參考,非屬正規醫療檢驗範疇。
398
- 若對於自身狀況有任何疑慮,敬請尋求正規專業醫療協助!♡第四組關心您♡""")
399
-
400
- demo.launch(share=True)
401
-
402
- # 如需免費永久托管,需在終端機模式執行「gradio deploy」部署到 Hugging Face Spaces。