shukdevdatta123 commited on
Commit
fd80886
Β·
verified Β·
1 Parent(s): b36760b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +443 -47
app.py CHANGED
@@ -7,14 +7,266 @@ from openai import OpenAI
7
  from together import Together
8
  from PIL import Image
9
  import io
 
 
 
 
 
10
 
11
- # Function to generate math solution using the Phi-4-reasoning-plus model via OpenRouter
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  def generate_math_solution_openrouter(api_key, problem_text, history=None):
13
  if not api_key.strip():
14
- return "Please enter your OpenRouter API key.", history
15
 
16
  if not problem_text.strip():
17
- return "Please enter a math problem.", history
18
 
19
  try:
20
  client = OpenAI(
@@ -31,16 +283,23 @@ def generate_math_solution_openrouter(api_key, problem_text, history=None):
31
  2. Explain why this step is necessary
32
  3. Connect it to relevant mathematical concepts
33
 
34
- Format your response with clear section headers using markdown.
35
  Begin with an "Initial Analysis" section, follow with numbered steps,
36
- and conclude with a "Final Answer" section."""},
 
 
 
 
 
 
 
37
  ]
38
 
39
  # Add conversation history if it exists
40
  if history:
41
  for exchange in history:
42
  messages.append({"role": "user", "content": exchange[0]})
43
- if exchange[1]: # Check if there's a response
44
  messages.append({"role": "assistant", "content": exchange[1]})
45
 
46
  # Add the current problem
@@ -56,38 +315,35 @@ def generate_math_solution_openrouter(api_key, problem_text, history=None):
56
  }
57
  )
58
 
59
- solution = completion.choices[0].message.content
 
 
 
 
 
 
 
 
 
60
 
61
  # Update history
62
  if history is None:
63
  history = []
64
- history.append((problem_text, solution))
65
 
66
- return solution, history
67
 
68
  except Exception as e:
69
  error_message = f"Error: {str(e)}"
70
- return error_message, history
71
-
72
- # Function to convert image to base64
73
- def image_to_base64(image_path):
74
- if image_path is None:
75
- return None
76
-
77
- try:
78
- with open(image_path, "rb") as img_file:
79
- return base64.b64encode(img_file.read()).decode("utf-8")
80
- except Exception as e:
81
- print(f"Error converting image to base64: {str(e)}")
82
- return None
83
 
84
- # Function to generate math solution using Together AI with support for images
85
  def generate_math_solution_together(api_key, problem_text, image_path=None, history=None):
86
  if not api_key.strip():
87
- return "Please enter your Together AI API key.", history
88
 
89
  if not problem_text.strip() and image_path is None:
90
- return "Please enter a math problem or upload an image of a math problem.", history
91
 
92
  try:
93
  client = Together(api_key=api_key)
@@ -103,9 +359,16 @@ def generate_math_solution_together(api_key, problem_text, image_path=None, hist
103
  2. Explain why this step is necessary
104
  3. Connect it to relevant mathematical concepts
105
 
106
- Format your response with clear section headers using markdown.
107
  Begin with an "Initial Analysis" section, follow with numbered steps,
108
- and conclude with a "Final Answer" section."""
 
 
 
 
 
 
 
109
  }
110
  ]
111
 
