AyobamiMichael commited on
Commit
dfe76a7
·
verified ·
1 Parent(s): 4414a75

Update app_gradio.py

Browse files
Files changed (1) hide show
  1. app_gradio.py +192 -449
app_gradio.py CHANGED
@@ -1,13 +1,12 @@
1
  """
2
  app_gradio.py
3
- Beautiful Web UI for Multi-Agent System using Gradio
4
  """
5
 
6
  from typing import Dict
7
  import gradio as gr
8
  import json
9
  import time
10
- from pathlib import Path
11
  import threading
12
 
13
  from demo_phase3 import Phase3System
@@ -15,520 +14,264 @@ from export_formats import ProposalExporter
15
 
16
 
17
  class GradioApp:
18
- """Gradio Web Interface for Grant Proposal Generator"""
19
-
20
  def __init__(self):
21
  self.system = None
22
  self.system_lock = threading.Lock()
23
  self.exporter = ProposalExporter()
24
  self.last_proposal_data = None
25
-
 
 
 
26
  def initialize_system(self):
27
- """Initialize the multi-agent system"""
28
  if self.system is None:
29
  with self.system_lock:
30
- if self.system is None: # Double-check
31
  self.system = Phase3System()
32
  self.system.start_all_agents()
33
  time.sleep(2)
34
-
35
- def analyze_paper(
36
- self,
37
- pdf_file,
38
- progress=gr.Progress()
39
- ):
40
- """
41
- Main function: Analyze paper and generate proposal
42
-
43
- Args:
44
- pdf_file: Uploaded PDF file
45
- progress: Gradio progress tracker
46
-
47
- Returns:
48
- Tuple of (analysis_html, proposal_text, download_json, download_txt, download_docx, download_pdf)
49
- """
50
  if pdf_file is None:
51
- return "Please upload a PDF file", "", None, None, None, None
52
-
53
- # Initialize system
54
- progress(0, desc="Initializing system...")
55
  self.initialize_system()
56
-
57
  try:
58
- # Step 1: Validate PDF (10%)
59
- progress(0.1, desc="Validating PDF...")
60
  pdf_path = pdf_file.name
61
-
62
  validation = self.system.pdf_reader.validate_pdf(pdf_path)
63
- if not validation['valid']:
64
- return f"Invalid PDF: {validation['errors']}", "", None, None, None, None
65
-
66
- # Step 2: Analysis (30%)
67
- progress(0.3, desc="🔬 Analyst extracting information...")
68
- analysis_result = self.system._get_analysis(pdf_path)
69
-
70
- if 'error' in analysis_result:
71
- return f"❌ Analysis failed: {analysis_result['error']}", "", None, None, None, None
72
-
73
- # Step 3: Evaluation (50%)
74
- progress(0.5, desc="⚖️ Evaluator assessing quality...")
75
- evaluation_result = self.system._get_evaluation(analysis_result)
76
-
77
- if 'error' in evaluation_result:
78
- return f"❌ Evaluation failed: {evaluation_result['error']}", "", None, None, None, None
79
-
80
- # Step 4: Innovation (70%)
81
- progress(0.7, desc="💡 Innovator generating future directions...")
82
- innovation_result = self.system._get_innovations(analysis_result, evaluation_result)
83
-
84
- if 'error' in innovation_result:
85
- return f"❌ Innovation failed: {innovation_result['error']}", "", None, None, None, None
86
-
87
- # Step 5: Detect conflicts (80%)
88
- progress(0.8, desc="🔍 Detecting conflicts...")
89
- conflicts = self.system._detect_conflicts(analysis_result, evaluation_result, innovation_result)
90
-
91
- # Step 6: Write proposal (90%)
92
- progress(0.9, desc="✍️ Writer synthesizing proposal...")
93
- proposal_result = self.system._get_proposal(
94
- analysis_result,
95
- evaluation_result,
96
- innovation_result,
97
- conflicts
98
  )
