aciang commited on
Commit
42cead7
·
verified ·
1 Parent(s): fce8f29

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +4 -2
  2. app.py +54 -122
  3. requirements.txt +1 -5
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: LanguageBridge — Math Hybrid (Phi + SymPy)
3
  emoji: 🧮
4
  colorFrom: yellow
5
- colorTo: blue
6
  sdk: gradio
7
  sdk_version: "4.44.1"
8
  app_file: app.py
9
  pinned: false
10
  ---
 
 
 
1
  ---
2
+ title: LanguageBridge — Math Fast Agent (SymPy)
3
  emoji: 🧮
4
  colorFrom: yellow
5
+ colorTo: gray
6
  sdk: gradio
7
  sdk_version: "4.44.1"
8
  app_file: app.py
9
  pinned: false
10
  ---
11
+
12
+ 純 SymPy 的數學推理代理(不依賴 LLM),支援一次貼上長式、簡化、解一元/聯立方程。
app.py CHANGED
@@ -1,136 +1,68 @@
1
-
2
- import os, re, time
3
  import gradio as gr
4
  import sympy as sp
5
 
6
- TITLE = "LanguageBridge — Math Hybrid (Phi + SymPy)"
7
-
8
- DEFAULT_MODEL_ID = os.environ.get("MODEL_ID", "microsoft/phi-2")
9
- MAX_NEW_TOKENS = int(os.environ.get("MAX_NEW_TOKENS", "96"))
10
 
11
- _llm = None
12
- _tok = None
13
-
14
- def _try_load_llm():
15
- global _llm, _tok
16
- if _llm is not None:
17
- return True
18
- try:
19
- import torch
20
- from transformers import AutoModelForCausalLM, AutoTokenizer
21
- _tok = AutoTokenizer.from_pretrained(DEFAULT_MODEL_ID, use_fast=True)
22
- _llm = AutoModelForCausalLM.from_pretrained(
23
- DEFAULT_MODEL_ID,
24
- torch_dtype=torch.float32,
25
- device_map="auto"
26
- )
27
- return True
28
- except Exception:
29
- _llm = None
30
- _tok = None
31
- return False
32
-
33
- def _llm_parse_to_math(text):
34
- # Rewrite user text to algebraic expression(s); fallback to original text
35
- if not _try_load_llm():
36
- return text
37
- import torch
38
- from transformers import AutoTokenizer
39
- prompt = (
40
- "Rewrite the following math question as a pure algebraic expression "
41
- "or semicolon-separated equations suitable for SymPy. "
42
- "Return only the expression/equations without explanations.\n\n"
43
- f"Question:\n{text}\n\nExpression:\n"
44
- )
45
- ids = _tok(prompt, return_tensors="pt").input_ids.to(_llm.device)
46
- gen = _llm.generate(
47
- ids,
48
- max_new_tokens=MAX_NEW_TOKENS,
49
- do_sample=False,
50
- pad_token_id=_tok.eos_token_id
51
- )
52
- out = _tok.decode(gen[0], skip_special_tokens=True)
53
- if "Expression:" in out:
54
- out = out.split("Expression:", 1)[-1].strip()
55
- out = out.replace("^", "**").strip()
56
- return out or text
57
-
58
- def _solve_with_sympy(q):
59
  q = (q or "").strip()
60
  if not q:
61
- return "Please enter an expression or equations. Example: 2*x + 5 = 11; or: sin(x)**2 + cos(x)**2"
62
-
63
- if "=" in q:
64
- parts = []
65
- for seg in q.split(";"):
66
- parts.extend([s for s in seg.split("\n")])
67
- eqs = []
68
- syms = set()
69
- for s in [p.strip() for p in parts if p.strip()]:
70
- if "=" not in s:
71
- expr = sp.sympify(s)
72
- eqs.append(sp.Eq(expr, 0))
73
- syms |= expr.free_symbols
74
- continue
75
- left, right = s.split("=", 1)
76
- L = sp.sympify(left)
77
- R = sp.sympify(right)
78
- eqs.append(sp.Eq(L, R))
79
- syms |= L.free_symbols
80
- syms |= R.free_symbols
81
- if not syms:
82
- syms = {sp.symbols("x")}
83
- sol = sp.solve(eqs, list(syms), dict=True)
84
- if not sol:
85
- return "No solution or more conditions are required."
86
- lines = []
87
- for i, d in enumerate(sol, 1):
88
- pretty = ", ".join([f"{k} = {sp.simplify(v)}" for k, v in d.items()])
89
- lines.append(f"Solution {i}: {pretty}")
90
- return "\n".join(lines)
91
-
92
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  expr = sp.sympify(q)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  except Exception as e:
95
- return f"SymPy parse failed: {e}"
96
-
97
- tips = []
98
- try:
99
- tips.append(f"Simplify: {sp.simplify(expr)}")
100
- except Exception:
101
- pass
102
- try:
103
- fac = sp.factor(expr)
104
- if fac != expr:
105
- tips.append(f"Factor: {fac}")
106
- except Exception:
107
- pass
108
- try:
109
- x = list(expr.free_symbols)[0] if expr.free_symbols else sp.symbols("x")
110
- tips.append(f"d/d{x}: {sp.diff(expr, x)}")
111
- tips.append(f"integrate wrt {x}: {sp.integrate(expr, x)}")
112
- except Exception:
113
- pass
114
- return "\n".join(tips) if tips else f"Result: {expr}"
115
-
116
- def hybrid_solve(user_text, use_llm):
117
- text = (user_text or "").strip()
118
- if not text:
119
- return "Please enter an expression or problem statement."
120
- if use_llm:
121
- normalized = _llm_parse_to_math(text)
122
- header = f"LLM normalized -> {normalized}\n---\n"
123
- return header + _solve_with_sympy(normalized)
124
- else:
125
- return _solve_with_sympy(text)
126
 