@@ -113,7 +376,7 @@ def generate_math_solution_together(api_key, problem_text, image_path=None, hist
113
  if history:
114
  for exchange in history:
115
  messages.append({"role": "user", "content": exchange[0]})
116
- if exchange[1]: # Check if there's a response
117
  messages.append({"role": "assistant", "content": exchange[1]})
118
 
119
  # Prepare the user message content
@@ -156,18 +419,40 @@ def generate_math_solution_together(api_key, problem_text, image_path=None, hist
156
  stream=False
157
  )
158
 
159
- solution = response.choices[0].message.content
 
 
 
 
 
 
 
 
 
 
160
 
161
  # Update history - for simplicity, just store the text problem
162
  if history is None:
163
  history = []
164
- history.append((problem_text if problem_text.strip() else "Image problem", solution))
165
 
166
- return solution, history
167
 
168
  except Exception as e:
169
  error_message = f"Error: {str(e)}"
170
- return error_message, history
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
  # Define the Gradio interface
173
  def create_demo():
@@ -175,6 +460,7 @@ def create_demo():
175
  gr.Markdown("# πŸ“š Advanced Math Tutor")
176
  gr.Markdown("""
177
  This application provides step-by-step solutions to math problems using advanced AI models.
 
178
  Choose between OpenRouter's Phi-4-reasoning-plus for text-based problems or Together AI's
179
  Llama-Vision for problems with images.
180
  """)
@@ -208,24 +494,65 @@ def create_demo():
208
  with gr.Row():
209
  openrouter_submit_btn = gr.Button("Solve Problem", variant="primary")
210
  openrouter_clear_btn = gr.Button("Clear")
211
-
212
  with gr.Column(scale=2):
213
- openrouter_solution_output = gr.Markdown(label="Solution")
 
 
 
 
 
 
 
 
 
 
214
 
215
  # Store conversation history (invisible to user)
216
  openrouter_conversation_history = gr.State(value=None)
217
 
218
  # Button actions
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  openrouter_submit_btn.click(
220
- fn=generate_math_solution_openrouter,
221
  inputs=[openrouter_api_key, text_problem_input, openrouter_conversation_history],
222
- outputs=[openrouter_solution_output, openrouter_conversation_history]
 
 
 
 
 
223
  )
224
 
 
 
 
 
 
 
 
 
225
  openrouter_clear_btn.click(
226
- fn=lambda: ("", None),
227
  inputs=[],
228
- outputs=[openrouter_solution_output, openrouter_conversation_history]
 
 
 
 
 
229
  )
230
 
231
  # Image-based problem solver (Together AI)
@@ -249,24 +576,65 @@ def create_demo():
249
  with gr.Row():
250
  together_submit_btn = gr.Button("Solve Problem", variant="primary")
251
  together_clear_btn = gr.Button("Clear")
252
-
253
  with gr.Column(scale=2):
254
- together_solution_output = gr.Markdown(label="Solution")
 
 
 
 
 
 
 
 
 
 
255
 
256
  # Store conversation history (invisible to user)
257
  together_conversation_history = gr.State(value=None)
258
 
259
  # Button actions
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  together_submit_btn.click(
261
- fn=generate_math_solution_together,
262
  inputs=[together_api_key, together_problem_input, together_image_input, together_conversation_history],
263
- outputs=[together_solution_output, together_conversation_history]
 
 
 
 
 
264
  )
265
 
 
 
 
 
 
 
 
 
266
  together_clear_btn.click(
267
- fn=lambda: ("", None),
268
  inputs=[],
269
- outputs=[together_solution_output, together_conversation_history]
 
 
 
 
 
270
  )
271
 
272
  # Help tab
@@ -274,6 +642,12 @@ def create_demo():
274
  gr.Markdown("""
275
  ## How to Use the Advanced Math Tutor
276
 
 
 
 
 
 
 
277
  ### Getting Started
278
 
279
  #### For Text-Based Problems (OpenRouter)
@@ -291,8 +665,16 @@ def create_demo():
291
  ### Solving Math Problems
292
  - For text problems: Type or paste your math problem in the input field
293
  - For image problems: Upload a clear image of the math problem
294
- - Click "Solve Problem" to get a detailed step-by-step solution
295
- - The solution will include explanations for each step
 
 
 
 
 
 
 
 
296
 
297
  ### Tips for Best Results
298
  - Be specific in your problem description
@@ -310,14 +692,28 @@ def create_demo():
310
  - Statistics and Probability
311
  - Number Theory
312
  - And many more!
 
 
 
 
 
 
313
  """)
314
 
315
  # Footer
316
  gr.Markdown("""
317
  ---
318
  ### About
319
- This application uses Microsoft's Phi-4-reasoning-plus model via OpenRouter for text-based problems
320
  and Llama-Vision-Free via Together AI for image-based problems.
 
 
 
 
 
 
 
 
321
  Your API keys are required but not stored permanently.
322
  """)
323
 
 
7
  from together import Together
8
  from PIL import Image
9
  import io
10
+ import markdown
11
+ from datetime import datetime
12
+ import tempfile
13
+ import weasyprint
14
+ from pathlib import Path
15
 
16
+ # Function to convert markdown to HTML with styling
17
+ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
18
+ """Convert markdown to styled HTML"""
19
+
20
+ # Convert markdown to HTML
21
+ html_content = markdown.markdown(markdown_text, extensions=['tables', 'fenced_code'])
22
+
23
+ # Get current timestamp
24
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
25
+
26
+ # Create styled HTML document
27
+ styled_html = f"""
28
+ <!DOCTYPE html>
29
+ <html lang="en">
30
+ <head>
31
+ <meta charset="UTF-8">
32
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
33
+ <title>Math Solution - Advanced Math Tutor</title>
34
+ <style>
35
+ body {{
36
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
37
+ line-height: 1.6;
38
+ color: #333;
39
+ max-width: 800px;
40
+ margin: 0 auto;
41
+ padding: 20px;
42
+ background-color: #f9f9f9;
43
+ }}
44
+ .container {{
45
+ background-color: white;
46
+ padding: 40px;
47
+ border-radius: 10px;
48
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
49
+ }}
50
+ .header {{
51
+ text-align: center;
52
+ border-bottom: 3px solid #4CAF50;
53
+ padding-bottom: 20px;
54
+ margin-bottom: 30px;
55
+ }}
56
+ .header h1 {{
57
+ color: #2c3e50;
58
+ margin: 0;
59
+ font-size: 2.5em;
60
+ }}
61
+ .header .subtitle {{
62
+ color: #7f8c8d;
63
+ font-style: italic;
64
+ margin-top: 10px;
65
+ }}
66
+ .problem-section {{
67
+ background-color: #e8f5e8;
68
+ padding: 20px;
69
+ border-radius: 8px;
70
+ margin-bottom: 30px;
71
+ border-left: 5px solid #4CAF50;
72
+ }}
73
+ .problem-section h2 {{
74
+ color: #2c3e50;
75
+ margin-top: 0;
76
+ }}
77
+ .solution-content {{
78
+ background-color: #f8f9fa;
79
+ padding: 25px;
80
+ border-radius: 8px;
81
+ border-left: 5px solid #007bff;
82
+ }}
83
+ h1, h2, h3, h4, h5, h6 {{
84
+ color: #2c3e50;
85
+ margin-top: 25px;
86
+ margin-bottom: 15px;
87
+ }}
88
+ h2 {{
89
+ border-bottom: 2px solid #eee;
90
+ padding-bottom: 10px;
91
+ }}
92
+ code {{
93
+ background-color: #f1f1f1;
94
+ padding: 2px 6px;
95
+ border-radius: 3px;
96
+ font-family: 'Courier New', monospace;
97
+ color: #d63384;
98
+ }}
99
+ pre {{
100
+ background-color: #f8f8f8;
101
+ padding: 15px;
102
+ border-radius: 5px;
103
+ overflow-x: auto;
104
+ border: 1px solid #ddd;
105
+ }}
106
+ pre code {{
107
+ background-color: transparent;
108
+ padding: 0;
109
+ color: inherit;
110
+ }}
111
+ .math-expression {{
112
+ background-color: #fff3cd;
113
+ padding: 10px;
114
+ border-radius: 5px;
115
+ border: 1px solid #ffeaa7;
116
+ margin: 10px 0;
117
+ font-family: 'Times New Roman', serif;
118
+ font-size: 1.1em;
119
+ }}
120
+ .step {{
121
+ margin: 20px 0;
122
+ padding: 15px;
123
+ background-color: #ffffff;
124
+ border-radius: 8px;
125
+ border: 1px solid #dee2e6;
126
+ }}
127
+ .final-answer {{
128
+ background-color: #d4edda;
129
+ border: 2px solid #4CAF50;
130
+ padding: 20px;
131
+ border-radius: 8px;
132
+ margin-top: 30px;
133
+ text-align: center;
134
+ font-weight: bold;
135
+ font-size: 1.2em;
136
+ }}
137
+ .timestamp {{
138
+ text-align: right;
139
+ color: #6c757d;
140
+ font-size: 0.9em;
141
+ margin-top: 30px;
142
+ padding-top: 20px;
143
+ border-top: 1px solid #eee;
144
+ }}
145
+ ul, ol {{
146
+ padding-left: 25px;
147
+ }}
148
+ li {{
149
+ margin: 8px 0;
150
+ }}
151
+ table {{
152
+ border-collapse: collapse;
153
+ width: 100%;
154
+ margin: 20px 0;
155
+ }}
156
+ th, td {{
157
+ border: 1px solid #ddd;
158
+ padding: 12px;
159
+ text-align: left;
160
+ }}
161
+ th {{
162
+ background-color: #f8f9fa;
163
+ font-weight: bold;
164
+ }}
165
+ .print-button {{
166
+ background-color: #007bff;
167
+ color: white;
168
+ border: none;
169
+ padding: 10px 20px;
170
+ border-radius: 5px;
171
+ cursor: pointer;
172
+ font-size: 16px;
173
+ margin: 10px 5px;
174
+ display: inline-block;
175
+ text-decoration: none;
176
+ }}
177
+ .print-button:hover {{
178
+ background-color: #0056b3;
179
+ }}
180
+ @media print {{
181
+ body {{
182
+ background-color: white;
183
+ }}
184
+ .container {{
185
+ box-shadow: none;
186
+ border: none;
187
+ }}
188
+ .print-button {{
189
+ display: none;
190
+ }}
191
+ }}
192
+ </style>
193
+ <script>
194
+ function printPage() {{
195
+ window.print();
196
+ }}
197
+ </script>
198
+ </head>
199
+ <body>
200
+ <div class="container">
201
+ <div class="header">
202
+ <h1>πŸ“š Advanced Math Tutor</h1>
203
+ <div class="subtitle">Step-by-Step Mathematical Solution</div>
204
+ </div>
205
+
206
+ <button class="print-button" onclick="printPage()">πŸ–¨οΈ Print to PDF</button>
207
+
208
+ {f'''
209
+ <div class="problem-section">
210
+ <h2>πŸ“ Problem Statement</h2>
211
+ <p><strong>{problem_text}</strong></p>
212
+ </div>
213
+ ''' if include_problem and problem_text.strip() else ''}
214
+
215
+ <div class="solution-content">
216
+ <h2>πŸ” Solution</h2>
217
+ {html_content}
218
+ </div>
219
+
220
+ <div class="timestamp">
221
+ Generated on: {timestamp}
222
+ </div>
223
+ </div>
224
+ </body>
225
+ </html>
226
+ """
227
+
228
+ return styled_html
229
+
230
+ # Function to save HTML to file
231
+ def save_html_to_file(html_content, filename_prefix="math_solution"):
232
+ """Save HTML content to a temporary file and return the file path"""
233
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
234
+ filename = f"{filename_prefix}_{timestamp}.html"
235
+
236
+ # Create a temporary file
237
+ temp_dir = tempfile.gettempdir()
238
+ file_path = os.path.join(temp_dir, filename)
239
+
240
+ with open(file_path, 'w', encoding='utf-8') as f:
241
+ f.write(html_content)
242
+
243
+ return file_path
244
+
245
+ # Function to convert HTML to PDF
246
+ def html_to_pdf(html_content, filename_prefix="math_solution"):
247
+ """Convert HTML content to PDF and return the file path"""
248
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
249
+ filename = f"{filename_prefix}_{timestamp}.pdf"
250
+
251
+ # Create a temporary file for PDF
252
+ temp_dir = tempfile.gettempdir()
253
+ pdf_path = os.path.join(temp_dir, filename)
254
+
255
+ try:
256
+ # Convert HTML to PDF using WeasyPrint
257
+ weasyprint.HTML(string=html_content).write_pdf(pdf_path)
258
+ return pdf_path
259
+ except Exception as e:
260
+ print(f"Error converting to PDF: {str(e)}")
261
+ return None
262
+
263
+ # Enhanced function to generate math solution using OpenRouter with HTML output
264
  def generate_math_solution_openrouter(api_key, problem_text, history=None):
265
  if not api_key.strip():
266
+ return "Please enter your OpenRouter API key.", None, None, history
267
 
268
  if not problem_text.strip():
269
+ return "Please enter a math problem.", None, None, history
270
 
271
  try:
272
  client = OpenAI(
 
283
  2. Explain why this step is necessary
284
  3. Connect it to relevant mathematical concepts
285
 
286
+ Format your response using markdown with clear section headers.
287
  Begin with an "Initial Analysis" section, follow with numbered steps,
288
+ and conclude with a "Final Answer" section.
289
+
290
+ Use proper markdown formatting including:
291
+ - Headers (##, ###)
292
+ - **Bold text** for important points
293
+ - `Code blocks` for mathematical expressions
294
+ - Lists and numbered steps
295
+ - Tables if needed for comparisons or data"""},
296
  ]
297
 
298
  # Add conversation history if it exists
299
  if history:
300
  for exchange in history:
301
  messages.append({"role": "user", "content": exchange[0]})
302
+ if len(exchange) > 1 and exchange[1]: # Check if there's a response
303
  messages.append({"role": "assistant", "content": exchange[1]})
304
 
305
  # Add the current problem
 
315
  }
316
  )
317
 
318
+ markdown_solution = completion.choices[0].message.content
319
+
320
+ # Convert to HTML
321
+ html_solution = markdown_to_html(markdown_solution, problem_text)
322
+
323
+ # Save HTML file
324
+ html_file_path = save_html_to_file(html_solution, "openrouter_solution")
325
+
326
+ # Convert to PDF
327
+ pdf_file_path = html_to_pdf(html_solution, "openrouter_solution")
328
 
329
  # Update history
330
  if history is None:
331
  history = []
332
+ history.append((problem_text, markdown_solution))
333
 
334
+ return html_solution, html_file_path, pdf_file_path, history
335
 
336
  except Exception as e:
337
  error_message = f"Error: {str(e)}"
338
+ return error_message, None, None, history
 
 
 
 
 
 
 
 
 
 
 
 
339
 
340
+ # Enhanced function to generate math solution using Together AI with HTML output
341
  def generate_math_solution_together(api_key, problem_text, image_path=None, history=None):
342
  if not api_key.strip():
343
+ return "Please enter your Together AI API key.", None, None, history
344
 
345
  if not problem_text.strip() and image_path is None:
346
+ return "Please enter a math problem or upload an image of a math problem.", None, None, history
347
 
348
  try:
349
  client = Together(api_key=api_key)
 
359
  2. Explain why this step is necessary
360
  3. Connect it to relevant mathematical concepts
361
 
362
+ Format your response using markdown with clear section headers.
363
  Begin with an "Initial Analysis" section, follow with numbered steps,
364
+ and conclude with a "Final Answer" section.
365
+
366
+ Use proper markdown formatting including:
367
+ - Headers (##, ###)
368
+ - **Bold text** for important points
369
+ - `Code blocks` for mathematical expressions
370
+ - Lists and numbered steps
371
+ - Tables if needed for comparisons or data"""
372
  }
373
  ]
374
 
 
376
  if history:
377
  for exchange in history:
378
  messages.append({"role": "user", "content": exchange[0]})
379
+ if len(exchange) > 1 and exchange[1]: # Check if there's a response
380
  messages.append({"role": "assistant", "content": exchange[1]})
381
 
382
  # Prepare the user message content
 
419
  stream=False
420
  )