99
-
100
- if 'error' in proposal_result:
101
- return f"❌ Proposal generation failed: {proposal_result['error']}", "", None, None, None, None
102
-
103
- # Step 7: Format results & Export (100%)
104
- progress(1.0, desc="✅ Creating exports...")
105
-
106
- # Store proposal data for export functions
107
  self.last_proposal_data = {
108
- 'analysis': analysis_result,
109
- 'evaluation': evaluation_result,
110
- 'innovations': innovation_result,
111
- 'conflicts': conflicts,
112
- 'proposal': proposal_result
113
  }
114
-
115
- # Create analysis HTML
116
  analysis_html = self._format_analysis_html(
117
- analysis_result,
118
- evaluation_result,
119
- innovation_result,
120
- conflicts
121
  )
122
-
123
- # Get proposal text
124
- proposal_text = proposal_result.get('full_text', '')
125
-
126
- # Create downloadable files
127
- json_data = {
128
- 'analysis': analysis_result,
129
- 'evaluation': evaluation_result,
130
- 'innovations': innovation_result,
131
- 'conflicts': conflicts,
132
- 'metadata': proposal_result.get('metadata', {})
133
- }
134
-
135
- json_file = self._create_json_file(json_data)
136
  txt_file = self._create_txt_file(proposal_text)
137
-
138
- # Auto-generate DOCX and PDF
139
  docx_file = self._export_docx(self.last_proposal_data)
140
  pdf_file = self._export_pdf(self.last_proposal_data)
141
-
142
- return analysis_html, proposal_text, json_file, txt_file, docx_file, pdf_file
143
-
 
 
 
 
 
 
 
144
  except Exception as e:
145
- return f"❌ Error: {str(e)}", "", None, None, None, None
146
-
 
 
 
147
  def _format_analysis_html(
148
- self,
149
- analysis: dict,
150
- evaluation: dict,
151
- innovations: dict,
152
- conflicts: list
153
  ) -> str:
154
- """Format analysis results as HTML"""
155
-
156
- html = "<div style='font-family: Arial, sans-serif;'>"
157
-
158
- # Title
159
- html += f"<h2>📄 {analysis.get('title', 'Unknown')}</h2>"
160
- html += f"<p><strong>Authors:</strong> {', '.join(analysis.get('authors', ['Unknown'])[:5])}</p>"
161
-
162
- if analysis.get('year'):
163
- html += f"<p><strong>Year:</strong> {analysis['year']}"
164
- if analysis.get('venue'):
165
- html += f" | <strong>Venue:</strong> {analysis['venue']}"
166
- html += "</p>"
167
-
168
- # Scores
169
- html += "<h3>📊 Quality Assessment</h3>"
170
- html += "<table style='width:100%; border-collapse: collapse;'>"
171
- html += "<tr style='background-color: #f0f0f0;'>"
172
- html += "<th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>Metric</th>"
173
- html += "<th style='padding: 8px; text-align: left; border: 1px solid #ddd;'>Score</th>"
174
- html += "</tr>"
175
-
176
- scores = evaluation.get('scores', {})
177
- for metric, score in scores.items():
178
- color = self._get_score_color(score)
179
- html += f"<tr>"
180
- html += f"<td style='padding: 8px; border: 1px solid #ddd;'>{metric.capitalize()}</td>"
181
- html += f"<td style='padding: 8px; border: 1px solid #ddd; background-color: {color};'><strong>{score}/10</strong></td>"
182
- html += "</tr>"
183
-
184
  html += "</table>"
