bboat commited on
Commit
1da28ef
·
verified ·
1 Parent(s): 74baf5f

Update scripts/summary.py

Browse files
Files changed (1) hide show
  1. scripts/summary.py +322 -66
scripts/summary.py CHANGED
@@ -1,7 +1,9 @@
1
  import os
2
  import pandas as pd
3
- from typing import Dict
 
4
  from pathlib import Path
 
5
 
6
  # Prefer HF router via OpenAI-compatible client. Use env `HF_TOKEN`.
7
  # HF_TOKEN loaded lazily to allow dotenv loading after import
@@ -34,9 +36,277 @@ def openai_summary(text: str, verbosity: str = 'brief', model: str = 'meta-llama
34
  except Exception:
35
  return None
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta-llama/Llama-3.1-8B-Instruct:novita', total_customers: float = None) -> Dict:
39
- """Summarize overall outage data with GenAI and reliability metrics."""
 
40
  # Basic statistics
41
  total_events = len(df)
42
  date_cols = ['OutageDateTime', 'FirstRestoDateTime', 'LastRestoDateTime', 'CreateEventDateTime', 'CloseEventDateTime']
@@ -61,8 +331,8 @@ def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta
61
  if 'AffectedCustomer' in df_copy.columns:
62
  total_affected = pd.to_numeric(df_copy['AffectedCustomer'], errors='coerce').sum()
63
 
64
- # Create summary text for GenAI
65
- summary_text = f"""
66
  ข้อมูลไฟฟ้าล้มทั้งหมด:
67
  - จำนวนเหตุการณ์ทั้งหมด: {total_events}
68
  - ช่วงเวลาที่เกิดเหตุการณ์: {date_range}
@@ -70,79 +340,55 @@ def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta
70
  - จำนวนลูกค้าที่ได้รับผลกระทบทั้งหมด: {int(total_affected) if not pd.isna(total_affected) else 'ไม่ระบุ'}
71
  """
72
 
73
- # Reliability metrics DataFrame
 
74
  reliability_df = pd.DataFrame()
75
  reliability_summary = ""
 
76
 
77
  if total_customers and total_customers > 0:
78
  try:
79
- from scripts.compute_reliability import compute_reliability
80
- import tempfile
81
- import os
82
-
83
- # Save df to temp CSV for compute_reliability
84
- with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
85
- df_copy.to_csv(f.name, index=False)
86
- temp_path = f.name
87
-
88
- try:
89
- reliability_results = compute_reliability(temp_path, total_customers=total_customers, exclude_planned=True)
90
- overall_metrics = reliability_results.get('overall', pd.DataFrame())
91
- if not overall_metrics.empty:
92
- row = overall_metrics.iloc[0]
93
-
94
- # Create reliability DataFrame with proper metric names
95
- reliability_data = [
96
- {
97
- 'Metric': 'SAIFI',
98
- 'Full Name': 'System Average Interruption Frequency Index',
99
- 'Value': f"{row.get('SAIFI', 'N/A'):.4f}",
100
- 'Unit': 'ครั้ง/ลูกค้า',
101
- 'Description': 'ความถี่เฉลี่ยของการขัดข้องต่อลูกค้า'
102
- },
103
- {
104
- 'Metric': 'SAIDI',
105
- 'Full Name': 'System Average Interruption Duration Index',
106
- 'Value': f"{row.get('SAIDI', 'N/A'):.2f}",
107
- 'Unit': 'นาที/ลูกค้า',
108
- 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อลูกค้า'
109
- },
110
- {
111
- 'Metric': 'CAIDI',
112
- 'Full Name': 'Customer Average Interruption Duration Index',
113
- 'Value': f"{row.get('CAIDI', 'N/A'):.2f}",
114
- 'Unit': 'นาที/ครั้ง',
115
- 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อครั้ง'
116
- },
117
- {
118
- 'Metric': 'MAIFI',
119
- 'Full Name': 'Momentary Average Interruption Frequency Index',
120
- 'Value': f"{row.get('MAIFI', 'N/A'):.4f}",
121
- 'Unit': 'ครั้ง/ลูกค้า',
122
- 'Description': 'ความถี่เฉลี่ยของการขัดข้องชั่วคราวต่อลูกค้า'
123
- }
124
- ]
125
- reliability_df = pd.DataFrame(reliability_data)
126
-
127
- reliability_summary = f"""
128
- ดัชนีความน่าเชื่อถือ:
129
- - SAIFI (System Average Interruption Frequency Index): {row.get('SAIFI', 'N/A'):.4f} ครั้ง/ลูกค้า
130
- - SAIDI (System Average Interruption Duration Index): {row.get('SAIDI', 'N/A'):.2f} นาที/ลูกค้า
131
- - CAIDI (Customer Average Interruption Duration Index): {row.get('CAIDI', 'N/A'):.2f} นาที/ครั้ง
132
- - MAIFI (Momentary Average Interruption Frequency Index): {row.get('MAIFI', 'N/A'):.4f} ครั้ง/ลูกค้า
133
  """
134
- summary_text += reliability_summary
135
- finally:
136
- os.unlink(temp_path)
137
  except Exception as e:
138
  reliability_summary = f"ไม่สามารถคำนวณดัชนีความน่าเชื่อถือได้: {str(e)}"
139
 
140
- # Use GenAI for overall summary
141
  ai_summary = None
142
  if use_hf and get_hf_token():
143
  try:
144
- instruction = "สรุปภาพรวมข้อมูลไฟฟ้าล้มจากข้อมูลนี้ สรุปเป็นย่อหน้าเดียว (ไทย) ระบุจำนวนเหตุการณ์ สาเหตุหลัก ผลกระทบ และข้อเสนอแนะในการปรับปรุงระบบไฟฟ้า:"
145
- prompt = f"{instruction}\n\n{summary_text}\n\nสรุปภาพรวม:"
 
 
 
 
146
  ai_summary = openai_summary(prompt, verbosity='recommend', model=model)
147
  except Exception as e:
148
  ai_summary = f"ไม่สามารถสร้างสรุปด้วย AI ได้: {str(e)}"
@@ -152,8 +398,18 @@ def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta
152
  'date_range': date_range,
153
  'event_types': event_types,
154
  'total_affected_customers': int(total_affected) if not pd.isna(total_affected) else None,
155
- 'basic_summary': summary_text.strip(),
156
  'reliability_summary': reliability_summary.strip() if reliability_summary else None,
 
157
  'reliability_df': reliability_df,
 
158
  'ai_summary': ai_summary,
 
 
 
 
 
 
 
 
159
  }
 
