NoiNE1 commited on
Commit
02007b6
·
verified ·
1 Parent(s): 74baf5f

Update scripts/summary.py

Browse files
Files changed (1) hide show
  1. scripts/summary.py +284 -75
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,252 @@ 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']
@@ -49,7 +294,7 @@ def summarize_overall(df: pd.DataFrame, use_hf: bool = False, model: str = 'meta
49
 
50
  # Calculate basic metrics
51
  if 'OutageDateTime' in df_copy.columns:
52
- date_range = f"{df_copy['OutageDateTime'].min()} ถึง {df_copy['OutageDateTime'].max()}" if pd.notna(df_copy['OutageDateTime'].min()) else "ไม่ระบุ"
53
  else:
54
  date_range = "ไม่ระบุ"
55
 
@@ -61,99 +306,63 @@ 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}
69
- - ประเภทเหตุการณ์หลัก: {', '.join([f'{k}: {v}' for k, v in event_types.items()])}
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)}"
149
 
150
  return {
151
  'total_events': total_events,
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, Optional, Tuple
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(outage_time: pd.Series, restore_time: pd.Series) -> pd.Series:
40
+ """Calculate outage duration in minutes."""
41
+ try:
42
+ outage_dt = pd.to_datetime(outage_time, dayfirst=True, errors='coerce')
43
+ restore_dt = pd.to_datetime(restore_time, dayfirst=True, errors='coerce')
44
+
45
+ # Calculate duration in minutes
46
+ duration = (restore_dt - outage_dt).dt.total_seconds() / 60
47
+ return duration.fillna(0)
48
+ except:
49
+ return pd.Series([0] * len(outage_time))
50
+
51
+ def calculate_reliability_indices(df: pd.DataFrame, total_customers: float) -> Dict:
52
+ """
53
+ Calculate power system reliability indices with proper formulas.
54
+
55
+ Formulas:
56
+ - SAIFI = Σ(Ni) / NT
57
+ - SAIDI = Σ(Ni × Ti) / NT
58
+ - CAIDI = SAIDI / SAIFI = Σ(Ni × Ti) / Σ(Ni)
59
+ - MAIFI = Σ(Ni_momentary) / NT
60
+ - ASAI = (NT × T - Σ(Ni × Ti)) / (NT × T)
61
+ - ASUI = Σ(Ni × Ti) / (NT × T)
62
+
63
+ Where:
64
+ - Ni = Number of customers affected by interruption i
65
+ - Ti = Duration of interruption i (minutes)
66
+ - NT = Total number of customers served
67
+ - T = Time period (typically 1 year = 525,600 minutes)
68
+ """
69
+
70
+ # Parse datetime columns
71
+ df_calc = df.copy()
72
+
73
+ # Calculate outage duration
74
+ if 'OutageDateTime' in df_calc.columns and ('FirstRestoDateTime' in df_calc.columns or 'LastRestoDateTime' in df_calc.columns):
75
+ restore_col = 'LastRestoDateTime' if 'LastRestoDateTime' in df_calc.columns else 'FirstRestoDateTime'
76
+ df_calc['Duration_Minutes'] = calculate_outage_duration(df_calc['OutageDateTime'], df_calc[restore_col])
77
+ else:
78
+ df_calc['Duration_Minutes'] = 0
79
+
80
+ # Handle affected customers
81
+ if 'AffectedCustomer' in df_calc.columns:
82
+ df_calc['Customers_Affected'] = pd.to_numeric(df_calc['AffectedCustomer'], errors='coerce').fillna(0)
83
+ else:
84
+ df_calc['Customers_Affected'] = 0
85
+
86
+ # Filter out invalid data
87
+ valid_data = df_calc[
88
+ (df_calc['Duration_Minutes'] >= 0) &
89
+ (df_calc['Customers_Affected'] >= 0) &
90
+ (~pd.isna(df_calc['Duration_Minutes'])) &
91
+ (~pd.isna(df_calc['Customers_Affected']))
92
+ ].copy()
93
+
94
+ # Separate planned and unplanned outages
95
+ if 'EventType' in valid_data.columns:
96
+ # Assume planned outages contain keywords like "planned", "maintenance", "scheduled"
97
+ planned_keywords = ['plan', 'maintenance', 'scheduled', 'แผน', 'บำรุงรักษา']
98
+ planned_mask = valid_data['EventType'].str.contains('|'.join(planned_keywords), case=False, na=False)
99
+ unplanned_data = valid_data[~planned_mask].copy()
100
+ planned_data = valid_data[planned_mask].copy()
101
+ else:
102
+ unplanned_data = valid_data.copy()
103
+ planned_data = pd.DataFrame()
104
+
105
+ # Calculate customer-minutes for unplanned outages
106
+ unplanned_data['Customer_Minutes'] = unplanned_data['Customers_Affected'] * unplanned_data['Duration_Minutes']
107
+
108
+ # Identify momentary interruptions (< 5 minutes)
109
+ momentary_data = unplanned_data[unplanned_data['Duration_Minutes'] < 5].copy()
110
+ sustained_data = unplanned_data[unplanned_data['Duration_Minutes'] >= 5].copy()
111
+
112
+ # Calculate indices
113
+ total_interruptions = len(unplanned_data)
114
+ total_customer_interruptions = unplanned_data['Customers_Affected'].sum()
115
+ total_customer_minutes = unplanned_data['Customer_Minutes'].sum()
116
+
117
+ # Momentary interruptions
118
+ momentary_customer_interruptions = momentary_data['Customers_Affected'].sum()
119
+
120
+ # Time period (assume 1 year = 525,600 minutes)
121
+ time_period_minutes = 525600
122
+
123
+ # Calculate SAIFI (System Average Interruption Frequency Index)
124
+ # SAIFI = Σ(Customer Interruptions) / Total Customers
125
+ saifi = total_customer_interruptions / total_customers if total_customers > 0 else 0
126
+
127
+ # Calculate SAIDI (System Average Interruption Duration Index)
128
+ # SAIDI = Σ(Customer Minutes) / Total Customers
129
+ saidi = total_customer_minutes / total_customers if total_customers > 0 else 0
130
+
131
+ # Calculate CAIDI (Customer Average Interruption Duration Index)
132
+ # CAIDI = SAIDI / SAIFI = Σ(Customer Minutes) / Σ(Customer Interruptions)
133
+ caidi = total_customer_minutes / total_customer_interruptions if total_customer_interruptions > 0 else 0
134
+
135
+ # Calculate MAIFI (Momentary Average Interruption Frequency Index)
136
+ # MAIFI = Σ(Momentary Customer Interruptions) / Total Customers
137
+ maifi = momentary_customer_interruptions / total_customers if total_customers > 0 else 0
138
+
139
+ # Calculate ASAI (Average System Availability Index)
140
+ # ASAI = (Total Customer Hours - Customer Hours of Interruption) / Total Customer Hours
141
+ total_customer_hours = total_customers * time_period_minutes / 60
142
+ customer_hours_interrupted = total_customer_minutes / 60
143
+ asai = (total_customer_hours - customer_hours_interrupted) / total_customer_hours if total_customer_hours > 0 else 0
144
+ asai_percent = asai * 100
145
+
146
+ # Calculate ASUI (Average System Unavailability Index)
147
+ # ASUI = Customer Hours of Interruption / Total Customer Hours
148
+ asui = customer_hours_interrupted / total_customer_hours if total_customer_hours > 0 else 0
149
+ asui_percent = asui * 100
150
+
151
+ # Additional metrics
152
+ avg_outage_duration = unplanned_data['Duration_Minutes'].mean() if len(unplanned_data) > 0 else 0
153
+ max_outage_duration = unplanned_data['Duration_Minutes'].max() if len(unplanned_data) > 0 else 0
154
+ avg_customers_per_outage = unplanned_data['Customers_Affected'].mean() if len(unplanned_data) > 0 else 0
155
+ max_customers_affected = unplanned_data['Customers_Affected'].max() if len(unplanned_data) > 0 else 0
156
+
157
+ # Calculate ENS (Energy Not Served) - approximate
158
+ # Assuming average load per customer (can be adjusted)
159
+ avg_load_per_customer_kw = 2.0 # Typical residential load
160
+ ens_kwh = (total_customer_minutes / 60) * avg_load_per_customer_kw
161
+
162
+ return {
163
+ 'SAIFI': saifi,
164
+ 'SAIDI': saidi,
165
+ 'CAIDI': caidi,
166
+ 'MAIFI': maifi,
167
+ 'ASAI': asai_percent,
168
+ 'ASUI': asui_percent,
169
+ 'ENS_kWh': ens_kwh,
170
+ 'Total_Interruptions': total_interruptions,
171
+ 'Total_Customer_Interruptions': int(total_customer_interruptions),
172
+ 'Total_Customer_Minutes': total_customer_minutes,
173
+ 'Momentary_Interruptions': len(momentary_data),
174
+ 'Sustained_Interruptions': len(sustained_data),
175
+ 'Avg_Outage_Duration': avg_outage_duration,
176
+ 'Max_Outage_Duration': max_outage_duration,
177
+ 'Avg_Customers_Per_Outage': avg_customers_per_outage,
178
+ 'Max_Customers_Affected': int(max_customers_affected),
179
+ 'Planned_Outages': len(planned_data) if not planned_data.empty else 0
180
+ }
181
+
182
+ def create_reliability_dataframe(metrics: Dict) -> pd.DataFrame:
183
+ """Create a formatted DataFrame for reliability metrics."""
184
+ reliability_data = [
185
+ {
186
+ 'Metric': 'SAIFI',
187
+ 'Full Name': 'System Average Interruption Frequency Index',
188
+ 'Formula': 'Σ(Ni) / NT',
189
+ 'Value': f"{metrics.get('SAIFI', 0):.4f}",
190
+ 'Unit': 'ครั้ง/ลูกค้า/ปี',
191
+ 'Description': 'ความถี่เฉลี่ยของการขัดข้องต่อลูกค้าต่อปี',
192
+ 'Benchmark': '< 1.5 (ดีมาก), 1.5-3.0 (ดี), > 3.0 (ต้องปรับปรุง)'
193
+ },
194
+ {
195
+ 'Metric': 'SAIDI',
196
+ 'Full Name': 'System Average Interruption Duration Index',
197
+ 'Formula': 'Σ(Ni × Ti) / NT',
198
+ 'Value': f"{metrics.get('SAIDI', 0):.2f}",
199
+ 'Unit': 'นาที/ลูกค้า/ปี',
200
+ 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อลูกค้าต่อปี',
201
+ 'Benchmark': '< 100 (ดีมาก), 100-300 (ดี), > 300 (ต้องปรับปรุง)'
202
+ },
203
+ {
204
+ 'Metric': 'CAIDI',
205
+ 'Full Name': 'Customer Average Interruption Duration Index',
206
+ 'Formula': 'SAIDI / SAIFI',
207
+ 'Value': f"{metrics.get('CAIDI', 0):.2f}",
208
+ 'Unit': 'นาที/ครั้ง',
209
+ 'Description': 'ระยะเวลาขัดข้องเฉลี่ยต่อครั้งที่เกิดขึ้น',
210
+ 'Benchmark': '< 120 (ดี), 120-240 (ปานกลาง), > 240 (ต้องปรับปรุง)'
211
+ },
212
+ {
213
+ 'Metric': 'MAIFI',
214
+ 'Full Name': 'Momentary Average Interruption Frequency Index',
215
+ 'Formula': 'Σ(Ni_momentary) / NT',
216
+ 'Value': f"{metrics.get('MAIFI', 0):.4f}",
217
+ 'Unit': 'ครั้ง/ลูกค้า/ปี',
218
+ 'Description': 'ความถี่เฉลี่ยของการขัดข้องชั่วคราว (<5 นาที)',
219
+ 'Benchmark': '< 5 (ดี), 5-10 (ปานกลาง), > 10 (ต้องปรับปรุง)'
220
+ },
221
+ {
222
+ 'Metric': 'ASAI',
223
+ 'Full Name': 'Average System Availability Index',
224
+ 'Formula': '(NT×T - Σ(Ni×Ti)) / (NT×T) × 100',
225
+ 'Value': f"{metrics.get('ASAI', 0):.4f}",
226
+ 'Unit': '%',
227
+ 'Description': 'ดัชนีความพร้อมใช้งานเฉลี่ยของระบบ',
228
+ 'Benchmark': '> 99.95% (ดีมาก), 99.9-99.95% (ดี), < 99.9% (ต้องปรับปรุง)'
229
+ },
230
+ {
231
+ 'Metric': 'ASUI',
232
+ 'Full Name': 'Average System Unavailability Index',
233
+ 'Formula': 'Σ(Ni×Ti) / (NT×T) × 100',
234
+ 'Value': f"{metrics.get('ASUI', 0):.4f}",
235
+ 'Unit': '%',
236
+ 'Description': 'ดัชนีความไม่พร้อมใช้งานเฉลี่ยของระบบ',
237
+ 'Benchmark': '< 0.05% (ดีมาก), 0.05-0.1% (ดี), > 0.1% (ต้องปรับปรุง)'
238
+ },
239
+ {
240
+ 'Metric': 'ENS',
241
+ 'Full Name': 'Energy Not Served',
242
+ 'Formula': 'Σ(Ni×Ti×Load_avg) / 60',
243
+ 'Value': f"{metrics.get('ENS_kWh', 0):.0f}",
244
+ 'Unit': 'kWh',
245
+ 'Description': 'พลังงานที่ไม่สามารถจ่ายให้ลูกค้าได้',
246
+ 'Benchmark': 'ยิ่งน้อยยิ่งดี (ขึ้นกับพื้นที่และประเภทลูกค้า)'
247
+ }
248
+ ]
249
+
250
+ return pd.DataFrame(reliability_data)
251
+
252
+ def generate_performance_summary(metrics: Dict, total_customers: float) -> str:
253
+ """Generate performance summary with benchmarking."""
254
+ saifi = metrics.get('SAIFI', 0)
255
+ saidi = metrics.get('SAIDI', 0)
256
+ asai = metrics.get('ASAI', 0)
257
+
258
+ # Performance assessment
259
+ performance_level = "ดี"
260
+ if saifi > 3.0 or saidi > 300 or asai < 99.9:
261
+ performance_level = "ต้องปรับปรุง"
262
+ elif saifi < 1.5 and saidi < 100 and asai > 99.95:
263
+ performance_level = "ดีมาก"
264
+
265
+ summary = f"""
266
+ การประเมินประสิทธิภาพระบบไฟฟ้า: {performance_level}
267
+
268
+ ดัชนีความน่าเชื่อถือหลัก:
269
+ • SAIFI: {saifi:.4f} ครั้ง/ลูกค้า/ปี (เป้าหมาย < 1.5)
270
+ • SAIDI: {saidi:.2f} นาที/ลูกค้า/ปี (เป้าหมาย < 100)
271
+ • ความพร้อมใช้งาน (ASAI): {asai:.4f}% (เป้าหมาย > 99.95%)
272
+
273
+ สถิติเหตุการณ์:
274
+ • เหตุการณ์ขัดข้องทั้งหมด: {metrics.get('Total_Interruptions', 0):,} ครั้ง
275
+ • ลูกค้าที่ได้รับผลกระทบ: {metrics.get('Total_Customer_Interruptions', 0):,} ครั้ง
276
+ • เวลาขัดข้องเฉลี่ย: {metrics.get('Avg_Outage_Duration', 0):.1f} นาที
277
+ • เวลาขัดข้องสูงสุด: {metrics.get('Max_Outage_Duration', 0):.1f} นาที
278
+ """
279
+
280
+ return summary.strip()
281
 
282
  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:
283
+ """Summarize overall outage data with enhanced GenAI and reliability metrics."""
284
+
285
  # Basic statistics
286
  total_events = len(df)
287
  date_cols = ['OutageDateTime', 'FirstRestoDateTime', 'LastRestoDateTime', 'CreateEventDateTime', 'CloseEventDateTime']
 
294
 
295
  # Calculate basic metrics
296
  if 'OutageDateTime' in df_copy.columns:
297
+ date_range = f"{df_copy['OutageDateTime'].min().strftime('%d/%m/%Y')} ถึง {df_copy['OutageDateTime'].max().strftime('%d/%m/%Y')}" if pd.notna(df_copy['OutageDateTime'].min()) else "ไม่ระบุ"
298
  else:
299
  date_range = "ไม่ระบุ"
300
 
 
306
  if 'AffectedCustomer' in df_copy.columns:
307
  total_affected = pd.to_numeric(df_copy['AffectedCustomer'], errors='coerce').sum()
308
 
309
+ # Calculate reliability metrics if total_customers is provided
310
+ reliability_metrics = {}
 
 
 
 
 
 
 
 
311
  reliability_df = pd.DataFrame()
312
  reliability_summary = ""
313
+ performance_summary = ""
314
+
315
  if total_customers and total_customers > 0:
316
  try:
317
+ reliability_metrics = calculate_reliability_indices(df_copy, total_customers)
318
+ reliability_df = create_reliability_dataframe(reliability_metrics)
319
+ performance_summary = generate_performance_summary(reliability_metrics, total_customers)
320
+
321
+ reliability_summary = f"""
322
+ ดัชนีความน่าเชื่อถือของระบบไฟฟ้า:
323
+ • SAIFI: {reliability_metrics.get('SAIFI', 0):.4f} ครั้ง/ลูกค้า/ปี
324
+ SAIDI: {reliability_metrics.get('SAIDI', 0):.2f} นาที/ลูกค้า/ปี
325
+ • CAIDI: {reliability_metrics.get('CAIDI', 0):.2f} นาที/ครั้ง
326
+ • MAIFI: {reliability_metrics.get('MAIFI', 0):.4f} ครั้ง/ลูกค้า/ปี
327
+ ความพร้อมใช้งาน (ASAI): {reliability_metrics.get('ASAI', 0):.4f}%
328
+ พลังงานที่สูญเสีย (ENS): {reliability_metrics.get('ENS_kWh', 0):,.0f} kWh
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  """
 
 
 
330
  except Exception as e:
331
  reliability_summary = f"ไม่สามารถคำนวณดัชนีความน่าเชื่อถือได้: {str(e)}"
332
 
333
+ # Create comprehensive summary text for GenAI
334
+ summary_text = f"""
335
+ รายงานสรุปข้อมูลไฟฟ้าล้ม:
336
+ • จำนวนเหตุการณ์ทั้งหมด: {total_events:,} ครั้ง
337
+ • ช่วงเวลาที่เกิดเหต���การณ์: {date_range}
338
+ • ประเภทเหตุการณ์หลัก: {', '.join([f'{k}: {v}' for k, v in event_types.items()])}
339
+ • จำนวนลูกค้าที่ได้รับผลกระทบรวม: {int(total_affected) if not pd.isna(total_affected) else 'ไม่ระบุ':,}
340
+ • จำนวนลูกค้าทั้งหมดในระบบ: {int(total_customers) if total_customers else 'ไม่ระบุ':,}
341
+
342
+ {reliability_summary}
343
+ {performance_summary}
344
+ """
345
+
346
+ # Use GenAI for comprehensive analysis
347
  ai_summary = None
348
  if use_hf and get_hf_token():
349
  try:
350
+ instruction = "วิเคราะห์และสรุปข้อมูลความน่าเชื่อถือของระบบไฟฟ้าจากข้อมูลนี้ สรุป 2-3 ย่อหน้า (ไทย) ระบุ: 1) ประสิทธิภาพระบบโดยรวม 2) จุดที่ต้องปรับปรุง 3) ข้อเสนะแนะเชิงเทคนิค:"
351
+ prompt = f"{instruction}\n\n{summary_text}\n\nการวิเคราะห์และข้อเสนอแนะ:"
352
  ai_summary = openai_summary(prompt, verbosity='recommend', model=model)
353
  except Exception as e:
354
+ ai_summary = f"ไม่สามารถสร้างการวิเคราะห์ด้วย AI ได้: {str(e)}"
355
 
356
  return {
357
  'total_events': total_events,
358
  'date_range': date_range,
359
  'event_types': event_types,
360
  'total_affected_customers': int(total_affected) if not pd.isna(total_affected) else None,
361
+ 'total_customers_served': int(total_customers) if total_customers else None,
362
  'basic_summary': summary_text.strip(),
363
  'reliability_summary': reliability_summary.strip() if reliability_summary else None,
364
+ 'performance_summary': performance_summary.strip() if performance_summary else None,
365
+ 'reliability_metrics': reliability_metrics,
366
  'reliability_df': reliability_df,
367
  'ai_summary': ai_summary,
368
  }