rishabh5752 commited on
Commit
07adbc0
·
verified ·
1 Parent(s): af0780a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -52
app.py CHANGED
@@ -1,18 +1,15 @@
1
  """
2
- Governance-GPT QuizLLM-powered bucket report
3
  Author: Rishabh Sharma · 2025-09-14
4
- One-file Gradio Space → 15-Q Likert survey → bucket scores → FLAN-T5 summary → PDF
5
  """
6
 
7
- import datetime, tempfile, warnings
8
  import gradio as gr
9
  import pandas as pd
10
- from fpdf import FPDF # pure-Python PDF (core Helvetica font)
11
- from transformers import pipeline # Hugging Face inference
12
 
13
- # ───────────────────────────────────────────────────────────
14
- # 1. Load a lightweight model once (≈ 80 M params, CPU-friendly)
15
- # ───────────────────────────────────────────────────────────
16
  warnings.filterwarnings("ignore", category=UserWarning)
17
  summariser = pipeline(
18
  task="text2text-generation",
@@ -21,9 +18,7 @@ summariser = pipeline(
21
  max_new_tokens=150,
22
  )
23
 
24
- # ───────────────────────────────────────────────────────────
25
- # 2. Question bank & buckets
26
- # ───────────────────────────────────────────────────────────
27
  QUESTIONS = [
28
  "Governance framework is documented and communicated across the organisation.",
29
  "Roles & responsibilities for AI oversight are clearly assigned.",
@@ -62,24 +57,19 @@ TIERS = {
62
  "Optimized": (4.51, 5.00),
63
  }
64
 
65
- # ───────────────────────────────────────────────────────────
66
- # 3. Helper functions
67
- # ───────────────────────────────────────────────────────────
68
- def score_to_tier(avg: float) -> str:
69
- for tier, (low, high) in TIERS.items():
70
- if low <= avg <= high:
71
  return tier
72
  return "Unclassified"
73
 
74
  def latin1(txt: str) -> str:
75
- """Force text into Latin-1 for the core fonts used by FPDF."""
 
76
  return txt.encode("latin-1", "replace").decode("latin-1")
77
 
78
  def llm_remediation(product: str, bucket_avgs: dict, overall_tier: str) -> str:
79
- """
80
- Ask FLAN-T5-small to write a short markdown summary.
81
- Uses only ASCII bullets ('-') so the PDF core font can render them.
82
- """
83
  bucket_lines = "\n".join(f"- {b}: {v:.2f}" for b, v in bucket_avgs.items())
84
  prompt = (
85
  "You are an AI governance consultant.\n"
@@ -87,41 +77,42 @@ def llm_remediation(product: str, bucket_avgs: dict, overall_tier: str) -> str:
87
  f"Overall tier: {overall_tier}\n"
88
  "Bucket scores (1-5):\n"
89
  f"{bucket_lines}\n\n"
90
- "Write a concise markdown summary (120 words) with:\n"
91
  "- One overall assessment sentence.\n"
92
  "- 3-5 bullet remediation actions referencing bucket names.\n"
93
  "Return only the summary."
94
  )
95
 
96
- # Generate
97
- raw = summariser(prompt)[0]["generated_text"].strip()
98
 
99
- # Some T5 models echo a slice of the prompt. Remove if present.
100
- if raw.startswith(prompt[:50]):
101
- raw = raw[len(prompt):].strip()
 
 
 
102
 
103
- # Replace any unicode bullets with ASCII "- "
104
- summary = raw.replace("•", "- ")
105
- return summary if summary else "Summary unavailable."
106
 
107
- def build_pdf(product: str, bucket_df: pd.DataFrame,
108
- overall_avg: float, overall_tier: str,
109
- file_path: str, summary_text: str):
110
  pdf = FPDF()
111
  pdf.set_auto_page_break(auto=True, margin=15)
112
  pdf.add_page()
113
 
114
  pdf.set_font("Helvetica", "B", 16)
115
- pdf.cell(0, 10, latin1(f"AI Governance Maturity Report {product}"), ln=1, align="C")
116
 
117
  pdf.set_font("Helvetica", "", 12)
118
- pdf.cell(0, 8, f"Generated on {datetime.date.today().isoformat()}", ln=1, align="C")
119
  pdf.ln(4)
120
 
121
  pdf.set_font("Helvetica", "B", 12)
122
- pdf.cell(0, 8, latin1(f"Overall Score: {overall_avg:.2f} | Tier: {overall_tier}"), ln=1)
123
  pdf.set_font("Helvetica", "", 11)
124
- pdf.multi_cell(0, 6, latin1(summary_text))
125
  pdf.ln(4)
126
 
127
  pdf.set_font("Helvetica", "B", 11)
@@ -139,19 +130,16 @@ def build_pdf(product: str, bucket_df: pd.DataFrame,
139
  pdf.cell(35, 8, f"{overall_avg:.2f}", 1)
140
  pdf.cell(35, 8, overall_tier, 1, ln=1)
141
 
142
- pdf.output(file_path)
143
 
144
- # ───────────────────────────────────────────────────────────
145
- # 4. Gradio callback
146
- # ───────────────────────────────────────────────────────────
147
  def generate_report(product_name, *scores):
148
  product = product_name.strip() or "your product"
149
  scores = list(scores)
150
 
151
- # Bucket averages
152
  bucket_avgs = {
153
- bucket: sum(scores[i] for i in idxs) / len(idxs)
154
- for bucket, idxs in BUCKETS.items()
155
  }
156
  overall_avg = sum(scores) / len(scores)
157
  overall_tier = score_to_tier(overall_avg)
@@ -169,24 +157,22 @@ def generate_report(product_name, *scores):
169
 
170
  return summary_md, tmp_pdf.name
171
 
172
- # ───────────────────────────────────────────────────────────
173
- # 5. Gradio UI
174
- # ───────────────────────────────────────────────────────────
175
  with gr.Blocks(title="Governance-GPT Quiz") as demo:
176
  gr.Markdown(
177
  """
178
  # Governance-GPT Quiz
179
  Enter your **product / system name**, rate each statement from **1 (Strongly Disagree)** to **5 (Strongly Agree)**,
180
- and receive an LLM-generated remediation plan plus a PDF bucket report.
181
  """
182
  )
183
 
184
- product_inp = gr.Textbox(label="Product / System Name", placeholder="e.g. AcmeAI Recommendation Engine")
185
- sliders = [gr.Slider(1, 5, value=3, step=1, label=q) for q in QUESTIONS]
186
 
187
  btn = gr.Button("Generate PDF Report")
188
  summary_out = gr.Markdown()
189
- pdf_out = gr.File(label="⬇️ Download your PDF")
190
 
191
  btn.click(fn=generate_report,
192
  inputs=[product_inp] + sliders,
 
1
  """
2
+ Governance-GPT Quiz – ASCII-safe, LLM-powered PDF
3
  Author: Rishabh Sharma · 2025-09-14
 
4
  """
5
 
6
+ import datetime, tempfile, re, warnings
7
  import gradio as gr
8
  import pandas as pd
9
+ from fpdf import FPDF
10
+ from transformers import pipeline
11
 
12
+ # ── Load a lightweight CPU model ───────────────────────────────────
 
 
13
  warnings.filterwarnings("ignore", category=UserWarning)
14
  summariser = pipeline(
15
  task="text2text-generation",
 
18
  max_new_tokens=150,
19
  )
20
 
21
+ # ── Questions & buckets ────────────────────────────────────────────
 
 
22
  QUESTIONS = [
23
  "Governance framework is documented and communicated across the organisation.",
24
  "Roles & responsibilities for AI oversight are clearly assigned.",
 
57
  "Optimized": (4.51, 5.00),
58
  }
59
 
60
+ # ── Helpers ─────────────────────────────────────────────────────────
61
+ def score_to_tier(avg):
62
+ for tier, (lo, hi) in TIERS.items():
63
+ if lo <= avg <= hi:
 
 
64
  return tier
65
  return "Unclassified"
66
 
67
  def latin1(txt: str) -> str:
68
+ """Replace common Unicode chars with ASCII equivalents, then enforce Latin-1."""
69
+ txt = txt.replace("–", "-").replace("—", "-").replace("•", "-")
70
  return txt.encode("latin-1", "replace").decode("latin-1")
71
 
72
  def llm_remediation(product: str, bucket_avgs: dict, overall_tier: str) -> str:
 
 
 
 
73
  bucket_lines = "\n".join(f"- {b}: {v:.2f}" for b, v in bucket_avgs.items())
74
  prompt = (
75
  "You are an AI governance consultant.\n"
 
77
  f"Overall tier: {overall_tier}\n"
78
  "Bucket scores (1-5):\n"
79
  f"{bucket_lines}\n\n"
80
+ "Write a concise markdown summary (<=120 words) with:\n"
81
  "- One overall assessment sentence.\n"
82
  "- 3-5 bullet remediation actions referencing bucket names.\n"
83
  "Return only the summary."
84
  )
85
 
86
+ raw = summariser(prompt)[0]["generated_text"]
 
87
 
88
+ # ── Strip any prompt echo or leftover instruction lines ──
89
+ lines = [
90
+ ln for ln in raw.splitlines()
91
+ if not re.search(r"bullet remediation|overall assessment|Write a concise", ln, re.I)
92
+ ]
93
+ cleaned = "\n".join(lines).strip()
94
 
95
+ # Replace bullets with ASCII dash (in case model outputs •)
96
+ cleaned = cleaned.replace("•", "- ")
 
97
 
98
+ return cleaned or "LLM summary unavailable."
99
+
100
+ def build_pdf(product, bucket_df, overall_avg, overall_tier, pdf_path, summary):
101
  pdf = FPDF()
102
  pdf.set_auto_page_break(auto=True, margin=15)
103
  pdf.add_page()
104
 
105
  pdf.set_font("Helvetica", "B", 16)
106
+ pdf.cell(0, 10, latin1(f"AI Governance Maturity Report - {product}"), ln=1, align="C")
107
 
108
  pdf.set_font("Helvetica", "", 12)
109
+ pdf.cell(0, 8, datetime.date.today().isoformat(), ln=1, align="C")
110
  pdf.ln(4)
111
 
112
  pdf.set_font("Helvetica", "B", 12)
113
+ pdf.cell(0, 8, latin1(f"Overall Score: {overall_avg:.2f} | Tier: {overall_tier}"), ln=1)
114
  pdf.set_font("Helvetica", "", 11)
115
+ pdf.multi_cell(0, 6, latin1(summary))
116
  pdf.ln(4)
117
 
118
  pdf.set_font("Helvetica", "B", 11)
 
130
  pdf.cell(35, 8, f"{overall_avg:.2f}", 1)
131
  pdf.cell(35, 8, overall_tier, 1, ln=1)
132
 
133
+ pdf.output(pdf_path)
134
 
135
+ # ── Gradio callback ────────────────────────────────────────────────
 
 
136
  def generate_report(product_name, *scores):
137
  product = product_name.strip() or "your product"
138
  scores = list(scores)
139
 
 
140
  bucket_avgs = {
141
+ b: sum(scores[i] for i in idxs) / len(idxs)
142
+ for b, idxs in BUCKETS.items()
143
  }
144
  overall_avg = sum(scores) / len(scores)
145
  overall_tier = score_to_tier(overall_avg)
 
157
 
158
  return summary_md, tmp_pdf.name
159
 
160
+ # ── UI ────────────────────────────────────────────────────────────
 
 
161
  with gr.Blocks(title="Governance-GPT Quiz") as demo:
162
  gr.Markdown(
163
  """
164
  # Governance-GPT Quiz
165
  Enter your **product / system name**, rate each statement from **1 (Strongly Disagree)** to **5 (Strongly Agree)**,
166
+ then download an LLM-generated remediation plan and bucket-level PDF.
167
  """
168
  )
169
 
170
+ product_inp = gr.Textbox(label="Product / System Name", placeholder="e.g. AcmeAI Recommender")
171
+ sliders = [gr.Slider(1, 5, 3, 1, label=q) for q in QUESTIONS]
172
 
173
  btn = gr.Button("Generate PDF Report")
174
  summary_out = gr.Markdown()
175
+ pdf_out = gr.File(label="⬇️ Download PDF")
176
 
177
  btn.click(fn=generate_report,
178
  inputs=[product_inp] + sliders,