Spaces:
Sleeping
Sleeping
File size: 5,768 Bytes
d323307 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | import math
import gradio
import pandas
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
# Instantiate the model that we'll be calling. This is a tiny one!
MODEL_ID = "HuggingFaceTB/SmolLM2-135M-Instruct"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
pipe = pipeline(
task="text-generation",
model=AutoModelForCausalLM.from_pretrained(
MODEL_ID,
),
tokenizer=tokenizer
)
# Create a function to do the Young's Modulus calculation
def youngs_modulus_calc(F_N: float, A_m2: float, L0_m: float, delta_L_m: float) -> float:
"""
Calculates Young's Modulus (E) in GPa.
F_N: Force in Newtons
A_m2: Area in square meters
L0_m: Original length in meters
delta_L_m: Change in length in meters
"""
if A_m2 == 0 or L0_m == 0 or delta_L_m == 0:
return math.inf # Avoid division by zero
stress_Pa = F_N / A_m2
strain = delta_L_m / L0_m
E_Pa = stress_Pa / strain
E_GPa = E_Pa / 1e9
return E_GPa
# This helper function applies a chat format to help the LLM understand what
# is going on
def _format_chat(system_prompt: str, user_prompt: str) -> str:
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
]
template = getattr(tokenizer, "chat_template", None)
return tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# This functoin uses hte LLM to generate a response.
def _llm_generate(prompt: str, max_tokens: int) -> str:
out = pipe(
prompt,
max_new_tokens=max_tokens,
do_sample=True,
temperature=0.5,
return_full_text=False,
)
return out[0]["generated_text"]
# This function generates an explanation of the results
def llm_explain(E_GPa: float, inputs: list) -> str:
system_prompt = (
"Explain engineering concepts to a smart 5-year-old using food analogies. "
"Keep responses concise, only one sentence."
)
F_N, A_m2, L0_m, delta_L_m = inputs
aluminum_E_GPa = 70.0
comparison = "more flexible" if E_GPa < aluminum_E_GPa else "stiffer" if E_GPa > aluminum_E_GPa else "about as stiff"
user_prompt = (
f"An unknown material was tested with a force of {F_N:g} N, area of {A_m2:g} m², original length of {L0_m:g} m, and change in length of {delta_L_m:g} m.\n"
f"The unknown material's Young's Modulus is {E_GPa:.2f} GPa.\n"
f"Aluminum's Young's Modulus is {aluminum_E_GPa} GPa.\n"
f"Explain if this material is {comparison} than aluminum."
"Explain the Young's modulus of the unknown material and the compare it to aluminum in ONE friendly sentence for a non-expert."
)
formatted = _format_chat(system_prompt, user_prompt)
return _llm_generate(formatted, max_tokens=128)
# This function ties everythign together (evaluation, LLM explanaation, output)
# And will be out main entry point for teh GUI
def run_once(F_N, A_m2, L0_m, delta_L_m):
# Young's Modulus calculation part
youngs_modulus_inputs = [F_N, A_m2, L0_m, delta_L_m]
youngs_modulus_result = youngs_modulus_calc(
F_N=float(F_N),
A_m2=float(A_m2),
L0_m=float(L0_m),
delta_L_m=float(delta_L_m)
)
aluminum_E_GPa = 70.0
stiffness_comparison = "stiff" if youngs_modulus_result > aluminum_E_GPa else "flexible" if youngs_modulus_result < aluminum_E_GPa else "similar stiffness"
youngs_modulus_df = pandas.DataFrame([{
"Young's Modulus [GPa]": round(youngs_modulus_result, 3),
"Compared to Aluminum": stiffness_comparison
}])
youngs_modulus_narrative = llm_explain(youngs_modulus_result, youngs_modulus_inputs).split("\n")[0]
return youngs_modulus_df, youngs_modulus_narrative
# Last but not least, here's the UI!
with gradio.Blocks() as demo:
# Let's start by adding a title and introduction
gradio.Markdown(
"# Run and Explain Young's Modulus Calculation"
)
gradio.Markdown(
"This app calculates Young's Modulus and provides a natural language description of the result, comparing it to aluminum."
)
# This row contains all of the physical parameters for Young's Modulus
with gradio.Row():
F_N = gradio.Number(value=1000.0, label="Force [N]")
A_m2 = gradio.Number(value=0.01, label="Area [m²]")
L0_m = gradio.Number(value=1.0, label="Original Length [m]")
delta_L_m = gradio.Number(value=0.001, label="Change in Length [m]")
# Add a button to click to run the interface
youngs_modulus_run_btn = gradio.Button("Compute Young's Modulus")
# These are the outputs for Young's Modulus
youngs_modulus_results_df = gradio.Dataframe(label="Numerical results (deterministic)", interactive=False)
youngs_modulus_explain_md = gradio.Markdown(label="Explanation")
# Run the calculations when the button is clicked
youngs_modulus_run_btn.click(
fn=run_once,
inputs=[F_N, A_m2, L0_m, delta_L_m],
outputs=[youngs_modulus_results_df, youngs_modulus_explain_md]
)
# Finally, add a few examples
gradio.Examples(
examples=[
[1000000.0, 0.001, 1.0, 0.01], # Example 1 (should be around 100 GPa - stiffer than aluminum)
[50000.0, 0.01, 1.0, 0.0002], # Example 2 (should be around 25 GPa - more flexible than aluminum)
[700000.0, 0.01, 1.0, 0.001], # Example 3 (should be around 70 GPa - about as stiff as aluminum)
],
inputs=[F_N, A_m2, L0_m, delta_L_m],
label="Representative Young's Modulus Cases",
examples_per_page=3,
cache_examples=False,
)
if __name__ == "__main__":
demo.launch(debug=False)
|