Spaces:
Sleeping
Sleeping
File size: 5,936 Bytes
f3779c7 b677070 f3779c7 b677070 f3779c7 b677070 f3779c7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | import gradio as gr
import pandas as pd
import plotly.graph_objects as go
from ui.multi_report_functions import (
load_multi_pdfs,
run_coverage_scores,
run_commitment_scores,
run_positioning_chart,
recalculate_from_revised_file,
run_revised_positioning_chart
)
def build_multi_report_page():
"""
Builds the Multi-Report Comparative Analysis page.
Returns back_btn so interface.py can wire the Back navigation.
This page is placed inside a gr.Tab by build_interface() rather than
toggled via Column visibility, to avoid Gradio's known rendering bug
where complex children (Dataframe, Plot, Gallery) can break after a
parent Column's visibility is toggled off and back on.
"""
back_btn = gr.Button("⬅ Back to Home", size="sm")
gr.Markdown("# Multi-Report Comparative Analysis")
gr.Markdown(
"Upload multiple company sustainability reports to compare "
"their ESG disclosure coverage and commitment levels."
)
# =========================
# UPLOAD
# =========================
gr.Markdown("## Step 1: Upload Reports")
multi_file = gr.File(
label="Upload PDF Reports (you can select multiple files)",
file_count="multiple"
)
load_multi_btn = gr.Button("Load Reports", variant="primary")
upload_status = gr.Markdown()
extracted_download = gr.File(label="Download Combined Extracted CSV")
# =========================
# COVERAGE SCORES
# =========================
gr.Markdown("## Step 2: Coverage Scores")
gr.Markdown(
"Measures how much of each report is sustainability-relevant: "
"**Relevant ÷ (Relevant + Irrelevant) × 100**"
)
coverage_btn = gr.Button("Run Coverage Scores", variant="primary")
coverage_status = gr.Markdown()
coverage_table = gr.Dataframe(value=pd.DataFrame(), label="Coverage Scores (ranked)", interactive=False)
coverage_download = gr.File(label="Download Coverage Scores CSV (per-report summary)")
coverage_detail_download = gr.File(label="Download Per-Paragraph Detail CSV")
# =========================
# COMMITMENT SCORES
# =========================
gr.Markdown("## Step 3: Commitment Scores")
gr.Markdown(
"Measures the depth of disclosure among relevant paragraphs "
"(quantitative claims are weighted higher than qualitative ones). "
"Requires Coverage Scores to be run first."
)
commitment_btn = gr.Button("Run Commitment Scores", variant="primary")
commitment_status = gr.Markdown()
commitment_table = gr.Dataframe(value=pd.DataFrame(), label="Commitment Scores (ranked)", interactive=False)
commitment_download = gr.File(label="Download Commitment Scores CSV (per-report summary)")
commitment_detail_download = gr.File(label="Download Per-Paragraph Detail CSV (PM/FC retrieval + classification)")
# ---------- Positioning Quadrant Chart ----------
gr.Markdown("### Positioning")
gr.Markdown(
"Plots each company by Commitment Score (x-axis) vs Coverage Score "
"(y-axis), split into four quadrants at the average of each score "
"across all uploaded reports."
)
positioning_btn = gr.Button("Run Positioning", variant="primary")
positioning_status = gr.Markdown()
positioning_chart = gr.Plot(value=go.Figure(), label="Positioning")
# =========================
# REVISE & RECALCULATE
# =========================
gr.Markdown("## Step 4: Revise & Recalculate (Optional)")
gr.Markdown(
"If you reviewed the downloaded per-paragraph detail CSVs and "
"corrected some predictions by hand, upload the revised file here "
"to recompute Coverage Scores, Commitment Scores, and a new "
"Positioning chart from it. The original results above are left "
"untouched, so you can compare both side by side.\n\n"
"Expected columns: `Doc_name`, `SA_label` (Relevant/Irrelevant), "
"`QQ_label` (Qualitative/Quantitative), `PMFC_Label` "
"(`Answer: PM` / `Answer: FC`). Rows with missing or unrecognized "
"values in these columns are excluded from the relevant counts "
"rather than causing an error."
)
revised_file = gr.File(label="Upload Revised Per-Paragraph CSV")
recalculate_btn = gr.Button("Recalculate Scores", variant="primary")
recalculate_status = gr.Markdown()
revised_coverage_table = gr.Dataframe(value=pd.DataFrame(), label="Revised Coverage Scores (ranked)", interactive=False)
revised_commitment_table = gr.Dataframe(value=pd.DataFrame(), label="Revised Commitment Scores (ranked)", interactive=False)
revised_positioning_btn = gr.Button("Run Revised Positioning", variant="primary")
revised_positioning_status = gr.Markdown()
revised_positioning_chart = gr.Plot(value=go.Figure(), label="Positioning (Revised)")
# =========================
# CONNECTIONS
# =========================
load_multi_btn.click(
load_multi_pdfs,
inputs=multi_file,
outputs=[extracted_download, upload_status]
)
coverage_btn.click(
run_coverage_scores,
outputs=[coverage_table, coverage_download, coverage_detail_download, coverage_status]
)
commitment_btn.click(
run_commitment_scores,
outputs=[commitment_table, commitment_download, commitment_detail_download, commitment_status]
)
positioning_btn.click(
run_positioning_chart,
outputs=[positioning_chart, positioning_status]
)
recalculate_btn.click(
recalculate_from_revised_file,
inputs=revised_file,
outputs=[revised_coverage_table, revised_commitment_table, recalculate_status]
)
revised_positioning_btn.click(
run_revised_positioning_chart,
outputs=[revised_positioning_chart, revised_positioning_status]
)
return back_btn
|