atz21 commited on
Commit
1696b58
Β·
verified Β·
1 Parent(s): a85f94d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +245 -33
app.py CHANGED
@@ -633,38 +633,250 @@ def align_and_grade_pipeline(qp_path, ms_path, ans_path, imprint=False):
633
  print("❌ Pipeline error:", e)
634
  return f"❌ Error: {e}", None, None, None, None
635
 
636
- # ---------------- GRADIO UI ----------------
637
- with gr.Blocks(title=" AI Grading (Final Flow )") as demo:
638
- gr.Markdown("## πŸ“˜ AI Grading β€” Final Flow")
639
-
640
- with gr.Row():
641
- qp_file = gr.File(label="πŸ“„ Upload Question Paper (PDF)")
642
- ms_file = gr.File(label="πŸ“„ Upload Markscheme (PDF)")
643
- ans_file = gr.File(label="πŸ“ Upload Student Answer Sheet (PDF)")
644
-
645
- imprint_toggle = gr.Checkbox(label="✍ Imprint Marks on Student Answer Sheet", value=False)
646
- run_button = gr.Button("πŸš€ Run Pipeline")
647
-
648
- with gr.Row():
649
- grading_pdf_file = gr.File(label="πŸ“₯ Download Grading PDF")
650
- imprint_pdf_file = gr.File(label="πŸ“₯ Download Imprinted PDF (Optional)")
651
-
652
- def run_pipeline(qp_file_obj, ms_file_obj, ans_file_obj, imprint_flag):
653
- qp_path = qp_file_obj.name
654
- ms_path = ms_file_obj.name
655
- ans_path = ans_file_obj.name
656
-
657
- qpms_text, as_text, grading_text, grading_pdf_path, imprinted_pdf_path = align_and_grade_pipeline(
658
- qp_path, ms_path, ans_path, imprint=imprint_flag
659
- )
660
-
661
- return grading_pdf_path, imprinted_pdf_path
662
-
663
- run_button.click(
664
- fn=run_pipeline,
665
- inputs=[qp_file, ms_file, ans_file, imprint_toggle],
666
- outputs=[grading_pdf_file, imprint_pdf_file]
667
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
 
669
- if __name__ == "__main__":
670
  demo.launch()
 
633
  print("❌ Pipeline error:", e)
634
  return f"❌ Error: {e}", None, None, None, None
635
 
636
+ # ---------------- MASS GRADING HELPERS ----------------
637
+ def process_single_triplet(triplet_data, triplet_index):
638
+ """Process a single QP+MS+AS triplet and return results."""
639
+ try:
640
+ qp_path = triplet_data["qp_file"]
641
+ ms_path = triplet_data["ms_file"]
642
+ ans_path = triplet_data["ans_file"]
643
+ imprint_flag = triplet_data["imprint"]
644
+
645
+ print(f"πŸ”„ Processing triplet {triplet_index + 1}: {os.path.basename(ans_path)}")
646
+
647
+ qpms_text, as_text, grading_text, grading_pdf_path, imprinted_pdf_path = align_and_grade_pipeline(
648
+ qp_path, ms_path, ans_path, imprint=imprint_flag
649
+ )
650
+
651
+ return {
652
+ "triplet_index": triplet_index,
653
+ "status": "βœ… Complete",
654
+ "grading_pdf": grading_pdf_path,
655
+ "imprinted_pdf": imprinted_pdf_path if imprint_flag else None,
656
+ "error": None
657
+ }
658
+ except Exception as e:
659
+ print(f"❌ Error processing triplet {triplet_index + 1}: {e}")
660
+ return {
661
+ "triplet_index": triplet_index,
662
+ "status": f"❌ Error: {str(e)[:50]}...",
663
+ "grading_pdf": None,
664
+ "imprinted_pdf": None,
665
+ "error": str(e)
666
+ }
667
+
668
+ def process_all_triplets(triplets_data):
669
+ """Process all triplets sequentially and return results."""
670
+ results = []
671
+ for i, triplet in enumerate(triplets_data):
672
+ if triplet["qp_file"] and triplet["ms_file"] and triplet["ans_file"]:
673
+ result = process_single_triplet(triplet, i)
674
+ results.append(result)
675
+ yield results # Yield intermediate results for progress updates
676
+ return results
677
+
678
+ # ---------------- GRADIO UI ----------------
679
+ with gr.Blocks(title="πŸŽ“ AI Mass Grading System", theme=gr.themes.Soft()) as demo:
680
+ gr.Markdown("# πŸŽ“ AI Mass Grading System")
681
+ gr.Markdown("Upload multiple sets of Question Papers, Markschemes, and Answer Sheets for batch processing.")
682
+
683
+ # State to store triplets
684
+ triplets_state = gr.State([])
685
+
686
+ # Dynamic triplet container
687
+ triplets_container = gr.Column()
688
+
689
+ # Add triplet button
690
+ with gr.Row():
691
+ add_triplet_btn = gr.Button("βž• Add New Triplet", variant="secondary")
692
+ start_grading_btn = gr.Button("πŸš€ Start Mass Grading", variant="primary", visible=False)
693
+
694
+ # Status table
695
+ status_table = gr.Dataframe(
696
+ headers=["Set", "QP File", "MS File", "Answer Sheets", "Status"],
697
+ datatype=["number", "str", "str", "str", "str"],
698
+ label="πŸ“Š Grading Status",
699
+ visible=False
700
+ )
701
+
702
+ # Results section
703
+ results_section = gr.Column(visible=False)
704
+ with results_section:
705
+ gr.Markdown("## πŸ“₯ Download Results")
706
+ results_files = gr.Column()
707
+
708
+ def create_triplet_row(triplet_index):
709
+ """Create a new triplet upload row."""
710
+ with gr.Row() as row:
711
+ with gr.Column(scale=2):
712
+ qp_file = gr.File(label=f"πŸ“„ QP {triplet_index + 1}", file_types=[".pdf"])
713
+ with gr.Column(scale=2):
714
+ ms_file = gr.File(label=f"πŸ“‹ MS {triplet_index + 1}", file_types=[".pdf"])
715
+ with gr.Column(scale=2):
716
+ ans_file = gr.File(label=f"πŸ“ AS {triplet_index + 1}", file_types=[".pdf"])
717
+ with gr.Column(scale=1):
718
+ imprint_check = gr.Checkbox(label="βœ… Imprint", value=False)
719
+ with gr.Column(scale=1):
720
+ remove_btn = gr.Button("πŸ—‘οΈ", variant="stop", size="sm")
721
+
722
+ return row, qp_file, ms_file, ans_file, imprint_check, remove_btn
723
+
724
+ def add_triplet(current_triplets):
725
+ """Add a new triplet to the list."""
726
+ new_triplet = {
727
+ "qp_file": None,
728
+ "ms_file": None,
729
+ "ans_file": None,
730
+ "imprint": False
731
+ }
732
+ current_triplets.append(new_triplet)
733
+ return current_triplets, gr.update(visible=len(current_triplets) > 0)
734
+
735
+ def update_status_table(triplets):
736
+ """Update the status table with current triplets."""
737
+ if not triplets:
738
+ return gr.update(visible=False, value=[])
739
+
740
+ table_data = []
741
+ for i, triplet in enumerate(triplets):
742
+ qp_name = os.path.basename(triplet["qp_file"]) if triplet["qp_file"] else "Not uploaded"
743
+ ms_name = os.path.basename(triplet["ms_file"]) if triplet["ms_file"] else "Not uploaded"
744
+ ans_name = os.path.basename(triplet["ans_file"]) if triplet["ans_file"] else "Not uploaded"
745
+
746
+ # Determine status
747
+ if triplet["qp_file"] and triplet["ms_file"] and triplet["ans_file"]:
748
+ status = "πŸ“‹ Ready"
749
+ else:
750
+ status = "⏳ Pending uploads"
751
+
752
+ table_data.append([i + 1, qp_name, ms_name, ans_name, status])
753
+
754
+ return gr.update(visible=True, value=table_data)
755
+
756
+ def start_mass_grading(triplets):
757
+ """Start processing all triplets."""
758
+ if not triplets:
759
+ return gr.update(), gr.update(visible=False)
760
+
761
+ # Filter only complete triplets
762
+ complete_triplets = [t for t in triplets if t["qp_file"] and t["ms_file"] and t["ans_file"]]
763
+
764
+ if not complete_triplets:
765
+ return gr.update(value=[["No complete triplets to process"]]), gr.update(visible=False)
766
+
767
+ # Process triplets and update table progressively
768
+ results = []
769
+ table_data = []
770
+
771
+ for i, triplet in enumerate(complete_triplets):
772
+ # Update status to processing
773
+ table_row = [
774
+ i + 1,
775
+ os.path.basename(triplet["qp_file"]),
776
+ os.path.basename(triplet["ms_file"]),
777
+ os.path.basename(triplet["ans_file"]),
778
+ "πŸ”„ Processing..."
779
+ ]
780
+ table_data.append(table_row)
781
+
782
+ # Process the triplet
783
+ result = process_single_triplet(triplet, i)
784
+ results.append(result)
785
+
786
+ # Update status
787
+ table_data[i][4] = result["status"]
788
+
789
+ # Create download links
790
+ download_components = []
791
+ for i, result in enumerate(results):
792
+ if result["grading_pdf"]:
793
+ download_components.append(
794
+ gr.File(value=result["grading_pdf"], label=f"πŸ“„ Set {i+1} - Grading PDF", visible=True)
795
+ )
796
+ if result["imprinted_pdf"]:
797
+ download_components.append(
798
+ gr.File(value=result["imprinted_pdf"], label=f"✍️ Set {i+1} - Imprinted PDF", visible=True)
799
+ )
800
+
801
+ return gr.update(value=table_data), gr.update(visible=True)
802
+
803
+ # Event handlers
804
+ add_triplet_btn.click(
805
+ fn=add_triplet,
806
+ inputs=[triplets_state],
807
+ outputs=[triplets_state, start_grading_btn]
808
+ ).then(
809
+ fn=update_status_table,
810
+ inputs=[triplets_state],
811
+ outputs=[status_table]
812
+ )
813
+
814
+ # File upload handlers to update triplets state
815
+ def create_file_update_handler(triplet_idx, file_type):
816
+ def update_triplet_file(file_obj, current_triplets):
817
+ if triplet_idx < len(current_triplets):
818
+ current_triplets[triplet_idx][file_type] = file_obj.name if file_obj else None
819
+ return current_triplets
820
+ return update_triplet_file
821
+
822
+ def create_imprint_update_handler(triplet_idx):
823
+ def update_triplet_imprint(imprint_val, current_triplets):
824
+ if triplet_idx < len(current_triplets):
825
+ current_triplets[triplet_idx]["imprint"] = imprint_val
826
+ return current_triplets
827
+ return update_triplet_imprint
828
+
829
+ # Dynamic UI management
830
+ @gr.render(inputs=[triplets_state])
831
+ def render_triplets(triplets):
832
+ if not triplets:
833
+ return
834
+
835
+ for i in range(len(triplets)):
836
+ row, qp_file, ms_file, ans_file, imprint_check, remove_btn = create_triplet_row(i)
837
+
838
+ # Set up file upload handlers
839
+ qp_file.change(
840
+ fn=create_file_update_handler(i, "qp_file"),
841
+ inputs=[qp_file, triplets_state],
842
+ outputs=[triplets_state]
843
+ ).then(
844
+ fn=update_status_table,
845
+ inputs=[triplets_state],
846
+ outputs=[status_table]
847
+ )
848
+
849
+ ms_file.change(
850
+ fn=create_file_update_handler(i, "ms_file"),
851
+ inputs=[ms_file, triplets_state],
852
+ outputs=[triplets_state]
853
+ ).then(
854
+ fn=update_status_table,
855
+ inputs=[triplets_state],
856
+ outputs=[status_table]
857
+ )
858
+
859
+ ans_file.change(
860
+ fn=create_file_update_handler(i, "ans_file"),
861
+ inputs=[ans_file, triplets_state],
862
+ outputs=[triplets_state]
863
+ ).then(
864
+ fn=update_status_table,
865
+ inputs=[triplets_state],
866
+ outputs=[status_table]
867
+ )
868
+
869
+ imprint_check.change(
870
+ fn=create_imprint_update_handler(i),
871
+ inputs=[imprint_check, triplets_state],
872
+ outputs=[triplets_state]
873
+ )
874
+
875
+ start_grading_btn.click(
876
+ fn=start_mass_grading,
877
+ inputs=[triplets_state],
878
+ outputs=[status_table, results_section]
879
+ )
880
 
881
+ if __name__ == "__main__":
882
  demo.launch()