Khoi1234210 commited on
Commit
8b5cec5
·
verified ·
1 Parent(s): 6296ee3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -5
app.py CHANGED
@@ -4,6 +4,7 @@ from huggingface_hub import InferenceClient
4
  from datasets import load_dataset
5
  import random
6
  import re
 
7
 
8
  # Global datasets - load lazily
9
  math_samples = None
@@ -109,7 +110,7 @@ def create_math_system_message():
109
  Always be precise, educational, and encourage mathematical thinking."""
110
 
111
  def render_latex(text):
112
- """Minimal LaTeX cleanup - let the model do the work"""
113
  if not text:
114
  return text
115
 
@@ -118,17 +119,100 @@ def render_latex(text):
118
  text = re.sub(r'\\\[(.*?)\\\]', r'$$\1$$', text, flags=re.DOTALL)
119
  text = re.sub(r'\\\((.*?)\\\)', r'$\1$', text, flags=re.DOTALL)
120
 
121
- # Fix boxed answers ONLY if not already in math mode
122
  if '\\boxed' in text and not re.search(r'\$.*\\boxed.*\$', text):
123
- text = re.sub(r'\\boxed\{([^}]+)\}', r'$\\boxed{\1}$', text)
 
 
 
 
 
 
124
 
125
  except Exception as e:
126
  print(f"⚠️ LaTeX error: {e}")
127
 
128
  return text
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  def respond(message, history, system_message, max_tokens, temperature, top_p):
131
- """Non-streaming response for stability"""
132
  client = InferenceClient(model="Qwen/Qwen2.5-Math-7B-Instruct")
133
 
134
  messages = [{"role": "system", "content": system_message}]
@@ -148,6 +232,12 @@ def respond(message, history, system_message, max_tokens, temperature, top_p):
148
  top_p=top_p,
149
  )
150
  response = completion.choices[0].message.content
 
 
 
 
 
 
151
  return render_latex(response)
152
  except Exception as e:
153
  return f"❌ Error: {str(e)[:100]}... Try a simpler problem."
@@ -193,7 +283,9 @@ with gr.Blocks(title="🧮 Mathetics AI") as demo:
193
  examples=[
194
  ["derivative of x^2 sin(x)"],
195
  ["area of triangle 5-12-13"],
196
- ["∫x^2 dx"]
 
 
197
  ],
198
  inputs=msg
199
  )
 
4
  from datasets import load_dataset
5
  import random
6
  import re
7
+ import sympy as sp # Added SymPy for symbolic computation and better rendering/verification
8
 
9
  # Global datasets - load lazily
10
  math_samples = None
 
110
  Always be precise, educational, and encourage mathematical thinking."""
111
 
112
  def render_latex(text):
113
+ """Enhanced LaTeX cleanup with support for advanced SymPy outputs"""
114
  if not text:
115
  return text
116
 
 
119
  text = re.sub(r'\\\[(.*?)\\\]', r'$$\1$$', text, flags=re.DOTALL)
120
  text = re.sub(r'\\\((.*?)\\\)', r'$\1$', text, flags=re.DOTALL)
121
 
122
+ # Fix boxed answers if not in math mode
123
  if '\\boxed' in text and not re.search(r'\$.*\\boxed.*\$', text):
124
+ text = re.sub(r'\\boxed\{([^}]+)\}', r'$$\boxed{\1}$$', text)
125
+
126
+ # Handle equation environments for display in Gradio (convert to $$...$$)
127
+ text = re.sub(r'\\begin\{equation\*\}(.*?)\\end\{equation\*\}', r'$$\1$$', text, flags=re.DOTALL)
128
+
129
+ # Clean up any escaped % or special chars for Markdown compatibility
130
+ text = re.sub(r'\\%', '%', text)
131
 
132
  except Exception as e:
133
  print(f"⚠️ LaTeX error: {e}")
134
 
135
  return text
136
 