1
  import os
2
  import pandas as pd
3
+ import numpy as np
4
+ from typing import Dict, Tuple, Optional
5
  from pathlib import Path
6
+ from datetime import datetime, timedelta
7
 
8
  # Prefer HF router via OpenAI-compatible client. Use env `HF_TOKEN`.
9
  # HF_TOKEN loaded lazily to allow dotenv loading after import
 
36
  except Exception:
37
  return None
38
 
39
+ def calculate_outage_duration_minutes(df: pd.DataFrame) -> pd.Series:
40
+ """
41
+ คำนวณระยะเวลาการขัดข้องเป็นนาที
42
+ """
43
+ durations = pd.Series(index=df.index, dtype='float64')
44
+
45
+ # ลองใช้คอลัมน์ต่างๆ สำหรับคำนวณระยะเวลา
46
+ if 'OutageDateTime' in df.columns and 'FirstRestoDateTime' in df.columns:
47
+ outage_time = pd.to_datetime(df['OutageDateTime'], dayfirst=True, errors='coerce')
48
+ restore_time = pd.to_datetime(df['FirstRestoDateTime'], dayfirst=True, errors='coerce')
49
+ durations = (restore_time - outage_time).dt.total_seconds() / 60
50
+ elif 'OutageDateTime' in df.columns and 'LastRestoDateTime' in df.columns:
51
+ outage_time = pd.to_datetime(df['OutageDateTime'], dayfirst=True, errors='coerce')
52
+ restore_time = pd.to_datetime(df['LastRestoDateTime'], dayfirst=True, errors='coerce')
53
+ durations = (restore_time - outage_time).dt.total_seconds() / 60
54
+ elif 'CreateEventDateTime' in df.columns and 'CloseEventDateTime' in df.columns:
55
+ create_time = pd.to_datetime(df['CreateEventDateTime'], dayfirst=True, errors='coerce')
56
+ close_time = pd.to_datetime(df['CloseEventDateTime'], dayfirst=True, errors='coerce')
57
+ durations = (close_time - create_time).dt.total_seconds() / 60
58
+
59
+ # แทนที่ค่าลบหรือ NaN ด้วย 0
60
+ durations = durations.fillna(0)
61
+ durations = durations.where(durations >= 0, 0)
62
+
63
+ return durations
64
+
65
+ def compute_reliability_metrics(df: pd.DataFrame, total_customers: float) -> Dict:
66
+ """
67
+ คำนวณตัวชี้วัดความน่าเชื่อถือของระบบไฟฟ้า
68
+
69
+ สูตรการคำนวณ:
70
+ SAIFI = Σ(λᵢ × Nᵢ) / Nₜ
71
+ SAIDI = Σ(Uᵢ × Nᵢ) / Nₜ
72
+ CAIDI = SAIDI / SAIFI
73
+ MAIFI = Σ(λₘᵢ × Nᵢ) / Nₜ
74
+ CTAIDI = Σ(rᵢ × Nᵢ × λᵢ) / Σ(Nᵢ × λᵢ)
75
+ ASAI = (Nₜ × T - Σ(rᵢ × Nᵢ)) / (Nₜ × T)
76
+
77
+ โดยที่:
78
+ λᵢ = ความถี่การขัดข้องของจุดโหลด i
79
+ Nᵢ = จำนวนลูกค้าที่ได้รับผลกระทบในจุดโหลด i
80
+ Nₜ = จำนวนลูกค้าทั้งหมดในระบบ
81
+ Uᵢ = ระยะเวลาขัดข้องรายปีของจุดโหลด i (นาที)
82
+ rᵢ = ระยะเวลาขัดข้องเฉลี่ยต่อครั้งของจุดโหลด i (นาที)
83
+ λₘᵢ = ความถี่การขัดข้องชั่วคราว (< 1 นาที)
84
+ T = ระยะเวลารวม (8760 ชั่วโมง = 525,600 นาที)
85
+ """
86
+
87
+ # เตรียมข้อมูล
88
+ df_clean = df.copy()
89
+
90
+ # คำนวณระยะเวลาขัดข้อง
91
+ df_clean['duration_minutes'] = calculate_outage_duration_minutes(df_clean)
92
+
93
+ # จำนวนลูกค้าที่ได้รับผลกระทบ
94
+ if 'AffectedCustomer' in df_clean.columns:
95
+ df_clean['affected_customers'] = pd.to_numeric(df_clean['AffectedCustomer'], errors='coerce').fillna(0)
96
+ else:
97
+ df_clean['affected_customers'] = 0
98
+
99
+ # แยกประเภทการขัดข้อง
100
+ df_clean['is_momentary'] = df_clean['duration_minutes'] < 1 # ขัดข้องชั่วคราว < 1 นาที
101
+ df_clean['is_sustained'] = df_clean['duration_minutes'] >= 1 # ขัดข้องยาวนาน >= 1 นาที
102
+
103
+ # คำนวณตัวชี้วัด
104
+
105
+ # 1. SAIFI - System Average Interruption Frequency Index
106
+ # SAIFI = Σ(λᵢ × Nᵢ) / Nₜ
107
+ sustained_interruptions = df_clean[df_clean['is_sustained']]
108
+ total_customer_interruptions = sustained_interruptions['affected_customers'].sum()
109
+ saifi = total_customer_interruptions / total_customers if total_customers > 0 else 0
110
+
111
+ # 2. SAIDI - System Average Interruption Duration Index
112
+ # SAIDI = Σ(Uᵢ × Nᵢ) / Nₜ
113
+ customer_minutes = (sustained_interruptions['duration_minutes'] * sustained_interruptions['affected_customers']).sum()
114
+ saidi = customer_minutes / total_customers if total_customers > 0 else 0
115
+
116
+ # 3. CAIDI - Customer Average Interruption Duration Index
117
+ # CAIDI = SAIDI / SAIFI
118
+ caidi = saidi / saifi if saifi > 0 else 0
119
+
120
+ # 4. MAIFI - Momentary Average Interruption Frequency Index
121
+ # MAIFI = Σ(λₘᵢ × Nᵢ) / Nₜ
122
+ momentary_interruptions = df_clean[df_clean['is_momentary']]
123
+ total_momentary_customer_interruptions = momentary_interruptions['affected_customers'].sum()
124
+ maifi = total_momentary_customer_interruptions / total_customers if total_customers > 0 else 0
125
+
126
+ # 5. CTAIDI - Customer Total Average Interruption Duration Index
127
+ # CTAIDI = Σ(rᵢ × Nᵢ × λᵢ) / Σ(Nᵢ × λᵢ)
128
+ total_customer_duration = (df_clean['duration_minutes'] * df_clean['affected_customers']).sum()
129
+ total_customer_events = df_clean['affected_customers'].sum()
130
+ ctaidi = total_customer_duration / total_customer_events if total_customer_events > 0 else 0
131
+
132
+ # 6. ASAI - Average Service Availability Index
133
+ # ASAI = (Nₜ × T - Σ(rᵢ × Nᵢ)) / (Nₜ × T)
134
+ total_minutes_per_year = 525600 # 365 × 24 × 60
135
+ total_available_customer_minutes = total_customers * total_minutes_per_year
136
+ total_unavailable_customer_minutes = customer_minutes
137
+ asai = (total_available_customer_minutes - total_unavailable_customer_minutes) / total_available_customer_minutes if total_available_customer_minutes > 0 else 0
138
+ asai_percent = asai * 100
139
+
140
+ # 7. ASUI - Average Service Unavailability Index
141
+ asui = (1 - asai) * 100
142
+
143
+ # 8. ENS - Energy Not Supplied (ประมาณการ)
144
+ # สมมติว่าลูกค้าแต่ละรายใช้ไฟฟ้าเฉลี่ย 3 kW
145
+ average_demand_kw = 3.0
146
+ ens_kwh = (total_unavailable_customer_minutes / 60) * average_demand_kw
147
+
148
+ # 9. AENS - Average Energy Not Supplied per Customer
149
+ aens = ens_kwh / total_customers if total_customers > 0 else 0
150
+
151
+ # สถิติเพิ่มเติม
152
+ total_events = len(df_clean)
153
+ total_sustained_events = len(sustained_interruptions)
154
+ total_momentary_events = len(momentary_interruptions)
155
+ avg_duration_per_event = df_clean['duration_minutes'].mean()
156
+ max_duration = df_clean['duration_minutes'].max()
157
+ total_affected = df_clean['affected_customers'].sum()
158
+
159
+ return {
160
+ # Primary Reliability Indices
161
+ 'SAIFI': round(saifi, 4),
162
+ 'SAIDI': round(saidi, 2),
163
+ 'CAIDI': round(caidi, 2),
164
+ 'MAIFI': round(maifi, 4),
165
+
166
+ # Additional Indices
167
+ 'CTAIDI': round(ctaidi, 2),
168
+ 'ASAI': round(asai, 6),
169
+ 'ASAI_percent': round(asai_percent, 4),
170
+ 'ASUI_percent': round(asui, 4),
171
+ 'ENS_kWh': round(ens_kwh, 2),
172
+ 'AENS_kWh_per_customer': round(aens, 4),
173
+
174
+ # Supporting Statistics
175
+ 'total_events': total_events,
176
+ 'sustained_events': total_sustained_events,
177
+ 'momentary_events': total_momentary_events,
178
+ 'total_customer_interruptions': int(total_customer_interruptions),
179
+ 'total_customer_minutes': round(customer_minutes, 2),
180
+ 'avg_duration_per_event_minutes': round(avg_duration_per_event, 2),
181
+ 'max_duration_minutes': round(max_duration, 2),
182
+ 'total_affected_customers': int(total_affected)
183
+ }
184
+
185
+ def create_reliability_dataframe(metrics: Dict) -> pd.DataFrame:
186
+ """
187
+ สร้าง DataFrame สำหรับแสดงตัวชี้วัดความน่าเชื่อถือ
188
+ """
189
+ reliability_data = [
190
+ {
191
+ 'Metric': 'SAIFI',
192
+ 'Full Name': 'System Average Interruption Frequency Index',
193
+ 'Value': metrics['SAIFI'],
194
+ 'Unit': 'ครั้ง/ลูกค้า/ปี',
195
+ 'Formula': 'Σ(λᵢ × Nᵢ) / Nₜ',
196
+ 'Description': 'ความถี่เฉลี่ยของการขัดข้องต่อลูกค้าต่อปี',
197
+ 'Good_Value': '< 1.0'
198
+ },
199
+ {
200
+ 'Metric': 'SAIDI',
201
+ 'Full Name': 'System Average Interruption Duration Index',
202
+ 'Value': metrics['SAIDI'],
203
+ 'Unit': 'นาที/ลูกค้า/ปี',
204
+ 'Formula': 'Σ(Uᵢ × Nᵢ) / Nₜ',
205
+ 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อลูกค้าต่อปี',
206
+ 'Good_Value': '< 200'
207
+ },
208
+ {
209
+ 'Metric': 'CAIDI',
210
+ 'Full Name': 'Customer Average Interruption Duration Index',
211
+ 'Value': metrics['CAIDI'],
212
+ 'Unit': 'นาที/ครั้ง',
213
+ 'Formula': 'SAIDI / SAIFI',
214
+ 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อครั้งที่เกิดขัดข้อง',
215
+ 'Good_Value': '< 120'
216
+ },
217
+ {
218
+ 'Metric': 'MAIFI',
219
+ 'Full Name': 'Momentary Average Interruption Frequency Index',
220
+ 'Value': metrics['MAIFI'],
221
+ 'Unit': 'ครั้ง/ลูกค้า/ปี',
222
+ 'Formula': 'Σ(λₘᵢ × Nᵢ) / Nₜ',
223
+ 'Description': 'ความถี่เฉลี่ยของการขัดข้องชั่วคราว (< 1 นาที)',
224
+ 'Good_Value': '< 5.0'
225
+ },
226
+ {
227
+ 'Metric': 'CTAIDI',
228
+ 'Full Name': 'Customer Total Average Interruption Duration Index',
229
+ 'Value': metrics['CTAIDI'],
230
+ 'Unit': 'นาที/ครั้ง',
231
+ 'Formula': 'Σ(rᵢ × Nᵢ × λᵢ) / Σ(Nᵢ × λᵢ)',
232
+ 'Description': 'ระยะเวลาขัดข้องเฉลี่ยรวมทั้งชั่วคราวและยาวนาน',
233
+ 'Good_Value': '< 100'
234
+ },
235
+ {
236
+ 'Metric': 'ASAI',
237
+ 'Full Name': 'Average Service Availability Index',
238
+ 'Value': metrics['ASAI_percent'],
239
+ 'Unit': '%',
240
+ 'Formula': '(Nₜ×T - Σ(rᵢ×Nᵢ)) / (Nₜ×T) × 100',
241
+ 'Description': 'ดัชนีความพร้อมใช้งานเฉลี่ยของระบบ',
242
+ 'Good_Value': '> 99.95%'
243
+ },
244
+ {
245
+ 'Metric': 'ASUI',
246
+ 'Full Name': 'Average Service Unavailability Index',
247
+ 'Value': metrics['ASUI_percent'],
248
+ 'Unit': '%',
249
+ 'Formula': '100 - ASAI',
250
+ 'Description': 'ดัชนีความไม่พร้อมใช้งานเฉลี่ยของระบบ',
251
+ 'Good_Value': '< 0.05%'
252
+ },
253
+ {
254
+ 'Metric': 'AENS',
255
+ 'Full Name': 'Average Energy Not Supplied per Customer',
256
+ 'Value': metrics['AENS_kWh_per_customer'],
257
+ 'Unit': 'kWh/ลูกค้า/ปี',
258
+ 'Formula': 'ENS / Nₜ',
259
+ 'Description': 'พลังงานไฟฟ้าเฉลี่ยที่ไม่สามารถจ่ายให้ลูกค้าได้',
260
+ 'Good_Value': '< 10'
261
+ }
262
+ ]
263
+
264
+ return pd.DataFrame(reliability_data)
265
+
266
+ def interpret_reliability_metrics(metrics: Dict) -> str:
267
+ """
268
+ ตีความผลตัวชี้วัดความน่าเชื่อถือ
269
+ """
270
+ interpretations = []
271
+
272
+ # SAIFI interpretation
273
+ saifi = metrics['SAIFI']
274
+ if saifi < 1.0:
275
+ interpretations.append("SAIFI: ดีมาก - ลูกค้าขัดข้องน้อยกว่า 1 ครั้งต่อปี")
276
+ elif saifi < 2.0:
277
+ interpretations.append("SAIFI: ดี - ลูกค้าขัดข้องประมาณ 1-2 ครั้งต่อปี")
278
+ elif saifi < 5.0:
279
+ interpretations.append("SAIFI: พอใช้ - ลูกค้าขัดข้อง 2-5 ครั้งต่อปี")
280
+ else:
281
+ interpretations.append("SAIFI: ต้องปรับปรุง - ลูกค้าขัดข้องบ่อยเกิน 5 ครั้งต่อปี")
282
+
283
+ # SAIDI interpretation
284
+ saidi = metrics['SAIDI']
285
+ if saidi < 100:
286
+ interpretations.append("SAIDI: ดีมาก - ขัดข้องน้อยกว่า 100 นาทีต่อปี")
287
+ elif saidi < 200:
288
+ interpretations.append("SAIDI: ดี - ขัดข้อง 100-200 นาทีต่อปี")
289
+ elif saidi < 500:
290
+ interpretations.append("SAIDI: พอใช้ - ขัดข้อง 200-500 นาทีต่อปี")
291
+ else:
292
+ interpretations.append("SAIDI: ต้องปรับปรุง - ขัดข้องเกิน 500 นาทีต่อปี")
293
+
294
+ # ASAI interpretation
295
+ asai = metrics['ASAI_percent']
296
+ if asai > 99.98:
297
+ interpretations.append("ASAI: ดีเยี่ยม - ระบบพร้อมใช้งานเกิน 99.98%")
298
+ elif asai > 99.95:
299
+ interpretations.append("ASAI: ดีมาก - ระบบพร้อมใช้งาน 99.95-99.98%")
300
+ elif asai > 99.90:
301
+ interpretations.append("ASAI: ดี - ระบบพร้อมใช้งาน 99.90-99.95%")
302
+ else:
303
+ interpretations.append("ASAI: ต้องปรับปรุง - ระบบพร้อมใช้งานต่ำกว่า 99.90%")
304
+
305
+ return " | ".join(interpretations)
306
 
