Spaces:
Sleeping
Sleeping
| 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 | |
| ) | |
| # 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"] | |
| # Create a function to do the Reynolds number calculation | |
| def reynolds_number_calc(rho: float, v: float, D: float, mu: float) -> dict: | |
| """ | |
| Calculates the Reynolds number for flow in a circular pipe. | |
| Determines the flow regime (laminar, transitional, or turbulent). | |
| Inputs: | |
| rho: fluid density [kg/m^3] | |
| v: fluid velocity [m/s] | |
| D: pipe diameter [m] | |
| mu: dynamic viscosity [Pa*s] or [kg/(m*s)] | |
| Returns: | |
| reynolds_number: The calculated Reynolds number | |
| flow_regime: The determined flow regime | |
| """ | |
| # Input validation | |
| if rho <= 0 or v < 0 or D <= 0 or mu <= 0: | |
| return { | |
| "reynolds_number": None, | |
| "flow_regime": "Invalid input: Density, velocity, diameter, and viscosity must be positive (velocity can be zero).", | |
| } | |
| reynolds_number = (rho * v * D) / mu | |
| if reynolds_number < 2100: | |
| flow_regime = "Laminar" | |
| elif 2100 <= reynolds_number <= 4000: | |
| flow_regime = "Transitional" | |
| else: | |
| flow_regime = "Turbulent" | |
| return { | |
| "reynolds_number": reynolds_number, | |
| "flow_regime": flow_regime, | |
| } | |
| # This function generates an explanation of the results for Reynolds number | |
| def llm_explain_reynolds(results: dict, inputs: list) -> str: | |
| rho, v, D, mu = inputs | |
| reynolds_number = results.get("reynolds_number") | |
| flow_regime = results.get("flow_regime") | |
| if reynolds_number is None: | |
| return flow_regime # Return the error message from the calculation | |
| system_prompt = ( | |
| "You explain fluid mechanics to a smart 5-year-old. " | |
| "Use food-based analogies to support the explanation." | |
| "You always return CONCISE responses, only one sentence." | |
| ) | |
| user_prompt = ( | |
| f"For a fluid with density {rho:g} kg/m³ and viscosity {mu:g} Pa*s, " | |
| f"flowing at {v:g} m/s through a pipe with diameter {D:g} m, " | |
| f"the Reynolds number is {reynolds_number:.2f}. " | |
| f"The flow regime is {flow_regime}. " | |
| "Explain the Reynolds number and the flow regime 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 everything together for the Reynolds number calculator | |
| def run_reynolds_once(rho, v, D, mu): | |
| inputs = [rho, v, D, mu] | |
| d = reynolds_number_calc( | |
| rho=float(rho), | |
| v=float(v), | |
| D=float(D), | |
| mu=float(mu) | |
| ) | |
| if d.get("reynolds_number") is None: | |
| return pandas.DataFrame(), d["flow_regime"] | |
| df = pandas.DataFrame([{ | |
| "Reynolds Number [-]": round(d["reynolds_number"], 3), | |
| "Flow Regime": d["flow_regime"], | |
| }]) | |
| narrative = llm_explain_reynolds(d, inputs).split("\n")[0] | |
| return df, narrative | |
| # Define the Gradio interface directly | |
| with gradio.Blocks() as demo: | |
| gradio.Markdown( | |
| "# Reynolds Number Calculator" | |
| ) | |
| gradio.Markdown( | |
| "This app calculates the Reynolds number for flow in a circular pipe and determines the flow regime (laminar, transitional, or turbulent)." | |
| ) | |
| with gradio.Row(): | |
| rho = gradio.Number(value=1000.0, label="Fluid density [kg/m³]") | |
| v = gradio.Number(value=1.0, label="Fluid velocity [m/s]") | |
| D = gradio.Number(value=0.1, label="Pipe diameter [m]") | |
| mu = gradio.Number(value=0.001, label="Dynamic viscosity [Pa*s]") | |
| run_btn_reynolds = gradio.Button("Compute Reynolds Number") | |
| results_df_reynolds = gradio.Dataframe(label="Calculation Results", interactive=False) | |
| # Add an explicit title for the explanation panel | |
| gradio.Markdown("## Explanation") | |
| explain_md_reynolds = gradio.Markdown(label="Explanation") | |
| run_btn_reynolds.click(fn=run_reynolds_once, inputs=[rho, v, D, mu], outputs=[results_df_reynolds, explain_md_reynolds]) | |
| gradio.Examples( | |
| examples=[ | |
| [1000.0, 0.1, 0.05, 0.001], # Laminar example | |
| [1000.0, 0.5, 0.1, 0.001], # Transitional example | |
| [1000.0, 2.0, 0.1, 0.001], # Turbulent example | |
| ], | |
| inputs=[rho, v, D, mu], | |
| label="Representative cases", | |
| examples_per_page=3, | |
| cache_examples=False, | |
| ) | |
| # Launch the Gradio interface for Hugging Face Spaces | |
| demo.launch() | |