rishabh5752 commited on
Commit
ee78979
·
verified ·
1 Parent(s): d82715f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -76
app.py CHANGED
@@ -1,135 +1,194 @@
 
 
 
 
 
 
1
  import os, tempfile, datetime
2
  import gradio as gr
3
  import pandas as pd
4
- from fpdf import FPDF # pure-python PDF generator – no wkhtmltopdf needed
5
 
6
- # ---------- Quiz Definition ---------- #
7
  QUESTIONS = [
8
- "1. Governance framework is documented and communicated across the organisation.",
9
- "2. Roles & responsibilities for AI oversight are clearly assigned.",
10
- "3. Data lineage is captured and auditable for all production models.",
11
- "4. Privacy impact assessments are performed before every new AI use-case.",
12
- "5. Model cards or equivalent documentation exist for each deployed model.",
13
- "6. Bias / fairness metrics are monitored post-deployment.",
14
- "7. Incident response playbooks cover AI system failures & ethics breaches.",
15
- "8. Third-party models and datasets are licensed and risk-assessed.",
16
- "9. KPIs link AI outcomes to business & societal value.",
17
- "10. Continuous training keeps staff aware of AI policy updates.",
18
- "11. Security controls protect model artefacts and inference endpoints.",
19
- "12. Explainability techniques are applied commensurate with model impact.",
20
- "13. Human-in-the-loop overrides exist for high-risk decisions.",
21
- "14. End-of-life or rollback criteria are defined for all models.",
22
- "15. Governance performance is reviewed by senior leadership at least quarterly.",
 
 
 
 
23
  ]
24
 
 
 
 
 
 
 
 
 
 
25
  TIERS = {
26
- "Initial": (1.0, 2.0),
27
- "Repeatable": (2.01, 2.5),
28
- "Defined": (2.51, 3.5),
29
- "Managed": (3.51, 4.5),
30
- "Optimized": (4.51, 5.0),
31
  }
32
 
33
- ACTIONS = {
34
- "Initial": "Kick-off a cross-functional task-force, map critical use-cases, prioritise policy creation.",
35
- "Repeatable": "Formalise processes; introduce mandatory model documentation & basic monitoring.",
36
- "Defined": "Scale governance with automated lineage capture, bias dashboards, and internal audits.",
37
- "Managed": "Integrate governance KPIs into OKRs; adopt continuous compliance tooling.",
38
- "Optimized": "Benchmark externally (OECD, ISO 42001), publish transparency reports, champion open-governance.",
 
39
  }
40
 
41
- # ---------- Helper Functions ---------- #
 
 
 
 
 
 
 
 
 
42
  def score_to_tier(avg: float) -> str:
43
  for tier, (low, high) in TIERS.items():
44
  if low <= avg <= high:
45
  return tier
46
  return "Unclassified"
47
 
48
- def latin1_safe(txt: str) -> str:
49
- """Replace problematic chars & force Latin-1 compliance for FPDF core fonts."""
50
- txt = txt.replace("…", "...") # swap Unicode ellipsis
51
- return txt.encode("latin-1", "replace").decode("latin-1")
52
 
53
- def build_pdf(name: str, df: pd.DataFrame, avg: float, tier: str, file_path: str):
54
- from fpdf import FPDF
55
  pdf = FPDF()
56
  pdf.set_auto_page_break(auto=True, margin=15)
57
  pdf.add_page()
58
 
59
- # Title block
60
  pdf.set_font("Helvetica", "B", 16)
61
- pdf.cell(0, 10, latin1_safe("AI Governance Maturity Report"), ln=1, align="C")
62
  pdf.set_font("Helvetica", "", 12)
63
  pdf.cell(0, 8, f"Generated on {datetime.date.today().isoformat()}", ln=1, align="C")
64
  pdf.ln(4)
65
 
66
  # Summary
67
  pdf.set_font("Helvetica", "B", 12)
68
- pdf.cell(0, 8, latin1_safe(f"Overall Score: {avg:.2f} | Tier: {tier}"), ln=1)
69
  pdf.set_font("Helvetica", "", 11)
