LLM_explanation / app.py
EricCRX's picture
Update app.py
cc767c4 verified
# -*- coding: utf-8 -*-
"""Untitled3.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/11sS74P6WlrbXCzSh9_b8ELPTtcfdsz8s
"""
# -*- coding: utf-8 -*-
# HW3: Deterministic calculator + LLM explanation (Gradio)
# Topic: Simply supported beam with center point load (max bending stress & midspan deflection)
# -*- coding: utf-8 -*-
# HW3: Deterministic calculator + Gradio + LLM explanation
# Simply Supported Beam with Center Load
import gradio as gr
import math
import json
from transformers import pipeline
# -------------------------------
# 1. Deterministic backend function
# -------------------------------
def beam_calculator(L, P, E, I, c, sigma_allow=250.0, fy=350.0, n=1.5):
"""
Deterministic first-principles calculation for a simply supported beam
under a central point load.
Inputs:
L (m): span length
P (kN): central load
E (GPa): elastic modulus
I (cm^4): second moment of area
c (cm): extreme fiber distance
sigma_allow (MPa): allowable stress
fy (MPa): yield strength
n (–): safety factor
"""
# --- Unit conversions ---
P_N = P * 1000 # kN -> N
E_Pa = E * 1e9 # GPa -> Pa
I_m4 = I * 1e-8 # cm^4 -> m^4
c_m = c / 100.0 # cm -> m
# --- Mechanics formulas ---
M_max = P_N * L / 4.0 # Max bending moment (N·m)
delta_max = (P_N * L**3) / (48 * E_Pa * I_m4) # Max deflection (m)
sigma_max = M_max * c_m / I_m4 / 1e6 # Max stress (MPa)
# --- Safety checks ---
utilization_stress = sigma_max / sigma_allow
utilization_yield = sigma_max / (fy / n)
# Structured record
record = {
"inputs": {
"L_m": L, "P_kN": P, "E_GPa": E, "I_cm4": I, "c_cm": c,
"sigma_allow_MPa": sigma_allow, "fy_MPa": fy, "safety_factor": n
},
"results": {
"M_max_Nm": M_max,
"delta_max_m": delta_max,
"sigma_max_MPa": sigma_max,
"utilization_vs_allow": utilization_stress,
"utilization_vs_yield": utilization_yield
}
}
return record
# -------------------------------
# 2. LLM Explanation
# -------------------------------
explainer = pipeline("text-generation", model="distilgpt2")
def explain_results(record):
"""Use LLM to produce a clear explanation grounded in numbers."""
text = json.dumps(record, indent=2)
prompt = f"""
You are an engineering assistant. A beam calculation was performed.
Here are the structured results:
{text}
Explain the results to a civil engineering student in plain English:
- Report the maximum bending moment, stress, and deflection.
- Compare stress with allowable stress and yield strength.
- State clearly if the beam is safe or unsafe.
Avoid speculation. Base explanation only on the provided numbers.
"""
explanation = explainer(prompt, max_new_tokens=200)[0]["generated_text"]
return explanation
# -------------------------------
# 3. Wrapper for Gradio
# -------------------------------
def run_calculation(L, P, E, I, c, sigma_allow, fy, n):
try:
rec = beam_calculator(L, P, E, I, c, sigma_allow, fy, n)
explanation = explain_results(rec)
return json.dumps(rec["results"], indent=2), explanation
except Exception as e:
return {"error": str(e)}, "Error during calculation."
# -------------------------------
# 4. Gradio UI
# -------------------------------
with gr.Blocks() as demo:
gr.Markdown("# Simply Supported Beam — Center Load")
gr.Markdown("Deterministic calculator + LLM explanation (first principles).")
with gr.Row():
with gr.Column():
L = gr.Slider(0.5, 30.0, value=2.0, label="Span L (m)")
P = gr.Slider(0.1, 500.0, value=10.0, label="Center load P (kN)")
E = gr.Slider(10, 300, value=200, label="Elastic modulus E (GPa)")
I = gr.Number(value=8000, label="Second moment of area I (cm^4)")
c = gr.Number(value=15, label="Extreme fiber distance c (cm)")
with gr.Accordion("Optional: Allowables", open=False):
sigma_allow = gr.Number(value=250, label="Allowable stress σ_allow (MPa)")
fy = gr.Number(value=350, label="Yield strength fy (MPa)")
n = gr.Number(value=1.5, label="Safety factor n")
run_btn = gr.Button("Compute")
with gr.Column():
results_out = gr.Textbox(label="Numerical Results")
explain_out = gr.Textbox(label="LLM Explanation")
run_btn.click(
fn=run_calculation,
inputs=[L, P, E, I, c, sigma_allow, fy, n],
outputs=[results_out, explain_out],
)
if __name__ == "__main__":
demo.launch()