307
  def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta-llama/Llama-3.1-8B-Instruct:novita', total_customers: float = None) -> Dict:
308
+ """Summarize overall outage data with enhanced reliability metrics and GenAI analysis."""
309
+
310
  # Basic statistics
311
  total_events = len(df)
312
  date_cols = ['OutageDateTime', 'FirstRestoDateTime', 'LastRestoDateTime', 'CreateEventDateTime', 'CloseEventDateTime']
 
331
  if 'AffectedCustomer' in df_copy.columns:
332
  total_affected = pd.to_numeric(df_copy['AffectedCustomer'], errors='coerce').sum()
333
 
334
+ # Create basic summary text
335
+ basic_summary = f"""
336
  ข้อมูลไฟฟ้าล้มทั้งหมด:
337
  - จำนวนเหตุการณ์ทั้งหมด: {total_events}
338
  - ช่วงเวลาที่เกิดเหตุการณ์: {date_range}
 
340
  - จำนวนลูกค้าที่ได้รับผลกระทบทั้งหมด: {int(total_affected) if not pd.isna(total_affected) else 'ไม่ระบุ'}
341
  """
342
 
343
+ # Compute reliability metrics
344
+ reliability_metrics = {}
345
  reliability_df = pd.DataFrame()
346
  reliability_summary = ""
