codeboosterstech commited on
Commit
d5d3f1f
·
verified ·
1 Parent(s): 9c343fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -233
app.py CHANGED
@@ -1,242 +1,105 @@
1
- """
2
- Main Gradio application optimized for Hugging Face Spaces
3
- """
4
-
5
- import gradio as gr
6
  import os
7
  import tempfile
8
- import json
9
- from multi_agent import MultiAgentSystem
10
- from docx_builder import generate_all_documents
11
 
12
- # Initialize the multi-agent system
13
- agent_system = MultiAgentSystem()
 
 
 
 
 
14
 
15
- def generate_exam_package(subject, stream, part_a_count, part_b_count, part_c_count, syllabus_file, reference_file):
16
- """Main function called by Gradio interface"""
17
-
18
- try:
19
- # Convert counts to integers
20
- part_a_count = int(part_a_count) if part_a_count else 5
21
- part_b_count = int(part_b_count) if part_b_count else 5
22
- part_c_count = int(part_c_count) if part_c_count else 1
23
-
24
- # Validate inputs
25
- if not subject or not syllabus_file:
26
- return None, None, None, "❌ Please provide subject name and syllabus PDF"
27
-
28
- # Generate exam package
29
- final_output, status = agent_system.generate_exam_package(
30
- subject=subject,
31
- stream=stream,
32
- part_a_count=part_a_count,
33
- part_b_count=part_b_count,
34
- part_c_count=part_c_count,
35
- syllabus_file=syllabus_file,
36
- reference_file=reference_file
37
- )
38
-
39
- if status != "Success":
40
- return None, None, None, f"❌ {status}"
41
-
42
- # Create temporary directory for outputs
43
- with tempfile.TemporaryDirectory() as temp_dir:
44
- # Generate DOCX files
45
- files = generate_all_documents(final_output, subject, stream, temp_dir)
46
-
47
- # Return file paths
48
- return files["question_paper"], files["answer_key"], files["obe_summary"], "✅ Generation completed successfully!"
49
-
50
- except Exception as e:
51
- error_msg = f"❌ Error: {str(e)}"
52
- print(error_msg)
53
- return None, None, None, error_msg
54
-
55
- def update_progress_ui():
56
- """Update progress in UI"""
57
- progress = agent_system.get_progress()
58
- return f"🔄 {progress['stage'].upper()}: {progress['message']} ({progress['percentage']}%)"
59
-
60
- def validate_inputs(subject, part_a_count, part_b_count, part_c_count):
61
- """Validate user inputs"""
62
- errors = []
63
- if not subject:
64
- errors.append("Subject name is required")
65
-
66
  try:
67
- if part_a_count and int(part_a_count) <= 0:
68
- errors.append("Part A count must be positive")
69
- if part_b_count and int(part_b_count) <= 0:
70
- errors.append("Part B count must be positive")
71
- if part_c_count and int(part_c_count) <= 0:
72
- errors.append("Part C count must be positive")
73
  except:
74
- errors.append("Question counts must be numbers")
75
-
76
- return errors
77
-
78
- # Gradio interface
79
- with gr.Blocks(title="AI Exam Generator", theme=gr.themes.Soft()) as demo:
80
- gr.Markdown("""
81
- # 🚀 AI-Powered Question Paper Generator
82
- *Generate complete exam packages with OBE compliance using multi-agent AI system*
83
- """)
84
-
85
- with gr.Row():
86
- with gr.Column(scale=1):
87
- # Input section
88
- gr.Markdown("### 📝 Exam Configuration")
89
-
90
- subject_name = gr.Textbox(
91
- label="Subject Name",
92
- placeholder="e.g., Data Structures, Algorithms, Database Systems",
93
- value="Data Structures"
94
- )
95
-
96
- stream = gr.Dropdown(
97
- choices=["CSE", "Non-CSE"],
98
- label="Engineering Stream",
99
- value="CSE",
100
- info="CSE: Company tags | Non-CSE: GATE patterns"
101
- )
102
-
103
- with gr.Row():
104
- part_a_count = gr.Number(
105
- label="Part A Questions",
106
- value=5,
107
- minimum=1,
108
- maximum=20,
109
- info="2 marks each"
110
- )
111
-
112
- part_b_count = gr.Number(
113
- label="Part B Questions",
114
- value=5,
115
- minimum=1,
116
- maximum=10,
117
- info="13 marks each"
118
- )
119
-
120
- part_c_count = gr.Number(
121
- label="Part C Questions",
122
- value=1,
123
- minimum=1,
124
- maximum=3,
125
- info="14 marks each"
126
- )
127
-
128
- syllabus_pdf = gr.File(
129
- label="Upload Syllabus PDF",
130
- file_types=[".pdf"],
131
- type="filepath",
132
- file_count="single"
133
- )
134
-
135
- reference_qp = gr.File(
136
- label="Reference Question Paper (Optional)",
137
- file_types=[".pdf"],
138
- type="filepath",
139
- file_count="single"
140
- )
141
-
142
- generate_btn = gr.Button("🎯 Generate Exam Package", variant="primary", size="lg")
143
-
144
- with gr.Column(scale=1):
145
- # Output section
146
- gr.Markdown("### 📤 Generated Outputs")
147
-
148
- status_display = gr.Textbox(
149
- label="Status",
150
- value="🟢 Ready to generate exam package",
151
- interactive=False,
152
- lines=2
153
- )
154
-
155
- with gr.Group():
156
- gr.Markdown("#### 📄 Download Files")
157
- with gr.Row():
158
- qp_download = gr.File(
159
- label="Question Paper",
160
- file_types=[".docx"],
161
- interactive=False,
162
- visible=False
163
- )
164
-
165
- answers_download = gr.File(
166
- label="Answer Key",
167
- file_types=[".docx"],
168
- interactive=False,
169
- visible=False
170
- )
171
-
172
- obe_download = gr.File(
173
- label="OBE Summary",
174
- file_types=[".docx"],
175
- interactive=False,
176
- visible=False
177
- )
178
-
179
- # Progress section
180
- gr.Markdown("### 🔄 Generation Progress")
181
- progress_text = gr.Textbox(
182
- label="Real-time Progress",
183
- value="🟢 System initialized and ready",
184
- interactive=False,
185
- every=1
186
- )
187
-
188
- # Instructions
189
- gr.Markdown("""
190
- ## 📖 How to Use This System
191
-
192
- 1. **Enter Subject Details**: Provide the subject name and select engineering stream
193
- 2. **Configure Questions**: Set the number of questions for each part (A, B, C)
194
- 3. **Upload Syllabus**: PDF file containing course syllabus and learning outcomes
195
- 4. **Optional Reference**: Upload previous question papers for style reference
196
- 5. **Generate**: Click the button to create your complete exam package
197
- 6. **Download**: Get all three DOCX files (Question Paper, Answer Key, OBE Summary)
198
-
199
- ## 🎯 Features
200
-
201
- - **🤖 Multi-Agent AI**: Three specialized agents for generation, verification, and formatting
202
- - **📊 OBE Compliant**: Automatic Outcome-Based Education reporting
203
- - **🔄 Real-time Updates**: Incorporates recent developments in the field
204
- - **🎓 Stream-specific**: CSE (company tags) vs Non-CSE (GATE patterns)
205
- - **✅ Quality Verified**: Automated validation of standards and requirements
206
- - **📝 Professional Output**: Ready-to-use DOCX files with proper formatting
207
-
208
- ## ⚠️ Important Notes
209
-
210
- - Ensure your syllabus PDF is readable and contains clear learning outcomes
211
- - For best results, provide a descriptive subject name
212
- - The system works without API keys but with enhanced capabilities when configured
213
- - Generation may take 1-2 minutes depending on complexity
214
- """)
215
-
216
- # Event handlers
217
- generate_btn.click(
218
- fn=generate_exam_package,
219
- inputs=[subject_name, stream, part_a_count, part_b_count, part_c_count, syllabus_pdf, reference_qp],
220
- outputs=[qp_download, answers_download, obe_download, status_display]
221
- ).then(
222
- fn=lambda: (gr.File(visible=True), gr.File(visible=True), gr.File(visible=True)),
223
- outputs=[qp_download, answers_download, obe_download]
224
  )
225
-
226
- # Progress updates
227
- progress_text.change(
228
- fn=update_progress_ui,
229
- inputs=[],
230
- outputs=[progress_text]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  )
232
 
233
- # Deployment configuration
234
- if __name__ == "__main__":
235
- # For Hugging Face Spaces
236
- demo.queue(concurrency_count=1, max_size=10)
237
- demo.launch(
238
- server_name="0.0.0.0",
239
- server_port=7860,
240
- share=False,
241
- show_error=True
242
- )
 
 
 
 
 
 
1
  import os