421
 
422
+ markdown_solution = response.choices[0].message.content
423
+
424
+ # Convert to HTML
425
+ problem_display = problem_text if problem_text.strip() else "Image-based problem"
426
+ html_solution = markdown_to_html(markdown_solution, problem_display)
427
+
428
+ # Save HTML file
429
+ html_file_path = save_html_to_file(html_solution, "together_solution")
430
+
431
+ # Convert to PDF
432
+ pdf_file_path = html_to_pdf(html_solution, "together_solution")
433
 
434
  # Update history - for simplicity, just store the text problem
435
  if history is None:
436
  history = []
437
+ history.append((problem_display, markdown_solution))
438
 
439
+ return html_solution, html_file_path, pdf_file_path, history
440
 
441
  except Exception as e:
442
  error_message = f"Error: {str(e)}"
443
+ return error_message, None, None, history
444
+
445
+ # Function to convert image to base64
446
+ def image_to_base64(image_path):
447
+ if image_path is None:
448
+ return None
449
+
450
+ try:
451
+ with open(image_path, "rb") as img_file:
452
+ return base64.b64encode(img_file.read()).decode("utf-8")
453
+ except Exception as e:
454
+ print(f"Error converting image to base64: {str(e)}")
455
+ return None
456
 
457
  # Define the Gradio interface