185
-
186
- # Funding potential
187
- funding = evaluation.get('funding_potential', 'UNKNOWN')
188
- funding_color = {'HIGH': '#90EE90', 'MEDIUM': '#FFD700', 'LOW': '#FFB6C1', 'UNKNOWN': '#D3D3D3'}.get(funding, '#D3D3D3')
189
- html += f"<p><strong>💰 Funding Potential:</strong> <span style='background-color: {funding_color}; padding: 4px 8px; border-radius: 4px;'>{funding}</span></p>"
190
-
191
- # Key Contributions
192
- html += "<h3>✨ Key Contributions</h3>"
193
- html += "<ul>"
194
- for contrib in analysis.get('key_contributions', [])[:5]:
195
- html += f"<li>{contrib}</li>"
196
  html += "</ul>"
197
-
198
- # Strengths & Weaknesses
199
- html += "<div style='display: flex; gap: 20px;'>"
200
-
201
- # Strengths
202
- html += "<div style='flex: 1;'>"
203
- html += "<h3>✅ Strengths</h3>"
204
- html += "<ul>"
205
- for strength in evaluation.get('strengths', [])[:5]:
206
- html += f"<li>{strength}</li>"
207
  html += "</ul>"
208
- html += "</div>"
209
-
210
- # Weaknesses
211
- html += "<div style='flex: 1;'>"
212
- html += "<h3>⚠️ Weaknesses</h3>"
213
- html += "<ul>"
214
- for weakness in evaluation.get('weaknesses', [])[:5]:
215
- html += f"<li>{weakness}</li>"
216
  html += "</ul>"
217
- html += "</div>"
218
-
219
- html += "</div>"
220
-
221
- # Future Directions
222
- html += "<h3>💡 Future Research Directions</h3>"
223
- html += "<ol>"
224
- for direction in innovations.get('future_directions', [])[:5]:
225
- html += f"<li><strong>{direction.get('direction', 'N/A')}</strong><br>"
226
- html += f"<small>{direction.get('description', '')}</small><br>"
227
- html += f"<small>Feasibility: {direction.get('feasibility', 'N/A')} | "
228
- html += f"Timeframe: {direction.get('timeframe', 'N/A')}</small></li>"
229
  html += "</ol>"
230
-
231
- # Industry Applications
232
- html += "<h3>🏭 Industry Applications</h3>"
233
- html += "<ul>"
234
- for app in innovations.get('industry_applications', [])[:5]:
235
- html += f"<li><strong>{app.get('domain', 'N/A')}:</strong> {app.get('application', 'N/A')}</li>"
236
- html += "</ul>"
237
-
238
- # Conflicts
239
  if conflicts:
240
- html += "<h3>🔍 Conflicts Resolved</h3>"
241
- html += "<ul>"
242
- for conflict in conflicts:
243
- html += f"<li><strong>{conflict['type']}:</strong> {conflict['description']}<br>"
244
- html += f"<small>Resolution: {conflict['resolution']}</small></li>"
245
  html += "</ul>"
246
-
247
- # Commercial Potential
248
- commercial = innovations.get('commercial_potential', 'UNKNOWN')
249
- commercial_color = {'HIGH': '#90EE90', 'MEDIUM': '#FFD700', 'LOW': '#FFB6C1', 'UNKNOWN': '#D3D3D3'}.get(commercial, '#D3D3D3')
250
- html += f"<p><strong>💼 Commercial Potential:</strong> <span style='background-color: {commercial_color}; padding: 4px 8px; border-radius: 4px;'>{commercial}</span></p>"
251
-
252
- # Vision
253
- if innovations.get('ten_year_vision'):
254
- html += "<h3>🔮 10-Year Vision</h3>"
255
- html += f"<p>{innovations['ten_year_vision']}</p>"
256
-
257
  html += "</div>"
258
-
259
  return html
260
-
261
- def _get_score_color(self, score):
262
- """Get color based on score"""
263
- if score >= 8:
264
- return "#90EE90" # Light green
265
- elif score >= 6:
266
- return "#FFD700" # Gold
267
- elif score >= 4:
268
- return "#FFB6C1" # Light pink
269
- else:
270
- return "#FFB6C1" # Light red
271
-
272
  def _create_json_file(self, data: dict) -> str:
273
- """Create JSON file for download"""
274
- filepath = "grant_proposal_data.json"
275
- with open(filepath, 'w') as f:
276
  json.dump(data, f, indent=2)
277
- return filepath
278
-
279
  def _create_txt_file(self, text: str) -> str:
280
- """Create text file for download"""
281
- filepath = "grant_proposal.txt"
282
- with open(filepath, 'w', encoding='utf-8') as f:
283
  f.write(text)
284
- return filepath
285
-
286
- def _export_docx(self, proposal_data: Dict) -> str:
287
- """Export to DOCX"""
288
- try:
289
- filepath = "grant_proposal.docx"
290
- self.exporter.export_to_docx(proposal_data, filepath, template='nsf')
291
- return filepath
292
- except Exception as e:
293
- print(f"⚠️ DOCX export error: {e}")
294
- return None
295
-
296
- def _export_pdf(self, proposal_data: Dict) -> str:
297
- """Export to PDF"""
298
- try:
299
- filepath = "grant_proposal.pdf"
300
- self.exporter.export_to_pdf(proposal_data, filepath, method='reportlab')
301
- return filepath
302
- except Exception as e:
303
- print(f"⚠️ PDF export error: {e}")
304
- return None
305
-
306
- def _export_html(self, proposal_data: Dict) -> str:
307
- """Export to HTML"""
308
- try:
309
- filepath = "grant_proposal.html"
310
- self.exporter.export_to_html(proposal_data, filepath)
311
- return filepath
312
- except Exception as e:
313
- print(f"⚠️ HTML export error: {e}")
314
- return None
315
-
316
- def export_docx_callback(self):
317
- """Callback for DOCX export button"""
318
- if self.last_proposal_data:
319
- return self._export_docx(self.last_proposal_data)
320
- return None
321
-
322
- def export_pdf_callback(self):
323
- """Callback for PDF export button"""
324
- if self.last_proposal_data:
325
- return self._export_pdf(self.last_proposal_data)
326
- return None
327
-
328
- def export_html_callback(self):
329
- """Callback for HTML export button"""
330
- if self.last_proposal_data:
331
- return self._export_html(self.last_proposal_data)
332
- return None
333
-
334
  def create_interface(self):
335
- """Create Gradio interface"""
336
-
337
- # Custom CSS
338
  css = """
339
- .container {
340
- max-width: 1200px;
341
- margin: auto;
342
- }
343
- .header {
344
- text-align: center;
345
- padding: 20px;
346
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
347
- color: white;
348
- border-radius: 10px;
349
- margin-bottom: 20px;
350
- }
351
  """
352
-
353
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as app:
354
  gr.HTML("""
355
- <div class="header">
356
- <h1> AI Grant Proposal Generator </h1>
357
- <p>Multi-Agent System for Research Paper Analysis & Grant Writing</p>
358
- </div>
359
  """)
360
-
361
  with gr.Row():
362
  with gr.Column(scale=1):
363
- gr.Markdown("### 📤 Upload Paper")
364
  pdf_input = gr.File(
365
  label="Research Paper (PDF)",
366
  file_types=[".pdf"],
367
- type="filepath"
368
- )
369
-
370
- analyze_btn = gr.Button(
371
- "🚀 Generate Grant Proposal",
372
- variant="primary",
373
- size="lg"
374
  )
375
-
 
376
  gr.Markdown("""
377
- ### ℹ️ How it works
378
-
379
- 1. **Upload** your research paper (PDF)
380
- 2. **Wait** 60-90 seconds for analysis
381
- 3. **Review** the analysis and proposal
382
- 4. **Download** results in JSON/TXT format
383
-
384
- ### ⚙️ System Features
385
-
386
- - 5 AI agents working together
387
- - Quality assessment (0-10 scores)
388
- - Future research directions
389
- - Industry applications
390
- - Complete grant proposal
391
- - Conflict resolution
392
  """)
