gladguy commited on
Commit
5992639
ยท
1 Parent(s): 0d1b188

Add Book Learning mode with PDF upload and analysis

Browse files
Files changed (1) hide show
  1. app.py +170 -21
app.py CHANGED
@@ -4,6 +4,9 @@ import os
4
  from dotenv import load_dotenv
5
  from io import BytesIO
6
  from PIL import Image
 
 
 
7
 
8
  # Load environment variables
9
  load_dotenv()
@@ -368,6 +371,120 @@ def process_anatomy_query(query: str) -> tuple:
368
  return image, info, error_message
369
 
370
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  # VIVA Mode Handler Functions
372
  def start_viva_mode(topic, image):
373
  """Initialize VIVA mode with questions."""
@@ -501,28 +618,60 @@ with gr.Blocks(title="AnatomyBot - MBBS Anatomy Tutor") as demo:
501
  with gr.Column(scale=1):
502
  image_output = gr.Image(label="๐Ÿ–ผ๏ธ Anatomy Diagram", type="pil")
503
 
504
- # VIVA MODE TAB
505
- with gr.Tab("๐ŸŽฏ VIVA Training Mode") as viva_tab:
506
- viva_status = gr.Markdown("Click 'Start VIVA Training' from Learning Mode after studying a topic!")
 
 
 
 
 
 
507
 
508
- with gr.Column(visible=False) as viva_container:
509
- with gr.Row():
510
- with gr.Column(scale=1):
511
- viva_image = gr.Image(label="Reference Image", type="pil", interactive=False)
512
-
513
- with gr.Column(scale=2):
514
- current_question_display = gr.Markdown("### Question will appear here")
515
- hint_display = gr.Markdown("๐Ÿ’ก Hint will appear here")
516
-
517
- student_answer = gr.Textbox(
518
- label="Your Answer",
519
- placeholder="Type your answer here...",
520
- lines=4
521
- )
522
-
523
- submit_answer_btn = gr.Button("Submit Answer", variant="primary")
524
-
525
- feedback_display = gr.Markdown("Feedback will appear here after you submit your answer")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
 
527
  # Event handlers for Learning Mode
528
  def handle_query(query):
 
4
  from dotenv import load_dotenv
5
  from io import BytesIO
6
  from PIL import Image
7
+ import PyPDF2
8
+ from pdf2image import convert_from_path
9
+ import tempfile
10
 
11
  # Load environment variables
12
  load_dotenv()
 
371
  return image, info, error_message
372
 
373
 
374
+ # Book Learning Mode Functions
375
+ def process_uploaded_book(pdf_file):
376
+ """
377
+ Process uploaded PDF book and extract first 20 pages with images.
378
+ Returns (list_of_images, status_message)
379
+ """
380
+ if pdf_file is None:
381
+ return [], "Please upload a PDF file."
382
+
383
+ try:
384
+ extracted_images = []
385
+
386
+ # Save uploaded file temporarily
387
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file:
388
+ tmp_file.write(pdf_file)
389
+ tmp_path = tmp_file.name
390
+
391
+ try:
392
+ # Convert first 20 pages to images
393
+ pages = convert_from_path(tmp_path, first_page=1, last_page=20, dpi=150)
394
+
395
+ for i, page in enumerate(pages):
396
+ extracted_images.append((page, f"Page {i+1}"))
397
+
398
+ status = f"โœ… Successfully processed {len(extracted_images)} pages from your anatomy textbook!"
399
+ return extracted_images, status
400
+
401
+ finally:
402
+ # Clean up temp file
403
+ if os.path.exists(tmp_path):
404
+ os.unlink(tmp_path)
405
+
406
+ except Exception as e:
407
+ return [], f"โš ๏ธ Error processing PDF: {str(e)}"
408
+
409
+
410
+ def analyze_book_image(image, page_info):
411
+ """
412
+ Analyze selected image from book using AI to extract anatomical information.
413
+ Returns formatted explanation text.
414
+ """
415
+ if image is None:
416
+ return "Please select an image from the book."
417
+
418
+ try:
419
+ # For now, we'll use the Hyperbolic API to analyze what might be in the image
420
+ # In a production version, you'd use vision models or OCR
421
+
422
+ headers = {
423
+ "Content-Type": "application/json",
424
+ "Authorization": f"Bearer {HYPERBOLIC_API_KEY}"
425
+ }
426
+
427
+ prompt = f"""You are an anatomy professor helping MBBS students learn from their textbook.
428
+
429
+ A student is looking at {page_info} which contains an anatomical diagram or illustration.
430
+
431
+ Provide a comprehensive explanation that would typically accompany anatomical images in medical textbooks:
432
+
433
+ ## ๐Ÿ“– Anatomical Structure Overview
434
+
435
+ [Explain what anatomical structure is likely shown]
436
+
437
+ ## ๐Ÿ” Key Features to Observe
438
+
439
+ - [Feature 1 - what students should look for in the diagram]
440
+ - [Feature 2]
441
+ - [Feature 3]
442
+ - [Feature 4]
443
+
444
+ ## ๐Ÿฅ Clinical Relevance
445
+
446
+ - [Clinical point 1]
447
+ - [Clinical point 2]
448
+
449
+ ## ๐Ÿ’ก Study Tips
450
+
451
+ [How to effectively study this diagram/structure]
452
+
453
+ ## โ“ Self-Test Questions
454
+
455
+ 1. [Question about identification]
456
+ 2. [Question about function/relationship]
457
+ 3. [Question about clinical application]
458
+
459
+ Be thorough and educational, as if explaining a textbook figure."""
460
+
461
+ payload = {
462
+ "model": HYPERBOLIC_MODEL,
463
+ "messages": [{"role": "user", "content": prompt}],
464
+ "max_tokens": 800,
465
+ "temperature": 0.7
466
+ }
467
+
468
+ response = requests.post(HYPERBOLIC_API_URL, headers=headers, json=payload, timeout=25)
469
+ response.raise_for_status()
470
+
471
+ result = response.json()
472
+ explanation = result["choices"][0]["message"]["content"]
473
+
474
+ formatted_output = f"""# ๐Ÿ“š Textbook Page Analysis: {page_info}
475
+
476
+ {explanation}
477
+
478
+ ---
479
+
480
+ ๐Ÿ’ช **Next Steps:** After studying this page, you can test your knowledge in VIVA mode!"""
481
+
482
+ return formatted_output
483
+
484
+ except Exception as e:
485
+ return f"โš ๏ธ Error analyzing image: {str(e)}"
486
+
487
+
488
  # VIVA Mode Handler Functions