458
  def create_demo():
 
460
  gr.Markdown("# πŸ“š Advanced Math Tutor")
461
  gr.Markdown("""
462
  This application provides step-by-step solutions to math problems using advanced AI models.
463
+ Solutions are generated in **HTML format** with download and print-to-PDF capabilities.
464
  Choose between OpenRouter's Phi-4-reasoning-plus for text-based problems or Together AI's
465
  Llama-Vision for problems with images.
466
  """)
 
494
  with gr.Row():
495
  openrouter_submit_btn = gr.Button("Solve Problem", variant="primary")
496
  openrouter_clear_btn = gr.Button("Clear")
497
+
498
  with gr.Column(scale=2):
499
+ openrouter_solution_output = gr.HTML(label="Solution (HTML Format)")
500
+
501
+ with gr.Row():
502
+ openrouter_html_download = gr.File(
503
+ label="πŸ“„ Download HTML Solution",
504
+ visible=False
505
+ )
506
+ openrouter_pdf_download = gr.File(
507
+ label="πŸ“„ Download PDF Solution",
508
+ visible=False
509
+ )
510
 
511
  # Store conversation history (invisible to user)
512
  openrouter_conversation_history = gr.State(value=None)
513
 
514
  # Button actions
515
+ def handle_openrouter_submit(api_key, problem_text, history):
516
+ html_solution, html_file, pdf_file, updated_history = generate_math_solution_openrouter(
517
+ api_key, problem_text, history
518
+ )
519
+
520
+ # Return outputs including file updates
521
+ return (
522
+ html_solution,
523
+ updated_history,
524
+ gr.update(value=html_file, visible=html_file is not None),
525
+ gr.update(value=pdf_file, visible=pdf_file is not None)
526
+ )
527
+
528
  openrouter_submit_btn.click(
529
+ fn=handle_openrouter_submit,
530
  inputs=[openrouter_api_key, text_problem_input, openrouter_conversation_history],
531
+ outputs=[
532
+ openrouter_solution_output,
533
+ openrouter_conversation_history,
534
+ openrouter_html_download,
535
+ openrouter_pdf_download
536
+ ]
537
  )
