aciang commited on
Commit
3e7998b
·
verified ·
1 Parent(s): 8a4e70b

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. README.md +2 -7
  2. app.py +70 -113
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: LanguageBridge — Math Fast Agent (SymPy, Safe)
3
  emoji: 🧮
4
  colorFrom: yellow
5
  colorTo: blue
@@ -9,9 +9,4 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- A lightweight SymPy-based math agent. No torch needed.
13
-
14
- Usage examples:
15
- - 2*x + 5 = 11
16
- - sin(theta) = sqrt(3)/2, 0 <= theta < 2*pi
17
- - factor(x**4 - 1)
 
1
  ---
2
+ title: LanguageBridge — Math Fast Agent (SymPy)
3
  emoji: 🧮
4
  colorFrom: yellow
5
  colorTo: blue
 
9
  pinned: false
10
  ---
11
 
12
+ **SymPy** 的數學推理代理(不依賴 LLM)。支援一次貼上長式、簡化、解一元/聯立方程與基本微積分。
 
 
 
 
 
app.py CHANGED
@@ -1,131 +1,88 @@
1
-
2
  import gradio as gr
3
  import sympy as sp
4
 
5
- def default_symbols():
6
- names = ["x","y","z","t","theta","a","b","c","n","m"]
7
- d = {name: sp.symbols(name, real=True) for name in names}
8
- d["pi"] = sp.pi
9
- d["e"] = sp.E
10
- d["sqrt"] = sp.sqrt
11
- return d
12
 
13
- def parse_constraints(parts, syms):
14
- cons = []
15
- for p in parts:
16
- s = p.strip()
17
- if not s:
18
- continue
19
- try:
20
- rel = sp.sympify(s, locals=syms)
21
- cons.append(rel)
22
- except Exception:
23
- pass
24
- return cons
25
 
26
- def solve_line(txt):
27
- syms = default_symbols()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- # constraints after comma: "eq, 0 <= theta < 2*pi"
30
- if "," in txt:
31
- main = txt.split(",", 1)[0].strip()
32
- cons = parse_constraints(txt.split(",")[1:].copy(), syms)
33
- else:
34
- main = txt.strip()
35
- cons = []
36
 
37
- if not main:
38
- return "Empty input."
 
39
 
40
- if "=" in main:
41
- left, right = main.split("=", 1)
42
  try:
43
- eq = sp.Eq(sp.sympify(left, locals=syms), sp.sympify(right, locals=syms))
44
- except Exception as e:
45
- return f"Parse equation failed: {e}"
46
-
47
- vars_set = set(eq.free_symbols)
48
- if not vars_set:
49
- vars_set = {sp.symbols("x", real=True)}
50
- vars_list = list(vars_set)
51
-
52
- # try solveset on first var with simple real-domain extraction
53
- if cons:
54
- v = vars_list[0]
55
- domain = sp.S.Reals
56
- try:
57
- # If constraints form an And of relationals, keep as boolean condition.
58
- cond = cons[0]
59
- for c in cons[1:]:
60
- cond = sp.And(cond, c)
61
- # best-effort: do not over-process; pass domain=Reals
62
- sol = sp.solveset(eq, v, domain=domain)
63
- return f"solveset({v} in Reals): {sp.simplify(sol)}"
64
- except Exception:
65
- pass
66
 
67
  try:
68
- sols = sp.solve([eq], vars_list, dict=True)
69
- if not sols:
70
- return "No solution or need more conditions."
71
- lines = []
72
- for i, s in enumerate(sols, 1):
73
- parts = []
74
- for k, v in s.items():
75
- parts.append(f"{k} = {sp.simplify(v)}")
76
- lines.append("Solution " + str(i) + ": " + ", ".join(parts))
77
- return "\n".join(lines)
78
- except Exception as e:
79
- return f"Solve failed: {e}"
80
-
81
- # pure expression branch
82
- try:
83
- expr = sp.sympify(main, locals=syms)
84
- except Exception as e:
85
- return f"Parse failed: {e}"
86
 
87
- out = []
88
- try:
89
- out.append("Simplify: " + str(sp.simplify(expr)))
90
- except Exception:
91
- pass
92
- try:
93
- fact = sp.factor(expr)
94
- if fact != expr:
95
- out.append("Factor: " + str(fact))
96
- except Exception:
97
- pass
98
- try:
99
- v = list(expr.free_symbols)[0] if expr.free_symbols else sp.symbols("x", real=True)
100
- out.append("d/d" + str(v) + ": " + str(sp.diff(expr, v)))
101
- out.append("Integral d" + str(v) + ": " + str(sp.integrate(expr, v)))
102
- except Exception:
103
- pass
104
 
105
- if out:
106
- return "\n".join(out)
107
- return "Result: " + str(expr)
108
 