393
-
394
  with gr.Column(scale=2):
395
- gr.Markdown("### 📊 Analysis Results")
396
-
397
  with gr.Tabs():
398
- with gr.Tab("📄 Analysis"):
399
- analysis_output = gr.HTML(
400
- label="Paper Analysis",
401
- elem_classes="analysis-output"
402
- )
403
-
404
- with gr.Tab("📝 Grant Proposal"):
405
- proposal_output = gr.Textbox(
406
- label="Complete Proposal",
407
- lines=30,
408
- max_lines=50,
409
- show_copy_button=True
410
- )
411
-
412
- with gr.Tab("💾 Downloads"):
413
- gr.Markdown("### Download Results")
414
-
415
- with gr.Row():
416
- with gr.Column():
417
- json_download = gr.File(
418
- label="📊 Structured Data (JSON)"
419
- )
420
-
421
- txt_download = gr.File(
422
- label="📝 Full Proposal (TXT)"
423
- )
424
-
425
- with gr.Column():
426
- docx_download = gr.File(
427
- label="📄 Word Document (DOCX)"
428
- )
429
-
430
- pdf_download = gr.File(
431
- label="📕 PDF Document"
432
- )
433
-
434
- gr.Markdown("### Export Options")
435
-
436
- with gr.Row():
437
- export_docx_btn = gr.Button("📄 Export to DOCX", size="sm")
438
- export_pdf_btn = gr.Button("📕 Export to PDF", size="sm")
439
- export_html_btn = gr.Button("🌐 Export to HTML", size="sm")
440
-
441
- html_download = gr.File(
442
- label="🌐 HTML Document",
443
- visible=False
444
- )
445
-
446
- # Examples
447
- # gr.Markdown("### 📚 Example Papers")
448
- #gr.Examples(
449
- # examples=[
450
- # ["example_papers/transformer.pdf"],
451
- # ["example_papers/resnet.pdf"],
452
- # ["example_papers/bert.pdf"]
453
- # ],
454
- # inputs=pdf_input,
455
- # label="Try these examples (if available)"
456
- #)
457
-
458
- # Connect button
459
  analyze_btn.click(
460
  fn=self.analyze_paper,
461
  inputs=[pdf_input],
462
- outputs=[analysis_output, proposal_output, json_download, txt_download, docx_download, pdf_download]
463
- )
464
-
465
- # Connect export buttons
466
- export_docx_btn.click(
467
- fn=self.export_docx_callback,
468
- outputs=[docx_download]
469
- )
470
-
471
- export_pdf_btn.click(
472
- fn=self.export_pdf_callback,
473
- outputs=[pdf_download]
474
- )
475
-
476
- export_html_btn.click(
477
- fn=self.export_html_callback,
478
- outputs=[html_download]
479
- ).then(
480
- lambda: gr.update(visible=True),
481
- outputs=[html_download]
482
  )
483
-
484
  gr.Markdown("""
485
  ---
486
- ### 🎓 About
487
-
488
- This system uses 5 specialized AI agents:
489
- - **Supervisor**: Orchestrates the workflow
490
- - **Analyst**: Extracts paper information
491
- - **Evaluator**: Assesses quality and funding potential
492
- - **Innovator**: Generates future directions
493
- - **Writer**: Synthesizes grant proposal
494
-
495
- Built with: Python, Groq LLM, Multi-Agent Architecture
496
  """)
497
-
498
  return app
499
-
500
- def launch(self, share=False, server_port=7860):
501
- """Launch the Gradio app"""
502
- app = self.create_interface()
503
- app.launch(
504
- share=share,
505
- server_port=server_port,
506
- server_name="0.0.0.0"
507
- )
508
 
509
 
510
  def main():
