Spaces:
Sleeping
Sleeping
File size: 3,935 Bytes
5c5cb4d 2f94119 5c5cb4d 2f94119 3e7998b 2f94119 5c5cb4d cf28e8a 5c5cb4d cf28e8a 5c5cb4d 3e7998b 5c5cb4d 3e7998b 5c5cb4d cf28e8a 5c5cb4d f09d15a 3e7998b 5c5cb4d 3e7998b 5c5cb4d 3e7998b 5c5cb4d 8a4e70b cf28e8a 5c5cb4d cf28e8a 8a4e70b f09d15a cf28e8a 3e7998b 5c5cb4d cf28e8a 5c5cb4d 3e7998b 2f94119 3e7998b 5c5cb4d 3e7998b 5c5cb4d f09d15a 2f94119 cf28e8a |
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 |
import re
import gradio as gr
import sympy as sp
from sympy.parsing.sympy_parser import (
parse_expr, standard_transformations,
implicit_multiplication_application, convert_xor
)
TITLE = "LanguageBridge — Math Fast Agent (SymPy)"
# ---------- 輸入正規化:隱式乘法 / ^→** / 全形→半形 / √→sqrt ----------
def normalize_ascii(s: str) -> str:
table = str.maketrans({
'(':'(', ')':')', ',':',', ';':';', ':':':',
'=':'=', '-':'-', '+':'+', '*':'*', '/':'/', '。':'.',
'×':'*', '√':'sqrt'
})
return s.translate(table)
def auto_insert_stars(s: str) -> str:
s = re.sub(r'(\d)([A-Za-z])', r'\1*\2', s) # 3x -> 3*x
s = re.sub(r'([A-Za-z0-9_])\(', r'\1*(', s) # x( -> x*(
s = re.sub(r'\)([A-Za-z0-9_])', r')*\1', s) # )x -> )*x
s = re.sub(r'(\d)\s*sqrt', r'\1*sqrt', s) # 2sqrt -> 2*sqrt
return s
def preprocess(expr: str) -> str:
s = (expr or "").strip()
s = normalize_ascii(s)
s = s.replace("^", "**") # 2^3 -> 2**3
s = auto_insert_stars(s) # 隱式乘法 -> 顯式
return s
TRANS = standard_transformations + (implicit_multiplication_application, convert_xor)
def to_sympy_expr(s: str):
s = preprocess(s)
return parse_expr(s, transformations=TRANS)
def to_sympy_eq(s: str):
s = preprocess(s)
if "=" not in s:
raise ValueError("等式缺少 '='")
L, R = s.split("=", 1)
return sp.Eq(parse_expr(L, transformations=TRANS),
parse_expr(R, transformations=TRANS))
def solve_math(q: str):
q = (q or "").strip()
if not q:
return "請輸入算式或方程,例如:2x+3=11;sin(x)^2 + cos(x)^2;factor(x^2-9)"
try:
parts = [s.strip() for seg in q.split(";") for s in seg.split("\n")]
parts = [p for p in parts if p]
# 有 '=' 就走解方程(可聯立)
if any("=" in p for p in parts):
eqs, syms = [], set()
for s in parts:
if "=" in s:
e = to_sympy_eq(s)
eqs.append(e)
syms |= e.free_symbols | e.rhs.free_symbols
if not syms:
syms = {sp.symbols("x")}
sol = sp.solve(eqs, list(syms), dict=True)
if not sol:
return "無解或需要更多條件。"
return "\n".join(
f"解 {i}: " + ", ".join([f\"{k} = {sp.simplify(v)}\" for k, v in d.items()])
for i, d in enumerate(sol, 1)
)
# 否則當一般表達式:簡化/因式/微分/積分
expr = to_sympy_expr(q)
out = []
try: out.append(f"簡化:{sp.simplify(expr)}")
except Exception: out.append(f"簡化:{expr}")
try:
fact = sp.factor(expr)
if fact != expr: out.append(f"因式分解:{fact}")
except Exception: pass
try:
x = next(iter(expr.free_symbols)) if expr.free_symbols else sp.symbols("x")
out.append(f"對 {x} 微分:{sp.diff(expr, x)}")
out.append(f"對 {x} 積分:{sp.integrate(expr, x)}")
except Exception: pass
return "\n".join(out) if out else f"結果:{expr}"
except Exception as e:
return f"解析失敗:{e}"
with gr.Blocks(title=TITLE) as demo:
gr.Markdown(
"## " + TITLE + "\\n"
"貼上算式(可多行 / 用分號 `;` 分隔)。\\n\\n"
"**可直接輸入隱式乘法:** `3x`、`2(x+1)`、`(x)(x+1)`、`2sqrt(x)`;"
"也可用 `x^2`(自動轉為 `x**2`),`√(x)`(自動轉為 `sqrt(x)`)。"
)
q = gr.Textbox(lines=6, label="題目 / 算式(可含聯立方程)")
out = gr.Textbox(lines=12, label="輸出")
gr.Button("送出 🚀").click(fn=solve_math, inputs=q, outputs=out)
if __name__ == "__main__":
demo.launch() # 在 Space 環境不用 share
|