70
- pdf.multi_cell(0, 6, latin1_safe(f"Next step recommendation: {ACTIONS[tier]}"))
71
  pdf.ln(4)
72
 
73
- # Table header
74
  pdf.set_font("Helvetica", "B", 11)
75
- pdf.cell(10, 8, "#", 1)
76
- pdf.cell(150, 8, "Question", 1)
77
- pdf.cell(20, 8, "Score", 1, ln=1)
78
  pdf.set_font("Helvetica", "", 10)
79
 
80
- for idx, row in df.iterrows():
81
- question_txt = row["Question"]
82
- if len(question_txt) > 65:
83
- question_txt = question_txt[:62] + "..." # ASCII dots
 
84
 
85
- pdf.cell(10, 8, str(idx + 1), 1)
86
- pdf.cell(150, 8, latin1_safe(question_txt), 1)
87
- pdf.cell(20, 8, str(row["Score"]), 1, ln=1)
 
88
 
89
  pdf.output(file_path)
90
 
91
- def generate_report(*scores):
92
- """Gradio callback returns Markdown summary + PDF path."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  scores = list(scores)
94
- avg = sum(scores) / len(scores)
95
- tier = score_to_tier(avg)
96
 
97
- # DataFrame for table in PDF
98
- df = pd.DataFrame({"Question": QUESTIONS, "Score": scores})
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
- # Temporary PDF file
 
 
 
101
  tmp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
102
- build_pdf("Report", df, avg, tier, tmp_pdf.name)
103
 
104
- md_summary = (
105
- f"### ✅ Your AI Governance Tier: **{tier}** \n"
106
- f"**Average score:** {avg:.2f} / 5.00 \n"
107
- f"**Action plan:** {ACTIONS[tier]}"
108
- )
109
- return md_summary, tmp_pdf.name
110
 
111
- # ---------- Gradio UI ---------- #
112
  with gr.Blocks(title="Governance-GPT Quiz") as demo:
113
  gr.Markdown(
114
  """
115
  # Governance-GPT Quiz