347
+ reliability_interpretation = ""
348
 
349
  if total_customers and total_customers > 0:
350
  try:
351
+ reliability_metrics = compute_reliability_metrics(df_copy, total_customers)
352
+ reliability_df = create_reliability_dataframe(reliability_metrics)
353
+ reliability_interpretation = interpret_reliability_metrics(reliability_metrics)
354
+
355
+ reliability_summary = f"""
356
+ ดัชนีความน่าเชื่อถือของระบบไฟฟ้า:
357
+
358
+ ตัวชี้วัดหลัก:
359
+ - SAIFI: {reliability_metrics['SAIFI']:.4f} ครั้ง/ลูกค้า/ปี (ความถี่การขัดข้อง)
360
+ - SAIDI: {reliability_metrics['SAIDI']:.2f} นาที/ลูกค้า/ปี (ระยะเวลาขัดข้อง)
361
+ - CAIDI: {reliability_metrics['CAIDI']:.2f} นาที/ครั้ง (ระยะเวลาเฉลี่ยต่อครั้ง)
362
+ - MAIFI: {reliability_metrics['MAIFI']:.4f} ครั้ง/ลูกค้า/ปี (ขัดข้องชั่วคราว)
363
+
364
+ ตัวชี้วัดเพิ่มเติม:
365
+ - ASAI: {reliability_metrics['ASAI_percent']:.4f}% (ความพร้อมใช้งาน)
366
+ - ASUI: {reliability_metrics['ASUI_percent']:.4f}% (ความไม่พร้อมใช้งาน)
367
+ - AENS: {reliability_metrics['AENS_kWh_per_customer']:.4f} kWh/ลูกค้า/ปี (พลังงานที่สูญเสีย)
368
+
369
+ การตีความ: {reliability_interpretation}
370
+
371
+ สถิติสนับสนุน:
372
+ - เหตุการณ์ยาวนาน: {reliability_metrics['sustained_events']} ครั้ง
373
+ - เหตุการณ์ชั่วคราว: {reliability_metrics['momentary_events']} ครั้ง
374
+ - ระยะเวลาเฉลี่ยต่อเหตุการณ์: {reliability_metrics['avg_duration_per_event_minutes']:.2f} นาที
375
+ - ระยะเวลาสูงสุด: {reliability_metrics['max_duration_minutes']:.2f} นาที
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  """
377
+ basic_summary += reliability_summary
378
+
 