538
 
539
+ def clear_openrouter():
540
+ return (
541
+ "",
542
+ None,
543
+ gr.update(value=None, visible=False),
544
+ gr.update(value=None, visible=False)
545
+ )
546
+
547
  openrouter_clear_btn.click(
548
+ fn=clear_openrouter,
549
  inputs=[],
550
+ outputs=[
551
+ openrouter_solution_output,
552
+ openrouter_conversation_history,
553
+ openrouter_html_download,
554
+ openrouter_pdf_download
555
+ ]
556
  )
557
 
558
  # Image-based problem solver (Together AI)
 
576
  with gr.Row():
577
  together_submit_btn = gr.Button("Solve Problem", variant="primary")
578
  together_clear_btn = gr.Button("Clear")
579
+
580
  with gr.Column(scale=2):
581
+ together_solution_output = gr.HTML(label="Solution (HTML Format)")
582
+
583
+ with gr.Row():
584
+ together_html_download = gr.File(
585
+ label="πŸ“„ Download HTML Solution",
586
+ visible=False
587
+ )
588
+ together_pdf_download = gr.File(
589
+ label="πŸ“„ Download PDF Solution",
590
+ visible=False
591
+ )
592
 
593
  # Store conversation history (invisible to user)
594
  together_conversation_history = gr.State(value=None)