2
  import tempfile
3
+ from pathlib import Path
4
+ import gradio as gr
5
+ from pypdf import PdfReader
6
 
7
+ from agents import GroqClient, SerpClient
8
+ from multi_agent import MultiAgentOrchestrator
9
+ from docx_builder import (
10
+ build_question_paper_docx,
11
+ build_answers_docx,
12
+ build_obe_docx,
13
+ )
14
 
15
+ # ---------------------------
16
+ # Utility: Extract PDF text
17
+ # ---------------------------
18
+ def extract_text_from_pdf(file_obj) -> str:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  try:
20
+ reader = PdfReader(file_obj.name)
21
+ pages = [p.extract_text() or "" for p in reader.pages]
22
+ return "\n".join(pages)
 
 
 
23
  except:
24
+ return ""
25
+
26
+ # ---------------------------
27
+ # Initialize Clients
28
+ # ---------------------------
29
+ def init_clients():
30
+ groq_key = os.getenv("GROQ_API_KEY")
31
+ serp_key = os.getenv("SERPAPI_KEY")
32
+ groq = GroqClient(api_key=groq_key)
33
+ serp = SerpClient(api_key=serp_key)
34
+ return groq, serp
35
+
36
+ groq_client, serp_client = init_clients()
37
+ orchestrator = MultiAgentOrchestrator(groq_client, serp_client)
38
+
39
+ # ---------------------------
40
+ # Main Pipeline Trigger
41
+ # ---------------------------
42
+ def run_system(subject, stream, partA, partB, partC, syl_file, ref_file):
43
+
44
+ if syl_file is None:
45
+ return None, None, None, "Upload syllabus first."
46
+
47
+ syllabus_text = extract_text_from_pdf(syl_file)
48
+ ref_text = extract_text_from_pdf(ref_file) if ref_file else ""
49
+
50
+ output = orchestrator.run_pipeline(
51
+ subject=subject,
52
+ stream=stream,
53
+ partA=int(partA),
54
+ partB=int(partB),
55
+ partC=int(partC),
56
+ syllabus_text=syllabus_text,
57
+ ref_qp_text=ref_text,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  )
59
+
60
+ final_json = output.get("final", {})
61
+ generator_raw = output.get("generator_raw", "")
62
+
63
+ tmpdir = Path(tempfile.mkdtemp())
64
+ qp_path = tmpdir / f"{subject}_QP.docx"
65
+ ans_path = tmpdir / f"{subject}_Answers.docx"
66
+ obe_path = tmpdir / f"{subject}_OBE.docx"
67
+
68
+ build_question_paper_docx(qp_path, final_json, generator_raw, subject)
69
+ build_answers_docx(ans_path, final_json, subject)
70
+ build_obe_docx(obe_path, final_json, subject)
71
+
72
+ return qp_path, ans_path, obe_path, "Done!"
73
+
74
+ # ---------------------------
75
+ # Gradio UI
76
+ # ---------------------------
77
+ with gr.Blocks() as app:
78
+ gr.Markdown("# Multi-Agent Question Paper Generator (Groq + SerpAPI)")
79
+
80
+ with gr.Row():
81
+ subject = gr.Textbox(label="Subject Name")
82
+ stream = gr.Dropdown(["CSE", "Non-CSE"], value="CSE", label="Stream")
83
+
84
+ with gr.Row():
85
+ partA = gr.Number(value=10, precision=0, label="Part A Count")
86
+ partB = gr.Number(value=5, precision=0, label="Part B Count")
87
+ partC = gr.Number(value=1, precision=0, label="Part C Count")
88
+
89
+ syllabus = gr.File(label="Upload Syllabus PDF")
90
+ ref_qp = gr.File(label="Upload Reference QP (Optional)")
91
+
92
+ btn = gr.Button("Generate Question Paper")
93
+
94
+ qp_file = gr.File(label="Question Paper")
95
+ ans_file = gr.File(label="Answer Key")
96
+ obe_file = gr.File(label="OBE Summary")
97
+ status = gr.Markdown("Status: Idle")
98
+
99
+ btn.click(
100
+ run_system,
101
+ inputs=[subject, stream, partA, partB, partC, syllabus, ref_qp],
102
+ outputs=[qp_file, ans_file, obe_file, status]
103
  )
104
 
105
+ app.launch()