116
- Rate each statement from **1 (Strongly Disagree)** to **5 (Strongly Agree)**.
117
- The tool benchmarks your AI-governance maturity and produces a PDF action plan aligned with OECD AI Principles.
118
  """
119
  )
120
 
121
- sliders = []
122
- for q in QUESTIONS:
123
- sliders.append(gr.Slider(1, 5, value=3, step=1, label=q))
124
 
125
- generate_btn = gr.Button("Generate Report")
126
- summary_md = gr.Markdown()
127
- pdf_file = gr.File(label="⬇️ Download PDF")
128
 
129
- generate_btn.click(
130
  fn=generate_report,
131
- inputs=sliders,
132
- outputs=[summary_md, pdf_file],
133
  )
134
 
135
  demo.launch()
 
1
+ """
2
+ Governance-GPT Quiz – AI-Maturity Self-Assessment (bucket version)
3
+ Author: Rishabh Sharma – 2025-09-14
4
+ Single-file Gradio Space: 15-question Likert survey ➜ bucket scores ➜ PDF+summary
5
+ """
6
+
7
  import os, tempfile, datetime
8
  import gradio as gr
9
  import pandas as pd
10
+ from fpdf import FPDF # pure-python PDF – no external binaries
11
 
12
+ # ------------------- Question bank ------------------- #
13
  QUESTIONS = [
14
+ "Governance framework is documented and communicated across the organisation.",
15
+ "Roles & responsibilities for AI oversight are clearly assigned.",
16
+ "KPIs link AI outcomes to business & societal value.",
17
+
18
+ "Data lineage is captured and auditable for all production models.",
19
+ "Privacy impact assessments are performed before every new AI use-case.",
20
+ "Bias / fairness metrics are monitored post-deployment.",
21
+
22
+ "Incident response playbooks cover AI system failures & ethics breaches.",
23
+ "Third-party models and datasets are licensed and risk-assessed.",
24
+ "Governance performance is reviewed by senior leadership at least quarterly.",
25
+
26
+ "Security controls protect model artefacts and inference endpoints.",
27
+ "Continuous training keeps staff aware of AI policy updates.",
28
+ "Explainability techniques are applied commensurate with model impact.",
29
+
30
+ "Human-in-the-loop overrides exist for high-risk decisions.",
31
+ "End-of-life or rollback criteria are defined for all models.",
32
+ "Model cards or equivalent documentation exist for each deployed model.",
33
  ]
34
 
35
+ # Five buckets, 3 questions each (index positions are 0-based)
36
+ BUCKETS = {
37
+ "Governance & Strategy": [0, 1, 2],
38
+ "Data & Privacy": [3, 4, 5],
39
+ "Risk & Compliance": [6, 7, 8],
40
+ "Security & Infrastructure": [9, 10, 11],
41
+ "Lifecycle & Oversight": [12, 13, 14],
42
+ }
43
+
44
  TIERS = {
45
+ "Initial": (1.00, 2.00),
46
+ "Repeatable": (2.01, 2.50),
47
+ "Defined": (2.51, 3.50),
48
+ "Managed": (3.51, 4.50),
49
+ "Optimized": (4.51, 5.00),
50
  }
51
 
52
+ # Generic tier actions (overall)
53
+ OVERALL_ACTION = {
54
+ "Initial": "kick-off a cross-functional task-force and establish a basic AI policy.",
55
+ "Repeatable": "formalise core processes and create mandatory model documentation.",
56
+ "Defined": "scale governance with automated monitoring and periodic audits.",
57
+ "Managed": "integrate governance KPIs into OKRs and adopt continuous compliance tooling.",
58
+ "Optimized": "benchmark externally, publish transparency reports, and champion open governance.",
59
  }
60
 
61
+ # Bucket-specific remediation snippets
62
+ BUCKET_ACTION = {
63
+ "Governance & Strategy": "formalise decision rights and publish an organisation-wide AI charter.",
64
+ "Data & Privacy": "implement end-to-end data lineage and privacy impact assessments.",
65
+ "Risk & Compliance": "create incident playbooks and third-party risk registers.",
66
+ "Security & Infrastructure": "harden model artefact storage and secure inference endpoints.",
67
+ "Lifecycle & Oversight": "define human-override mechanisms and retirement criteria for models.",
68
+ }
69
+
70
+ # ------------------- Helpers ------------------- #
71
  def score_to_tier(avg: float) -> str:
72
  for tier, (low, high) in TIERS.items():
73
  if low <= avg <= high:
74
  return tier
75
  return "Unclassified"
76
 
77
+ def latin1(txt: str) -> str:
78
+ """Convert to Latin-1 safe string for FPDF."""
79
+ return txt.replace("…", "...").encode("latin-1", "replace").decode("latin-1")
 
80
 
81
+ def build_pdf(product: str, bucket_df: pd.DataFrame, overall_avg: float,
82
+ overall_tier: str, file_path: str, summary_text: str):
83
  pdf = FPDF()
84
  pdf.set_auto_page_break(auto=True, margin=15)
85
  pdf.add_page()
86
 
87
+ # Title
88
  pdf.set_font("Helvetica", "B", 16)
89
+ pdf.cell(0, 10, latin1(f"AI Governance Maturity Report – {product}"), ln=1, align="C")
90
  pdf.set_font("Helvetica", "", 12)
91
  pdf.cell(0, 8, f"Generated on {datetime.date.today().isoformat()}", ln=1, align="C")
92
  pdf.ln(4)
93
 
94
  # Summary
95
  pdf.set_font("Helvetica", "B", 12)
96
+ pdf.cell(0, 8, latin1(f"Overall Score: {overall_avg:.2f} | Tier: {overall_tier}"), ln=1)
97
  pdf.set_font("Helvetica", "", 11)
98
+ pdf.multi_cell(0, 6, latin1(summary_text))
99
  pdf.ln(4)
100
 
101
+ # Bucket table header
102
  pdf.set_font("Helvetica", "B", 11)
103
+ pdf.cell(80, 8, "Bucket", 1)
104
+ pdf.cell(35, 8, "Avg Score", 1)
105
+ pdf.cell(35, 8, "Tier", 1, ln=1)
106
  pdf.set_font("Helvetica", "", 10)
107
 
108
+ # Rows
109
+ for _, row in bucket_df.iterrows():
110
+ pdf.cell(80, 8, latin1(row["Bucket"][:40]), 1)
111
+ pdf.cell(35, 8, f'{row["Avg Score"]:.2f}', 1)
112
+ pdf.cell(35, 8, row["Tier"], 1, ln=1)
113
 
114
+ # Overall row
115
+ pdf.cell(80, 8, "Overall", 1)
116
+ pdf.cell(35, 8, f"{overall_avg:.2f}", 1)
117
+ pdf.cell(35, 8, overall_tier, 1, ln=1)
118
 
119
  pdf.output(file_path)
120
 
121
+ def generate_summary(product: str, bucket_avgs: dict, overall_tier: str) -> str:
122
+ """Return markdown remediation summary."""
123
+ lines = [f"### 🏷️ AI Governance Summary for **{product}**",
124
+ f"- **Overall tier:** {overall_tier}"]
125
+
126
+ # Bucket-specific feedback
127
+ for bucket, avg in bucket_avgs.items():
128
+ tier = score_to_tier(avg)
129
+ # Only add remediation if below Managed
130
+ if tier in ("Initial", "Repeatable", "Defined"):
131
+ lines.append(f"- **{bucket}** score is {avg:.2f} → *{tier}*. "
132
+ f"{product} should {BUCKET_ACTION[bucket]}")
133
+ # If all buckets high, generic kudos
134
+ if len(lines) == 2:
135
+ lines.append("Great job! All buckets are Managed or Optimized.")
136
+
137
+ # Overall action line
138
+ lines.append(f"- Next step: {product} should {OVERALL_ACTION[overall_tier]}")
139
+ return " \n".join(lines)
140
+
141
+ # ------------------- Gradio callback ------------------- #
142
+ def generate_report(product_name, *scores):
143
+ product = product_name.strip() or "your product"
144
  scores = list(scores)
 
 
145
 
146
+ # Compute bucket averages
147
+ bucket_avgs = {}
148
+ for bucket, idxs in BUCKETS.items():
149
+ bucket_avgs[bucket] = sum(scores[i] for i in idxs) / len(idxs)
150
+
151
+ overall_avg = sum(scores) / len(scores)
152
+ overall_tier = score_to_tier(overall_avg)
153
+
154
+ # Prepare DF for PDF table
155
+ bucket_df = pd.DataFrame({
156
+ "Bucket": list(bucket_avgs.keys()),
157
+ "Avg Score": list(bucket_avgs.values()),
158
+ "Tier": [score_to_tier(v) for v in bucket_avgs.values()],
159
+ })
160
 
161
+ # Build remediation summary
162
+ summary_md = generate_summary(product, bucket_avgs, overall_tier)
163
+
164
+ # Generate PDF
165
  tmp_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf")
166
+ build_pdf(product, bucket_df, overall_avg, overall_tier, tmp_pdf.name, summary_md)
167
 
168
+ return summary_md, tmp_pdf.name
 
 
 
 
 
169
 
170
+ # ------------------- Gradio UI ------------------- #
171
  with gr.Blocks(title="Governance-GPT Quiz") as demo:
172
  gr.Markdown(
173
  """
174
  # Governance-GPT Quiz
175
+ Enter your **product / system name**, rate each statement from **1 (Strongly Disagree)** to **5 (Strongly Agree)**,
176
+ and get a bucket-wise governance score with a personalised remediation plan.
177
  """
178
  )
179
 
180
+ product_inp = gr.Textbox(label="Product / System Name", placeholder="e.g. AcmeAI Recommendation Engine")
181
+
182
+ sliders = [gr.Slider(1, 5, value=3, step=1, label=q) for q in QUESTIONS]
183
 
184
+ btn = gr.Button("Generate PDF Report")
185
+ summary_out = gr.Markdown()
186
+ pdf_out = gr.File(label="⬇️ Download your PDF")
187
 
188
+ btn.click(
189
  fn=generate_report,
190
+ inputs=[product_inp] + sliders,
191
+ outputs=[summary_out, pdf_out],
192
  )
193
 
194
  demo.launch()