Spaces:
Sleeping
Sleeping
Fix tab switching bug - move all tabs inside gr.Tabs() container
Browse files
app.py
CHANGED
|
@@ -816,160 +816,160 @@ with gr.Blocks(title="AnatomyBot - MBBS Anatomy Tutor") as demo:
|
|
| 816 |
image_output = gr.Image(label="πΌοΈ Anatomy Diagram", type="pil")
|
| 817 |
|
| 818 |
# VIVA MODE TAB (Defined before Book Mode to allow component access)
|
| 819 |
-
|
| 820 |
-
|
| 821 |
|
| 822 |
-
|
| 823 |
-
|
| 824 |
|
| 825 |
-
|
| 826 |
-
|
| 827 |
-
|
| 828 |
-
|
| 829 |
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
|
| 834 |
-
|
| 835 |
-
|
| 836 |
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
|
| 843 |
-
|
| 844 |
|
| 845 |
-
|
| 846 |
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
|
| 858 |
-
|
| 859 |
-
|
| 860 |
|
| 861 |
-
|
| 862 |
-
|
| 863 |
|
| 864 |
-
|
| 865 |
-
|
| 866 |
|
| 867 |
-
|
| 868 |
-
|
| 869 |
|
| 870 |
-
|
| 871 |
-
|
| 872 |
-
|
| 873 |
-
|
| 874 |
-
|
| 875 |
-
|
| 876 |
|
| 877 |
-
|
| 878 |
-
|
| 879 |
-
|
| 880 |
-
|
| 881 |
|
| 882 |
-
|
| 883 |
-
|
| 884 |
-
|
| 885 |
|
| 886 |
-
|
| 887 |
-
|
| 888 |
-
|
| 889 |
-
|
| 890 |
-
|
| 891 |
|
| 892 |
-
|
| 893 |
-
|
| 894 |
-
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
| 899 |
-
|
| 900 |
-
|
| 901 |
|
| 902 |
-
|
| 903 |
-
|
| 904 |
|
| 905 |
-
|
| 906 |
|
| 907 |
-
|
| 908 |
-
|
| 909 |
|
| 910 |
-
|
| 911 |
|
| 912 |
-
|
| 913 |
-
|
| 914 |
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
|
| 920 |
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
| 930 |
-
|
| 931 |
-
|
| 932 |
-
|
| 933 |
-
|
| 934 |
-
|
| 935 |
-
|
| 936 |
-
|
| 937 |
-
|
| 938 |
-
|
| 939 |
|
| 940 |
-
|
| 941 |
-
|
| 942 |
-
|
| 943 |
-
|
| 944 |
|
| 945 |
-
|
| 946 |
-
|
| 947 |
-
|
| 948 |
-
|
| 949 |
-
|
| 950 |
-
|
| 951 |
-
|
| 952 |
-
|
| 953 |
-
|
| 954 |
|
| 955 |
-
|
| 956 |
|
| 957 |
-
|
| 958 |
-
|
| 959 |
-
|
| 960 |
|
| 961 |
-
|
| 962 |
|
| 963 |
-
|
| 964 |
-
|
| 965 |
-
|
| 966 |
|
| 967 |
-
|
| 968 |
-
|
| 969 |
-
|
| 970 |
-
|
| 971 |
-
|
| 972 |
-
|
| 973 |
|
| 974 |
|
| 975 |
|
|
|
|
| 816 |
image_output = gr.Image(label="πΌοΈ Anatomy Diagram", type="pil")
|
| 817 |
|
| 818 |
# VIVA MODE TAB (Defined before Book Mode to allow component access)
|
| 819 |
+
with gr.Tab("π― VIVA Training Mode") as viva_tab:
|
| 820 |
+
viva_status = gr.Markdown("Click 'Start VIVA Training' from Learning Mode after studying a topic!")
|
| 821 |
|
| 822 |
+
# Additional greeting component (initially hidden)
|
| 823 |
+
viva_greeting = gr.Markdown("", visible=False)
|
| 824 |
|
| 825 |
+
with gr.Column(visible=False) as viva_container:
|
| 826 |
+
with gr.Row():
|
| 827 |
+
with gr.Column(scale=1):
|
| 828 |
+
viva_image = gr.Image(label="Reference Image", type="pil", interactive=False)
|
| 829 |
|
| 830 |
+
with gr.Column(scale=2):
|
| 831 |
+
current_question_display = gr.Markdown("### Question will appear here")
|
| 832 |
+
hint_display = gr.Markdown("π‘ Hint will appear here")
|
| 833 |
|
| 834 |
+
# Audio player for question
|
| 835 |
+
question_audio = gr.Audio(label="π Listen to Question", autoplay=True, interactive=False)
|
| 836 |
|
| 837 |
+
student_answer = gr.Textbox(
|
| 838 |
+
label="Your Answer",
|
| 839 |
+
placeholder="Type your answer here...",
|
| 840 |
+
lines=4
|
| 841 |
+
)
|
| 842 |
|
| 843 |
+
submit_answer_btn = gr.Button("Submit Answer", variant="primary")
|
| 844 |
|
| 845 |
+
feedback_display = gr.Markdown("Feedback will appear here after you submit your answer")
|
| 846 |
|
| 847 |
+
# BOOK LEARNING MODE TAB
|
| 848 |
+
with gr.Tab("π Book Learning Mode") as book_tab:
|
| 849 |
+
# Upload PDF
|
| 850 |
+
pdf_upload = gr.File(label="Upload Anatomy Textbook (PDF)", file_types=[".pdf"], type="binary")
|
| 851 |
+
upload_status = gr.Markdown()
|
| 852 |
|
| 853 |
+
# State to hold extracted images, captions, and text
|
| 854 |
+
book_images_state = gr.State([])
|
| 855 |
+
page_captions_state = gr.State([])
|
| 856 |
+
page_texts_state = gr.State([])
|
| 857 |
|
| 858 |
+
# Dropdown to select a page after processing
|
| 859 |
+
page_dropdown = gr.Dropdown(label="Select Page", choices=[], interactive=False)
|
| 860 |
|
| 861 |
+
# Display selected page image
|
| 862 |
+
selected_page_image = gr.Image(label="Selected Page", type="pil")
|
| 863 |
|
| 864 |
+
# Analysis output
|
| 865 |
+
analysis_output = gr.Markdown(label="Page Analysis")
|
| 866 |
|
| 867 |
+
# Button to start VIVA from this page
|
| 868 |
+
start_viva_book_btn = gr.Button("π― Start VIVA Training from this Page", variant="primary", visible=False)
|
| 869 |
|
| 870 |
+
# Process upload
|
| 871 |
+
def handle_book_upload(pdf_bytes):
|
| 872 |
+
extracted_data, status_msg = process_uploaded_book(pdf_bytes)
|
| 873 |
+
if not extracted_data:
|
| 874 |
+
# No data extracted
|
| 875 |
+
return [], status_msg, [], [], gr.update(choices=[], interactive=False), None, ""
|
| 876 |
|
| 877 |
+
# Separate images, captions, and text
|
| 878 |
+
img_list = [item[0] for item in extracted_data]
|
| 879 |
+
caps = [item[1] for item in extracted_data]
|
| 880 |
+
texts = [item[2] for item in extracted_data]
|
| 881 |
|
| 882 |
+
# Update dropdown with captions and enable it
|
| 883 |
+
dropdown_update = gr.update(choices=caps, interactive=True)
|
| 884 |
+
return img_list, status_msg, caps, texts, dropdown_update, None, ""
|
| 885 |
|
| 886 |
+
pdf_upload.upload(
|
| 887 |
+
fn=handle_book_upload,
|
| 888 |
+
inputs=[pdf_upload],
|
| 889 |
+
outputs=[book_images_state, upload_status, page_captions_state, page_texts_state, page_dropdown, selected_page_image, analysis_output]
|
| 890 |
+
)
|
| 891 |
|
| 892 |
+
# When a page is selected, show image and analysis
|
| 893 |
+
def show_page_analysis(selected_caption, images, captions, texts):
|
| 894 |
+
if not selected_caption:
|
| 895 |
+
return None, ""
|
| 896 |
+
# Find index
|
| 897 |
+
try:
|
| 898 |
+
idx = captions.index(selected_caption)
|
| 899 |
+
except ValueError:
|
| 900 |
+
return None, ""
|
| 901 |
|
| 902 |
+
img = images[idx]
|
| 903 |
+
text = texts[idx] if idx < len(texts) else ""
|
| 904 |
|
| 905 |
+
analysis = analyze_book_image(img, selected_caption, text)
|
| 906 |
|
| 907 |
+
# Construct a topic string for VIVA
|
| 908 |
+
viva_topic = f"Anatomy of {selected_caption} (from textbook)"
|
| 909 |
|
| 910 |
+
return img, analysis, viva_topic, gr.update(visible=True)
|
| 911 |
|
| 912 |
+
# Hidden state to store current page topic for VIVA
|
| 913 |
+
current_book_topic = gr.State("")
|
| 914 |
|
| 915 |
+
page_dropdown.change(
|
| 916 |
+
fn=show_page_analysis,
|
| 917 |
+
inputs=[page_dropdown, book_images_state, page_captions_state, page_texts_state],
|
| 918 |
+
outputs=[selected_page_image, analysis_output, current_book_topic, start_viva_book_btn]
|
| 919 |
+
)
|
| 920 |
|
| 921 |
+
# Start VIVA from Book Mode - Use pre-collected name
|
| 922 |
+
start_viva_book_btn.click(
|
| 923 |
+
fn=lambda name, topic, image: start_viva_with_name(name, topic, image),
|
| 924 |
+
inputs=[student_name_state, current_book_topic, selected_page_image],
|
| 925 |
+
outputs=[
|
| 926 |
+
viva_container, viva_status, viva_image,
|
| 927 |
+
current_question_display, hint_display,
|
| 928 |
+
student_answer, feedback_display, submit_answer_btn,
|
| 929 |
+
viva_questions_state,
|
| 930 |
+
question_audio, viva_greeting, student_name_state
|
| 931 |
+
]
|
| 932 |
+
).then(
|
| 933 |
+
fn=lambda: gr.update(selected=1), # Switch to VIVA tab
|
| 934 |
+
outputs=[tabs]
|
| 935 |
+
).then(
|
| 936 |
+
fn=lambda: 0,
|
| 937 |
+
outputs=[current_question_idx]
|
| 938 |
+
)
|
| 939 |
|
| 940 |
+
# ADMIN PANEL TAB
|
| 941 |
+
with gr.Tab("π Admin Panel") as admin_tab:
|
| 942 |
+
gr.Markdown("## Admin Panel - Student Database")
|
| 943 |
+
gr.Markdown("Enter the admin password to view registered students.")
|
| 944 |
|
| 945 |
+
# Password input
|
| 946 |
+
with gr.Row():
|
| 947 |
+
admin_password_input = gr.Textbox(
|
| 948 |
+
label="Admin Password",
|
| 949 |
+
placeholder="Enter admin password",
|
| 950 |
+
type="password",
|
| 951 |
+
scale=2
|
| 952 |
+
)
|
| 953 |
+
admin_login_btn = gr.Button("π Login", variant="primary", scale=1)
|
| 954 |
|
| 955 |
+
admin_status = gr.Markdown("")
|
| 956 |
|
| 957 |
+
# Admin content (hidden until authenticated)
|
| 958 |
+
with gr.Column(visible=False) as admin_content:
|
| 959 |
+
gr.Markdown("### π Registered Students")
|
| 960 |
|
| 961 |
+
admin_stats = gr.Markdown("")
|
| 962 |
|
| 963 |
+
with gr.Row():
|
| 964 |
+
refresh_btn = gr.Button("π Refresh Data", variant="secondary")
|
| 965 |
+
logout_btn = gr.Button("πͺ Logout", variant="secondary")
|
| 966 |
|
| 967 |
+
students_table = gr.Dataframe(
|
| 968 |
+
headers=["ID", "Name", "Medical School", "Year", "Registration Date"],
|
| 969 |
+
label="Students Database",
|
| 970 |
+
interactive=False,
|
| 971 |
+
wrap=True
|
| 972 |
+
)
|
| 973 |
|
| 974 |
|
| 975 |
|