127
  with gr.Blocks(title=TITLE) as demo:
128
- gr.Markdown(f"## {TITLE}\nPaste text or math: LLM helps rewrite -> SymPy solves (optional).")
129
- q = gr.Textbox(lines=6, label="Problem / Expression (semicolon or newline for systems)")
130
- use_llm = gr.Checkbox(value=False, label="Use Phi-2 to normalize text first (optional)")
131
- out = gr.Textbox(lines=12, label="Output")
132
- btn = gr.Button("Solve", variant="primary")
133
- btn.click(hybrid_solve, inputs=[q, use_llm], outputs=out, concurrency_limit=1)
134
 
135
  if __name__ == "__main__":
136
  demo.launch()
 
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
  try:
12
+ # 支援方程/聯立:可用分號或換行分隔
13
+ if "=" in q:
14
+ parts = [s.strip() for seg in q.split(";") for s in seg.split("\n")]
15
+ eqs, syms = [], set()
16
+ for s in parts:
17
+ if not s:
18
+ continue
19
+ if "=" not in s:
20
+ continue
21
+ left, right = s.split("=", 1)
22
+ eq = sp.Eq(sp.sympify(left), sp.sympify(right))
23
+ eqs.append(eq)
24
+ syms |= eq.free_symbols
25
+ if hasattr(eq, "rhs"):
26
+ syms |= eq.rhs.free_symbols
27
+ if not syms:
28
+ x = sp.symbols("x")
29
+ syms = {x}
30
+ sol = sp.solve(eqs, list(syms), dict=True)
31
+ if not sol:
32
+ return "無解或需要更多條件。"
33
+ lines = []
34
+ for i, s in enumerate(sol, 1):
35
+ lines.append(f"解 {i}: " + ", ".join([f"{k} = {sp.simplify(v)}" for k, v in s.items()]))
36
+ return "\n".join(lines)
37
+
38
+ # 非方程:做一輪常見操作
39
  expr = sp.sympify(q)
40
+ tips = []
41
+ try:
42
+ tips.append(f"簡化:{sp.simplify(expr)}")
43
+ except Exception:
44
+ tips.append(f"簡化:{expr}")
45
+ try:
46
+ fact = sp.factor(expr)
47
+ if fact != expr:
48
+ tips.append(f"因式分解:{fact}")
49
+ except Exception:
50
+ pass
51
+ try:
52
+ x = list(expr.free_symbols)[0] if expr.free_symbols else sp.symbols("x")
53
+ tips.append(f"對 {x} 微分:{sp.diff(expr, x)}")
54
+ tips.append(f"對 {x} 積分:{sp.integrate(expr, x)}")
55
+ except Exception:
56
+ pass
57
+ return "\n".join(tips) if tips else f"結果:{expr}"
58
  except Exception as e:
59
+ return f"解析失敗:{e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  with gr.Blocks(title=TITLE) as demo:
62
+ gr.Markdown(f"## {TITLE}\n貼上算式(可多行 / 用分號 `;` 分隔):")
63
+ q = gr.Textbox(lines=6, label="題目 / 算式(可含聯立方程)")
64
+ out = gr.Textbox(lines=10, label="輸出")
65
+ gr.Button("送出 🚀").click(fn=solve_math, inputs=q, outputs=out)
 
 
66
 
67
  if __name__ == "__main__":
68
  demo.launch()
requirements.txt CHANGED
@@ -1,7 +1,3 @@
1
  gradio==4.44.1
2
- huggingface_hub==0.23.5
3
  sympy>=1.12
4
- torch==2.4.1
5
- transformers==4.44.2
6
- accelerate==0.34.2
7
- safetensors>=0.4.4
 
1
  gradio==4.44.1
 
2
  sympy>=1.12
3
+ huggingface_hub==0.23.4