File size: 4,854 Bytes
930062b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import json
import pandas as pd
import gradio as gr
from transformers import pipeline, set_seed

SCOPE = """
**Scope:** DC, steady-state Ohm's Law.
**Assumptions:** Ideal components; temperature effects ignored.
**Units:** V (volts), I (amps), R (ohms).
**Valid ranges:** 0 ≤ V ≤ 1000, 0 ≤ I ≤ 100, 0.1 ≤ R ≤ 1e6.
"""

set_seed(42)
try:
    explain_llm = pipeline("text2text-generation", model="google/flan-t5-small")
except Exception as e:
    print("LLM pipeline init failed; using fallback text only.", e)
    explain_llm = None

def validate(target, V, I, R):
    errs = []
    if target != "Voltage (V)"   and not (0 <= V <= 1000): errs.append("V must be 0–1000 V.")
    if target != "Current (I)"   and not (0 <= I <= 100):  errs.append("I must be 0–100 A.")
    if target != "Resistance (R)"and not (0.1 <= R <= 1e6):errs.append("R must be 0.1–1e6 Ω.")
    if target == "Current (I)"   and R == 0: errs.append("R cannot be 0 for I = V/R.")
    if target == "Resistance (R)"and I == 0: errs.append("I cannot be 0 for R = V/I.")
    return errs

def compute_structured(target, V, I, R):
    if target == "Voltage (V)":
        value = I * R
        steps = [f"Use V = I·R", f"V = {I} A × {R} Ω = {value} V"]
        out = {"quantity":"V","value":value,"units":"V"}
    elif target == "Current (I)":
        value = V / R
        steps = [f"Use I = V/R", f"I = {V} V ÷ {R} Ω = {value} A"]
        out = {"quantity":"I","value":value,"units":"A"}
    else:
        value = V / I
        steps = [f"Use R = V/I", f"R = {V} V ÷ {I} A = {value} Ω"]
        out = {"quantity":"R","value":value,"units":"Ω"}

    return {
        "calculation":"Ohm's Law",
        "equations":{"V":"V=I·R","I":"I=V/R","R":"R=V/I"},
        "target":target,
        "inputs":{"V":V,"I":I,"R":R,"units":{"V":"V","I":"A","R":"Ω"}},
        "steps":steps,
        "output":out
    }

def explain(_data: dict) -> str:
    """
    Always ask the LLM to explain what Ohm's Law is; fallback if unavailable.
    """
    prompt = (
        "Explain Ohm’s Law for a non-expert in <=80 words. "
        "Use symbols ×, ·, and Ω (no Unicode escapes). "
        "Include the three forms (V = I·R, I = V/R, R = V/I) and list the units."
    )
    if explain_llm is not None:
        try:
            txt = explain_llm(prompt, do_sample=False, num_beams=1, max_new_tokens=120)[0]["generated_text"].strip()
            if txt:
                return (txt.replace("\u00b7","·")
                          .replace("\u00D7","×").replace("\u00d7","×")
                          .replace("\u03a9","Ω").replace("\u03A9","Ω"))
        except Exception as e:
            print("LLM explanation failed:", e)
    return ("Ohm’s Law relates voltage (V), current (I), and resistance (R): "
            "V = I·R, I = V/R, R = V/I. Units: V (volts), A (amps), Ω (ohms).")

def run(target, V, I, R):
    errs = validate(target, V, I, R)
    if errs: raise gr.Error("\n".join(errs))
    data = compute_structured(target, V, I, R)
    df = pd.DataFrame([{
        "Target": data["target"],
        "V (V)": data["inputs"]["V"],
        "I (A)": data["inputs"]["I"],
        "R (Ω)": data["inputs"]["R"],
        "Result": f'{data["output"]["quantity"]} = {data["output"]["value"]} {data["output"]["units"]}'
    }])
    return df, json.dumps(data, indent=2), explain(data)

with gr.Blocks(title="Ohm's Law — see the math") as demo:
    gr.Markdown("# 🔌 Ohm's Law — Deterministic Calculator")
    gr.Markdown(SCOPE)
    with gr.Row():
        with gr.Column():
            target = gr.Radio(["Voltage (V)","Current (I)","Resistance (R)"], value="Voltage (V)", label="Compute")
            V = gr.Number(value=12.0, label="Voltage V (V) [ignored if computing V]")
            I = gr.Number(value=2.0,  label="Current I (A) [ignored if computing I]")
            R = gr.Number(value=6.0,  label="Resistance R (Ω) [ignored if computing R]")
            btn = gr.Button("Compute", variant="primary")
        with gr.Column():
            with gr.Tabs():
                with gr.Tab("Results"):
                    out_table = gr.Dataframe(label="Results", interactive=False)
                with gr.Tab("Explanation"):
                    out_expl = gr.Markdown(value="_Explanation will appear here after you click **Compute**._")
                with gr.Tab("Structured JSON"):
                    out_json = gr.Code(label="Structured output (JSON)", language="json")
    inputs = [target, V, I, R]
    btn.click(run, inputs=inputs, outputs=[out_table, out_json, out_expl])
    gr.Examples(
        inputs=inputs,
        examples=[
            ["Voltage (V)", 0.0, 2.0, 50.0],
            ["Current (I)", 12.0, 0.0, 6.0],
            ["Resistance (R)", 5.0, 0.01, 0.0]
        ],
        label="Examples"
    )
if __name__ == "__main__":
    demo.launch()