511
- """Main entry point"""
512
- print("="*70)
513
- print("🚀 Starting Gradio Web UI...")
514
- print("="*70)
515
- print()
516
-
517
- app = GradioApp()
518
-
519
- print("✅ Initializing multi-agent system...")
520
- print(" This may take a few seconds...")
521
- print()
522
-
523
- print("🌐 Launching web interface...")
524
- print(" Local URL: http://localhost:7860")
525
- print(" Share URL: Use share=True for public link")
526
- print()
527
- print("Press Ctrl+C to stop the server")
528
- print("="*70)
529
-
530
- app.launch(share=False)
531
 
532
 
533
  if __name__ == "__main__":
534
- main()
 
1
  """
2
  app_gradio.py
3
+ Professional Web UI for Multi-Agent Grant Proposal System
4
  """
5
 
6
  from typing import Dict
7
  import gradio as gr
8
  import json
9
  import time
 
10
  import threading
11
 
12
  from demo_phase3 import Phase3System
 
14
 
15
 
16
  class GradioApp:
17
+ """Professional Gradio Interface for Grant Proposal Generation"""
18
+
19
  def __init__(self):
20
  self.system = None
21
  self.system_lock = threading.Lock()
22
  self.exporter = ProposalExporter()
23
  self.last_proposal_data = None
24
+
25
+ # ------------------------------------------------------------------
26
+ # System Initialization
27
+ # ------------------------------------------------------------------
28
  def initialize_system(self):
 
29
  if self.system is None:
30
  with self.system_lock:
31
+ if self.system is None:
32
  self.system = Phase3System()
33
  self.system.start_all_agents()
34
  time.sleep(2)
35
+
36
+ # ------------------------------------------------------------------
37
+ # Main Pipeline
38
+ # ------------------------------------------------------------------
39
+ def analyze_paper(self, pdf_file, progress=gr.Progress()):
 
 
 
 
 
 
 
 
 
 
 
40
  if pdf_file is None:
41
+ return "Please upload a PDF file.", "", None, None, None, None
42
+
43
+ progress(0.0, desc="Initializing system")
 
44
  self.initialize_system()
45
+
46
  try:
47
+ progress(0.1, desc="Validating document")
 
48
  pdf_path = pdf_file.name
 
49
  validation = self.system.pdf_reader.validate_pdf(pdf_path)
50
+ if not validation["valid"]:
51
+ return f"Invalid PDF: {validation['errors']}", "", None, None, None, None
52
+
53
+ progress(0.3, desc="Performing technical analysis")
54
+ analysis = self.system._get_analysis(pdf_path)
55
+ if "error" in analysis:
56
+ return analysis["error"], "", None, None, None, None
57
+
58
+ progress(0.5, desc="Evaluating research quality")
59
+ evaluation = self.system._get_evaluation(analysis)
60
+ if "error" in evaluation:
61
+ return evaluation["error"], "", None, None, None, None
62
+
63
+ progress(0.7, desc="Generating innovation directions")
64
+ innovations = self.system._get_innovations(analysis, evaluation)
65
+ if "error" in innovations:
66
+ return innovations["error"], "", None, None, None, None
67
+
68
+ progress(0.8, desc="Resolving analytical conflicts")
69
+ conflicts = self.system._detect_conflicts(
70
+ analysis, evaluation, innovations
71
+ )
72
+
73
+ progress(0.9, desc="Drafting grant proposal")
74
+ proposal = self.system._get_proposal(
75
+ analysis, evaluation, innovations, conflicts
 
 
 
 
 
 
 
 
 
76
  )
77
+ if "error" in proposal:
78
+ return proposal["error"], "", None, None, None, None
79
+
80
+ progress(1.0, desc="Preparing outputs")
81
+
 
 
 
82
  self.last_proposal_data = {
83
+ "analysis": analysis,
84
+ "evaluation": evaluation,
85
+ "innovations": innovations,
86
+ "conflicts": conflicts,
87
+ "proposal": proposal,
88
  }
89
+
 