595
 
596
  # Button actions
597
+ def handle_together_submit(api_key, problem_text, image_path, history):
598
+ html_solution, html_file, pdf_file, updated_history = generate_math_solution_together(
599
+ api_key, problem_text, image_path, history
600
+ )
601
+
602
+ # Return outputs including file updates
603
+ return (
604
+ html_solution,
605
+ updated_history,
606
+ gr.update(value=html_file, visible=html_file is not None),
607
+ gr.update(value=pdf_file, visible=pdf_file is not None)
608
+ )
609
+
610
  together_submit_btn.click(
611
+ fn=handle_together_submit,
612
  inputs=[together_api_key, together_problem_input, together_image_input, together_conversation_history],
613
+ outputs=[
614
+ together_solution_output,
615
+ together_conversation_history,
616
+ together_html_download,
617
+ together_pdf_download
618
+ ]
619
  )
620
 
621
+ def clear_together():
622
+ return (
623
+ "",
624
+ None,
625
+ gr.update(value=None, visible=False),
626
+ gr.update(value=None, visible=False)
627
+ )
628
+
629
  together_clear_btn.click(
630
+ fn=clear_together,
631
  inputs=[],
632
+ outputs=[
633
+ together_solution_output,
634
+ together_conversation_history,
635
+ together_html_download,
636
+ together_pdf_download
637
+ ]
638
  )
