shukdevdattaEX commited on
Commit
399c426
Β·
verified Β·
1 Parent(s): d31135e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -177
app.py CHANGED
@@ -10,8 +10,21 @@ 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 and MathJax
17
  def markdown_to_html(markdown_text, problem_text="", include_problem=True):
@@ -20,16 +33,6 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
20
  # Convert markdown to HTML
21
  html_content = markdown.markdown(markdown_text, extensions=['tables', 'fenced_code'])
22
 
23
- # Replace LaTeX delimiters for MathJax
24
- # Handle display math: \[ ... \] and $$ ... $$
25
- html_content = re.sub(r'\\\[(.*?)\\\]', r'\\[\1\\]', html_content, flags=re.DOTALL)
26
- html_content = re.sub(r'\$\$(.*?)\$\$', r'\\[\1\\]', html_content, flags=re.DOTALL)
27
-
28
- # Handle inline math: \( ... \) and $ ... $
29
- html_content = re.sub(r'\\\((.*?)\\\)', r'\\(\1\\)', html_content)
30
- # Be careful with single $ as it might be regular dollar signs
31
- html_content = re.sub(r'(?<!\$)\$(?!\$)([^\$]+?)(?<!\$)\$(?!\$)', r'\\(\1\\)', html_content)
32
-
33
  # Get current timestamp
34
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
35
 
@@ -43,99 +46,140 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
43
  <title>Math Solution - Advanced Math Tutor</title>
44
 
45
  <!-- MathJax for rendering mathematical notation -->
46
- <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
47
- <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
48
  <script>
49
  window.MathJax = {{
50
  tex: {{
51
- inlineMath: [['\\\\(', '\\\\)']],
52
- displayMath: [['\\\\[', '\\\\]']],
53
  processEscapes: true,
54
- processEnvironments: true
 
55
  }},
56
  options: {{
57
- skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre']
 
 
 
 
 
 
 
 
 
 
 
58
  }}
59
  }};
60
  </script>
 
61
 
62
  <style>
63
  body {{
64
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
65
  line-height: 1.8;
66
- color: #333;
67
  max-width: 900px;
68
  margin: 0 auto;
69
- padding: 20px;
70
  background-color: #f5f7fa;
71
  }}
 
 
 
 
 
 
 
 
 
 
72
  .container {{
73
  background-color: white;
74
  padding: 50px;
75
  border-radius: 12px;
76
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
77
  }}
 
78
  .header {{
79
  text-align: center;
80
  border-bottom: 4px solid #4CAF50;
81
  padding-bottom: 25px;
82
  margin-bottom: 40px;
83
  }}
 
84
  .header h1 {{
85
  color: #2c3e50;
86
  margin: 0;
87
  font-size: 2.8em;
88
  font-weight: 700;
89
  }}
 
90
  .header .subtitle {{
91
  color: #7f8c8d;
92
  font-style: italic;
93
  margin-top: 10px;
94
  font-size: 1.1em;
95
  }}
 
96
  .problem-section {{
97
  background-color: #e8f5e9;
98
  padding: 25px;
99
  border-radius: 10px;
100
  margin-bottom: 35px;
101
  border-left: 6px solid #4CAF50;
102
- box-shadow: 0 2px 5px rgba(0,0,0,0.05);
103
  }}
 
104
  .problem-section h2 {{
105
  color: #2c3e50;
106
  margin-top: 0;
107
  font-size: 1.6em;
108
  }}
 
109
  .problem-section p {{
110
- font-size: 1.1em;
111
  line-height: 1.6;
 
112
  }}
 
113
  .solution-content {{
114
  background-color: #fafbfc;
115
- padding: 30px;
116
  border-radius: 10px;
117
  border-left: 6px solid #007bff;
118
- box-shadow: 0 2px 5px rgba(0,0,0,0.05);
119
  }}
 
120
  h1, h2, h3, h4, h5, h6 {{
121
  color: #2c3e50;
122
  margin-top: 30px;
123
  margin-bottom: 15px;
124
  font-weight: 600;
 
125
  }}
 
126
  h2 {{
127
  border-bottom: 2px solid #e1e4e8;
128
  padding-bottom: 12px;
129
  font-size: 1.8em;
130
  }}
 
131
  h3 {{
132
- font-size: 1.4em;
133
  color: #34495e;
 
134
  }}
 
135
  h4 {{
136
- font-size: 1.2em;
137
  color: #34495e;
138
  }}
 
 
 
 
 
 
