import os import gspread import pandas as pd from google.oauth2.service_account import Credentials from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline # ========== STEP 1: ตั้งค่า path ========== BASE_DIR = os.path.dirname(__file__) CRED_PATH = os.path.join(BASE_DIR, "credentials.json") DATA_DIR = os.path.join(BASE_DIR, "Senti_real", "Data") SENTIMENT_DIR = os.path.join(BASE_DIR, "Senti_real", "Sentiment") os.makedirs(DATA_DIR, exist_ok=True) os.makedirs(SENTIMENT_DIR, exist_ok=True) # ========== STEP 2: เชื่อมต่อ Google Sheet ========== scopes = ['https://www.googleapis.com/auth/spreadsheets'] credentials = Credentials.from_service_account_file(CRED_PATH, scopes=scopes) client = gspread.authorize(credentials) sheet_url = "https://docs.google.com/spreadsheets/d/1M3hwj9BRg4diW8_7rdk0OskLndnEUscdn_CWM2vNj_0/edit?usp=sharing" worksheet = client.open_by_url(sheet_url).get_worksheet(0) data = worksheet.get_all_records() df = pd.DataFrame(data) # ========== STEP 3: Preprocess ========== column_mapping = { 'ประทับเวลา': 'timestamp', 'เพศ': 'gender', 'อายุ (ใส่เป็นตัวเลข)': 'age', 'บทบาทของคุณในการใช้งาน แอปพลิเคชัน Check PD': 'user_role', 'ผลลัพธ์ที่ได้จาก แอปพลิเคชัน Check PD': 'app_result', 'สถานที่ท่านเข้ารับบริการ ( อื่น ๆ โปรดระบุจังหวัด )': 'service_location', 'วันที่เข้ารับบริการ ': 'service_date', 'แอปพลิเคชัน CheckPD ใช้งานง่ายและไม่ซับซ้อน ': 'app_usability', 'ข้อมูลและคำแนะนำในแอปพลิเคชันมีความเข้าใจง่าย ': 'app_info_clarity', 'คุณรู้สึกว่าแอปพลิเคชันให้ผลวิเคราะห์ที่แม่นยำและน่าเชื่อถือ': 'app_accuracy', 'แอปช่วยให้คุณสามารถติดตามหรือวางแผนดูแลอาการได้ดีขึ้น': 'app_support_effectiveness', 'โดยรวมแล้วคุณพึงพอใจกับการใช้งานแอปพลิเคชัน CheckPD มากน้อยเพียงใด ': 'app_overall_satisfaction', 'การให้บริการของเจ้าหน้าที่': 'staff_service_quality', 'ความรวดเร็วในการให้บริการของเจ้าหน้าที่': 'staff_response_speed', 'เจ้าหน้าที่สามารถให้คำแนะนำหรือข้อมูลเบื้องต้นได้ชัดเจน': 'staff_info_clarity', 'คุณรู้สึกสะดวกและประทับใจเมื่อขอความช่วยเหลือ ': 'staff_comfort', 'คุณพึงพอใจต่อการบริการจากเจ้าหน้าที่ทางการแพทย์หรือไม่ ': 'staff_overall_satisfaction', 'คุณรู้สึกอย่างไรเมื่อใช้งานแอปพลิเคชัน CheckPD ครั้งแรก? ': 'user_feeling_first_use', 'บริการของเจ้าหน้าที่ทำให้คุณรู้สึกอย่างไร?': 'staff_emotion_feedback', 'สิ่งใดในแอปพลิเคชันหรืองานบริการที่คุณคิดว่าควรปรับปรุง? ': 'improvement_suggestions', 'แบบทดสอบที่ได้ทำในแอปพลิเคชัน Check PD ': 'app_quiz_used', 'ปัญหาการใช้งานแอปพลิเคชัน Check PD ': 'app_issue_encountered', ' ความพร้อมในการให้บริการของเจ้าหน้าที่ ': 'staff_readiness', } df.rename(columns=column_mapping, inplace=True) # แยกแบบทดสอบ df_split = df['app_quiz_used'].str.split(',\s*', expand=True) quiz_column_names = { "ประวัติส่วนตัว (ชื่อ-นามสกุล เลขบัตรประจำตัวประชาชน ที่อยู่)": "personal_info", "การออกเสียง 'อาาา' (Voice Test - Ahhh)": "voice_ahhh", "การออกเสียง 'ยายพาหลานไปซื้อขนมที่ตลาด' (Voice Test - ยายพาหลานไปซื้อขนมที่ตลาด)": "voice_sentence", "อาการสั่นขณะนั่งนิ่ง (Resting Tremor)": "resting_tremor", "อาการสั่นขณะยกแขน (Postural Tremor)": "postural_tremor", "แตะสลับนิ้วขวา (Dual Tap - Right)": "dual_tap_right", "แตะสลับนิ้วซ้าย (Dual Tap - Left)": "dual_tap_left", "การขยายวงกลม - ขวา (Pinch to Size - Right)": "pinch_size_right", "การขยายวงกลม - ซ้าย (Pinch to Size - Left)": "pinch_size_left", "การเดิน (Gait walk)": "gait_walk", "การทรงตัวขณะยืน (Balance)": "balance", "ตอบคำถาม 20 ข้อ (Questionnaire)": "questionnaire" } for col in quiz_column_names.values(): df[col] = 0 for idx, row in df_split.iterrows(): for val in row.dropna(): en_col = quiz_column_names.get(val.strip()) if en_col: df.at[idx, en_col] = 1 df.drop(columns=['app_quiz_used'], inplace=True) # ========== STEP 4: บันทึกข้อมูลหลัง Preprocess ========== csv_path_clean = os.path.join(DATA_DIR, "checkpd_data.csv") df.to_csv(csv_path_clean, index=False) # ========== STEP 5: Sentiment Analysis ========== text_columns = ['user_feeling_first_use', 'staff_emotion_feedback', 'improvement_suggestions'] df_sentiment = df[['service_location', 'user_feeling_first_use', 'staff_emotion_feedback', 'improvement_suggestions']].copy() model_name = "phoner45/wangchan-sentiment-thai-text-model" tokenizer = AutoTokenizer.from_pretrained(model_name , use_fast=False) model = AutoModelForSequenceClassification.from_pretrained(model_name) sentiment_pipe = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer) def analyze_sentiment(series): labels = [] scores = [] for text in series.fillna("").astype(str): if text.strip() == "": labels.append("NA") scores.append(None) else: try: result = sentiment_pipe(text[:512])[0] labels.append(result['label']) scores.append(round(result['score'], 4)) except: labels.append("ERROR") scores.append(None) return labels, scores for col in text_columns: label_col = col + "_sentiment" score_col = col + "_score" labels, scores = analyze_sentiment(df_sentiment[col]) df_sentiment[label_col] = labels df_sentiment[score_col] = scores # ========== STEP 6: บันทึกผลลัพธ์ ========== output_path = os.path.join(SENTIMENT_DIR, "checkpd_sentiment.csv") df_sentiment.to_csv(output_path, index=False) print(f"\n✅ วิเคราะห์ Sentiment เสร็จสมบูรณ์! บันทึกที่: {output_path}")