489
  def start_viva_mode(topic, image):
490
  """Initialize VIVA mode with questions."""
 
618
  with gr.Column(scale=1):
619
  image_output = gr.Image(label="๐Ÿ–ผ๏ธ Anatomy Diagram", type="pil")
620
 
621
+ # BOOK LEARNING MODE TAB
622
+ with gr.Tab("๐Ÿ“– Book Learning Mode") as book_tab:
623
+ # Upload PDF
624
+ pdf_upload = gr.File(label="Upload Anatomy Textbook (PDF)", file_types=[".pdf"], type="bytes")
625
+ upload_status = gr.Markdown()
626
+
627
+ # State to hold extracted images and captions
628
+ book_images_state = gr.State([])
629
+ page_captions_state = gr.State([])
630
 
631
+ # Dropdown to select a page after processing
632
+ page_dropdown = gr.Dropdown(label="Select Page", choices=[], interactive=False)
633
+
634
+ # Display selected page image
635
+ selected_page_image = gr.Image(label="Selected Page", type="pil")
636
+
637
+ # Analysis output
638
+ analysis_output = gr.Markdown(label="Page Analysis")
639
+
640
+ # Process upload
641
+ def handle_book_upload(pdf_bytes):
642
+ images, status_msg = process_uploaded_book(pdf_bytes)
643
+ if not images:
644
+ # No images extracted
645
+ return [], status_msg, [], gr.update(choices=[], interactive=False), None, ""
646
+ # Separate images and captions
647
+ img_list = [img for img, cap in images]
648
+ caps = [cap for img, cap in images]
649
+ # Update dropdown with captions and enable it
650
+ dropdown_update = gr.update(choices=caps, interactive=True)
651
+ return img_list, status_msg, caps, dropdown_update, None, ""
652
+
653
+ pdf_upload.upload(
654
+ fn=handle_book_upload,
655
+ inputs=[pdf_upload],
656
+ outputs=[book_images_state, upload_status, page_captions_state, page_dropdown, selected_page_image, analysis_output]
657
+ )
658
+
659
+ # When a page is selected, show image and analysis
660
+ def show_page_analysis(selected_caption, images, captions):
661
+ if not selected_caption:
662
+ return None, ""
663
+ # Find index
664
+ try:
665
+ idx = captions.index(selected_caption)
666
+ except ValueError:
667
+ return None, ""
668
+ img = images[idx]
669
+ analysis = analyze_book_image(img, selected_caption)
670
+ return img, analysis
671
+
672
+ page_dropdown.change(fn=show_page_analysis, inputs=[page_dropdown, book_images_state, page_captions_state], outputs=[selected_page_image, analysis_output])
673
+
674
+
675
 
676
  # Event handlers for Learning Mode
677
  def handle_query(query):