rayhan13ads commited on
Commit
fce9eea
·
verified ·
1 Parent(s): bbebaf9

create app.py

Browse files
Files changed (1) hide show
  1. app.py +891 -0
app.py ADDED
@@ -0,0 +1,891 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+
4
+
5
+
6
+ import os
7
+
8
+
9
+ import re
10
+
11
+
12
+ import time
13
+
14
+
15
+ import base64
16
+
17
+
18
+ from openai import OpenAI
19
+
20
+
21
+ from together import Together
22
+
23
+
24
+ from PIL import Image
25
+
26
+
27
+ import io
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+ def generate_math_solution_openrouter(api_key, problem_text, history=None):
36
+
37
+
38
+ if not api_key.strip():
39
+
40
+
41
+ return "Please enter your OpenRouter API key.", history
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+ if not problem_text.strip():
50
+
51
+
52
+ return "Please enter a math problem.", history
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+ try:
61
+
62
+
63
+ client=OpenAI(
64
+
65
+
66
+ base_url="https://openrouter.ai/api/v1",
67
+
68
+
69
+ api_key=api_key
70
+
71
+
72
+ )
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+ messages= [
81
+
82
+
83
+ {"role": "system", "content":
84
+
85
+
86
+ """You are an expert math tutor who explains concepts clearly and thoroughly.
87
+
88
+
89
+ Analyze the given math problem and provide a detailed step-by-step solution.
90
+
91
+
92
+ For each step:
93
+
94
+
95
+ 1. Show the mathematical operation
96
+
97
+
98
+ 2. Explain why this step is necessary
99
+
100
+
101
+ 3. Connect it to relevant mathematical concepts
102
+
103
+
104
+
105
+
106
+
107
+ Format your response with clear section headers using markdown.
108
+
109
+
110
+ Begin with an "Initial Analysis" section, follow with numbered steps,
111
+
112
+
113
+ and conclude with a "Final Answer" section."""},
114
+
115
+
116
+ ]
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+ if history:
125
+
126
+
127
+ for exchange in history:
128
+
129
+
130
+ messages.append({"role": "user", "content": exchange[0]}) # asking a math prob solution
131
+
132
+
133
+ if exchange[1]: # Check if there's a response
134
+
135
+
136
+ messages.append({"role": "assistant", "content": exchange[1]}) # getting the step by step solution of asked math prob
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+ # Add the current problem
145
+
146
+
147
+ messages.append({"role": "user", "content": f"Solve this math problem step-by-step: {problem_text}"}) # what is 2+2? = problem_text
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+ # calling the model
156
+
157
+
158
+ completion=client.chat.completions.create(
159
+
160
+
161
+ model="microsoft/phi-4-reasoning-plus:free",
162
+
163
+
164
+ messages=messages,
165
+
166
+
167
+ extra_headers={
168
+
169
+
170
+ "HTTP-Referer": "https://advancedmathtutor.edu",
171
+
172
+
173
+ "X-Title": "Advanced Math Tutor",
174
+
175
+
176
+ }
177
+
178
+
179
+ )
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+ solution=completion.choices[0].message.content # finally you are getting solution of math prob here
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+ # Update history
196
+
197
+
198
+ if history is None:
199
+
200
+
201
+ history = []
202
+
203
+
204
+ history.append((problem_text, solution)) # user: what is 2+2? => LLM: 4
205
+
206
+
207
+
208
+
209
+
210
+ return solution, history
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+ except Exception as e:
219
+
220
+
221
+ error_message = f"Error: {str(e)}"
222
+
223
+
224
+ return error_message, history
225
+
226
+
227
+
228
+
229
+
230
+ # Function to convert image to base64
231
+
232
+
233
+ def image_to_base64(image_path):
234
+
235
+
236
+ if image_path is None:
237
+
238
+
239
+ return None
240
+
241
+
242
+
243
+
244
+
245
+ try:
246
+
247
+
248
+ with open(image_path, "rb") as img_file:
249
+
250
+
251
+ return base64.b64encode(img_file.read()).decode("utf-8")
252
+
253
+
254
+ except Exception as e:
255
+
256
+
257
+ print(f"Error converting image to base64: {str(e)}")
258
+
259
+
260
+ return None
261
+
262
+
263
+
264
+
265
+
266
+
267
+
268
+ # Function to generate math solution using Together AI with support for images
269
+
270
+
271
+ def generate_math_solution_together(api_key, problem_text, image_path=None, history=None):
272
+
273
+
274
+ if not api_key.strip():
275
+
276
+
277
+ return "Please enter your Together AI API key.", history
278
+
279
+
280
+
281
+
282
+
283
+ if not problem_text.strip() and image_path is None:
284
+
285
+
286
+ return "Please enter a math problem or upload an image of a math problem.", history
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+ try:
295
+
296
+
297
+ client=Together(api_key=api_key)
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+ messages= [
306
+
307
+
308
+ {
309
+
310
+
311
+ "role": "system",
312
+
313
+
314
+ "content": """You are an expert math tutor who explains concepts clearly and thoroughly.
315
+
316
+
317
+ Analyze the given math problem and provide a detailed step-by-step solution.
318
+
319
+
320
+ For each step:
321
+
322
+
323
+ 1. Show the mathematical operation
324
+
325
+
326
+ 2. Explain why this step is necessary
327
+
328
+
329
+ 3. Connect it to relevant mathematical concepts
330
+
331
+
332
+
333
+
334
+
335
+ Format your response with clear section headers using markdown.
336
+
337
+
338
+ Begin with an "Initial Analysis" section, follow with numbered steps,
339
+
340
+
341
+ and conclude with a "Final Answer" section."""
342
+
343
+
344
+ }
345
+
346
+
347
+ ]
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+ # Add conversation history if it exists
356
+
357
+
358
+ if history:
359
+
360
+
361
+ for exchange in history:
362
+
363
+
364
+ messages.append({"role": "user", "content": exchange[0]})
365
+
366
+
367
+ if exchange[1]: # Check if there's a response
368
+
369
+
370
+ messages.append({"role": "assistant", "content": exchange[1]})
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+ # Prepare the user message content # image upload + text details to help solve the problem in image
379
+
380
+
381
+ user_message_content = []
382
+
383
+
384
+
385
+
386
+
387
+
388
+
389
+ # Add text content if provided #extra info provided # image of 2+2=? + pls show detailed explanation
390
+
391
+
392
+ if problem_text.strip():
393
+
394
+
395
+ user_message_content.append({
396
+
397
+
398
+ "type": "text",
399
+
400
+
401
+ "text": f"Solve this math problem: {problem_text}"
402
+
403
+
404
+ })
405
+
406
+
407
+ else:
408
+
409
+
410
+ user_message_content.append({ #no extra info
411
+
412
+
413
+ "type": "text",
414
+
415
+
416
+ "text": "Solve this math problem from the image:" # image of 2+2=?
417
+
418
+
419
+ })
420
+
421
+
422
+
423
+
424
+
425
+
426
+
427
+ # Add image if provided
428
+
429
+
430
+ if image_path:
431
+
432
+
433
+ # Convert image to base64
434
+
435
+
436
+ base64_image = image_to_base64(image_path)
437
+
438
+
439
+ if base64_image:
440
+
441
+
442
+ user_message_content.append({
443
+
444
+
445
+ "type": "image_url", #together url format for img support in case of image models
446
+
447
+
448
+ "image_url": {
449
+
450
+
451
+ "url": f"data:image/jpeg;base64,{base64_image}"
452
+
453
+
454
+ }
455
+
456
+
457
+ })
458
+
459
+
460
+
461
+
462
+
463
+
464
+
465
+ # Add the user message with content
466
+
467
+
468
+ messages.append({
469
+
470
+
471
+ "role": "user",
472
+
473
+
474
+ "content": user_message_content
475
+
476
+
477
+ })
478
+
479
+
480
+
481
+
482
+
483
+ # Create the completion /calling the model
484
+
485
+
486
+ response = client.chat.completions.create(
487
+
488
+
489
+ model="meta-llama/Llama-Vision-Free",
490
+
491
+
492
+ messages=messages,
493
+
494
+
495
+ stream=False
496
+
497
+
498
+ )
499
+
500
+
501
+
502
+
503
+
504
+ solution = response.choices[0].message.content
505
+
506
+
507
+
508
+
509
+
510
+ # Update history - for simplicity, just store the text problem
511
+
512
+
513
+ if history is None:
514
+
515
+
516
+ history = []
517
+
518
+
519
+ history.append((problem_text if problem_text.strip() else "Image problem", solution))
520
+
521
+
522
+
523
+
524
+
525
+ return solution, history
526
+
527
+
528
+
529
+
530
+
531
+ except Exception as e:
532
+
533
+
534
+ error_message = f"Error: {str(e)}"
535
+
536
+
537
+ return error_message, history
538
+
539
+
540
+
541
+
542
+
543
+ ### what the gradio website interface will look like? answer korbo
544
+
545
+
546
+
547
+
548
+
549
+
550
+
551
+ def create_demo():
552
+
553
+
554
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
555
+
556
+
557
+ gr.Markdown("# 📚 Advanced Math Tutor")
558
+
559
+
560
+ gr.Markdown("""
561
+
562
+
563
+ This application provides step-by-step solutions to math problems using advanced AI models.
564
+
565
+
566
+ Choose between OpenRouter's Phi-4-reasoning-plus for text-based problems or Together AI's
567
+
568
+
569
+ Llama-Vision for problems with images.
570
+
571
+
572
+ """)
573
+
574
+
575
+
576
+
577
+
578
+
579
+
580
+ ### pages/tabs = 2 tabs
581
+
582
+
583
+
584
+
585
+
586
+
587
+
588
+ with gr.Tabs():
589
+
590
+
591
+ # Text-based problem solver (OpenRouter)
592
+
593
+
594
+ with gr.TabItem("Text Problem Solver (OpenRouter)/PHI"):
595
+
596
+
597
+ with gr.Row():
598
+
599
+
600
+ with gr.Column(scale=1):
601
+
602
+
603
+ openrouter_api_key = gr.Textbox(
604
+
605
+
606
+ label="OpenRouter API Key",
607
+
608
+
609
+ placeholder="Enter your OpenRouter API key (starts with sk-or-)",
610
+
611
+
612
+ type="password"
613
+
614
+
615
+ )
616
+
617
+
618
+ text_problem_input = gr.Textbox(
619
+
620
+
621
+ label="Math Problem",
622
+
623
+
624
+ placeholder="Enter your math problem here...",
625
+
626
+
627
+ lines=5
628
+
629
+
630
+ )
631
+
632
+
633
+ example_problems = gr.Examples(
634
+
635
+
636
+ examples=[
637
+
638
+
639
+ ["Solve the quadratic equation: 3x² + 5x - 2 = 0"],
640
+
641
+
642
+ ["Find the derivative of f(x) = x³ln(x)"],
643
+
644
+
645
+ ["Calculate the area of a circle with radius 5 cm"],
646
+
647
+
648
+ ["Find all values of x that satisfy the equation: log₂(x-1) + log₂(x+3) = 5"]
649
+
650
+
651
+ ],
652
+
653
+
654
+ inputs=[text_problem_input],
655
+
656
+
657
+ label="Example Problems"
658
+
659
+
660
+ )
661
+
662
+
663
+ with gr.Row():
664
+
665
+
666
+ openrouter_submit_btn = gr.Button("Solve Problem", variant="primary")
667
+
668
+
669
+ openrouter_clear_btn = gr.Button("Clear")
670
+
671
+
672
+
673
+
674
+
675
+
676
+
677
+ with gr.Column(scale=2):
678
+
679
+
680
+ openrouter_solution_output = gr.Markdown(label="Solution")
681
+
682
+
683
+
684
+
685
+
686
+
687
+
688
+ # Store conversation history (invisible to user)
689
+
690
+
691
+ openrouter_conversation_history = gr.State(value=None)
692
+
693
+
694
+
695
+
696
+
697
+ # Button actions
698
+
699
+
700
+ openrouter_submit_btn.click(
701
+
702
+
703
+ fn=generate_math_solution_openrouter,
704
+
705
+
706
+ inputs=[openrouter_api_key, text_problem_input, openrouter_conversation_history],
707
+
708
+
709
+ outputs=[openrouter_solution_output, openrouter_conversation_history]
710
+
711
+
712
+ )
713
+
714
+
715
+
716
+
717
+
718
+ openrouter_clear_btn.click(
719
+
720
+
721
+ fn=lambda: ("", None),
722
+
723
+
724
+ inputs=[],
725
+
726
+
727
+ outputs=[openrouter_solution_output, openrouter_conversation_history]
728
+
729
+
730
+ )
731
+
732
+
733
+
734
+
735
+
736
+
737
+
738
+
739
+
740
+
741
+ # Image-based problem solver (Together AI)
742
+
743
+
744
+ with gr.TabItem("Image Problem Solver (Together AI)"):
745
+
746
+
747
+ with gr.Row():
748
+
749
+
750
+ with gr.Column(scale=1):
751
+
752
+
753
+ together_api_key = gr.Textbox(
754
+
755
+
756
+ label="Together AI API Key",
757
+
758
+
759
+ placeholder="Enter your Together AI API key",
760
+
761
+
762
+ type="password"
763
+
764
+
765
+ )
766
+
767
+
768
+ together_problem_input = gr.Textbox(
769
+
770
+
771
+ label="Problem Description (Optional)",
772
+
773
+
774
+ placeholder="Enter additional context for the image problem...",
775
+
776
+
777
+ lines=3
778
+
779
+
780
+ )
781
+
782
+
783
+ together_image_input = gr.Image(
784
+
785
+
786
+ label="Upload Math Problem Image",
787
+
788
+
789
+ type="filepath"
790
+
791
+
792
+ )
793
+
794
+
795
+ with gr.Row():
796
+
797
+
798
+ together_submit_btn = gr.Button("Solve Problem", variant="primary")
799
+
800
+
801
+ together_clear_btn = gr.Button("Clear")
802
+
803
+
804
+
805
+
806
+
807
+ with gr.Column(scale=2):
808
+
809
+
810
+ together_solution_output = gr.Markdown(label="Solution")
811
+
812
+
813
+
814
+
815
+
816
+ # Store conversation history (invisible to user)
817
+
818
+
819
+ together_conversation_history = gr.State(value=None)
820
+
821
+
822
+
823
+
824
+
825
+ # Button actions
826
+
827
+
828
+ together_submit_btn.click(
829
+
830
+
831
+ fn=generate_math_solution_together,
832
+
833
+
834
+ inputs=[together_api_key, together_problem_input, together_image_input, together_conversation_history],
835
+
836
+
837
+ outputs=[together_solution_output, together_conversation_history]
838
+
839
+
840
+ )
841
+
842
+
843
+
844
+
845
+
846
+ together_clear_btn.click(
847
+
848
+
849
+ fn=lambda: ("", None),
850
+
851
+
852
+ inputs=[],
853
+
854
+
855
+ outputs=[together_solution_output, together_conversation_history]
856
+
857
+
858
+ )
859
+
860
+
861
+
862
+
863
+
864
+
865
+
866
+ return demo
867
+
868
+
869
+
870
+
871
+
872
+
873
+
874
+ ### launch the app
875
+
876
+
877
+
878
+
879
+
880
+
881
+
882
+ if __name__ == "__main__":
883
+
884
+
885
+ demo=create_demo()
886
+
887
+
888
+ demo.launch()
889
+
890
+
891
+