90
  analysis_html = self._format_analysis_html(
91
+ analysis, evaluation, innovations, conflicts
 
 
 
92
  )
93
+
94
+ proposal_text = proposal.get("full_text", "")
95
+
96
+ json_file = self._create_json_file(
97
+ {
98
+ "analysis": analysis,
99
+ "evaluation": evaluation,
100
+ "innovations": innovations,
101
+ "conflicts": conflicts,
102
+ }
103
+ )
104
+
 
 
105
  txt_file = self._create_txt_file(proposal_text)
 
 
106
  docx_file = self._export_docx(self.last_proposal_data)
107
  pdf_file = self._export_pdf(self.last_proposal_data)
108
+
109
+ return (
110
+ analysis_html,
111
+ proposal_text,
112
+ json_file,
113
+ txt_file,
114
+ docx_file,
115
+ pdf_file,
116
+ )
117
+
118
  except Exception as e:
119
+ return str(e), "", None, None, None, None
120
+
121
+ # ------------------------------------------------------------------
122
+ # Formatting
123
+ # ------------------------------------------------------------------
124
  def _format_analysis_html(
125
+ self, analysis: dict, evaluation: dict, innovations: dict, conflicts: list
 
 
 
 
126
  ) -> str:
127
+ html = "<div style='font-family: Inter, Arial; line-height:1.6;'>"
128
+
129
+ html += f"<h2>{analysis.get('title','Unknown Title')}</h2>"
130
+ html += f"<p><strong>Authors:</strong> {', '.join(analysis.get('authors',[])[:5])}</p>"
131
+ html += "<hr>"
132
+
133
+ html += "<h3>Quality Assessment</h3><table width='100%' border='1' cellspacing='0' cellpadding='6'>"
134
+ html += "<tr><th align='left'>Metric</th><th align='left'>Score</th></tr>"
135
+ for m, s in evaluation.get("scores", {}).items():
136
+ html += f"<tr><td>{m.capitalize()}</td><td>{s}/10</td></tr>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  html += "</table>"
138
+
139
+ html += f"<p><strong>Funding Potential:</strong> {evaluation.get('funding_potential','UNKNOWN')}</p>"
140
+
141
+ html += "<h3>Key Contributions</h3><ul>"
142
+ for c in analysis.get("key_contributions", [])[:5]:
143
+ html += f"<li>{c}</li>"
 
 
 
 
 
144
  html += "</ul>"
145
+
146
+ html += "<h3>Strengths</h3><ul>"
147
+ for s in evaluation.get("strengths", [])[:5]:
148
+ html += f"<li>{s}</li>"
 
 
 
 
 
 
149
  html += "</ul>"
150
+
151
+ html += "<h3>Limitations</h3><ul>"
152
+ for w in evaluation.get("weaknesses", [])[:5]:
153
+ html += f"<li>{w}</li>"
 
 
 
 
154
  html += "</ul>"
155
+
156
+ html += "<h3>Future Research Directions</h3><ol>"
157
+ for d in innovations.get("future_directions", [])[:5]:
158
+ html += f"<li><strong>{d.get('direction')}</strong><br>{d.get('description')}</li>"
 
 
 
 
 
 
 
 
159
  html += "</ol>"
160
+
161
+ html += f"<p><strong>Commercial Potential:</strong> {innovations.get('commercial_potential','UNKNOWN')}</p>"
162
+
 
 
 
 
 
 
163
  if conflicts:
164
+ html += "<h3>Resolved Conflicts</h3><ul>"
165
+ for c in conflicts:
166
+ html += f"<li>{c['description']} — <em>{c['resolution']}</em></li>"
 
 
167
  html += "</ul>"
168
+
 
 
 
 
 
 
 
 
 
 
169
  html += "</div>"
 
170
  return html
171
+
172
+ # ------------------------------------------------------------------
173
+ # File Exports
174
+ # ------------------------------------------------------------------
 
 
 
 
 
 
 
 
175
  def _create_json_file(self, data: dict) -> str:
176
+ path = "grant_data.json"
177
+ with open(path, "w") as f:
 
178
  json.dump(data, f, indent=2)
179
+ return path
180
+
181
  def _create_txt_file(self, text: str) -> str:
182
+ path = "grant_proposal.txt"
183
+ with open(path, "w", encoding="utf-8") as f:
 
184
  f.write(text)
185
+ return path
186
+
187
+ def _export_docx(self, data: Dict) -> str:
188
+ path = "grant_proposal.docx"
189
+ self.exporter.export_to_docx(data, path, template="nsf")
190
+ return path
191
+
192
+ def _export_pdf(self, data: Dict) -> str:
193
+ path = "grant_proposal.pdf"
194
+ self.exporter.export_to_pdf(data, path, method="reportlab")
195
+ return path
196
+
197
+ # ------------------------------------------------------------------
198
+ # Interface
199
+ # ------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  def create_interface(self):
 
 
 
201
  css = """
202
+ body { background:#f9fafb; }
203
+ .container { max-width:1100px; margin:auto; }
 
 
 
 
 
 
 
 
 
 
204
  """
205
+
206
  with gr.Blocks(css=css, theme=gr.themes.Soft()) as app:
207
  gr.HTML("""
208
+ <div style="padding:24px 0;border-bottom:1px solid #e5e7eb">
209
+ <h1>AI Grant Proposal Generator</h1>
210
+ <p>Multi-agent research analysis and funding synthesis platform</p>
211
+ </div>
212
  """)
213
+
214
  with gr.Row():
215
  with gr.Column(scale=1):
216
+ gr.Markdown("### Input Document")
217
  pdf_input = gr.File(
218
  label="Research Paper (PDF)",
219
  file_types=[".pdf"],
220
+ type="filepath",
 
 
 
 
 
 
221
  )
222
+ analyze_btn = gr.Button("Start Analysis", variant="primary")
223
+
224
  gr.Markdown("""
225
+ ### Analysis Pipeline
226
+ - Document validation
227
+ - Technical analysis
228
+ - Quality evaluation
229
+ - Innovation synthesis
230
+ - Proposal drafting
 
 
 
 
 
 
 
 
 
231
  """)
232
+
233
  with gr.Column(scale=2):
 
 
234
  with gr.Tabs():
235
+ with gr.Tab("Analysis Overview"):
236
+ analysis_output = gr.HTML()
237
+ with gr.Tab("Grant Proposal Draft"):
238
+ proposal_output = gr.Textbox(lines=28, show_copy_button=True)
239
+ with gr.Tab("Exports"):
240
+ json_download = gr.File(label="Structured Data (JSON)")
241
+ txt_download = gr.File(label="Proposal Draft (TXT)")
242
+ docx_download = gr.File(label="Formatted Proposal (DOCX)")
243
+ pdf_download = gr.File(label="Submission PDF")
244
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  analyze_btn.click(
246
  fn=self.analyze_paper,
247
  inputs=[pdf_input],
248
+ outputs=[
249
+ analysis_output,
250
+ proposal_output,
251
+ json_download,
252
+ txt_download,
253
+ docx_download,
254
+ pdf_download,
255
+ ],
 
 
 
 
 
 
 
 
 
 
 
 
256
  )
257
+
258
  gr.Markdown("""
259
  ---
260
+ **System Architecture**
261
+ Supervisor, Analyst, Evaluator, Innovator, and Writer agents operate
262
+ in a coordinated multi-stage pipeline designed for research teams
263
+ and funding professionals.
 
 
 
 
 
 
264
  """)
265
+
266
  return app
267
+
268
+ def launch(self):
269
+ self.create_interface().launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
270
 
271
 
272
  def main():
273
+ GradioApp().launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
 
276
  if __name__ == "__main__":
277
+ main()