139
  code {{
140
  background-color: #f1f3f5;
141
  padding: 3px 8px;
@@ -144,6 +188,7 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
144
  color: #e83e8c;
145
  font-size: 0.9em;
146
  }}
 
147
  pre {{
148
  background-color: #f6f8fa;
149
  padding: 20px;
@@ -152,75 +197,105 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
152
  border: 1px solid #d1d5da;
153
  line-height: 1.6;
154
  }}
 
155
  pre code {{
156
  background-color: transparent;
157
  padding: 0;
158
  color: #24292e;
159
  }}
160
- .math-expression {{
161
- background-color: #fff9e6;
162
- padding: 15px;
163
- border-radius: 6px;
164
- border: 1px solid #ffe066;
165
- margin: 15px 0;
166
- text-align: center;
167
- font-size: 1.15em;
168
- }}
169
  .step {{
170
- margin: 25px 0;
171
- padding: 20px;
172
  background-color: #ffffff;
173
  border-radius: 8px;
174
  border: 1px solid #dee2e6;
175
- box-shadow: 0 1px 3px rgba(0,0,0,0.05);
176
- }}
177
- .final-answer {{
178
- background-color: #d4edda;
179
- border: 3px solid #28a745;
180
- padding: 25px;
181
- border-radius: 10px;
182
- margin-top: 35px;
183
- text-align: center;
184
- font-size: 1.3em;
185
  }}
186
- .final-answer h2, .final-answer h3 {{
187
- color: #155724;
 
188
  margin-top: 0;
189
  }}
190
- .timestamp {{
191
- text-align: right;
192
- color: #6c757d;
193
- font-size: 0.95em;
194
- margin-top: 40px;
195
- padding-top: 25px;
196
- border-top: 2px solid #e9ecef;
197
- }}
198
  ul, ol {{
199
  padding-left: 30px;
200
  line-height: 1.8;
201
  }}
 
202
  li {{
203
- margin: 10px 0;
204
  }}
 
205
  table {{
206
  border-collapse: collapse;
207
  width: 100%;
208
  margin: 25px 0;
209
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
210
  }}
 
211
  th, td {{
212
  border: 1px solid #dee2e6;
213
  padding: 14px;
214
  text-align: left;
215
  }}
 
216
  th {{
217
  background-color: #f8f9fa;
218
  font-weight: 600;
219
  color: #495057;
220
  }}
 