109
- def solve_math(q):
110
- q = (q or "").strip()
111
- if not q:
112
- return "Enter expression(s) or equation(s). Use semicolons or newlines to separate.\nExamples:\n 2*x + 5 = 11\n sin(theta) = sqrt(3)/2, 0 <= theta < 2*pi\n factor(x**4 - 1)"
113
- segs = []
114
- for line in q.splitlines():
115
- segs.extend([p for p in line.split(";")])
116
- segs = [s.strip() for s in segs if s.strip()]
117
- outputs = []
118
- for s in segs:
119
- outputs.append(">>> " + s + "\n" + solve_line(s))
120
- return "\n\n".join(outputs)
121
 
122
- with gr.Blocks(title="LanguageBridge — Math Fast Agent (SymPy)") as demo:
123
- gr.Markdown("# LanguageBridge Math Fast Agent (SymPy)")
124
- gr.Markdown("Paste expressions or equations. Add constraints after a comma. Examples:\n- 2*x + 5 = 11\n- sin(theta) = sqrt(3)/2, 0 <= theta < 2*pi\n- factor(x**4 - 1)")
125
- q = gr.Textbox(lines=6, label="Problem / Expression (semicolon or newline for systems)")
126
- out = gr.Textbox(lines=12, label="Output")
127
- btn = gr.Button("Solve")
128
- btn.click(fn=solve_math, inputs=q, outputs=out)
129
 
130
  if __name__ == "__main__":
 
131
  demo.launch(share=True)
 
1
+ \
2
  import gradio as gr
3
  import sympy as sp
4
 
5
+ TITLE = "LanguageBridge — Math Fast Agent (SymPy)"
 
 
 
 
 
 
6
 
7
+ def solve_math(q: str):
8
+ q = (q or "").strip()
9
+ if not q:
10
+ return "請輸入算式或方程,例如:2x+3=11;或:sin(x)**2 + cos(x)**2;或:factor(x**2-9)"
 
 
 
 
 
 
 
 
11
 
12
+ try:
13
+ # 情境 A:含 '=' → 視為(可能多條)方程,支援分號/換行分隔
14
+ if "=" in q:
15
+ # 將多行與分號斷開
16
+ parts = []
17
+ for seg in q.split(";"):
18
+ parts += [s.strip() for s in seg.split("\n")]
19
+ parts = [s for s in parts if s]
20
+
21
+ eqs = []
22
+ syms = set()
23
+ for s in parts:
24
+ if "=" not in s:
25
+ continue
26
+ left, right = s.split("=", 1)
27
+ L = sp.sympify(left)
28
+ R = sp.sympify(right)
29
+ eq = sp.Eq(L, R)
30
+ eqs.append(eq)
31
+ syms |= L.free_symbols | R.free_symbols
32
+
33
+ if not eqs:
34
+ return "沒有可解析的方程式。"
35
+ if not syms:
36
+ syms = {sp.symbols("x")}
37
+
38
+ # 解聯立(回傳 dict 列表)
39
+ sol = sp.solve(eqs, list(syms), dict=True)
40
+ if not sol:
41
+ return "無解或需要更多條件。"
42
 
43
+ lines = []
44
+ for i, s in enumerate(sol, 1):
45
+ lines.append(
46
+ "解 {}: ".format(i) + ", ".join(f"{k} = {sp.simplify(v)}" for k, v in s.items())
47
+ )
48
+ return "\n".join(lines)
 
49
 
50
+ # 情境 B:純表達式 → 嘗試簡化、因式、微分、積分
51
+ expr = sp.sympify(q)
52
+ out = []
53
 
 
 
54
  try:
55
+ simp = sp.simplify(expr)
56
+ out.append(f"簡化:{simp}")
57
+ except Exception:
58
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
60
  try:
61
+ fac = sp.factor(expr)
62
+ if fac != expr:
63
+ out.append(f"因式分解:{fac}")
64
+ except Exception:
65
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ try:
68
+ x = list(expr.free_symbols)[0] if expr.free_symbols else sp.symbols("x")
69
+ out.append(f" {x} 微分:{sp.diff(expr, x)}")
70
+ out.append(f"對 {x} 積分:{sp.integrate(expr, x)}")
71
+ except Exception:
72
+ pass
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ return "\n".join(out) if out else f"結果:{expr}"
 
 
75
 
76
+ except Exception as e:
77
+ return f"解析失敗:{e}"
 
 
 
 
 
 
 
 
 
 
78
 
79
+ with gr.Blocks(title=TITLE) as demo:
80
+ gr.Markdown(f"## {TITLE}\n- 貼上**算式/方程**(可多行;或用分號 `;` 分隔聯立)\n- 範例:`2x+3=11`、`x+y=3; x-y=1`、`sin(x)**2 + cos(x)**2`、`factor(x**2-9)`")
81
+ q = gr.Textbox(lines=6, label="題目 / 算式(可含聯立方程)")
82
+ out = gr.Textbox(lines=12, label="輸出")
83
+ btn = gr.Button("送出 🚀")
84
+ btn.click(solve_math, q, out)
 
85
 
86
  if __name__ == "__main__":
87
+ # 在 Colab 預覽:一定要 share=True 才會印出 public URL
88
  demo.launch(share=True)