Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -288,6 +288,67 @@ class PowerSystemsConsultant:
|
|
288 |
|
289 |
return None
|
290 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
def create_chat_session(self, user_id: int, title: str = None) -> str:
|
292 |
"""Create new chat session"""
|
293 |
session_id = str(uuid.uuid4())
|
@@ -772,6 +833,9 @@ def create_app():
|
|
772 |
|
773 |
<h4>Line-to-Line Fault:</h4>
|
774 |
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>I_fault = √3 × V_nominal / (Z1 + Z2)</code></p>
|
|
|
|
|
|
|
775 |
</div>
|
776 |
""")
|
777 |
|
@@ -782,4 +846,240 @@ def create_app():
|
|
782 |
<ul style='margin-left: 1.5rem;'>
|
783 |
<li>Inverse Time Characteristics</li>
|
784 |
<li>Coordination Time Intervals (0.2-0.5s)</li>
|
785 |
-
<li>Pickup Current Settings (1.25-1.5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
|
289 |
return None
|
290 |
|
291 |
+
def generate_practice_pack(self, topic: str, difficulty: str, num_questions: int) -> str:
|
292 |
+
"""Generate practice questions pack"""
|
293 |
+
try:
|
294 |
+
practice_prompt = f"""Generate {num_questions} power systems practice questions about {topic} at {difficulty} level.
|
295 |
+
Format the response with:
|
296 |
+
1. Question number and statement
|
297 |
+
2. Multiple choice options (A, B, C, D) when appropriate
|
298 |
+
3. Detailed solution with step-by-step calculations
|
299 |
+
4. Key concepts and formulas used
|
300 |
+
5. References to relevant standards
|
301 |
+
|
302 |
+
Focus on practical engineering scenarios and include numerical calculations where applicable."""
|
303 |
+
|
304 |
+
messages = [
|
305 |
+
{"role": "system", "content": "You are an expert power systems engineer creating practice questions for students and professionals."},
|
306 |
+
{"role": "user", "content": practice_prompt}
|
307 |
+
]
|
308 |
+
|
309 |
+
response = self.groq_client.chat.completions.create(
|
310 |
+
model="llama3-70b-8192",
|
311 |
+
messages=messages,
|
312 |
+
max_tokens=3000,
|
313 |
+
temperature=0.7
|
314 |
+
)
|
315 |
+
|
316 |
+
return response.choices[0].message.content
|
317 |
+
|
318 |
+
except Exception as e:
|
319 |
+
return f"Error generating practice pack: {str(e)}"
|
320 |
+
|
321 |
+
def explain_standard(self, standard: str) -> str:
|
322 |
+
"""Explain power systems standard"""
|
323 |
+
try:
|
324 |
+
standard_prompt = f"""Provide a comprehensive explanation of the {standard} standard including:
|
325 |
+
1. Purpose and scope of the standard
|
326 |
+
2. Key requirements and specifications
|
327 |
+
3. Practical applications in power systems
|
328 |
+
4. Important clauses and sections
|
329 |
+
5. Relationship to other standards
|
330 |
+
6. Implementation considerations
|
331 |
+
7. Common misconceptions or challenges
|
332 |
+
|
333 |
+
Make it practical and useful for power systems engineers."""
|
334 |
+
|
335 |
+
messages = [
|
336 |
+
{"role": "system", "content": "You are an expert in power systems standards and regulations with deep knowledge of IEEE, IEC, and ANSI standards."},
|
337 |
+
{"role": "user", "content": standard_prompt}
|
338 |
+
]
|
339 |
+
|
340 |
+
response = self.groq_client.chat.completions.create(
|
341 |
+
model="llama3-70b-8192",
|
342 |
+
messages=messages,
|
343 |
+
max_tokens=2500,
|
344 |
+
temperature=0.6
|
345 |
+
)
|
346 |
+
|
347 |
+
return response.choices[0].message.content
|
348 |
+
|
349 |
+
except Exception as e:
|
350 |
+
return f"Error explaining standard: {str(e)}"
|
351 |
+
|
352 |
def create_chat_session(self, user_id: int, title: str = None) -> str:
|
353 |
"""Create new chat session"""
|
354 |
session_id = str(uuid.uuid4())
|
|
|
833 |
|
834 |
<h4>Line-to-Line Fault:</h4>
|
835 |
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>I_fault = √3 × V_nominal / (Z1 + Z2)</code></p>
|
836 |
+
|
837 |
+
<h4>Double Line-to-Ground Fault:</h4>
|
838 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>I_fault = V_nominal × [Z2 + Z0] / [Z1 × (Z2 + Z0) + Z2 × Z0]</code></p>
|
839 |
</div>
|
840 |
""")
|
841 |
|
|
|
846 |
<ul style='margin-left: 1.5rem;'>
|
847 |
<li>Inverse Time Characteristics</li>
|
848 |
<li>Coordination Time Intervals (0.2-0.5s)</li>
|
849 |
+
<li>Pickup Current Settings (1.25-1.5 × Full Load)</li>
|
850 |
+
<li>Time Dial Settings</li>
|
851 |
+
</ul>
|
852 |
+
|
853 |
+
<h4>Distance Protection:</h4>
|
854 |
+
<ul style='margin-left: 1.5rem;'>
|
855 |
+
<li>Zone 1: 80-85% of line length</li>
|
856 |
+
<li>Zone 2: 120% of protected line + 50% of next</li>
|
857 |
+
<li>Zone 3: Backup protection</li>
|
858 |
+
</ul>
|
859 |
+
|
860 |
+
<h4>Differential Protection:</h4>
|
861 |
+
<ul style='margin-left: 1.5rem;'>
|
862 |
+
<li>CT ratio matching</li>
|
863 |
+
<li>Restraint characteristics</li>
|
864 |
+
<li>Second harmonic blocking</li>
|
865 |
+
</ul>
|
866 |
+
</div>
|
867 |
+
""")
|
868 |
+
|
869 |
+
with gr.Accordion("📐 Power System Calculations", open=False):
|
870 |
+
gr.HTML("""
|
871 |
+
<div style='background: #f8f9fa; padding: 1.5rem; border-radius: 8px; margin: 1rem 0;'>
|
872 |
+
<h4>Power Formulas:</h4>
|
873 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>P = √3 × V × I × cos(φ)</code> (Three-phase real power)</p>
|
874 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>Q = √3 × V × I × sin(φ)</code> (Three-phase reactive power)</p>
|
875 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>S = √3 × V × I</code> (Three-phase apparent power)</p>
|
876 |
+
|
877 |
+
<h4>Impedance Calculations:</h4>
|
878 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>Z_pu = Z_actual × (S_base / V_base²)</code></p>
|
879 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>Z_new = Z_old × (S_new/S_old) × (V_old/V_new)²</code></p>
|
880 |
+
|
881 |
+
<h4>Transformer Calculations:</h4>
|
882 |
+
<p><code style='background: #e9ecef; padding: 0.25rem 0.5rem; border-radius: 4px;'>X_pu = (% impedance / 100) × (S_base / S_transformer)</code></p>
|
883 |
+
</div>
|
884 |
+
""")
|
885 |
+
|
886 |
+
with gr.Accordion("📊 Standards Quick Reference", open=False):
|
887 |
+
gr.HTML("""
|
888 |
+
<div style='background: #f8f9fa; padding: 1.5rem; border-radius: 8px; margin: 1rem 0;'>
|
889 |
+
<h4>IEEE Standards:</h4>
|
890 |
+
<ul style='margin-left: 1.5rem;'>
|
891 |
+
<li><strong>C37.2:</strong> Device Function Numbers</li>
|
892 |
+
<li><strong>519:</strong> Harmonic Control</li>
|
893 |
+
<li><strong>1547:</strong> Distributed Generation Interconnection</li>
|
894 |
+
<li><strong>242:</strong> Protection and Coordination</li>
|
895 |
+
<li><strong>399:</strong> Industrial Power Systems Analysis</li>
|
896 |
+
</ul>
|
897 |
+
|
898 |
+
<h4>IEC Standards:</h4>
|
899 |
+
<ul style='margin-left: 1.5rem;'>
|
900 |
+
<li><strong>61850:</strong> Substation Automation</li>
|
901 |
+
<li><strong>60909:</strong> Short-Circuit Calculations</li>
|
902 |
+
<li><strong>60255:</strong> Electrical Relays</li>
|
903 |
+
<li><strong>61131:</strong> PLC Programming</li>
|
904 |
+
</ul>
|
905 |
+
</div>
|
906 |
+
""")
|
907 |
+
|
908 |
+
with gr.Accordion("🎓 Exam Preparation Tips", open=False):
|
909 |
+
gr.HTML("""
|
910 |
+
<div style='background: #f8f9fa; padding: 1.5rem; border-radius: 8px; margin: 1rem 0;'>
|
911 |
+
<h4>PE Exam Power Topics:</h4>
|
912 |
+
<ul style='margin-left: 1.5rem;'>
|
913 |
+
<li>Three-phase circuit analysis</li>
|
914 |
+
<li>Symmetrical components</li>
|
915 |
+
<li>Fault analysis calculations</li>
|
916 |
+
<li>Protection system coordination</li>
|
917 |
+
<li>Power flow studies</li>
|
918 |
+
<li>Economic dispatch</li>
|
919 |
+
<li>Stability studies</li>
|
920 |
+
<li>Grounding systems</li>
|
921 |
+
</ul>
|
922 |
+
|
923 |
+
<h4>Key Formulas to Memorize:</h4>
|
924 |
+
<ul style='margin-left: 1.5rem;'>
|
925 |
+
<li>Symmetrical component transformations</li>
|
926 |
+
<li>Fault current calculations</li>
|
927 |
+
<li>Power triangle relationships</li>
|
928 |
+
<li>Per-unit system conversions</li>
|
929 |
+
<li>Transmission line parameters</li>
|
930 |
+
</ul>
|
931 |
+
</div>
|
932 |
+
""")
|
933 |
+
|
934 |
+
# Event handlers for login
|
935 |
+
def handle_login(username, password):
|
936 |
+
success, user_data, message, sessions_update, main_visibility = login_user(username, password)
|
937 |
+
if success:
|
938 |
+
welcome_html = f"""
|
939 |
+
<div class="feature-box" style="text-align: center;">
|
940 |
+
<h2>👋 Welcome, {user_data['full_name']}!</h2>
|
941 |
+
<p>Ready to tackle power systems challenges? Let's get started!</p>
|
942 |
+
</div>
|
943 |
+
"""
|
944 |
+
return (
|
945 |
+
message,
|
946 |
+
user_data,
|
947 |
+
gr.update(visible=False), # Hide login
|
948 |
+
gr.update(visible=True), # Show main
|
949 |
+
welcome_html,
|
950 |
+
sessions_update
|
951 |
+
)
|
952 |
+
else:
|
953 |
+
return (
|
954 |
+
message,
|
955 |
+
None,
|
956 |
+
gr.update(visible=True), # Keep login visible
|
957 |
+
gr.update(visible=False), # Keep main hidden
|
958 |
+
"",
|
959 |
+
gr.update()
|
960 |
+
)
|
961 |
+
|
962 |
+
def handle_registration(username, email, password, confirm_password, full_name):
|
963 |
+
success, message = register_user(username, email, password, confirm_password, full_name)
|
964 |
+
return message
|
965 |
+
|
966 |
+
def handle_new_chat(user_data):
|
967 |
+
if user_data:
|
968 |
+
session_id, session_choices = start_new_chat(user_data)
|
969 |
+
session_choices_formatted = [(f"{s['title']} ({s['created_at'][:10]})", s['session_id'])
|
970 |
+
for s in consultant.user_manager.get_user_sessions(user_data['id'])]
|
971 |
+
return (
|
972 |
+
session_id,
|
973 |
+
gr.update(choices=session_choices_formatted, value=session_id),
|
974 |
+
[] # Clear chat history
|
975 |
+
)
|
976 |
+
return None, gr.update(), []
|
977 |
+
|
978 |
+
def handle_chat_selection(session_id, user_data):
|
979 |
+
if session_id and user_data:
|
980 |
+
history = load_selected_chat(session_id, user_data)
|
981 |
+
return history, session_id
|
982 |
+
return [], None
|
983 |
+
|
984 |
+
def handle_chat_message(message, history, user_data, session_id):
|
985 |
+
return chat_interface(message, history, user_data, session_id)
|
986 |
+
|
987 |
+
def clear_chat():
|
988 |
+
return [], ""
|
989 |
+
|
990 |
+
def handle_practice_generation(topic, difficulty, num_questions, user_data):
|
991 |
+
return generate_practice_questions(topic, difficulty, num_questions, user_data)
|
992 |
+
|
993 |
+
def handle_standard_explanation(standard, user_data):
|
994 |
+
return explain_standard_interface(standard, user_data)
|
995 |
+
|
996 |
+
# Wire up event handlers
|
997 |
+
login_btn.click(
|
998 |
+
fn=handle_login,
|
999 |
+
inputs=[login_username, login_password],
|
1000 |
+
outputs=[login_status, user_state, login_section, main_section, user_welcome, chat_sessions_dropdown]
|
1001 |
+
)
|
1002 |
+
|
1003 |
+
register_btn.click(
|
1004 |
+
fn=handle_registration,
|
1005 |
+
inputs=[reg_username, reg_email, reg_password, reg_confirm_password, reg_full_name],
|
1006 |
+
outputs=[register_status]
|
1007 |
+
)
|
1008 |
+
|
1009 |
+
new_chat_btn.click(
|
1010 |
+
fn=handle_new_chat,
|
1011 |
+
inputs=[user_state],
|
1012 |
+
outputs=[session_state, chat_sessions_dropdown, chatbot]
|
1013 |
+
)
|
1014 |
+
|
1015 |
+
chat_sessions_dropdown.change(
|
1016 |
+
fn=handle_chat_selection,
|
1017 |
+
inputs=[chat_sessions_dropdown, user_state],
|
1018 |
+
outputs=[chatbot, session_state]
|
1019 |
+
)
|
1020 |
+
|
1021 |
+
submit_btn.click(
|
1022 |
+
fn=handle_chat_message,
|
1023 |
+
inputs=[msg, chatbot, user_state, session_state],
|
1024 |
+
outputs=[chatbot, msg, diagram_display]
|
1025 |
+
)
|
1026 |
+
|
1027 |
+
msg.submit(
|
1028 |
+
fn=handle_chat_message,
|
1029 |
+
inputs=[msg, chatbot, user_state, session_state],
|
1030 |
+
outputs=[chatbot, msg, diagram_display]
|
1031 |
+
)
|
1032 |
+
|
1033 |
+
clear_btn.click(
|
1034 |
+
fn=clear_chat,
|
1035 |
+
outputs=[chatbot, msg]
|
1036 |
+
)
|
1037 |
+
|
1038 |
+
generate_btn.click(
|
1039 |
+
fn=handle_practice_generation,
|
1040 |
+
inputs=[topic_input, difficulty_input, num_questions_input, user_state],
|
1041 |
+
outputs=[practice_output]
|
1042 |
+
)
|
1043 |
+
|
1044 |
+
explain_btn.click(
|
1045 |
+
fn=handle_standard_explanation,
|
1046 |
+
inputs=[standard_input, user_state],
|
1047 |
+
outputs=[standard_output]
|
1048 |
+
)
|
1049 |
+
|
1050 |
+
return app
|
1051 |
+
|
1052 |
+
# Launch the application
|
1053 |
+
if __name__ == "__main__":
|
1054 |
+
app = create_app()
|
1055 |
+
|
1056 |
+
# Add some helpful startup information
|
1057 |
+
print("🚀 Power Systems Mini-Consultant Starting...")
|
1058 |
+
print("📋 Features included:")
|
1059 |
+
print(" - AI-powered chat consultant")
|
1060 |
+
print(" - Practice question generator")
|
1061 |
+
print(" - Standards explanations")
|
1062 |
+
print(" - Engineering diagram generation")
|
1063 |
+
print(" - User authentication & session management")
|
1064 |
+
print(" - Chat history persistence")
|
1065 |
+
print()
|
1066 |
+
|
1067 |
+
if consultant is None:
|
1068 |
+
print("⚠️ Warning: System not fully initialized")
|
1069 |
+
print(" Please ensure GROQ_API_KEY is set in your environment")
|
1070 |
+
print(" Some features may not work properly")
|
1071 |
+
else:
|
1072 |
+
print("✅ System ready!")
|
1073 |
+
|
1074 |
+
print()
|
1075 |
+
print("🌐 Access your consultant at: http://localhost:7860")
|
1076 |
+
print("📚 Study resources and formulas available in the Resources tab")
|
1077 |
+
print("💡 Try asking about fault analysis, protection systems, or request diagrams!")
|
1078 |
+
|
1079 |
+
app.launch(
|
1080 |
+
server_name="0.0.0.0",
|
1081 |
+
server_port=7860,
|
1082 |
+
share=False,
|
1083 |
+
show_api=False,
|
1084 |
+
quiet=False
|
1085 |
+
)
|