137
+ def try_sympy_compute(message):
138
+ """Attempt to compute the result using SymPy for verification and better rendering, with advanced LaTeX options."""
139
+ message_lower = message.lower()
140
+
141
+ x = sp.Symbol('x')
142
+
143
+ # Handle definite integrals
144
+ if 'integral' in message_lower or '∫' in message:
145
+ match = re.search(r'(?:integral of|∫) (.+?) from (.+?) to (.+)', message_lower)
146
+ if match:
147
+ expr_str, lower, upper = match.groups()
148
+ try:
149
+ expr = sp.sympify(expr_str.replace('^', '**')) # Handle ^ for power
150
+ result = sp.integrate(expr, (x, sp.sympify(lower), sp.sympify(upper)))
151
+ # Advanced LaTeX: fold fractions, plain mode, manual box
152
+ return r'\boxed{' + sp.latex(result, mode='plain', fold_frac_powers=True) + r'}'
153
+ except Exception as e:
154
+ print(f"⚠️ SymPy integral error: {e}")
155
+ return None
156
+
157
+ # Handle derivatives with inv_trig_style
158
+ elif 'derivative' in message_lower:
159
+ match = re.search(r'derivative of (.+)', message_lower)
160
+ if match:
161
+ expr_str = match.group(1)
162
+ try:
163
+ expr = sp.sympify(expr_str.replace('^', '**'))
164
+ result = sp.diff(expr, x)
165
+ # Advanced LaTeX: power style for inv trig, fold short frac
166
+ return r'\boxed{' + sp.latex(result, inv_trig_style='power', fold_short_frac=True) + r'}'
167
+ except Exception as e:
168
+ print(f"⚠️ SymPy derivative error: {e}")
169
+ return None
170
+
171
+ # Handle limits
172
+ elif 'limit' in message_lower or 'lim' in message_lower:
173
+ match = re.search(r'(?:limit|lim) (.+?) as (.+?) to (.+)', message_lower)
174
+ if match:
175
+ expr_str, var, to_val = match.groups()
176
+ try:
177
+ expr = sp.sympify(expr_str.replace('^', '**'))
178
+ result = sp.limit(expr, sp.Symbol(var), sp.sympify(to_val))
179
+ # Advanced LaTeX: equation* mode for display
180
+ return sp.latex(result, mode='equation*')
181
+ except Exception as e:
182
+ print(f"⚠️ SymPy limit error: {e}")
183
+ return None
184
+
185
+ # Handle triangle area (Heron's formula)
186
+ elif 'area of triangle' in message_lower:
187
+ match = re.search(r'(\d+)[ -](\d+)[ -](\d+)', message_lower) # Matches 5-12-13 or 5 12 13
188
+ if match:
189
+ a, b, c = map(float, match.groups())
190
+ try:
191
+ s = (a + b + c) / 2
192
+ area = sp.sqrt(s * (s - a) * (s - b) * (s - c))
193
+ # Advanced LaTeX: inline mode with folding
194
+ return r'\boxed{' + sp.latex(area, mode='inline', fold_frac_powers=True) + r'}'
195
+ except Exception as e:
196
+ print(f"⚠️ SymPy area error: {e}")
197
+ return None
198
+
199
+ # Handle simple matrices (e.g., "matrix [[1,2],[3,4]]")
200
+ elif 'matrix' in message_lower:
201
+ match = re.search(r'matrix \[\[(.+?)\]\]', message_lower) # Basic parsing; extend as needed
202
+ if match:
203
+ try:
204
+ elements = [list(map(sp.sympify, row.split(','))) for row in match.group(1).split('],[')]
205
+ m = sp.Matrix(elements)
206
+ # Advanced LaTeX: custom delimiters and matrix style
207
+ return sp.latex(m, mat_delim='[', mat_str='bmatrix')
208
+ except Exception as e:
209
+ print(f"⚠️ SymPy matrix error: {e}")
210
+ return None
211
+
212
+ return None
213
+
214
  def respond(message, history, system_message, max_tokens, temperature, top_p):
215
+ """Non-streaming response for stability, with SymPy verification for supported queries."""
216
  client = InferenceClient(model="Qwen/Qwen2.5-Math-7B-Instruct")
217
 
218
  messages = [{"role": "system", "content": system_message}]
 
232
  top_p=top_p,
233
  )
234
  response = completion.choices[0].message.content
235
+
236
+ # Add SymPy verification if applicable (now with advanced LaTeX)
237
+ sympy_result = try_sympy_compute(message)
238
+ if sympy_result:
239
+ response += "\n\n**Verified with SymPy (for exact symbolic computation):** $$" + sympy_result + "$$"
240
+
241
  return render_latex(response)
242
  except Exception as e:
243
  return f"❌ Error: {str(e)[:100]}... Try a simpler problem."
 
283
  examples=[
284
  ["derivative of x^2 sin(x)"],
285
  ["area of triangle 5-12-13"],
286
+ ["∫x^2 dx from 0 to 2"],
287
+ ["limit sin(x)/x as x to 0"],
288
+ ["matrix [[1,2],[3,4]]"]
289
  ],
290
  inputs=msg
291
  )