atz21 commited on
Commit
45f3df3
·
verified ·
1 Parent(s): 6fb7138

back to main

Browse files
Files changed (1) hide show
  1. app.py +33 -236
app.py CHANGED
@@ -633,241 +633,38 @@ 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
- # ---------------- 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
- with gr.Row():
684
- with gr.Column():
685
- qp_files = gr.File(
686
- label="📄 Upload Question Papers (PDF)",
687
- file_count="multiple",
688
- file_types=[".pdf"]
689
- )
690
- with gr.Column():
691
- ms_files = gr.File(
692
- label="📋 Upload Markschemes (PDF)",
693
- file_count="multiple",
694
- file_types=[".pdf"]
695
- )
696
- with gr.Column():
697
- ans_files = gr.File(
698
- label="📝 Upload Answer Sheets (PDF)",
699
- file_count="multiple",
700
- file_types=[".pdf"]
701
- )
702
-
703
- imprint_all = gr.Checkbox(label="✍ Imprint Marks on All Answer Sheets", value=False)
704
-
705
- with gr.Row():
706
- start_grading_btn = gr.Button("🚀 Start Mass Grading", variant="primary", size="lg")
707
-
708
- # Status and results
709
- status_info = gr.Markdown("", visible=False)
710
- status_table = gr.Dataframe(
711
- headers=["Set", "QP File", "MS File", "Answer Sheet", "Status"],
712
- datatype=["number", "str", "str", "str", "str"],
713
- label="📊 Grading Progress",
714
- visible=False
715
- )
716
-
717
- results_section = gr.Column(visible=False)
718
- with results_section:
719
- gr.Markdown("## 📥 Download Results")
720
- results_container = gr.Column()
721
-
722
- def create_triplets_from_files(qp_list, ms_list, ans_list, imprint_setting):
723
- """Create triplets from uploaded file lists."""
724
- if not qp_list or not ms_list or not ans_list:
725
- return []
726
-
727
- # Convert single files to lists
728
- if not isinstance(qp_list, list):
729
- qp_list = [qp_list] if qp_list else []
730
- if not isinstance(ms_list, list):
731
- ms_list = [ms_list] if ms_list else []
732
- if not isinstance(ans_list, list):
733
- ans_list = [ans_list] if ans_list else []
734
-
735
- # Create triplets by matching files by index
736
- triplets = []
737
- max_files = max(len(qp_list), len(ms_list), len(ans_list))
738
-
739
- for i in range(max_files):
740
- qp_file = qp_list[i].name if i < len(qp_list) else None
741
- ms_file = ms_list[i].name if i < len(ms_list) else None
742
- ans_file = ans_list[i].name if i < len(ans_list) else None
743
-
744
- # Only create triplet if all three files are present
745
- if qp_file and ms_file and ans_file:
746
- triplets.append({
747
- "qp_file": qp_file,
748
- "ms_file": ms_file,
749
- "ans_file": ans_file,
750
- "imprint": imprint_setting
751
- })
752
-
753
- return triplets
754
-
755
- def update_status_display(qp_list, ms_list, ans_list):
756
- """Update the status display showing file matching."""
757
- if not qp_list and not ms_list and not ans_list:
758
- return gr.update(visible=False), gr.update(visible=False, value=[])
759
-
760
- # Convert single files to lists
761
- if not isinstance(qp_list, list):
762
- qp_list = [qp_list] if qp_list else []
763
- if not isinstance(ms_list, list):
764
- ms_list = [ms_list] if ms_list else []
765
- if not isinstance(ans_list, list):
766
- ans_list = [ans_list] if ans_list else []
767
-
768
- max_files = max(len(qp_list), len(ms_list), len(ans_list))
769
-
770
- if max_files == 0:
771
- return gr.update(visible=False), gr.update(visible=False, value=[])
772
-
773
- # Create status info
774
- complete_sets = 0
775
- table_data = []
776
-
777
- for i in range(max_files):
778
- qp_name = os.path.basename(qp_list[i].name) if i < len(qp_list) else "❌ Missing"
779
- ms_name = os.path.basename(ms_list[i].name) if i < len(ms_list) else "❌ Missing"
780
- ans_name = os.path.basename(ans_list[i].name) if i < len(ans_list) else "❌ Missing"
781
-
782
- # Determine status
783
- if i < len(qp_list) and i < len(ms_list) and i < len(ans_list):
784
- status = "✅ Ready"
785
- complete_sets += 1
786
- else:
787
- status = "⏳ Incomplete"
788
-
789
- table_data.append([i + 1, qp_name, ms_name, ans_name, status])
790
-
791
- status_text = f"**📊 File Summary:** {complete_sets} complete set(s) ready for grading out of {max_files} total."
792
-
793
- return (
794
- gr.update(visible=True, value=status_text),
795
- gr.update(visible=True, value=table_data)
796
- )
797
-
798
- def process_mass_grading(qp_list, ms_list, ans_list, imprint_setting):
799
- """Process all complete triplets."""
800
- triplets = create_triplets_from_files(qp_list, ms_list, ans_list, imprint_setting)
801
-
802
- if not triplets:
803
- return (
804
- gr.update(value="❌ No complete sets found. Please ensure each set has QP, MS, and AS files."),
805
- gr.update(visible=False),
806
- gr.update(visible=False)
807
- )
808
-
809
- # Update status to show processing
810
- table_data = []
811
- for i, triplet in enumerate(triplets):
812
- table_data.append([
813
- i + 1,
814
- os.path.basename(triplet["qp_file"]),
815
- os.path.basename(triplet["ms_file"]),
816
- os.path.basename(triplet["ans_file"]),
817
- "🔄 Processing..."
818
- ])
819
-
820
- # Process each triplet
821
- results = []
822
- result_components = []
823
-
824
- for i, triplet in enumerate(triplets):
825
- print(f"\n🔄 Processing Set {i + 1}/{len(triplets)}")
826
-
827
- try:
828
- result = process_single_triplet(triplet, i)
829
- results.append(result)
830
-
831
- # Update table status
832
- table_data[i][4] = result["status"]
833
-
834
- # Create download components
835
- if result["grading_pdf"]:
836
- result_components.append(
837
- gr.File(value=result["grading_pdf"], label=f"📄 Set {i+1} - Grading PDF", visible=True)
838
- )
839
- if result["imprinted_pdf"]:
840
- result_components.append(
841
- gr.File(value=result["imprinted_pdf"], label=f"✍️ Set {i+1} - Imprinted PDF", visible=True)
842
- )
843
-
844
- except Exception as e:
845
- print(f"❌ Error processing set {i + 1}: {e}")
846
- table_data[i][4] = f"❌ Error: {str(e)[:30]}..."
847
-
848
- # Final status
849
- successful = len([r for r in results if r.get("status") == "✅ Complete"])
850
- status_text = f"**🏁 Processing Complete:** {successful}/{len(triplets)} sets processed successfully."
851
-
852
- return (
853
- gr.update(value=status_text),
854
- gr.update(value=table_data),
855
- gr.update(visible=True)
856
- )
857
-
858
- # Event handlers
859
- for file_input in [qp_files, ms_files, ans_files]:
860
- file_input.change(
861
- fn=update_status_display,
862
- inputs=[qp_files, ms_files, ans_files],
863
- outputs=[status_info, status_table]
864
- )
865
-
866
- start_grading_btn.click(
867
- fn=process_mass_grading,
868
- inputs=[qp_files, ms_files, ans_files, imprint_all],
869
- outputs=[status_info, status_table, results_section]
870
- )
871
 
872
- if __name__ == "__main__":
873
  demo.launch()
 
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()