Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -264,70 +264,150 @@ def voice_to_text(audio_path):
|
|
| 264 |
except Exception as e:
|
| 265 |
return f"Audio error: {str(e)}"
|
| 266 |
|
|
|
|
| 267 |
def convert_speech_to_math(text):
|
| 268 |
-
"""Convert natural language to math expressions"""
|
| 269 |
if not text or text.strip() == "":
|
| 270 |
return "0"
|
| 271 |
|
| 272 |
text = text.lower().strip()
|
|
|
|
| 273 |
|
| 274 |
-
#
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
(r'subtract\s+(\d+)\s+from\s+(\d+)', r'\2 - \1'),
|
| 279 |
-
(r'(\d+)\s+minus\s+(\d+)', r'\1 - \2'),
|
| 280 |
-
(r'multiply\s+(\d+)\s+by\s+(\d+)', r'\1 * \2'),
|
| 281 |
-
(r'(\d+)\s+times\s+(\d+)', r'\1 * \2'),
|
| 282 |
-
(r'divide\s+(\d+)\s+by\s+(\d+)', r'\1 / \2'),
|
| 283 |
-
(r'(\d+)\s+divided by\s+(\d+)', r'\1 / \2'),
|
| 284 |
-
(r'(\d+)\s+to the power of\s+(\d+)', r'\1**\2'),
|
| 285 |
-
(r'(\d+)\s+squared', r'\1**2'),
|
| 286 |
-
(r'(\d+)\s+cubed', r'\1**3'),
|
| 287 |
-
(r'square root of\s+(\d+)', r'sqrt(\1)'),
|
| 288 |
-
(r'cube root of\s+(\d+)', r'(\1)**(1/3)'),
|
| 289 |
-
(r'log of\s+(\d+)', r'log(\1)'),
|
| 290 |
-
(r'natural log of\s+(\d+)', r'ln(\1)'),
|
| 291 |
-
(r'sine of\s+(.+)', r'sin(\1)'),
|
| 292 |
-
(r'cosine of\s+(.+)', r'cos(\1)'),
|
| 293 |
-
(r'tangent of\s+(.+)', r'tan(\1)'),
|
| 294 |
-
(r'derivative of\s+(.+)', r'diff(\1, x)'),
|
| 295 |
-
(r'integral of\s+(.+)', r'integrate(\1, x)'),
|
| 296 |
-
(r'factorial of\s+(\d+)', r'factorial(\1)'),
|
| 297 |
-
]
|
| 298 |
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
continue
|
| 305 |
|
| 306 |
-
#
|
| 307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
|
| 309 |
'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9',
|
| 310 |
-
'ten': '10', '
|
| 311 |
-
'
|
|
|
|
|
|
|
|
|
|
| 312 |
}
|
| 313 |
|
| 314 |
-
for word,
|
| 315 |
-
text = text.replace(word,
|
| 316 |
-
|
| 317 |
-
# Clean up spaces around operators (safe method)
|
| 318 |
-
operators = ['+', '-', '*', '/', '^', '(', ')']
|
| 319 |
-
for op in operators:
|
| 320 |
-
text = text.replace(f' {op} ', op).replace(f' {op}', op).replace(f'{op} ', op)
|
| 321 |
-
|
| 322 |
-
# Add multiplication where implied (safe method)
|
| 323 |
-
text = text.replace(')(', ')*(')
|
| 324 |
|
| 325 |
-
#
|
| 326 |
import re
|
| 327 |
-
text = re.sub(r'
|
| 328 |
|
|
|
|
| 329 |
return text
|
| 330 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
def evaluate_advanced_math(expression):
|
| 332 |
"""Evaluate mathematical expressions using SymPy"""
|
| 333 |
x, y, z = symbols('x y z') # Define symbols
|
|
|
|
| 264 |
except Exception as e:
|
| 265 |
return f"Audio error: {str(e)}"
|
| 266 |
|
| 267 |
+
|
| 268 |
def convert_speech_to_math(text):
|
| 269 |
+
"""Convert natural language to math expressions - SIMPLE & RELIABLE"""
|
| 270 |
if not text or text.strip() == "":
|
| 271 |
return "0"
|
| 272 |
|
| 273 |
text = text.lower().strip()
|
| 274 |
+
print(f"Original voice input: '{text}'") # Debug
|
| 275 |
|
| 276 |
+
# Remove common question phrases
|
| 277 |
+
question_phrases = ["what is", "calculate", "compute", "solve", "what's", "how much is"]
|
| 278 |
+
for phrase in question_phrases:
|
| 279 |
+
text = text.replace(phrase, "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 280 |
|
| 281 |
+
# Handle simple arithmetic directly
|
| 282 |
+
if any(op in text for op in ['+', '-', '*', '/', 'x', '×']):
|
| 283 |
+
# Replace word operators with symbols
|
| 284 |
+
text = text.replace('x', '*').replace('×', '*')
|
| 285 |
+
return text
|
|
|
|
| 286 |
|
| 287 |
+
# Handle spoken arithmetic patterns
|
| 288 |
+
if "plus" in text:
|
| 289 |
+
text = text.replace("plus", "+")
|
| 290 |
+
if "minus" in text:
|
| 291 |
+
text = text.replace("minus", "-")
|
| 292 |
+
if "times" in text or "multiplied by" in text:
|
| 293 |
+
text = text.replace("times", "*").replace("multiplied by", "*")
|
| 294 |
+
if "divided by" in text:
|
| 295 |
+
text = text.replace("divided by", "/")
|
| 296 |
+
|
| 297 |
+
# Handle number words
|
| 298 |
+
number_words = {
|
| 299 |
'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4',
|
| 300 |
'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9',
|
| 301 |
+
'ten': '10', 'eleven': '11', 'twelve': '12', 'thirteen': '13',
|
| 302 |
+
'fourteen': '14', 'fifteen': '15', 'sixteen': '16', 'seventeen': '17',
|
| 303 |
+
'eighteen': '18', 'nineteen': '19', 'twenty': '20', 'thirty': '30',
|
| 304 |
+
'forty': '40', 'fifty': '50', 'sixty': '60', 'seventy': '70',
|
| 305 |
+
'eighty': '80', 'ninety': '90'
|
| 306 |
}
|
| 307 |
|
| 308 |
+
for word, num in number_words.items():
|
| 309 |
+
text = text.replace(word, num)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
|
| 311 |
+
# Clean up spaces around operators
|
| 312 |
import re
|
| 313 |
+
text = re.sub(r'\s*([+\-*/])\s*', r'\1', text)
|
| 314 |
|
| 315 |
+
print(f"Converted to math: '{text}'") # Debug
|
| 316 |
return text
|
| 317 |
|
| 318 |
+
def evaluate_math_safely(expression):
|
| 319 |
+
"""Safely evaluate mathematical expressions"""
|
| 320 |
+
try:
|
| 321 |
+
# Handle simple arithmetic directly first
|
| 322 |
+
if any(op in expression for op in ['+', '-', '*', '/']):
|
| 323 |
+
try:
|
| 324 |
+
# Use sympy for evaluation
|
| 325 |
+
result = sp.sympify(expression)
|
| 326 |
+
return result
|
| 327 |
+
except:
|
| 328 |
+
pass
|
| 329 |
+
|
| 330 |
+
# Try direct evaluation
|
| 331 |
+
result = sp.sympify(expression)
|
| 332 |
+
return result
|
| 333 |
+
|
| 334 |
+
except Exception as e:
|
| 335 |
+
print(f"Evaluation error for '{expression}': {e}")
|
| 336 |
+
return None
|
| 337 |
+
|
| 338 |
+
def process_math_complete(query):
|
| 339 |
+
"""Complete math processing with proper error handling"""
|
| 340 |
+
try:
|
| 341 |
+
print(f"Processing query: '{query}'")
|
| 342 |
+
|
| 343 |
+
# Convert natural language to math
|
| 344 |
+
math_expr = convert_speech_to_math(query)
|
| 345 |
+
print(f"Converted expression: '{math_expr}'")
|
| 346 |
+
|
| 347 |
+
# Evaluate the math
|
| 348 |
+
result = evaluate_math_safely(math_expr)
|
| 349 |
+
print(f"Raw result: {result}, Type: {type(result)}")
|
| 350 |
+
|
| 351 |
+
if result is None:
|
| 352 |
+
return "❌ Could not evaluate the expression. Please try rephrasing.", None
|
| 353 |
+
|
| 354 |
+
# Handle boolean results (like comparisons)
|
| 355 |
+
if isinstance(result, bool):
|
| 356 |
+
if "=" in math_expr or "==" in math_expr or "!=" in math_expr:
|
| 357 |
+
return f"**Expression**: `{math_expr}`\n**Result**: `{result}`", None
|
| 358 |
+
else:
|
| 359 |
+
return "❌ Unexpected boolean result. Please check your expression.", None
|
| 360 |
+
|
| 361 |
+
# Format successful result
|
| 362 |
+
if hasattr(result, 'evalf'):
|
| 363 |
+
numerical = result.evalf()
|
| 364 |
+
result_text = f"""
|
| 365 |
+
**Input**: {query}
|
| 366 |
+
**Expression**: `{math_expr}`
|
| 367 |
+
**Result**: `{result}`
|
| 368 |
+
**Numerical Value**: `{numerical}`
|
| 369 |
+
**Method**: Symbolic Math
|
| 370 |
+
"""
|
| 371 |
+
else:
|
| 372 |
+
result_text = f"""
|
| 373 |
+
**Input**: {query}
|
| 374 |
+
**Expression**: `{math_expr}`
|
| 375 |
+
**Result**: `{result}`
|
| 376 |
+
**Method**: Direct Evaluation
|
| 377 |
+
"""
|
| 378 |
+
|
| 379 |
+
return result_text, None
|
| 380 |
+
|
| 381 |
+
except Exception as e:
|
| 382 |
+
error_msg = f"❌ Processing error: {str(e)}"
|
| 383 |
+
print(error_msg)
|
| 384 |
+
return error_msg, None
|
| 385 |
+
|
| 386 |
+
def main_handler(input_type, user_input, calculus_op="differentiate", variable="x", image=None):
|
| 387 |
+
"""Main handler for all math operations - UPDATED"""
|
| 388 |
+
try:
|
| 389 |
+
# Handle voice/text input
|
| 390 |
+
if input_type in ["basic", "equation"] and user_input:
|
| 391 |
+
return process_math_complete(user_input)
|
| 392 |
+
|
| 393 |
+
# Handle calculus
|
| 394 |
+
elif input_type == "calculus" and user_input:
|
| 395 |
+
return process_calculus(calculus_op, user_input, variable), None
|
| 396 |
+
|
| 397 |
+
# Handle image input
|
| 398 |
+
elif input_type == "image" and image is not None:
|
| 399 |
+
ocr_result, extracted_text = extract_text_from_image(image)
|
| 400 |
+
if extracted_text:
|
| 401 |
+
return process_math_complete(extracted_text)
|
| 402 |
+
return ocr_result, None
|
| 403 |
+
else:
|
| 404 |
+
return "❌ Please provide valid input", None
|
| 405 |
+
|
| 406 |
+
except Exception as e:
|
| 407 |
+
return f"❌ Unexpected error: {str(e)}", None
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
|
| 411 |
def evaluate_advanced_math(expression):
|
| 412 |
"""Evaluate mathematical expressions using SymPy"""
|
| 413 |
x, y, z = symbols('x y z') # Define symbols
|