shukdevdatta123 commited on
Commit
6fe23ea
·
verified ·
1 Parent(s): f8308a2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +237 -11
app.py CHANGED
@@ -24,8 +24,119 @@ def extract_text_from_pdf(pdf_path):
24
  except Exception as e:
25
  return f"Error extracting text from PDF: {str(e)}"
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  # Function to interact with OpenAI API for systematic review
28
- def generate_systematic_review(pdf_files, review_question, include_tables=True):
29
  if not api_key:
30
  return "Please enter your OpenAI API key first."
31
 
@@ -78,6 +189,8 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
78
  Include a comprehensive reference list following a specific citation style (APA, Vancouver, etc.). Provide links to source papers when available.
79
 
80
  Your response should be formatted in HTML (but avoid showing these tags ```html ```) but generate the content to look like a professional academic paper. Include proper section headers, abstracts, methodology sections, etc. Number all sections like an academic paper. Follow academic journal standards with double spacing, appropriate margins, and consistent formatting throughout.
 
 
81
  """
82
 
83
  # Extract text from each PDF
@@ -100,8 +213,22 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
100
  table_instruction = ""
101
  if include_tables:
102
  table_instruction = " Please include important new generated tables in your review."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- user_prompt = f"Please generate a systematic review of the following {len(pdf_files)} papers: {', '.join(pdf_names)}.{table_instruction}\n\nReview Question: {review_question}"
105
 
106
  # Create the messages for the API call
107
  messages = [
@@ -121,6 +248,41 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
121
  # Get the AI response
122
  review_content = response["choices"][0]["message"]["content"]
123
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  # Apply professional academic paper styling
125
  styled_html = f"""
126
  <!DOCTYPE html>
@@ -244,6 +406,13 @@ def generate_systematic_review(pdf_files, review_question, include_tables=True):
244
  font-size: 12px;
245
  color: #777;
246
  }}
 
 
 
 
 
 
 
