|
|
import sympy as sp |
|
|
import gradio as gr |
|
|
import os |
|
|
import re |
|
|
import numpy as np |
|
|
from PIL import Image |
|
|
import io |
|
|
import tempfile |
|
|
import subprocess |
|
|
from sympy import symbols, diff, integrate, limit, sin, cos, tan, log, sqrt, factorial, Matrix, oo, E, I, pi |
|
|
|
|
|
print("🚀 Math Solver starting...") |
|
|
|
|
|
|
|
|
def install_dependencies(): |
|
|
try: |
|
|
print("Installing system dependencies...") |
|
|
subprocess.run(["apt-get", "update", "-y"], capture_output=True) |
|
|
subprocess.run(["apt-get", "install", "-y", "tesseract-ocr", "libtesseract-dev", "espeak", "espeak-ng"], capture_output=True) |
|
|
print("✅ System dependencies installed") |
|
|
return True |
|
|
except Exception as e: |
|
|
print(f"⚠️ Dependency warning: {e}") |
|
|
return False |
|
|
|
|
|
install_dependencies() |
|
|
|
|
|
|
|
|
try: |
|
|
import speech_recognition as sr |
|
|
SPEECH_RECOGNITION_AVAILABLE = True |
|
|
except ImportError: |
|
|
SPEECH_RECOGNITION_AVAILABLE = False |
|
|
print("Speech recognition not available. Install with: pip install SpeechRecognition") |
|
|
|
|
|
try: |
|
|
from gtts import gTTS |
|
|
GTTS_AVAILABLE = True |
|
|
except ImportError: |
|
|
GTTS_AVAILABLE = False |
|
|
print("gTTS not available. Install with: pip install gTTS") |
|
|
|
|
|
try: |
|
|
import pyttsx3 |
|
|
PYTTSX3_AVAILABLE = False |
|
|
try: |
|
|
engine = pyttsx3.init() |
|
|
engine.setProperty('rate', 150) |
|
|
engine.setProperty('volume', 0.9) |
|
|
PYTTSX3_AVAILABLE = True |
|
|
except Exception as e: |
|
|
print(f"pyttsx3 initialization failed: {e}") |
|
|
engine = None |
|
|
except ImportError: |
|
|
PYTTSX3_AVAILABLE = False |
|
|
engine = None |
|
|
print("pyttsx3 not available. Install with: pip install pyttsx3") |
|
|
|
|
|
|
|
|
try: |
|
|
import pytesseract |
|
|
TESSERACT_AVAILABLE = True |
|
|
|
|
|
|
|
|
except ImportError: |
|
|
TESSERACT_AVAILABLE = False |
|
|
print("Tesseract not available. Install with: pip install pytesseract && sudo apt install tesseract-ocr") |
|
|
|
|
|
try: |
|
|
from transformers import pipeline |
|
|
TRANSFORMERS_AVAILABLE = True |
|
|
except ImportError: |
|
|
TRANSFORMERS_AVAILABLE = False |
|
|
print("Transformers not available. Install with: pip install transformers") |
|
|
|
|
|
class MathSolver: |
|
|
def __init__(self): |
|
|
self.ai_models_loaded = False |
|
|
self.load_ai_models() |
|
|
|
|
|
def load_ai_models(self): |
|
|
"""Load AI models with Hugging Face compatibility""" |
|
|
if TRANSFORMERS_AVAILABLE: |
|
|
try: |
|
|
|
|
|
self.math_solver = pipeline( |
|
|
"text2text-generation", |
|
|
model="google/flan-t5-small", |
|
|
tokenizer="google/flan-t5-small" |
|
|
) |
|
|
self.ai_models_loaded = True |
|
|
print("✅ AI models loaded successfully") |
|
|
except Exception as e: |
|
|
print(f"❌ AI model loading failed: {e}") |
|
|
self.ai_models_loaded = False |
|
|
else: |
|
|
print("❌ Transformers not available for AI models") |
|
|
|
|
|
def solve_with_ai(self, problem): |
|
|
"""Solve math problems using AI""" |
|
|
if not self.ai_models_loaded: |
|
|
return None |
|
|
|
|
|
try: |
|
|
prompt = f"Solve this math problem: {problem}. Provide the final answer." |
|
|
result = self.math_solver( |
|
|
prompt, |
|
|
max_length=100, |
|
|
num_return_sequences=1, |
|
|
temperature=0.1 |
|
|
) |
|
|
|
|
|
generated_text = result[0]['generated_text'] |
|
|
|
|
|
math_part = re.search(r'([-+]?\d*\.?\d+([eE][-+]?\d+)?|\S+)', generated_text) |
|
|
return math_part.group(0) if math_part else generated_text.strip() |
|
|
except Exception as e: |
|
|
print(f"AI solving error: {e}") |
|
|
return None |
|
|
|
|
|
|
|
|
math_solver = MathSolver() |
|
|
|
|
|
def generate_tts(text, engine_choice="auto"): |
|
|
"""Generate TTS audio - Hugging Face compatible""" |
|
|
temp_path = None |
|
|
try: |
|
|
|
|
|
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") |
|
|
temp_path = temp_file.name |
|
|
temp_file.close() |
|
|
|
|
|
|
|
|
clean_text = re.sub(r'[**`]', '', text) |
|
|
|
|
|
clean_text = clean_text.replace('+', ' plus ').replace('-', ' minus ').replace('*', ' times ').replace('/', ' divided by ').replace('**', ' to the power of ') |
|
|
clean_text = clean_text.replace('\n', '. ')[:300] |
|
|
|
|
|
success = False |
|
|
|
|
|
|
|
|
if engine_choice in ["auto", "pyttsx3"] and PYTTSX3_AVAILABLE and engine: |
|
|
try: |
|
|
engine.save_to_file(clean_text, temp_path) |
|
|
engine.runAndWait() |
|
|
success = True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"pyttsx3 failed: {e}") |
|
|
success = False |
|
|
|
|
|
|
|
|
if not success and (engine_choice in ["auto", "gTTS"] or not PYTTSX3_AVAILABLE) and GTTS_AVAILABLE: |
|
|
try: |
|
|
tts = gTTS(text=clean_text, lang='en', slow=False) |
|
|
tts.save(temp_path) |
|
|
success = True |
|
|
|
|
|
except Exception as e: |
|
|
print(f"gTTS failed: {e}") |
|
|
success = False |
|
|
|
|
|
if success: |
|
|
return temp_path |
|
|
else: |
|
|
print("Neither pyttsx3 nor gTTS could generate audio.") |
|
|
return None |
|
|
|
|
|
except Exception as e: |
|
|
print(f"TTS generation error: {e}") |
|
|
return None |
|
|
finally: |
|
|
|
|
|
if temp_path and not os.path.exists(temp_path): |
|
|
try: |
|
|
os.unlink(temp_path) |
|
|
except OSError as e: |
|
|
print(f"Error removing temp file {temp_path}: {e}") |
|
|
|
|
|
|
|
|
def extract_math_from_image(image_path): |
|
|
"""Extract math from image using OCR""" |
|
|
if not TESSERACT_AVAILABLE: |
|
|
return "OCR not available. Please install pytesseract and tesseract-ocr.", "" |
|
|
|
|
|
if image_path is None: |
|
|
return "No image provided.", "" |
|
|
|
|
|
try: |
|
|
|
|
|
if isinstance(image_path, np.ndarray): |
|
|
|
|
|
pil_image = Image.fromarray(image_path.astype('uint8')).convert("RGB") |
|
|
temp_img_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png") |
|
|
image_path = temp_img_file.name |
|
|
pil_image.save(image_path) |
|
|
temp_img_file.close() |
|
|
elif isinstance(image_path, Image.Image): |
|
|
|
|
|
temp_img_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png") |
|
|
image_path = temp_img_file.name |
|
|
image_path.convert("RGB").save(image_path) |
|
|
temp_img_file.close() |
|
|
elif not isinstance(image_path, str): |
|
|
return "Invalid image input type.", "" |
|
|
|
|
|
|
|
|
|
|
|
custom_config = r'--oem 3 --psm 6' |
|
|
text = pytesseract.image_to_string(image_path, config=custom_config) |
|
|
|
|
|
|
|
|
if isinstance(image_path, str) and (image_path.endswith(".png") or image_path.endswith(".jpg")): |
|
|
try: |
|
|
os.unlink(image_path) |
|
|
except OSError as e: |
|
|
print(f"Error removing temp image file {image_path}: {e}") |
|
|
|
|
|
|
|
|
if text.strip(): |
|
|
|
|
|
cleaned = clean_ocr_text(text) |
|
|
return f"📷 Extracted: {cleaned}", cleaned |
|
|
else: |
|
|
return "❌ No text found in image", "" |
|
|
|
|
|
except Exception as e: |
|
|
return f"❌ Image processing error: {str(e)}", "" |
|
|
|
|
|
def clean_ocr_text(text): |
|
|
"""Clean OCR-extracted text""" |
|
|
corrections = { |
|
|
'—': '-', '–': '-', '×': '*', '÷': '/', |
|
|
'**': '^', '``': '"', "''": '"', |
|
|
'O': '0', 'o': '0', 'l': '1', 'I': '1', |
|
|
'=': '==' |
|
|
} |
|
|
|
|
|
cleaned = text |
|
|
for wrong, correct in corrections.items(): |
|
|
cleaned = cleaned.replace(wrong, correct) |
|
|
|
|
|
cleaned = re.sub(r'\s+', ' ', cleaned).strip() |
|
|
return cleaned |
|
|
|
|
|
def voice_to_text(audio_path): |
|
|
"""Convert voice to text""" |
|
|
if not SPEECH_RECOGNITION_AVAILABLE: |
|
|
return "Speech recognition not available. Please type your problem." |
|
|
|
|
|
if audio_path is None: |
|
|
return "No audio provided." |
|
|
|
|
|
recognizer = sr.Recognizer() |
|
|
try: |
|
|
with sr.AudioFile(audio_path) as source: |
|
|
audio_data = recognizer.record(source) |
|
|
text = recognizer.recognize_google(audio_data) |
|
|
return text |
|
|
except sr.UnknownValueError: |
|
|
return "Could not understand audio" |
|
|
except sr.RequestError: |
|
|
return "Speech service unavailable" |
|
|
except Exception as e: |
|
|
return f"Audio error: {str(e)}" |
|
|
|
|
|
|
|
|
def convert_speech_to_math(text): |
|
|
"""Convert natural language to math expressions - SIMPLE & RELIABLE""" |
|
|
if not text or text.strip() == "": |
|
|
return "0" |
|
|
|
|
|
text = text.lower().strip() |
|
|
print(f"Original voice input: '{text}'") |
|
|
|
|
|
|
|
|
question_phrases = ["what is", "calculate", "compute", "solve", "what's", "how much is"] |
|
|
for phrase in question_phrases: |
|
|
text = text.replace(phrase, "").strip() |
|
|
|
|
|
|
|
|
if any(op in text for op in ['+', '-', '*', '/', 'x', '×']): |
|
|
|
|
|
text = text.replace('x', '*').replace('×', '*') |
|
|
return text |
|
|
|
|
|
|
|
|
if "plus" in text: |
|
|
text = text.replace("plus", "+") |
|
|
if "minus" in text: |
|
|
text = text.replace("minus", "-") |
|
|
if "times" in text or "multiplied by" in text: |
|
|
text = text.replace("times", "*").replace("multiplied by", "*") |
|
|
if "divided by" in text: |
|
|
text = text.replace("divided by", "/") |
|
|
|
|
|
|
|
|
number_words = { |
|
|
'zero': '0', 'one': '1', 'two': '2', 'three': '3', 'four': '4', |
|
|
'five': '5', 'six': '6', 'seven': '7', 'eight': '8', 'nine': '9', |
|
|
'ten': '10', 'eleven': '11', 'twelve': '12', 'thirteen': '13', |
|
|
'fourteen': '14', 'fifteen': '15', 'sixteen': '16', 'seventeen': '17', |
|
|
'eighteen': '18', 'nineteen': '19', 'twenty': '20', 'thirty': '30', |
|
|
'forty': '40', 'fifty': '50', 'sixty': '60', 'seventy': '70', |
|
|
'eighty': '80', 'ninety': '90' |
|
|
} |
|
|
|
|
|
for word, num in number_words.items(): |
|
|
text = text.replace(word, num) |
|
|
|
|
|
|
|
|
import re |
|
|
text = re.sub(r'\s*([+\-*/])\s*', r'\1', text) |
|
|
|
|
|
print(f"Converted to math: '{text}'") |
|
|
return text |
|
|
|
|
|
def evaluate_math_safely(expression): |
|
|
"""Safely evaluate mathematical expressions""" |
|
|
try: |
|
|
|
|
|
if any(op in expression for op in ['+', '-', '*', '/']): |
|
|
try: |
|
|
|
|
|
result = sp.sympify(expression) |
|
|
return result |
|
|
except: |
|
|
pass |
|
|
|
|
|
|
|
|
result = sp.sympify(expression) |
|
|
return result |
|
|
|
|
|
except Exception as e: |
|
|
print(f"Evaluation error for '{expression}': {e}") |
|
|
return None |
|
|
|
|
|
def process_math_complete(query): |
|
|
"""Complete math processing with proper error handling""" |
|
|
try: |
|
|
print(f"Processing query: '{query}'") |
|
|
|
|
|
|
|
|
math_expr = convert_speech_to_math(query) |
|
|
print(f"Converted expression: '{math_expr}'") |
|
|
|
|
|
|
|
|
result = evaluate_math_safely(math_expr) |
|
|
print(f"Raw result: {result}, Type: {type(result)}") |
|
|
|
|
|
if result is None: |
|
|
return "❌ Could not evaluate the expression. Please try rephrasing.", None |
|
|
|
|
|
|
|
|
if isinstance(result, bool): |
|
|
if "=" in math_expr or "==" in math_expr or "!=" in math_expr: |
|
|
return f"**Expression**: `{math_expr}`\n**Result**: `{result}`", None |
|
|
else: |
|
|
return "❌ Unexpected boolean result. Please check your expression.", None |
|
|
|
|
|
|
|
|
if hasattr(result, 'evalf'): |
|
|
numerical = result.evalf() |
|
|
result_text = f""" |
|
|
**Input**: {query} |
|
|
**Expression**: `{math_expr}` |
|
|
**Result**: `{result}` |
|
|
**Numerical Value**: `{numerical}` |
|
|
**Method**: Symbolic Math |
|
|
""" |
|
|
else: |
|
|
result_text = f""" |
|
|
**Input**: {query} |
|
|
**Expression**: `{math_expr}` |
|
|
**Result**: `{result}` |
|
|
**Method**: Direct Evaluation |
|
|
""" |
|
|
|
|
|
return result_text, None |
|
|
|
|
|
except Exception as e: |
|
|
error_msg = f"❌ Processing error: {str(e)}" |
|
|
print(error_msg) |
|
|
return error_msg, None |
|
|
|
|
|
def main_handler(input_type, user_input, calculus_op="differentiate", variable="x", image=None): |
|
|
"""Main handler for all math operations - UPDATED""" |
|
|
try: |
|
|
|
|
|
if input_type in ["basic", "equation"] and user_input: |
|
|
return process_math_complete(user_input) |
|
|
|
|
|
|
|
|
elif input_type == "calculus" and user_input: |
|
|
return process_calculus(calculus_op, user_input, variable), None |
|
|
|
|
|
|
|
|
elif input_type == "image" and image is not None: |
|
|
ocr_result, extracted_text = extract_text_from_image(image) |
|
|
if extracted_text: |
|
|
return process_math_complete(extracted_text) |
|
|
return ocr_result, None |
|
|
else: |
|
|
return "❌ Please provide valid input", None |
|
|
|
|
|
except Exception as e: |
|
|
return f"❌ Unexpected error: {str(e)}", None |
|
|
|
|
|
|
|
|
|
|
|
def evaluate_advanced_math(expression): |
|
|
"""Evaluate mathematical expressions using SymPy""" |
|
|
x, y, z = symbols('x y z') |
|
|
|
|
|
try: |
|
|
|
|
|
expr_lower = expression.lower() |
|
|
|
|
|
if 'diff(' in expr_lower: |
|
|
match = re.search(r'diff\((.*?),\s*(\w+)\)', expression) |
|
|
if match: |
|
|
expr_str, var = match.groups() |
|
|
|
|
|
return diff(sp.sympify(expr_str), symbols(var)) |
|
|
|
|
|
elif 'integrate(' in expr_lower or 'int(' in expr_lower: |
|
|
match = re.search(r'(?:integrate|int)\((.*?),\s*(\w+)\)', expression) |
|
|
if match: |
|
|
expr_str, var = match.groups() |
|
|
|
|
|
return integrate(sp.sympify(expr_str), symbols(var)) |
|
|
|
|
|
elif 'limit(' in expr_lower: |
|
|
match = re.search(r'limit\((.*?),\s*(\w+)\s*->\s*([^)]+)\)', expression) |
|
|
if match: |
|
|
expr_str, var, point = match.groups() |
|
|
|
|
|
return limit(sp.sympify(expr_str), symbols(var), sp.sympify(point)) |
|
|
|
|
|
elif 'factorial(' in expr_lower: |
|
|
match = re.search(r'factorial\((\d+)\)', expression) |
|
|
if match: |
|
|
return factorial(int(match.group(1))) |
|
|
|
|
|
|
|
|
return sp.sympify(expression) |
|
|
|
|
|
except Exception as e: |
|
|
raise ValueError(f"Could not evaluate: {expression}. Error: {str(e)}") |
|
|
|
|
|
def process_math(query, use_ai=True, auto_play=True, tts_engine_choice="auto"): |
|
|
"""Process math query and return result""" |
|
|
try: |
|
|
|
|
|
math_expr = convert_speech_to_math(query) |
|
|
|
|
|
result = None |
|
|
method_used = "Symbolic Math" |
|
|
|
|
|
|
|
|
try: |
|
|
result = evaluate_advanced_math(math_expr) |
|
|
except ValueError: |
|
|
|
|
|
if use_ai and math_solver.ai_models_loaded: |
|
|
ai_result = math_solver.solve_with_ai(query) |
|
|
if ai_result: |
|
|
result = ai_result |
|
|
method_used = "AI Model" |
|
|
else: |
|
|
result = f"❌ Unable to solve '{query}' using AI. Trying basic evaluation." |
|
|
method_used = "Fallback Evaluation" |
|
|
|
|
|
|
|
|
if result is None or "Unable to solve" in str(result): |
|
|
try: |
|
|
|
|
|
result = eval(math_expr) |
|
|
method_used = "Basic Evaluation (eval)" |
|
|
except: |
|
|
result = f"❌ Unable to solve '{query}'. Try rephrasing or check syntax." |
|
|
method_used = "Failed" |
|
|
|
|
|
|
|
|
|
|
|
if isinstance(result, sp.Basic): |
|
|
try: |
|
|
numerical = result.evalf() |
|
|
result_text = f"""**Input**: `{query}` |
|
|
**Symbolic Result**: `{result}` |
|
|
**Numerical Result**: `{numerical}` |
|
|
**Method**: {method_used}""" |
|
|
except Exception as e: |
|
|
|
|
|
result_text = f"""**Input**: `{query}` |
|
|
**Symbolic Result**: `{result}` |
|
|
**Numerical Result**: Could not evaluate numerically ({e}) |
|
|
**Method**: {method_used}""" |
|
|
else: |
|
|
result_text = f"""**Input**: `{query}` |
|
|
**Result**: `{result}` |
|
|
**Method**: {method_used}""" |
|
|
|
|
|
|
|
|
audio_path = None |
|
|
if auto_play and "Unable to solve" not in result_text: |
|
|
speak_text = f"Result is {result}" |
|
|
audio_path = generate_tts(speak_text, engine_choice=tts_engine_choice) |
|
|
|
|
|
return result_text, audio_path |
|
|
|
|
|
except Exception as e: |
|
|
error_msg = f"❌ An unexpected error occurred: {str(e)}" |
|
|
audio_path = generate_tts("Sorry, an error occurred while processing that problem.", engine_choice=tts_engine_choice) if auto_play else None |
|
|
return error_msg, audio_path |
|
|
|
|
|
def process_all_inputs(audio=None, text_input=None, image=None, use_ai=True, auto_play=True, tts_engine_choice="auto"): |
|
|
"""Process all input types""" |
|
|
query = "" |
|
|
output_message = "" |
|
|
|
|
|
|
|
|
if image is not None: |
|
|
extraction_result, extracted_text = extract_math_from_image(image) |
|
|
output_message = extraction_result |
|
|
if extracted_text: |
|
|
query = extracted_text |
|
|
else: |
|
|
|
|
|
audio_path = generate_tts(output_message, engine_choice=tts_engine_choice) if auto_play and "No text found" not in output_message else None |
|
|
return output_message, audio_path |
|
|
|
|
|
if not query and audio is not None: |
|
|
voice_text = voice_to_text(audio) |
|
|
if any(msg in voice_text for msg in ["not available", "not understand", "unavailable", "error"]): |
|
|
return voice_text, None |
|
|
|
|
|
query = voice_text |
|
|
output_message = f"🎤 Transcribed: {query}" |
|
|
|
|
|
if not query and text_input: |
|
|
query = text_input |
|
|
output_message = f"📝 Input: {query}" |
|
|
|
|
|
|
|
|
if not query: |
|
|
msg = "Please provide input via voice, text, or image." |
|
|
audio_path = generate_tts(msg, engine_choice=tts_engine_choice) if auto_play else None |
|
|
return msg, audio_path |
|
|
|
|
|
|
|
|
result_text, audio_path = process_math(query, use_ai, auto_play, tts_engine_choice) |
|
|
|
|
|
|
|
|
final_output_text = f"{output_message}\n\n{result_text}" if output_message and "Extracted:" not in output_message else result_text |
|
|
|
|
|
|
|
|
|
|
|
return final_output_text, audio_path if audio_path and os.path.exists(audio_path) else None |
|
|
|
|
|
|
|
|
def create_interface(): |
|
|
global PYTTSX3_AVAILABLE, GTTS_AVAILABLE, SPEECH_RECOGNITION_AVAILABLE, TESSERACT_AVAILABLE, math_solver |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft(), title="Math Solver Pro") as demo: |
|
|
gr.Markdown(""" |
|
|
# 🧮 Math Solver Pro |
|
|
**Solve math problems using Voice, Text, or Images with Audio Responses** |
|
|
|
|
|
*Powered by SymPy • Hugging Face • Advanced Math Engine* |
|
|
""") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
|
|
|
gr.Markdown("### 📥 Input Methods") |
|
|
|
|
|
with gr.Tab("🎤 Voice"): |
|
|
audio_input = gr.Audio( |
|
|
sources=["microphone", "upload"], |
|
|
type="filepath", |
|
|
label="Speak Math Problem" |
|
|
) |
|
|
|
|
|
with gr.Tab("📝 Text"): |
|
|
text_input = gr.Textbox( |
|
|
label="Type Math Problem", |
|
|
placeholder="Examples: 2+2, derivative of x^2, integrate sin(x)", |
|
|
lines=3 |
|
|
) |
|
|
|
|
|
with gr.Tab("📷 Image"): |
|
|
image_input = gr.Image( |
|
|
label="Upload Math Image", |
|
|
type="filepath", |
|
|
show_download_button=False |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Accordion("⚙️ Settings", open=False): |
|
|
with gr.Row(): |
|
|
use_ai = gr.Checkbox( |
|
|
value=math_solver.ai_models_loaded, |
|
|
label="Use AI Models", |
|
|
interactive=math_solver.ai_models_loaded |
|
|
) |
|
|
auto_play = gr.Checkbox( |
|
|
value=True, |
|
|
label="Auto-Play Audio" |
|
|
) |
|
|
with gr.Row(): |
|
|
tts_engine_choice = gr.Radio( |
|
|
["auto", "pyttsx3", "gTTS", "None"], |
|
|
label="TTS Engine", |
|
|
value="auto", |
|
|
info="auto: prefers pyttsx3 if available, then gTTS. None: no audio." |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Row(): |
|
|
solve_btn = gr.Button("🧠 Solve", variant="primary") |
|
|
clear_btn = gr.Button("🔄 Clear") |
|
|
|
|
|
with gr.Column(): |
|
|
|
|
|
gr.Markdown("### 📊 Results") |
|
|
output_text = gr.Markdown( |
|
|
label="Solution", |
|
|
value="Your solution will appear here..." |
|
|
) |
|
|
|
|
|
audio_output = gr.Audio( |
|
|
label="🔊 Audio Result", |
|
|
autoplay=True, |
|
|
visible=True, |
|
|
value=None |
|
|
) |
|
|
|
|
|
|
|
|
with gr.Accordion("🤖 System Status", open=False): |
|
|
status_text = f""" |
|
|
**Available Features:** |
|
|
- ✅ Advanced Math Engine (SymPy) |
|
|
- {'✅' if SPEECH_RECOGNITION_AVAILABLE else '❌'} Voice Input (Requires `SpeechRecognition`) |
|
|
- {'✅' if TESSERACT_AVAILABLE else '❌'} Image OCR (Requires `pytesseract` and `tesseract-ocr`) |
|
|
- {'✅' if GTTS_AVAILABLE else '❌'} Online TTS (Requires `gTTS`) |
|
|
- {'✅' if PYTTSX3_AVAILABLE else '❌'} Offline TTS (Requires `pyttsx3`) |
|
|
- {'✅' if math_solver.ai_models_loaded else '❌'} AI Models (Requires `transformers`) |
|
|
""" |
|
|
gr.Markdown(status_text) |
|
|
|
|
|
|
|
|
with gr.Accordion("📚 Examples", open=True): |
|
|
gr.Markdown(""" |
|
|
**Try these examples:** |
|
|
- **Voice**: "What is 15 times 27?" |
|
|
- **Text**: `integrate x^2 + 3x + 1 from 0 to 1` |
|
|
- **Image**: Upload equation photo (e.g., `sqrt(16)`) |
|
|
- **Text**: `diff(sin(x) + cos(x), x)` |
|
|
- **Voice**: "Calculate factorial of 7" |
|
|
""") |
|
|
|
|
|
|
|
|
solve_btn.click( |
|
|
fn=process_all_inputs, |
|
|
inputs=[audio_input, text_input, image_input, use_ai, auto_play, tts_engine_choice], |
|
|
outputs=[output_text, audio_output] |
|
|
) |
|
|
|
|
|
def clear_all(): |
|
|
|
|
|
|
|
|
return None, "", None, "Your solution will appear here...", None |
|
|
|
|
|
clear_btn.click( |
|
|
fn=clear_all, |
|
|
inputs=[], |
|
|
outputs=[audio_input, text_input, image_input, output_text, audio_output] |
|
|
) |
|
|
|
|
|
text_input.submit( |
|
|
fn=process_all_inputs, |
|
|
inputs=[gr.State(None), text_input, gr.State(None), use_ai, auto_play, tts_engine_choice], |
|
|
outputs=[output_text, audio_output] |
|
|
) |
|
|
|
|
|
return demo |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo = create_interface() |
|
|
demo.launch(share=True) |
|
|
|