Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- app.py +105 -0
- gradient_boosting_model.pkl +3 -0
- requirements.txt +4 -0
app.py
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import datetime
|
| 4 |
+
import re
|
| 5 |
+
import joblib
|
| 6 |
+
|
| 7 |
+
# Load the trained pipeline
|
| 8 |
+
model = joblib.load("gradient_boosting_model.pkl")
|
| 9 |
+
|
| 10 |
+
ERROR_LABELS = {
|
| 11 |
+
"UnderConstrained": "1) Under-constrained / rigid-body",
|
| 12 |
+
"MeshQuality": "2) Bad mesh / distortion",
|
| 13 |
+
"ContactFailure": "3) Contact issues",
|
| 14 |
+
"MaterialError": "4) Material / units issues",
|
| 15 |
+
"other_or_unknown": "Other / unknown"
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
GLOSSARY = {
|
| 19 |
+
"rigid body motion": "Movement of an entire structure without deformation, often caused by missing constraints.",
|
| 20 |
+
"jacobian": "A matrix used to calculate element distortion during deformation; bad values mean mesh issues.",
|
| 21 |
+
"newton-raphson": "A nonlinear solution method sensitive to poor contact setup or load step configuration.",
|
| 22 |
+
"initial penetration": "When contact surfaces start interpenetrated, often due to bad geometry or setup.",
|
| 23 |
+
"divergence": "The solver cannot find a converging solution, often caused by too-large load steps or unstable models.",
|
| 24 |
+
"singular matrix": "Solver can't invert the stiffness matrix, often caused by unconstrained parts.",
|
| 25 |
+
"degrees of freedom": "Independent movements allowed for a part (translation/rotation in X, Y, Z directions)."
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
EXPLANATIONS = {
|
| 29 |
+
"UnderConstrained": (
|
| 30 |
+
"Your model appears under-constrained. The solver detected rigid-body motion or insufficient constraints.",
|
| 31 |
+
"- Check if all bodies have proper supports.\n- Ensure key DOFs are restrained.\n- Avoid soft supports that only partially constrain motion.\n"),
|
| 32 |
+
"MeshQuality": (
|
| 33 |
+
"Your mesh likely has poor quality or distortion. This causes inaccurate results or solver failure.",
|
| 34 |
+
"- Refine the mesh near stress concentrations.\n- Improve skewed or stretched elements.\n- Use proper element types for geometry.\n"),
|
| 35 |
+
"ContactFailure": (
|
| 36 |
+
"Contact elements may be missing or misconfigured. The solver can't resolve interactions between parts.",
|
| 37 |
+
"- Check that all contacts are correctly defined.\n- Consider using bonded contact instead of frictionless.\n- Inspect contact surfaces and face orientation.\n"),
|
| 38 |
+
"MaterialError": (
|
| 39 |
+
"Material data or units are inconsistent. Properties like Young’s modulus or density may be off by scale.",
|
| 40 |
+
"- Verify if Young’s modulus is in MPa or Pa.\n- Check that material density makes sense (e.g. kg/m³).\n- Look at plastic strain curve units if applicable.\n"),
|
| 41 |
+
"other_or_unknown": (
|
| 42 |
+
"I couldn't confidently match this log to a known error category.",
|
| 43 |
+
"- Try checking boundary conditions, contact, and mesh. Rerun with more detailed solver output enabled.\n")
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
def classify_and_explain(log_text):
|
| 47 |
+
if not log_text.strip():
|
| 48 |
+
return ("No log detected", "Paste an ANSYS solver output to analyze.", log_text, "", None)
|
| 49 |
+
|
| 50 |
+
pred = model.predict([log_text])[0]
|
| 51 |
+
label = ERROR_LABELS.get(pred, "Other / unknown")
|
| 52 |
+
explanation, troubleshooting = EXPLANATIONS.get(pred, EXPLANATIONS["other_or_unknown"])
|
| 53 |
+
|
| 54 |
+
highlighted = re.sub(
|
| 55 |
+
r"(?i)\b(" + "|".join(re.escape(k) for k in GLOSSARY) + r")\b",
|
| 56 |
+
lambda m: f"**{m.group(1)}** 🛈",
|
| 57 |
+
log_text,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
found_terms = [term for term in GLOSSARY if term in log_text.lower()]
|
| 61 |
+
glossary_text = "\n\n".join(f"**{term.title()}**: {GLOSSARY[term]}" for term in found_terms)
|
| 62 |
+
|
| 63 |
+
return label, f"### Explanation\n{explanation}\n\n### Troubleshooting\n{troubleshooting}", highlighted, glossary_text, pred
|
| 64 |
+
|
| 65 |
+
def export_report(log_text, category, explanation):
|
| 66 |
+
if not log_text or not category:
|
| 67 |
+
return None, "⚠️ Please run analysis before exporting."
|
| 68 |
+
|
| 69 |
+
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 70 |
+
filename = f"/tmp/ansys_debug_report_{timestamp}.txt"
|
| 71 |
+
|
| 72 |
+
try:
|
| 73 |
+
with open(filename, "w", encoding="utf-8") as f:
|
| 74 |
+
f.write("ANSYS Solver Debug Report\n")
|
| 75 |
+
f.write("=" * 30 + "\n")
|
| 76 |
+
f.write(f"Category: {category}\n\n")
|
| 77 |
+
f.write("Explanation:\n")
|
| 78 |
+
f.write(explanation + "\n\n")
|
| 79 |
+
f.write("Original Log:\n")
|
| 80 |
+
f.write(log_text + "\n")
|
| 81 |
+
return filename, "✅ Report exported successfully."
|
| 82 |
+
except Exception as e:
|
| 83 |
+
return None, f"❌ Export failed: {str(e)}"
|
| 84 |
+
|
| 85 |
+
with gr.Blocks(title="ANSYS Structural Solver Debugger — ML Edition") as demo:
|
| 86 |
+
gr.Markdown("# 🧠 ANSYS Structural Solver Debugger — ML Edition")
|
| 87 |
+
|
| 88 |
+
with gr.Row():
|
| 89 |
+
with gr.Column(scale=2):
|
| 90 |
+
log_input = gr.Textbox(label="Paste ANSYS Solver Output", lines=20)
|
| 91 |
+
analyze_btn = gr.Button("🔍 Analyze Log")
|
| 92 |
+
export_btn = gr.Button("📁 Export Report")
|
| 93 |
+
export_status = gr.Textbox(label="Export Status", interactive=False)
|
| 94 |
+
report_file = gr.File(label="Download Report")
|
| 95 |
+
|
| 96 |
+
with gr.Column(scale=3):
|
| 97 |
+
category_out = gr.Textbox(label="Detected Error Type", interactive=False)
|
| 98 |
+
explanation_out = gr.Markdown()
|
| 99 |
+
highlighted_out = gr.Markdown(label="🔍 Highlighted Log")
|
| 100 |
+
glossary_box = gr.Markdown(label="📘 Glossary Definitions")
|
| 101 |
+
|
| 102 |
+
analyze_btn.click(classify_and_explain, inputs=[log_input], outputs=[category_out, explanation_out, highlighted_out, glossary_box])
|
| 103 |
+
export_btn.click(export_report, inputs=[log_input, category_out, explanation_out], outputs=[report_file, export_status])
|
| 104 |
+
|
| 105 |
+
demo.launch()
|
gradient_boosting_model.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:d8b9302b481d39c29473445f79f0299a79dd3af7564dc85cbe953a77ccc89563
|
| 3 |
+
size 128770
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
scikit-learn
|
| 3 |
+
joblib
|
| 4 |
+
pandas
|