247
  @media print {{
248
  body {{
249
  background-color: white;
@@ -422,18 +591,36 @@ custom_css = """
422
  border-radius: 8px;
423
  }
424
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  /* Responsive adjustments */
426
  @media screen and (max-width: 768px) {
427
  .gradio-container {
428
  padding: 10px;
429
  }
 
 
 
430
  }
431
  </style>
432
  """
433
 
434
  # Gradio UI Layout with improved styling
435
  with gr.Blocks(css=custom_css) as demo:
436
- gr.Markdown("# Systematic Review Generator for Research Papers")
437
 
438
  with gr.Accordion("How to Use This App", open=False):
439
  gr.Markdown("""
@@ -441,9 +628,15 @@ with gr.Blocks(css=custom_css) as demo:
441
  1. Enter your OpenAI API key in the field below and click "Set API Key"
442
  2. Upload multiple PDF research papers (2 or more recommended)
443
  3. Enter your review question or topic
444
- 4. Check the "Include Tables" option if you want the review to include comparison tables
445
- 5. Click "Generate Systematic Review" to start the process
446
- 6. After generation, you can download the review as HTML
 
 
 
 
 
 
447
 
448
  ### Tips for Best Results:
449
  - Upload papers that are related to the same research topic or field
@@ -472,6 +665,22 @@ with gr.Blocks(css=custom_css) as demo:
472
  placeholder="e.g., What are the effects of mindfulness meditation on stress reduction?"
473
  )
474
  include_tables = gr.Checkbox(label="Include Comparison Tables", value=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  generate_button = gr.Button("Generate Systematic Review", elem_id="generate_button", size="large")
476
 
477
  # Download link container
@@ -485,7 +694,10 @@ with gr.Blocks(css=custom_css) as demo:
485
  api_key_button.click(set_api_key, inputs=[api_key_input], outputs=[api_key_output])
486
 
487
  # Generate systematic review
488
- def process_files_and_generate_review(files, question, include_tables):
 
 
 
489
  if not files:
490
  return ("""
491
  <div style="padding: 20px; border: 1px solid #e0e0e0; border-radius: 5px; background-color: #f9f9f9;">
@@ -500,7 +712,7 @@ with gr.Blocks(css=custom_css) as demo:
500
  # Show loading message
501
  loading_message = """
502
  <div style="padding: 20px; text-align: center;">
503
- <h3>Generating Systematic Review...</h3>
504
  <p>This may take a few minutes depending on the number and size of papers.</p>
505
  <div style="width: 100%; height: 4px; background-color: #f0f0f0; margin: 20px 0; border-radius: 2px; overflow: hidden;">
506
  <div style="width: 30%; height: 100%; background: linear-gradient(90deg, #4a00e0, #8e2de2); animation: progress 2s infinite linear;"></div>
@@ -516,8 +728,19 @@ with gr.Blocks(css=custom_css) as demo:
516
 
517
  yield loading_message, ""
518
 
519
- # Generate review
520
- review = generate_systematic_review(saved_paths, question, include_tables)
 
 
 
 
 
 
 
 
 
 
 
521
 
522
  # Create HTML download link
523
  html_link = create_html_download_link(review)
@@ -543,7 +766,10 @@ with gr.Blocks(css=custom_css) as demo:
543
 
544
  generate_button.click(
545
  process_files_and_generate_review,
546
- inputs=[pdf_files, review_question, include_tables],
 
 
 
547
  outputs=[review_output, download_html_output]
548
  )
549
 
 
24
  except Exception as e:
25
  return f"Error extracting text from PDF: {str(e)}"
26
 
27
+ # Function to generate PRISMA flow chart SVG
28
+ def generate_prisma_flow_chart(records_db, records_other, duplicates, excluded_screening, excluded_fulltext, included_studies,
29
+ included_meta=None, fulltext_assessed=None):
30
+ # Calculate values if not provided
31
+ if fulltext_assessed is None:
32
+ fulltext_assessed = excluded_fulltext + included_studies
33
+
34
+ records_after_duplicates = records_db + records_other - duplicates
35
+
36
+ # Create SVG content for PRISMA flow chart
37
+ svg_content = f'''
38
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="700" height="700">
39
+ <style>
40
+ .box {{
41
+ fill: #f9f9f9;
42
+ stroke: #333;
43
+ stroke-width: 2;
44
+ }}
45
+ .arrow {{
46
+ stroke: #333;
47
+ stroke-width: 2;
48
+ marker-end: url(#arrowhead);
49
+ }}
50
+ text {{
51
+ font-family: Arial, sans-serif;
52
+ font-size: 14px;
53
+ text-anchor: middle;
54
+ }}
55
+ .box-title {{
56
+ font-weight: bold;
57
+ }}
58
+ </style>
59
+
60
+ <defs>
61
+ <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
62
+ <polygon points="0 0, 10 3.5, 0 7" />
63
+ </marker>
64
+ </defs>
65
+
66
+ <!-- Identification Section -->
67
+ <rect x="250" y="30" width="300" height="60" class="box" />
68
+ <text x="400" y="50" class="box-title">Identification</text>
69
+ <text x="400" y="75">Records identified through database searching</text>
70
+ <text x="400" y="90">(n = {records_db})</text>
71
+
72
+ <rect x="600" y="30" width="150" height="60" class="box" />
73
+ <text x="675" y="50" class="box-title">Additional</text>
74
+ <text x="675" y="75">Other sources</text>
75
+ <text x="675" y="90">(n = {records_other})</text>
76
+
77
+ <!-- Arrows -->
78
+ <line x1="400" y1="90" x2="400" y2="130" class="arrow" />
79
+ <line x1="675" y1="90" x2="675" y2="110" class="arrow" />
80
+ <line x1="675" y1="110" x2="400" y2="110" class="arrow" />
81
+
82
+ <!-- Screening Section -->
83
+ <rect x="250" y="130" width="300" height="60" class="box" />
84
+ <text x="400" y="150" class="box-title">Screening</text>
85
+ <text x="400" y="175">Records after duplicates removed</text>
86
+ <text x="400" y="190">(n = {records_after_duplicates})</text>
87
+
88
+ <line x1="400" y1="190" x2="400" y2="230" class="arrow" />
89
+
90
+ <rect x="250" y="230" width="300" height="60" class="box" />
91
+ <text x="400" y="250" class="box-title">Title/Abstract Screening</text>
92
+ <text x="400" y="275">Records screened</text>
93
+ <text x="400" y="290">(n = {records_after_duplicates})</text>
94
+
95
+ <rect x="600" y="230" width="150" height="60" class="box" />
96
+ <text x="675" y="255">Records excluded</text>
97
+ <text x="675" y="275">(n = {excluded_screening})</text>
98
+
99
+ <line x1="400" y1="290" x2="400" y2="330" class="arrow" />
100
+ <line x1="550" y1="260" x2="600" y2="260" class="arrow" />
101
+
102
+ <!-- Eligibility Section -->
103
+ <rect x="250" y="330" width="300" height="60" class="box" />
104
+ <text x="400" y="350" class="box-title">Eligibility</text>
105
+ <text x="400" y="375">Full-text articles assessed for eligibility</text>
106
+ <text x="400" y="390">(n = {fulltext_assessed})</text>
107
+
108
+ <rect x="600" y="330" width="150" height="60" class="box" />
109
+ <text x="675" y="350">Full-text articles</text>
110
+ <text x="675" y="370">excluded, with reasons</text>
111
+ <text x="675" y="390">(n = {excluded_fulltext})</text>
112
+
113
+ <line x1="400" y1="390" x2="400" y2="430" class="arrow" />
114
+ <line x1="550" y1="360" x2="600" y2="360" class="arrow" />
115
+
116
+ <!-- Included Section -->
117
+ <rect x="250" y="430" width="300" height="60" class="box" />
118
+ <text x="400" y="450" class="box-title">Included</text>
119
+ <text x="400" y="475">Studies included in qualitative synthesis</text>
120
+ <text x="400" y="490">(n = {included_studies})</text>
121
+
122
+ <!-- Optional Meta-Analysis Box -->
123
+ {f'''
124
+ <line x1="400" y1="490" x2="400" y2="530" class="arrow" />
125
+ <rect x="250" y="530" width="300" height="60" class="box" />
126
+ <text x="400" y="550" class="box-title">Meta-Analysis</text>
127
+ <text x="400" y="575">Studies included in quantitative synthesis</text>
128
+ <text x="400" y="590">(n = {included_meta})</text>
129
+ ''' if included_meta is not None else ''}
130
+
131
+ <!-- PRISMA Title -->
132
+ <text x="150" y="25" style="font-size: 18px; font-weight: bold; text-anchor: start;">PRISMA Flow Diagram</text>
133
+ </svg>
134
+ '''
135
+
136
+ return svg_content
137
+
138
  # Function to interact with OpenAI API for systematic review
139
+ def generate_systematic_review(pdf_files, review_question, prisma_numbers, include_tables=True):
140
  if not api_key:
141
  return "Please enter your OpenAI API key first."
142
 
 
189
  Include a comprehensive reference list following a specific citation style (APA, Vancouver, etc.). Provide links to source papers when available.
190
 
191
  Your response should be formatted in HTML (but avoid showing these tags ```html ```) but generate the content to look like a professional academic paper. Include proper section headers, abstracts, methodology sections, etc. Number all sections like an academic paper. Follow academic journal standards with double spacing, appropriate margins, and consistent formatting throughout.
192
+
193
+ Make sure to include that you conducted a PRISMA flow diagram as part of the methodology section. Reference the PRISMA diagram in your methodology section and explain the numbers used in the diagram.
194
  """
195
 
196
  # Extract text from each PDF
 
213
  table_instruction = ""
214
  if include_tables:
215
  table_instruction = " Please include important new generated tables in your review."
216
+
217
+ # Add PRISMA flow information
218
+ prisma_info = f"""
219
+ Additionally, I have conducted a PRISMA flow diagram with the following data:
220
+ - Records identified through database searching: {prisma_numbers['records_db']}
221
+ - Additional records identified through other sources: {prisma_numbers['records_other']}
222
+ - Records after duplicates removed: {int(prisma_numbers['records_db']) + int(prisma_numbers['records_other']) - int(prisma_numbers['duplicates'])}
223
+ - Records excluded during title/abstract screening: {prisma_numbers['excluded_screening']}
224
+ - Full-text articles excluded with reasons: {prisma_numbers['excluded_fulltext']}
225
+ - Studies included in qualitative synthesis: {prisma_numbers['included_studies']}
226
+ """
227
+
228
+ if prisma_numbers.get('included_meta') and prisma_numbers['included_meta'].strip():
229
+ prisma_info += f"- Studies included in quantitative synthesis (meta-analysis): {prisma_numbers['included_meta']}\n"
230
 
231
+ user_prompt = f"Please generate a systematic review of the following {len(pdf_files)} papers: {', '.join(pdf_names)}.{table_instruction}\n\nReview Question: {review_question}\n\n{prisma_info}"
232
 
233
  # Create the messages for the API call
234
  messages = [
 
248
  # Get the AI response
249
  review_content = response["choices"][0]["message"]["content"]
250
 
251
+ # Generate PRISMA flow chart SVG
252
+ prisma_svg = generate_prisma_flow_chart(
253
+ int(prisma_numbers['records_db']),
254
+ int(prisma_numbers['records_other']),
255
+ int(prisma_numbers['duplicates']),
256
+ int(prisma_numbers['excluded_screening']),
257
+ int(prisma_numbers['excluded_fulltext']),
258
+ int(prisma_numbers['included_studies']),
259
+ int(prisma_numbers['included_meta']) if prisma_numbers.get('included_meta') and prisma_numbers['included_meta'].strip() else None
260
+ )
261
+
262
+ # Find a suitable place to insert the PRISMA flow chart
263
+ # Look for the methodology section or PRISMA mentions
264
+ prisma_html = f'''
265
+ <div class="prisma-flow-chart">
266
+ <h3>Figure 1: PRISMA Flow Diagram</h3>
267
+ {prisma_svg}
268
+ </div>
269
+ '''
270
+
271
+ # Try to insert PRISMA diagram after methodology section or before results
272
+ if "<h2>3. Methodology" in review_content:
273
+ parts = review_content.split("<h2>3. Methodology", 1)
274
+ if len(parts) > 1:
275
+ # Find the next h2 section after methodology
276
+ next_section = parts[1].find("<h2>")
277
+ if next_section > -1:
278
+ review_content = parts[0] + "<h2>3. Methodology" + parts[1][:next_section] + prisma_html + parts[1][next_section:]
279
+ else:
280
+ review_content = parts[0] + "<h2>3. Methodology" + parts[1] + prisma_html
281
+ else:
282
+ # If methodology section not found, insert before results or at the end
283
+ insert_pos = review_content.find("<h2>4.") if "<h2>4." in review_content else len(review_content) - 100
284
+ review_content = review_content[:insert_pos] + prisma_html + review_content[insert_pos:]
285
+
286
  # Apply professional academic paper styling
287
  styled_html = f"""
288
  <!DOCTYPE html>
 
406
  font-size: 12px;
407
  color: #777;
408
  }}
409
+ .prisma-flow-chart {{
410
+ margin: 30px 0;
411
+ text-align: center;
412
+ }}
413
+ .prisma-flow-chart h3 {{
414
+ margin-bottom: 15px;
415
+ }}
416
  @media print {{
417
  body {{
418
  background-color: white;
 
591
  border-radius: 8px;
592
  }
593
 
594
+ /* PRISMA Flow Chart Container */
595
+ .prisma-section {
596
+ background-color: white;
597
+ padding: 20px;
598
+ border-radius: 8px;
599
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
600
+ margin-bottom: 20px;
601
+ }
602
+
603
+ .prisma-form {
604
+ display: grid;
605
+ grid-template-columns: 1fr 1fr;
606
+ gap: 15px;
607
+ }
608
+
609
  /* Responsive adjustments */
610
  @media screen and (max-width: 768px) {
611
  .gradio-container {
612
  padding: 10px;
613
  }
614
+ .prisma-form {
615
+ grid-template-columns: 1fr;
616
+ }
617
  }
618
  </style>
619
  """
620
 
621
  # Gradio UI Layout with improved styling
622
  with gr.Blocks(css=custom_css) as demo:
623
+ gr.Markdown("# Systematic Review Generator with PRISMA Flow Chart")
624
 
625
  with gr.Accordion("How to Use This App", open=False):
626
  gr.Markdown("""
 
628
  1. Enter your OpenAI API key in the field below and click "Set API Key"
629
  2. Upload multiple PDF research papers (2 or more recommended)
630
  3. Enter your review question or topic
631
+ 4. Fill in the PRISMA flow chart information (numbers at each stage of your review)
632
+ 5. Check the "Include Tables" option if you want the review to include comparison tables
633
+ 6. Click "Generate Systematic Review" to start the process
634
+ 7. After generation, you can download the review as HTML
635
+
636
+ ### PRISMA Flow Chart:
637
+ - The PRISMA (Preferred Reporting Items for Systematic Reviews and Meta-Analyses) flow diagram shows the flow of information through the different phases of your systematic review
638
+ - Fill in the numbers for each stage to generate an accurate diagram
639
+ - The diagram will be embedded in your systematic review
640
 
641
  ### Tips for Best Results:
642
  - Upload papers that are related to the same research topic or field
 
665
  placeholder="e.g., What are the effects of mindfulness meditation on stress reduction?"
666
  )
667
  include_tables = gr.Checkbox(label="Include Comparison Tables", value=True)
668
+
669
+ # PRISMA Flow Chart inputs
670
+ with gr.Row(elem_classes="prisma-section"):
671
+ with gr.Column():
672
+ gr.Markdown("### PRISMA Flow Chart Information")
673
+ gr.Markdown("Enter the numbers for each stage of your systematic review process:")
674
+
675
+ with gr.Row(elem_classes="prisma-form"):
676
+ prisma_records_db = gr.Textbox(label="Records from database searching", value="100", placeholder="e.g., 100")
677
+ prisma_records_other = gr.Textbox(label="Records from other sources", value="20", placeholder="e.g., 20")
678
+ prisma_duplicates = gr.Textbox(label="Duplicates removed", value="15", placeholder="e.g., 15")
679
+ prisma_excluded_screening = gr.Textbox(label="Records excluded at screening", value="60", placeholder="e.g., 60")
680
+ prisma_excluded_fulltext = gr.Textbox(label="Full-text articles excluded", value="30", placeholder="e.g., 30")
681
+ prisma_included_studies = gr.Textbox(label="Studies included in synthesis", value="15", placeholder="e.g., 15")
682
+ prisma_included_meta = gr.Textbox(label="Studies in meta-analysis (optional)", value="10", placeholder="e.g., 10")
683
+
684
  generate_button = gr.Button("Generate Systematic Review", elem_id="generate_button", size="large")
685
 
686
  # Download link container
 
694
  api_key_button.click(set_api_key, inputs=[api_key_input], outputs=[api_key_output])
695
 
696
  # Generate systematic review
697
+ def process_files_and_generate_review(files, question, include_tables,
698
+ records_db, records_other, duplicates,
699
+ excluded_screening, excluded_fulltext,
700
+ included_studies, included_meta):
701
  if not files:
702
  return ("""
703
  <div style="padding: 20px; border: 1px solid #e0e0e0; border-radius: 5px; background-color: #f9f9f9;">
 
712
  # Show loading message
713
  loading_message = """
714
  <div style="padding: 20px; text-align: center;">
715
+ <h3>Generating Systematic Review with PRISMA Flow Chart...</h3>
716
  <p>This may take a few minutes depending on the number and size of papers.</p>
717
  <div style="width: 100%; height: 4px; background-color: #f0f0f0; margin: 20px 0; border-radius: 2px; overflow: hidden;">
718
  <div style="width: 30%; height: 100%; background: linear-gradient(90deg, #4a00e0, #8e2de2); animation: progress 2s infinite linear;"></div>
 
728
 
729
  yield loading_message, ""
730
 
731
+ # Collect PRISMA flow chart data
732
+ prisma_numbers = {
733
+ 'records_db': records_db,
734
+ 'records_other': records_other,
735
+ 'duplicates': duplicates,
736
+ 'excluded_screening': excluded_screening,
737
+ 'excluded_fulltext': excluded_fulltext,
738
+ 'included_studies': included_studies,
739
+ 'included_meta': included_meta
740
+ }
741
+
742
+ # Generate review with PRISMA flow chart
743
+ review = generate_systematic_review(saved_paths, question, prisma_numbers, include_tables)
744
 
745
  # Create HTML download link
746
  html_link = create_html_download_link(review)
 
766
 
767
  generate_button.click(
768
  process_files_and_generate_review,
769
+ inputs=[pdf_files, review_question, include_tables,
770
+ prisma_records_db, prisma_records_other, prisma_duplicates,
771
+ prisma_excluded_screening, prisma_excluded_fulltext,
772
+ prisma_included_studies, prisma_included_meta],
773
  outputs=[review_output, download_html_output]
774
  )
775