221
  tr:nth-child(even) {{
222
  background-color: #f8f9fa;
223
  }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  .print-button {{
225
  background-color: #007bff;
226
  color: white;
@@ -235,31 +310,15 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
235
  font-weight: 500;
236
  transition: background-color 0.2s;
237
  }}
 
238
  .print-button:hover {{
239
  background-color: #0056b3;
240
  }}
241
 
242
- /* Math styling */
243
- mjx-container {{
244
- margin: 10px 0 !important;
245
- }}
246
-
247
- mjx-container[display="true"] {{
248
- margin: 20px 0 !important;
249
- }}
250
-
251
- /* Boxed answers */
252
- .boxed {{
253
- border: 2px solid #4CAF50;
254
- padding: 10px 15px;
255
- border-radius: 5px;
256
- display: inline-block;
257
- background-color: #f0f9f0;
258
- }}
259
-
260
  @media print {{
261
  body {{
262
  background-color: white;
 
263
  }}
264
  .container {{
265
  box-shadow: none;
@@ -275,15 +334,6 @@ def markdown_to_html(markdown_text, problem_text="", include_problem=True):
275
  function printPage() {{
276
  window.print();
277
  }}
278
-
279
- // Wait for MathJax to finish rendering before showing content
280
- window.addEventListener('load', function() {{
281
- if (window.MathJax) {{
282
- MathJax.startup.promise.then(function () {{
283
- console.log('MathJax rendering complete');
284
- }});
285
- }}
286
- }});
287
  </script>
288
  </head>
289
  <body>
@@ -332,26 +382,62 @@ def save_html_to_file(html_content, filename_prefix="math_solution"):
332
 
333
  return file_path
334
 
335
- # Function to convert HTML to PDF with proper math rendering
336
  def html_to_pdf(html_content, filename_prefix="math_solution"):
337
- """Convert HTML content to PDF and return the file path"""
338
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
339
  filename = f"{filename_prefix}_{timestamp}.pdf"
340
 
341
- # Create a temporary file for PDF
342
  temp_dir = tempfile.gettempdir()
343
  pdf_path = os.path.join(temp_dir, filename)
344
 
345
  try:
346
- # Note: WeasyPrint doesn't support MathJax rendering
347
- # For PDF with proper math, we need to use a different approach
348
- # This creates a basic PDF - for proper math rendering in PDF,
349
- # consider using tools like puppeteer or selenium with headless browser
350
- weasyprint.HTML(string=html_content).write_pdf(pdf_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  return pdf_path
352
  except Exception as e:
353
- print(f"Error converting to PDF: {str(e)}")
354
- return None
 
 
 
 
 
 
 
 
 
355
 
356
  # Enhanced function to generate math solution using OpenRouter with HTML output
357
  def generate_math_solution_openrouter(api_key, problem_text, history=None):
@@ -371,28 +457,37 @@ def generate_math_solution_openrouter(api_key, problem_text, history=None):
371
  {"role": "system", "content":
372
  """You are an expert math tutor who explains concepts clearly and thoroughly.
373
  Analyze the given math problem and provide a detailed step-by-step solution.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  For each step:
375
- 1. Show the mathematical operation using proper LaTeX notation wrapped in \\[ \\] for display math or \\( \\) for inline math
376
  2. Explain why this step is necessary
377
  3. Connect it to relevant mathematical concepts
378
 
379
- IMPORTANT: Use proper LaTeX notation for all mathematical expressions:
380
- - Use \\[ ... \\] for display (centered) equations
381
- - Use \\( ... \\) for inline math
382
- - Use \\boxed{} for final answers
383
- - Use \\text{} for text within math mode
384
- - Example: \\[ A = \\pi r^{2} \\]
385
- - Example: The area \\( A \\) equals \\( \\pi r^{2} \\)
386
 
387
- Format your response using markdown with clear section headers.
388
- Begin with an "Initial Analysis" section, follow with numbered steps,
389
- and conclude with a "Final Answer" section.
390
-
391
- Use proper markdown formatting including:
392
- - Headers (##, ###)
393
- - **Bold text** for important points
394
- - Lists and numbered steps
395
- - Tables if needed for comparisons or data"""},
396
  ]
397
 
398
  # Add conversation history if it exists
@@ -407,7 +502,7 @@ def generate_math_solution_openrouter(api_key, problem_text, history=None):
407
 
408
  # Create the completion
409
  completion = client.chat.completions.create(
410
- model="meta-llama/llama-3.3-70b-instruct:free",
411
  messages=messages,
412
  extra_headers={
413
  "HTTP-Referer": "https://advancedmathtutor.edu",
@@ -423,7 +518,7 @@ def generate_math_solution_openrouter(api_key, problem_text, history=None):
423
  # Save HTML file
424
  html_file_path = save_html_to_file(html_solution, "openrouter_solution")
425
 
426
- # Convert to PDF
427
  pdf_file_path = html_to_pdf(html_solution, "openrouter_solution")
428
 
429
  # Update history
@@ -454,28 +549,37 @@ def generate_math_solution_together(api_key, problem_text, image_path=None, hist
454
  "role": "system",
455
  "content": """You are an expert math tutor who explains concepts clearly and thoroughly.
456
  Analyze the given math problem and provide a detailed step-by-step solution.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  For each step:
458
- 1. Show the mathematical operation using proper LaTeX notation wrapped in \\[ \\] for display math or \\( \\) for inline math
459
  2. Explain why this step is necessary
460
  3. Connect it to relevant mathematical concepts
461
 
462
- IMPORTANT: Use proper LaTeX notation for all mathematical expressions:
463
- - Use \\[ ... \\] for display (centered) equations
464
- - Use \\( ... \\) for inline math
465
- - Use \\boxed{} for final answers
466
- - Use \\text{} for text within math mode
467
- - Example: \\[ A = \\pi r^{2} \\]
468
- - Example: The area \\( A \\) equals \\( \\pi r^{2} \\)
469
-
470
- Format your response using markdown with clear section headers.
471
- Begin with an "Initial Analysis" section, follow with numbered steps,
472
- and conclude with a "Final Answer" section.
473
 
474
- Use proper markdown formatting including:
475
- - Headers (##, ###)
476
- - **Bold text** for important points
477
- - Lists and numbered steps
478
- - Tables if needed for comparisons or data"""
479
  }
480
  ]
481
 
@@ -535,7 +639,7 @@ def generate_math_solution_together(api_key, problem_text, image_path=None, hist
535
  # Save HTML file
536
  html_file_path = save_html_to_file(html_solution, "together_solution")
537
 
538
- # Convert to PDF
539
  pdf_file_path = html_to_pdf(html_solution, "together_solution")
540
 
541
  # Update history
@@ -568,7 +672,7 @@ def create_demo():
568
  gr.Markdown("""
569
  This application provides step-by-step solutions to math problems using advanced AI models.
570
  Solutions are generated in **HTML format** with proper mathematical notation rendering using MathJax.
571
- Choose between OpenRouter or Together AI for problem solving.
572
  """)
573
 
574
  # Main tabs
@@ -592,7 +696,7 @@ def create_demo():
592
  ["Solve the quadratic equation: 3xΒ² + 5x - 2 = 0"],
593
  ["Find the derivative of f(x) = xΒ³ln(x)"],
594
  ["Calculate the area of a circle with radius 5 cm"],
595
- ["Find all values of x that satisfy: logβ‚‚(x-1) + logβ‚‚(x+3) = 5"]
596
  ],
597
  inputs=[text_problem_input],
598
  label="Example Problems"
@@ -610,7 +714,7 @@ def create_demo():
610
  visible=False
611
  )
612
  openrouter_pdf_download = gr.File(
613
- label="πŸ“„ Download PDF Solution",
614
  visible=False
615
  )
616
 
@@ -689,7 +793,7 @@ def create_demo():
689
  visible=False
690
  )
691
  together_pdf_download = gr.File(
692
- label="πŸ“„ Download PDF Solution",
693
  visible=False
694
  )
695
 
@@ -738,54 +842,42 @@ def create_demo():
738
  )
739
 
740
  # Help tab
741
- with gr.TabItem("Help"):
742
  gr.Markdown("""
743
- ## How to Use the Advanced Math Tutor
744
-
745
- ### Key Features πŸŽ‰
746
- - **Professional math rendering**: All equations rendered using MathJax/LaTeX
747
- - **HTML-formatted solutions**: Beautiful, readable format
748
- - **Download HTML**: Save solutions as HTML files with proper math notation
749
- - **Download PDF**: Convert solutions to PDF (Note: PDF math rendering may vary)
750
- - **Print functionality**: Print directly from your browser
751
-
752
- ### Getting Started
753
 
754
- #### For Text Problems (OpenRouter)
755
- 1. Get API key from [OpenRouter](https://openrouter.ai/)
756
- 2. Enter your problem in proper notation
757
- 3. Get beautifully formatted solutions with proper mathematical notation
758
 
759
- #### For Image Problems (Together AI)
760
- 1. Get API key from [Together AI](https://www.together.ai/)
761
- 2. Upload a clear image of the math problem
762
- 3. Optionally add context
763
 
764
- ### Math Notation Tips
765
- - Superscripts: xΒ² or x^2
766
- - Subscripts: x₁ or x_1
767
- - Fractions: Use / or describe as "numerator over denominator"
768
- - Greek letters: pi, alpha, beta, theta, etc.
769
- - Square roots: √ or sqrt()
770
 
771
- ### Types of Problems
772
- - Algebra, Calculus, Trigonometry
773
- - Geometry, Statistics
774
- - Number Theory, Linear Algebra
775
- - And much more!
 
 
 
 
 
 
 
 
 
 
 
 
776
 
777
- ### Note on PDF Export
778
- The HTML version will always have perfect math rendering. The PDF export uses
779
- WeasyPrint which may have limitations with complex math notation. For best results,
780
- use the "Print to PDF" button in the HTML view instead.
781
  """)
782
-
783
- gr.Markdown("""
784
- ---
785
- ### About
786
- Enhanced with **MathJax** for professional mathematical notation rendering.
787
- Your API keys are never stored permanently.
788
- """)
789
 
790
  return demo
791
 
 
10
  import markdown
11
  from datetime import datetime
12
  import tempfile
 
13
  from pathlib import Path
14
+ import subprocess
15
+ import sys
16
+
17
+ # Function to install playwright if not available
18
+ def ensure_playwright():
19
+ try:
20
+ from playwright.sync_api import sync_playwright
21
+ return True
22
+ except ImportError:
23
+ print("Installing playwright for PDF generation...")
24
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "playwright"])
25
+ subprocess.check_call([sys.executable, "-m", "playwright", "install", "chromium"])
26
+ from playwright.sync_api import sync_playwright
27
+ return True
28
 
29
  # Function to convert markdown to HTML with styling and MathJax
30
  def markdown_to_html(markdown_text, problem_text="", include_problem=True):
 
33
  # Convert markdown to HTML
34
  html_content = markdown.markdown(markdown_text, extensions=['tables', 'fenced_code'])
35
 
 
 
 
 
 
 
 
 
 
 
36
  # Get current timestamp
37
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
38
 
 
46
  <title>Math Solution - Advanced Math Tutor</title>
47
 
48
  <!-- MathJax for rendering mathematical notation -->
 
 
49
  <script>
50
  window.MathJax = {{
51
  tex: {{
52
+ inlineMath: [['\\\\(', '\\\\)'], ['$', '$']],
53
+ displayMath: [['\\\\[', '\\\\]'], ['$$', '$$']],
54
  processEscapes: true,
55
+ processEnvironments: true,
56
+ packages: {{'[+]': ['ams', 'newcommand', 'configmacros']}}
57
  }},
58
  options: {{
59
+ skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
60
+ ignoreHtmlClass: 'tex2jax_ignore',
61
+ processHtmlClass: 'tex2jax_process'
62
+ }},
63
+ startup: {{
64
+ ready: () => {{
65
+ MathJax.startup.defaultReady();
66
+ MathJax.startup.promise.then(() => {{
67
+ console.log('MathJax rendering complete');
68
+ document.body.classList.add('mathjax-ready');
69
+ }});
70
+ }}
71
  }}
72
  }};
73
  </script>
74
+ <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" id="MathJax-script" async></script>
75
 
76
  <style>
77
  body {{
78
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
79
  line-height: 1.8;
80
+ color: #1a1a1a;
81
  max-width: 900px;
82
  margin: 0 auto;
83
+ padding: 40px 20px;
84
  background-color: #f5f7fa;
85
  }}
86
+
87
+ body:not(.mathjax-ready) {{
88
+ opacity: 0;
89
+ }}
90
+
91
+ body.mathjax-ready {{
92
+ opacity: 1;
93
+ transition: opacity 0.3s ease-in;
94
+ }}
95
+
96
  .container {{
97
  background-color: white;
98
  padding: 50px;
99
  border-radius: 12px;
100
+ box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
101
  }}
102
+
103
  .header {{
104
  text-align: center;
105
  border-bottom: 4px solid #4CAF50;
106
  padding-bottom: 25px;
107
  margin-bottom: 40px;
108
  }}
109
+
110
  .header h1 {{
111
  color: #2c3e50;
112
  margin: 0;
113
  font-size: 2.8em;
114
  font-weight: 700;
115
  }}
116
+
117
  .header .subtitle {{
118
  color: #7f8c8d;
119
  font-style: italic;
120
  margin-top: 10px;
121
  font-size: 1.1em;
122
  }}
123
+
124
  .problem-section {{
125
  background-color: #e8f5e9;
126
  padding: 25px;
127
  border-radius: 10px;
128
  margin-bottom: 35px;
129
  border-left: 6px solid #4CAF50;
130
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
131
  }}
132
+
133
  .problem-section h2 {{
134
  color: #2c3e50;
135
  margin-top: 0;
136
  font-size: 1.6em;
137
  }}
138
+
139
  .problem-section p {{
140
+ font-size: 1.15em;
141
  line-height: 1.6;
142
+ margin: 10px 0;
143
  }}
144
+
145
  .solution-content {{
146
  background-color: #fafbfc;
147
+ padding: 35px;
148
  border-radius: 10px;
149
  border-left: 6px solid #007bff;
150
+ box-shadow: 0 2px 8px rgba(0,0,0,0.05);
151
  }}
152
+
153
  h1, h2, h3, h4, h5, h6 {{
154
  color: #2c3e50;
155
  margin-top: 30px;
156
  margin-bottom: 15px;
157
  font-weight: 600;
158
+ line-height: 1.3;
159
  }}
160
+
161
  h2 {{
162
  border-bottom: 2px solid #e1e4e8;
163
  padding-bottom: 12px;
164
  font-size: 1.8em;
165
  }}
166
+
167
  h3 {{
168
+ font-size: 1.5em;
169
  color: #34495e;
170
+ margin-top: 25px;
171
  }}
172
+
173
  h4 {{
174
+ font-size: 1.3em;
175
  color: #34495e;
176
  }}
177
+
178
+ p {{
179
+ margin: 15px 0;
180
+ line-height: 1.8;
181
+ }}
182
+
183
  code {{
184
  background-color: #f1f3f5;
185
  padding: 3px 8px;
 
188
  color: #e83e8c;
189
  font-size: 0.9em;
190
  }}
191
+
192
  pre {{
193
  background-color: #f6f8fa;
194
  padding: 20px;
 
197
  border: 1px solid #d1d5da;
198
  line-height: 1.6;
199
  }}
200
+
201
  pre code {{
202
  background-color: transparent;
203
  padding: 0;
204
  color: #24292e;
205
  }}
206
+
 
 
 
 
 
 
 
 
207
  .step {{
208
+ margin: 30px 0;
209
+ padding: 25px;
210
  background-color: #ffffff;
211
  border-radius: 8px;
212
  border: 1px solid #dee2e6;
213
+ box-shadow: 0 1px 4px rgba(0,0,0,0.05);
 
 
 
 
 
 
 
 
 
214
  }}
215
+
216
+ .step h3, .step h4 {{
217
+ color: #2c3e50;
218
  margin-top: 0;
219
  }}
220
+
 
 
 
 
 
 
 
221
  ul, ol {{
222
  padding-left: 30px;
223
  line-height: 1.8;
224
  }}
225
+
226
  li {{
227
+ margin: 12px 0;
228
  }}
229
+
230
  table {{
231
  border-collapse: collapse;
232
  width: 100%;
233
  margin: 25px 0;
234
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
235
  }}
236
+
237
  th, td {{
238
  border: 1px solid #dee2e6;
239
  padding: 14px;
240
  text-align: left;
241
  }}
242
+
243
  th {{
244
  background-color: #f8f9fa;
245
  font-weight: 600;
246
  color: #495057;
247
  }}
248
+
249
  tr:nth-child(even) {{
250
  background-color: #f8f9fa;
251
  }}
252
+
253
+ /* MathJax styling */
254
+ mjx-container {{
255
+ margin: 15px 0 !important;
256
+ overflow-x: auto;
257
+ overflow-y: hidden;
258
+ }}
259
+
260
+ mjx-container[display="true"] {{
261
+ margin: 25px 0 !important;
262
+ text-align: center;
263
+ }}
264
+
265
+ /* Ensure math displays properly */
266
+ .MathJax, .MathJax_Display {{
267
+ font-size: 1.1em !important;
268
+ }}
269
+
270
+ /* Final answer styling */
271
+ .final-answer {{
272
+ background-color: #d4edda;
273
+ border: 3px solid #28a745;
274
+ padding: 30px;
275
+ border-radius: 10px;
276
+ margin-top: 40px;
277
+ text-align: center;
278
+ }}
279
+
280
+ .final-answer h2, .final-answer h3 {{
281
+ color: #155724;
282
+ margin-top: 0;
283
+ margin-bottom: 20px;
284
+ }}
285
+
286
+ .final-answer mjx-container {{
287
+ font-size: 1.3em !important;
288
+ }}
289
+
290
+ .timestamp {{
291
+ text-align: right;
292
+ color: #6c757d;
293
+ font-size: 0.95em;
294
+ margin-top: 40px;
295
+ padding-top: 25px;
296
+ border-top: 2px solid #e9ecef;
297
+ }}
298
+
299
  .print-button {{
300
  background-color: #007bff;
301
  color: white;
 
310
  font-weight: 500;
311
  transition: background-color 0.2s;
312
  }}
313
+
314
  .print-button:hover {{
315
  background-color: #0056b3;
316
  }}
317
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  @media print {{
319
  body {{
320
  background-color: white;
321
+ padding: 20px;
322
  }}
323
  .container {{
324
  box-shadow: none;
 
334
  function printPage() {{
335
  window.print();
336
  }}
 
 
 
 
 
 
 
 
 
337
  </script>
338
  </head>
339
  <body>
 
382
 
383
  return file_path
384
 
385
+ # Function to convert HTML to PDF using Playwright (proper math rendering)
386
  def html_to_pdf(html_content, filename_prefix="math_solution"):
387
+ """Convert HTML content to PDF with proper MathJax rendering using Playwright"""
388
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
389
  filename = f"{filename_prefix}_{timestamp}.pdf"
390
 
 
391
  temp_dir = tempfile.gettempdir()
392
  pdf_path = os.path.join(temp_dir, filename)
393
 
394
  try:
395
+ # Ensure playwright is installed
396
+ ensure_playwright()
397
+ from playwright.sync_api import sync_playwright
398
+
399
+ with sync_playwright() as p:
400
+ # Launch browser
401
+ browser = p.chromium.launch(headless=True)
402
+ page = browser.new_page()
403
+
404
+ # Set content and wait for MathJax to render
405
+ page.set_content(html_content)
406
+
407
+ # Wait for MathJax to be ready
408
+ page.wait_for_selector('body.mathjax-ready', timeout=10000)
409
+
410
+ # Additional wait to ensure everything is rendered
411
+ page.wait_for_timeout(1000)
412
+
413
+ # Generate PDF
414
+ page.pdf(
415
+ path=pdf_path,
416
+ format='A4',
417
+ margin={
418
+ 'top': '20mm',
419
+ 'right': '20mm',
420
+ 'bottom': '20mm',
421
+ 'left': '20mm'
422
+ },
423
+ print_background=True
424
+ )
425
+
426
+ browser.close()
427
+
428
  return pdf_path
429
  except Exception as e:
430
+ print(f"Error converting to PDF with Playwright: {str(e)}")
431
+ print("Falling back to basic PDF generation...")
432
+
433
+ # Fallback to weasyprint if playwright fails
434
+ try:
435
+ import weasyprint
436
+ weasyprint.HTML(string=html_content).write_pdf(pdf_path)
437
+ return pdf_path
438
+ except Exception as e2:
439
+ print(f"Error with fallback PDF generation: {str(e2)}")
440
+ return None
441
 
442
  # Enhanced function to generate math solution using OpenRouter with HTML output
443
  def generate_math_solution_openrouter(api_key, problem_text, history=None):
 
457
  {"role": "system", "content":
458
  """You are an expert math tutor who explains concepts clearly and thoroughly.
459
  Analyze the given math problem and provide a detailed step-by-step solution.
460
+
461
+ CRITICAL: Use PROPER LaTeX notation for ALL mathematical expressions:
462
+ - Use \\[ ... \\] for display (centered) equations
463
+ - Use \\( ... \\) for inline math within text
464
+ - Use \\boxed{...} for final answers
465
+ - Use \\frac{numerator}{denominator} for fractions
466
+ - Use ^ for superscripts: x^2
467
+ - Use _ for subscripts: x_1
468
+ - Use \\cdot for multiplication
469
+ - Use \\pm for plus-minus
470
+ - Use \\sqrt{...} for square roots
471
+ - Greek letters: \\pi, \\alpha, \\beta, \\theta, etc.
472
+
473
+ EXAMPLES:
474
+ - Display equation: \\[ ax^2 + bx + c = 0 \\]
475
+ - Inline math: The quadratic formula \\( x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a} \\) gives us...
476
+ - Final answer: \\[ \\boxed{x = \\frac{1}{3}} \\]
477
+
478
  For each step:
479
+ 1. Show the mathematical operation in LaTeX
480
  2. Explain why this step is necessary
481
  3. Connect it to relevant mathematical concepts
482
 
483
+ Format your response using markdown with clear section headers:
484
+ - ## Initial Analysis
485
+ - ## Step-by-Step Solution
486
+ - ### Step 1: [description]
487
+ - ### Step 2: [description]
488
+ - ## Final Answer
 
489
 
490
+ Use **bold** for important points and proper lists."""},
 
 
 
 
 
 
 
 
491
  ]
492
 
493
  # Add conversation history if it exists
 
502
 
503
  # Create the completion
504
  completion = client.chat.completions.create(
505
+ model="deepseek/deepseek-r1-0528:free",
506
  messages=messages,
507
  extra_headers={
508
  "HTTP-Referer": "https://advancedmathtutor.edu",
 
518
  # Save HTML file
519
  html_file_path = save_html_to_file(html_solution, "openrouter_solution")
520
 
521
+ # Convert to PDF with proper math rendering
522
  pdf_file_path = html_to_pdf(html_solution, "openrouter_solution")
523
 
524
  # Update history
 
549
  "role": "system",
550
  "content": """You are an expert math tutor who explains concepts clearly and thoroughly.
551
  Analyze the given math problem and provide a detailed step-by-step solution.
552
+
553
+ CRITICAL: Use PROPER LaTeX notation for ALL mathematical expressions:
554
+ - Use \\[ ... \\] for display (centered) equations
555
+ - Use \\( ... \\) for inline math within text
556
+ - Use \\boxed{...} for final answers
557
+ - Use \\frac{numerator}{denominator} for fractions
558
+ - Use ^ for superscripts: x^2
559
+ - Use _ for subscripts: x_1
560
+ - Use \\cdot for multiplication
561
+ - Use \\pm for plus-minus
562
+ - Use \\sqrt{...} for square roots
563
+ - Greek letters: \\pi, \\alpha, \\beta, \\theta, etc.
564
+
565
+ EXAMPLES:
566
+ - Display equation: \\[ ax^2 + bx + c = 0 \\]
567
+ - Inline math: The quadratic formula \\( x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a} \\) gives us...
568
+ - Final answer: \\[ \\boxed{x = \\frac{1}{3}} \\]
569
+
570
  For each step:
571
+ 1. Show the mathematical operation in LaTeX
572
  2. Explain why this step is necessary
573
  3. Connect it to relevant mathematical concepts
574
 
575
+ Format your response using markdown with clear section headers:
576
+ - ## Initial Analysis
577
+ - ## Step-by-Step Solution
578
+ - ### Step 1: [description]
579
+ - ### Step 2: [description]
580
+ - ## Final Answer
 
 
 
 
 
581
 
582
+ Use **bold** for important points and proper lists."""
 
 
 
 
583
  }
584
  ]
585
 
 
639
  # Save HTML file
640
  html_file_path = save_html_to_file(html_solution, "together_solution")
641
 
642
+ # Convert to PDF with proper math rendering
643
  pdf_file_path = html_to_pdf(html_solution, "together_solution")
644
 
645
  # Update history
 
672
  gr.Markdown("""
673
  This application provides step-by-step solutions to math problems using advanced AI models.
674
  Solutions are generated in **HTML format** with proper mathematical notation rendering using MathJax.
675
+ **PDFs are generated using headless browser** for perfect math rendering!
676
  """)
677
 
678
  # Main tabs
 
696
  ["Solve the quadratic equation: 3xΒ² + 5x - 2 = 0"],
697
  ["Find the derivative of f(x) = xΒ³ln(x)"],
698
  ["Calculate the area of a circle with radius 5 cm"],
699
+ ["Integrate: ∫(2x + 3)dx from 0 to 5"]
700
  ],
701
  inputs=[text_problem_input],
702
  label="Example Problems"
 
714
  visible=False
715
  )
716
  openrouter_pdf_download = gr.File(
717
+ label="πŸ“„ Download PDF Solution (Perfect Math Rendering)",
718
  visible=False
719
  )
720
 
 
793
  visible=False
794
  )
795
  together_pdf_download = gr.File(
796
+ label="πŸ“„ Download PDF Solution (Perfect Math Rendering)",
797
  visible=False
798
  )
799
 
 
842
  )
