ashhal commited on
Commit
55d4d8d
·
verified ·
1 Parent(s): 004277c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +488 -0
app.py ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import json
4
+ import time
5
+ from datetime import datetime
6
+ from groq import Groq
7
+ import pandas as pd
8
+ from typing import Dict, List, Tuple, Optional
9
+ import re
10
+ import uuid
11
+
12
+ # Initialize Groq client
13
+ def get_groq_client():
14
+ api_key = os.getenv("GROQ_API_KEY")
15
+ if not api_key:
16
+ raise ValueError("GROQ_API_KEY environment variable not set")
17
+ return Groq(api_key=api_key)
18
+
19
+ class PowerSystemsConsultant:
20
+ def __init__(self):
21
+ self.groq_client = get_groq_client()
22
+ self.knowledge_base = self.load_knowledge_base()
23
+ self.conversation_history = []
24
+
25
+ def load_knowledge_base(self):
26
+ """Load the power systems knowledge base"""
27
+ try:
28
+ with open('data/knowledge_base.json', 'r', encoding='utf-8') as f:
29
+ return json.load(f)
30
+ except FileNotFoundError:
31
+ return self.get_default_knowledge_base()
32
+
33
+ def get_default_knowledge_base(self):
34
+ """Default knowledge base with power systems content"""
35
+ return {
36
+ "faults": {
37
+ "symmetrical_faults": {
38
+ "description": "Three-phase faults where all phases are equally affected",
39
+ "characteristics": "Balanced conditions, easiest to analyze",
40
+ "analysis_method": "Single-phase equivalent circuit"
41
+ },
42
+ "unsymmetrical_faults": {
43
+ "line_to_ground": "Most common fault (70-80% of all faults)",
44
+ "line_to_line": "Second most common fault (15-20%)",
45
+ "double_line_to_ground": "Less common but severe"
46
+ }
47
+ },
48
+ "protection": {
49
+ "overcurrent_protection": "Time-current characteristic curves, coordination",
50
+ "differential_protection": "Used for transformers, generators, buses",
51
+ "distance_protection": "Impedance-based protection for transmission lines"
52
+ },
53
+ "standards": {
54
+ "IEEE_standards": ["IEEE C37", "IEEE 1547", "IEEE 519"],
55
+ "IEC_standards": ["IEC 61850", "IEC 60909", "IEC 61131"]
56
+ },
57
+ "diagrams": {
58
+ "single_line_diagram": "Shows electrical connections and components",
59
+ "protection_coordination": "Time-current curves for protective devices",
60
+ "fault_analysis": "Sequence networks for fault calculations"
61
+ }
62
+ }
63
+
64
+ def retrieve_relevant_context(self, query: str) -> str:
65
+ """Simple keyword-based retrieval from knowledge base"""
66
+ query_lower = query.lower()
67
+ relevant_info = []
68
+
69
+ # Search through knowledge base
70
+ for category, content in self.knowledge_base.items():
71
+ if any(keyword in query_lower for keyword in [category]):
72
+ if isinstance(content, dict):
73
+ for key, value in content.items():
74
+ if any(keyword in query_lower for keyword in key.split('_')):
75
+ relevant_info.append(f"{category.title()} - {key}: {value}")
76
+ else:
77
+ relevant_info.append(f"{category.title()}: {content}")
78
+
79
+ return "\n".join(relevant_info[:5]) # Limit to top 5 matches
80
+
81
+ def generate_response(self, user_query: str, chat_history: List[Tuple[str, str]]) -> str:
82
+ """Generate response using Groq LLM with RAG context"""
83
+ try:
84
+ # Retrieve relevant context
85
+ context = self.retrieve_relevant_context(user_query)
86
+
87
+ # Prepare system prompt
88
+ system_prompt = f"""You are a Power Systems Mini-Consultant AI assistant specializing in electrical power systems.
89
+ You help with:
90
+ 1. Fault analysis and calculations
91
+ 2. Protection system design
92
+ 3. Standards interpretation
93
+ 4. Study materials and exam preparation
94
+ 5. Practice problem generation
95
+
96
+ Use the following context from the knowledge base:
97
+ {context}
98
+
99
+ Provide clear, technical explanations with practical examples. Include relevant formulas, standards references, and safety considerations when appropriate."""
100
+
101
+ # Prepare conversation context
102
+ messages = [{"role": "system", "content": system_prompt}]
103
+
104
+ # Add chat history
105
+ for human_msg, ai_msg in chat_history[-5:]: # Last 5 exchanges
106
+ messages.append({"role": "user", "content": human_msg})
107
+ messages.append({"role": "assistant", "content": ai_msg})
108
+
109
+ # Add current query
110
+ messages.append({"role": "user", "content": user_query})
111
+
112
+ # Generate response using Groq
113
+ response = self.groq_client.chat.completions.create(
114
+ model="mixtral-8x7b-32768",
115
+ messages=messages,
116
+ max_tokens=1500,
117
+ temperature=0.7
118
+ )
119
+
120
+ return response.choices[0].message.content
121
+
122
+ except Exception as e:
123
+ return f"Error generating response: {str(e)}. Please check your GROQ_API_KEY and try again."
124
+
125
+ def generate_practice_pack(self, topic: str, difficulty: str, num_questions: int) -> str:
126
+ """Generate practice questions for power systems topics"""
127
+ try:
128
+ prompt = f"""Generate {num_questions} practice questions about {topic} in power systems
129
+ with {difficulty} difficulty level. Include:
130
+
131
+ 1. Multiple choice questions with 4 options
132
+ 2. Short answer questions
133
+ 3. Calculation problems with given data
134
+ 4. Provide answers and brief explanations
135
+
136
+ Format as a structured practice pack suitable for exam preparation."""
137
+
138
+ response = self.groq_client.chat.completions.create(
139
+ model="mixtral-8x7b-32768",
140
+ messages=[{"role": "user", "content": prompt}],
141
+ max_tokens=2000,
142
+ temperature=0.8
143
+ )
144
+
145
+ return response.choices[0].message.content
146
+ except Exception as e:
147
+ return f"Error generating practice pack: {str(e)}"
148
+
149
+ def explain_standard(self, standard_name: str) -> str:
150
+ """Explain power system standards"""
151
+ try:
152
+ prompt = f"""Provide a comprehensive explanation of the {standard_name} standard in power systems.
153
+ Include:
154
+ 1. Purpose and scope
155
+ 2. Key requirements
156
+ 3. Applications
157
+ 4. Related standards
158
+ 5. Practical implementation notes
159
+
160
+ Keep it technically accurate but accessible."""
161
+
162
+ response = self.groq_client.chat.completions.create(
163
+ model="mixtral-8x7b-32768",
164
+ messages=[{"role": "user", "content": prompt}],
165
+ max_tokens=1500,
166
+ temperature=0.6
167
+ )
168
+
169
+ return response.choices[0].message.content
170
+ except Exception as e:
171
+ return f"Error explaining standard: {str(e)}"
172
+
173
+ # Initialize the consultant
174
+ try:
175
+ consultant = PowerSystemsConsultant()
176
+ initialization_status = "✅ Power Systems Consultant initialized successfully!"
177
+ except Exception as e:
178
+ consultant = None
179
+ initialization_status = f"❌ Initialization failed: {str(e)}"
180
+
181
+ def chat_interface(message, history):
182
+ """Main chat interface function"""
183
+ if consultant is None:
184
+ return "❌ System not initialized. Please check GROQ_API_KEY."
185
+
186
+ if not message.strip():
187
+ return "Please enter a question about power systems."
188
+
189
+ try:
190
+ response = consultant.generate_response(message, history)
191
+ return response
192
+ except Exception as e:
193
+ return f"Error: {str(e)}"
194
+
195
+ def generate_practice_questions(topic, difficulty, num_questions):
196
+ """Generate practice pack interface"""
197
+ if consultant is None:
198
+ return "❌ System not initialized. Please check GROQ_API_KEY."
199
+
200
+ try:
201
+ practice_pack = consultant.generate_practice_pack(topic, difficulty, int(num_questions))
202
+ return practice_pack
203
+ except Exception as e:
204
+ return f"Error generating practice pack: {str(e)}"
205
+
206
+ def explain_standard_interface(standard):
207
+ """Standards explanation interface"""
208
+ if consultant is None:
209
+ return "❌ System not initialized. Please check GROQ_API_KEY."
210
+
211
+ try:
212
+ explanation = consultant.explain_standard(standard)
213
+ return explanation
214
+ except Exception as e:
215
+ return f"Error explaining standard: {str(e)}"
216
+
217
+ # Create Gradio interface
218
+ with gr.Blocks(
219
+ theme=gr.themes.Soft(
220
+ primary_hue="blue",
221
+ secondary_hue="cyan",
222
+ neutral_hue="slate"
223
+ ),
224
+ title="Power Systems Mini-Consultant",
225
+ css="""
226
+ .header-text {
227
+ text-align: center;
228
+ font-size: 2.5em;
229
+ font-weight: bold;
230
+ color: #1f4e79;
231
+ margin-bottom: 0.5em;
232
+ }
233
+ .subtitle-text {
234
+ text-align: center;
235
+ font-size: 1.2em;
236
+ color: #666;
237
+ margin-bottom: 2em;
238
+ }
239
+ .status-box {
240
+ padding: 1em;
241
+ border-radius: 8px;
242
+ margin: 1em 0;
243
+ }
244
+ .feature-box {
245
+ border: 2px solid #e0e7ff;
246
+ border-radius: 12px;
247
+ padding: 1.5em;
248
+ margin: 1em 0;
249
+ background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
250
+ }
251
+ """
252
+ ) as app:
253
+
254
+ # Header
255
+ gr.HTML("""
256
+ <div class="header-text">⚡ Power Systems Mini-Consultant</div>
257
+ <div class="subtitle-text">
258
+ Advanced AI Assistant for Fault Analysis, Protection Systems & Standards
259
+ </div>
260
+ """)
261
+
262
+ # Status display
263
+ gr.HTML(f"""
264
+ <div class="status-box" style="background-color: {'#d4edda' if '✅' in initialization_status else '#f8d7da'};
265
+ color: {'#155724' if '✅' in initialization_status else '#721c24'};">
266
+ <strong>System Status:</strong> {initialization_status}
267
+ </div>
268
+ """)
269
+
270
+ with gr.Tabs():
271
+ # Main Chat Tab
272
+ with gr.TabItem("💬 AI Consultant Chat"):
273
+ gr.HTML("""
274
+ <div class="feature-box">
275
+ <h3>🤖 Intelligent Power Systems Consultant</h3>
276
+ <p>Ask questions about fault analysis, protection systems, standards, calculations, and more!</p>
277
+ <ul>
278
+ <li>Fault analysis and calculations</li>
279
+ <li>Protection system design</li>
280
+ <li>Standards interpretation (IEEE, IEC)</li>
281
+ <li>Study guidance and explanations</li>
282
+ </ul>
283
+ </div>
284
+ """)
285
+
286
+ chatbot = gr.Chatbot(
287
+ height=400,
288
+ placeholder="Your Power Systems AI Consultant will appear here...",
289
+ show_label=False
290
+ )
291
+
292
+ msg = gr.Textbox(
293
+ placeholder="Ask about faults, protection, standards, calculations...",
294
+ show_label=False,
295
+ container=False
296
+ )
297
+
298
+ with gr.Row():
299
+ submit_btn = gr.Button("Send 📤", variant="primary")
300
+ clear_btn = gr.Button("Clear Chat 🗑️", variant="secondary")
301
+
302
+ # Example questions
303
+ gr.HTML("""
304
+ <div class="feature-box">
305
+ <h4>💡 Example Questions:</h4>
306
+ <ul>
307
+ <li>"Explain symmetrical vs unsymmetrical faults"</li>
308
+ <li>"How to calculate short circuit current?"</li>
309
+ <li>"What is IEEE C37 standard about?"</li>
310
+ <li>"Design overcurrent protection for a 33kV feeder"</li>
311
+ </ul>
312
+ </div>
313
+ """)
314
+
315
+ submit_btn.click(
316
+ chat_interface,
317
+ inputs=[msg, chatbot],
318
+ outputs=[chatbot]
319
+ ).then(
320
+ lambda: "",
321
+ outputs=[msg]
322
+ )
323
+
324
+ msg.submit(
325
+ chat_interface,
326
+ inputs=[msg, chatbot],
327
+ outputs=[chatbot]
328
+ ).then(
329
+ lambda: "",
330
+ outputs=[msg]
331
+ )
332
+
333
+ clear_btn.click(lambda: None, outputs=[chatbot])
334
+
335
+ # Practice Pack Generator
336
+ with gr.TabItem("📚 Practice Pack Generator"):
337
+ gr.HTML("""
338
+ <div class="feature-box">
339
+ <h3>📝 AI-Generated Practice Questions</h3>
340
+ <p>Generate customized practice packs for power systems topics with varying difficulty levels.</p>
341
+ </div>
342
+ """)
343
+
344
+ with gr.Row():
345
+ with gr.Column(scale=1):
346
+ topic_input = gr.Dropdown(
347
+ choices=[
348
+ "Fault Analysis", "Protection Systems", "Power Flow",
349
+ "Stability Studies", "Relay Coordination", "Transformers",
350
+ "Transmission Lines", "Load Flow", "Short Circuit Analysis",
351
+ "Harmonics", "Power Quality", "SCADA Systems"
352
+ ],
353
+ label="📋 Select Topic",
354
+ value="Fault Analysis"
355
+ )
356
+
357
+ difficulty_input = gr.Radio(
358
+ choices=["Beginner", "Intermediate", "Advanced"],
359
+ label="🎯 Difficulty Level",
360
+ value="Intermediate"
361
+ )
362
+
363
+ num_questions_input = gr.Slider(
364
+ minimum=5,
365
+ maximum=20,
366
+ step=1,
367
+ value=10,
368
+ label="🔢 Number of Questions"
369
+ )
370
+
371
+ generate_btn = gr.Button("Generate Practice Pack 🎓", variant="primary")
372
+
373
+ with gr.Column(scale=2):
374
+ practice_output = gr.Textbox(
375
+ label="📖 Generated Practice Pack",
376
+ lines=20,
377
+ placeholder="Your practice questions will appear here..."
378
+ )
379
+
380
+ generate_btn.click(
381
+ generate_practice_questions,
382
+ inputs=[topic_input, difficulty_input, num_questions_input],
383
+ outputs=[practice_output]
384
+ )
385
+
386
+ # Standards Explorer
387
+ with gr.TabItem("📋 Standards Explorer"):
388
+ gr.HTML("""
389
+ <div class="feature-box">
390
+ <h3>📚 Power Systems Standards Guide</h3>
391
+ <p>Get detailed explanations of IEEE, IEC, and other international standards.</p>
392
+ </div>
393
+ """)
394
+
395
+ with gr.Row():
396
+ with gr.Column(scale=1):
397
+ standard_input = gr.Dropdown(
398
+ choices=[
399
+ "IEEE C37.2", "IEEE 1547", "IEEE 519", "IEEE C57.12.00",
400
+ "IEC 61850", "IEC 60909", "IEC 61131", "IEC 60255",
401
+ "ANSI C84.1", "IEEE 242", "IEEE 399", "IEEE C37.010"
402
+ ],
403
+ label="📑 Select Standard",
404
+ value="IEEE C37.2"
405
+ )
406
+
407
+ explain_btn = gr.Button("Explain Standard 📖", variant="primary")
408
+
409
+ with gr.Column(scale=2):
410
+ standard_output = gr.Textbox(
411
+ label="📋 Standard Explanation",
412
+ lines=15,
413
+ placeholder="Standard explanation will appear here..."
414
+ )
415
+
416
+ explain_btn.click(
417
+ explain_standard_interface,
418
+ inputs=[standard_input],
419
+ outputs=[standard_output]
420
+ )
421
+
422
+ # Study Resources
423
+ with gr.TabItem("📚 Study Resources"):
424
+ gr.HTML("""
425
+ <div class="feature-box">
426
+ <h3>📖 Power Systems Study Guide</h3>
427
+ <p>Essential formulas, concepts, and quick reference materials.</p>
428
+ </div>
429
+ """)
430
+
431
+ with gr.Accordion("⚡ Fault Analysis Formulas", open=False):
432
+ gr.HTML("""
433
+ <h4>Three-Phase Fault Current:</h4>
434
+ <p><code>I_fault = V_nominal / Z_total</code></p>
435
+
436
+ <h4>Line-to-Ground Fault:</h4>
437
+ <p><code>I_fault = 3 * V_nominal / (Z1 + Z2 + Z0)</code></p>
438
+
439
+ <h4>Line-to-Line Fault:</h4>
440
+ <p><code>I_fault = √3 * V_nominal / (Z1 + Z2)</code></p>
441
+ """)
442
+
443
+ with gr.Accordion("🛡️ Protection Principles", open=False):
444
+ gr.HTML("""
445
+ <h4>Overcurrent Protection:</h4>
446
+ <ul>
447
+ <li>Inverse Time Characteristics</li>
448
+ <li>Coordination Time Intervals</li>
449
+ <li>Pickup Current Settings</li>
450
+ </ul>
451
+
452
+ <h4>Distance Protection:</h4>
453
+ <ul>
454
+ <li>Zone 1: 80-90% of line length</li>
455
+ <li>Zone 2: 120% of protected line + 50% of next line</li>
456
+ <li>Zone 3: Backup protection</li>
457
+ </ul>
458
+ """)
459
+
460
+ with gr.Accordion("📊 Key Standards Summary", open=False):
461
+ gr.HTML("""
462
+ <h4>IEEE Standards:</h4>
463
+ <ul>
464
+ <li><strong>IEEE C37:</strong> Circuit breakers and switchgear</li>
465
+ <li><strong>IEEE 1547:</strong> Distributed energy resources</li>
466
+ <li><strong>IEEE 519:</strong> Harmonic control</li>
467
+ <li><strong>IEEE 242:</strong> Protection and coordination</li>
468
+ </ul>
469
+
470
+ <h4>IEC Standards:</h4>
471
+ <ul>
472
+ <li><strong>IEC 61850:</strong> Substation automation</li>
473
+ <li><strong>IEC 60909:</strong> Short-circuit calculations</li>
474
+ <li><strong>IEC 60255:</strong> Protective relays</li>
475
+ </ul>
476
+ """)
477
+
478
+ # Footer
479
+ gr.HTML("""
480
+ <div style="text-align: center; margin-top: 2em; padding: 1em; background-color: #f8f9fa; border-radius: 8px;">
481
+ <p><strong>⚡ Power Systems Mini-Consultant</strong></p>
482
+ <p>Built with Groq AI • Deployed on Hugging Face Spaces</p>
483
+ <p><em>For educational and professional use in power systems engineering</em></p>
484
+ </div>
485
+ """)
486
+
487
+ if __name__ == "__main__":
488
+ app.launch()