379
  except Exception as e:
380
  reliability_summary = f"ไม่สามารถคำนวณดัชนีความน่าเชื่อถือได้: {str(e)}"
381
 
382
+ # Use GenAI for overall summary with enhanced context
383
  ai_summary = None
384
  if use_hf and get_hf_token():
385
  try:
386
+ instruction = """สรุปภาพรวมข้อมูลไฟฟ้าล้มและวิเคราะห์ตัวชี้วัดความน่าเชื่อถือ สรุปเป็น 2-3 ย่อหน้า (ไทย) ประกอบด้วย:
387
+ 1. ภาพรวมเหตุการณ์และผลกระทบ
388
+ 2. การวิเคราะห์ตัวชี้วัด SAIFI, SAIDI, ASAI และการตีความ
389
+ 3. ข้อเสนอแนะในการปรับปรุงประสิทธิภาพและความน่าเชื่อถือของระบบ:"""
390
+
391
+ prompt = f"{instruction}\n\n{basic_summary}\n\nสรุปภาพรวมและการวิเคราะห์:"
392
  ai_summary = openai_summary(prompt, verbosity='recommend', model=model)
393
  except Exception as e:
394
  ai_summary = f"ไม่สามารถสร้างสรุปด้วย AI ได้: {str(e)}"
 
398
  'date_range': date_range,
399
  'event_types': event_types,
400
  'total_affected_customers': int(total_affected) if not pd.isna(total_affected) else None,
401
+ 'basic_summary': basic_summary.strip(),
402
  'reliability_summary': reliability_summary.strip() if reliability_summary else None,
403
+ 'reliability_metrics': reliability_metrics,
404
  'reliability_df': reliability_df,
405
+ 'reliability_interpretation': reliability_interpretation,
406
  'ai_summary': ai_summary,
407
+ 'formulas': {
408
+ 'SAIFI': 'Σ(λᵢ × Nᵢ) / Nₜ',
409
+ 'SAIDI': 'Σ(Uᵢ × Nᵢ) / Nₜ',
410
+ 'CAIDI': 'SAIDI / SAIFI',
411
+ 'MAIFI': 'Σ(λₘᵢ × Nᵢ) / Nₜ',
412
+ 'ASAI': '(Nₜ×T - Σ(rᵢ×Nᵢ)) / (Nₜ×T) × 100',
413
+ 'AENS': 'ENS / Nₜ'
414
+ }
415
  }