639
 
640
  # Help tab
 
642
  gr.Markdown("""
643
  ## How to Use the Advanced Math Tutor
644
 
645
+ ### New Features πŸŽ‰
646
+ - **HTML-formatted solutions**: All responses are now generated in beautiful HTML format
647
+ - **Download HTML**: Download the complete solution as an HTML file
648
+ - **Download PDF**: Convert and download solutions as PDF files
649
+ - **Print functionality**: Use the "Print to PDF" button in the HTML output to print directly
650
+
651
  ### Getting Started
652
 
653
  #### For Text-Based Problems (OpenRouter)
 
665
  ### Solving Math Problems
666
  - For text problems: Type or paste your math problem in the input field
667
  - For image problems: Upload a clear image of the math problem
668
+ - Click "Solve Problem" to get a detailed step-by-step solution in HTML format
669
+ - Use the download buttons to save HTML or PDF versions
670
+ - Click "Print to PDF" within the solution to print directly from your browser
671
+
672
+ ### HTML Output Features
673
+ - **Professional styling**: Clean, readable format with proper typography
674
+ - **Mathematical expressions**: Highlighted math expressions and code blocks
675
+ - **Step-by-step sections**: Clearly organized solution steps
676
+ - **Print-friendly**: Optimized for printing and PDF conversion
677
+ - **Timestamps**: Each solution includes generation timestamp
678
 
679
  ### Tips for Best Results
680
  - Be specific in your problem description
 
692
  - Statistics and Probability
693
  - Number Theory
694
  - And many more!
695
+
696
+ ### Required Dependencies
697
+ To run this application, you'll need to install:
698
+ ```bash
699
+ pip install gradio openai together pillow markdown weasyprint
700
+ ```
701
  """)
702
 
703
  # Footer
704
  gr.Markdown("""
705
  ---
706
  ### About
707
+ This enhanced application uses Microsoft's Phi-4-reasoning-plus model via OpenRouter for text-based problems
708
  and Llama-Vision-Free via Together AI for image-based problems.
709
+
710
+ **New Features:**
711
+ - HTML-formatted responses with professional styling
712
+ - Download solutions as HTML files
713
+ - Convert and download solutions as PDF files
714
+ - Print-to-PDF functionality
715
+ - Enhanced formatting with mathematical expressions highlighting
716
+
717
  Your API keys are required but not stored permanently.
718
  """)
719