843
 
844
  # Help tab
845
+ with gr.TabItem("Help & Installation"):
846
  gr.Markdown("""
847
+ ## Installation Instructions
 
 
 
 
 
 
 
 
 
848
 
849
+ This application requires the following packages:
 
 
 
850
 
851
+ ```bash
852
+ pip install gradio openai together pillow markdown playwright
853
+ python -m playwright install chromium
854
+ ```
855
 
856
+ **Note:** Playwright is used for PDF generation with perfect math rendering!
 
 
 
 
 
857
 
858
+ ## Key Features πŸŽ‰
859
+ - βœ… **Perfect math rendering** in both HTML and PDF using MathJax
860
+ - βœ… **HTML-formatted solutions** with professional styling
861
+ - βœ… **Download HTML**: Save solutions as HTML files
862
+ - βœ… **Download PDF**: PDFs with properly rendered mathematical notation (using headless browser)
863
+ - βœ… **Print functionality**: Print or save directly to PDF from browser
864
+ - βœ… **Image-to-Math capability** (via Together AI)
865
+ - βœ… **Conversation memory** β€” keeps context of your previous problems
866
+ - βœ… **Cross-model support** β€” OpenRouter and Together AI models
867
+
868
+ ## Troubleshooting 🧩
869
+ - If **PDF export fails**, ensure Playwright and Chromium are installed:
870
+ ```bash
871
+ python -m playwright install chromium
872
+ ```
873
+ - If **math symbols do not render**, reload the HTML file in a modern browser (MathJax will re-render).
874
+ - If **you get API errors**, verify your API key is valid and has active quota.
875
 
876
+ ## Usage Tips πŸ’‘
877
+ - For **OpenRouter**, use an API key starting with `sk-or-`.
878
+ - For **Together AI**, use your standard API key from [https://api.together.ai](https://api.together.ai).
879
+ - You can **copy and share** generated HTML or PDF solutions.
880
  """)
 
 
 
 
 
 
 
881
 
882
  return demo
883