Dave67350 commited on
Commit
8550003
·
verified ·
1 Parent(s): 75b830c

Update tools/ai_act_generator.py

Browse files
Files changed (1) hide show
  1. tools/ai_act_generator.py +40 -99
tools/ai_act_generator.py CHANGED
@@ -2,25 +2,16 @@
2
  # coding=utf-8
3
  import csv
4
  import datetime
5
- import mimetypes
6
  import os
7
  import re
8
- import shutil
9
- from typing import Optional
10
-
11
- from smolagents.agent_types import AgentAudio, AgentImage, AgentText, handle_agent_output_types
12
- from smolagents.agents import ActionStep, MultiStepAgent
13
- from smolagents.memory import MemoryStep
14
- from smolagents.utils import _is_package_available
15
-
16
- import gradio as gr
17
  from fpdf import FPDF
18
  from langdetect import detect
19
 
 
20
  from tools.common import prepend_metadata_questions
21
 
22
  # === PDF Export Function with Language Option ===
23
- def export_text_to_pdf(text, output_path=None, language="fr"):
24
  if output_path is None:
25
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
26
  output_path = f"ai_act_register_{timestamp}.pdf"
@@ -34,20 +25,21 @@ def export_text_to_pdf(text, output_path=None, language="fr"):
34
  pdf.set_text_color(0, 51, 102)
35
  title = "Documentation Record for High-Risk AI Systems" if language == "en" else "Registre de Conformité AI Act"
36
  pdf.cell(0, 15, title, ln=True, align='C')
37
- pdf.ln(10)
38
 
39
- # Subtitle
40
- pdf.set_font("Arial", 'I', 12)
41
- pdf.set_text_color(90, 90, 90)
42
- subtitle = f"Generated on {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
43
- pdf.cell(0, 10, subtitle, ln=True, align='C')
 
 
 
44
  pdf.ln(5)
45
 
46
- # Reset style for body
47
  pdf.set_font("Arial", '', 12)
48
  pdf.set_text_color(0, 0, 0)
49
-
50
- # Parse and format sections
51
  for line in text.strip().split('\n'):
52
  line = line.strip()
53
  if line.startswith("## "):
@@ -56,19 +48,18 @@ def export_text_to_pdf(text, output_path=None, language="fr"):
56
  pdf.set_text_color(30, 30, 120)
57
  pdf.ln(8)
58
  pdf.cell(0, 10, section_title, ln=True)
59
- pdf.ln(2)
60
  pdf.set_font("Arial", '', 12)
61
  pdf.set_text_color(0, 0, 0)
62
  elif line.startswith("- **"):
63
- key_value = re.match(r"- \*\*(.+?)\*\*: (.+)", line)
64
- if key_value:
65
- label, answer = key_value.groups()
66
  pdf.set_font("Arial", 'B', 12)
67
  pdf.cell(0, 10, f"{label}:", ln=True)
68
  pdf.set_font("Arial", '', 12)
69
- pdf.multi_cell(0, 10, f"{answer}")
70
  pdf.ln(2)
71
- elif line.strip() == "---":
72
  pdf.line(10, pdf.get_y(), 200, pdf.get_y())
73
  pdf.ln(5)
74
  else:
@@ -79,8 +70,7 @@ def export_text_to_pdf(text, output_path=None, language="fr"):
79
  return output_path
80
 
81
  # === Sequential Questions ===
82
- QUESTIONS = [
83
- ("organization_name", "What is the name of your organization?"),
84
  ("responsible_person", "Who is responsible for this AI system?"),
85
  ("deployment_date", "When is the AI system scheduled to be deployed?"),
86
  ("ai_type", "What type of AI system is it?"),
@@ -93,9 +83,7 @@ QUESTIONS = [
93
  ("transparency_measures", "What transparency mechanisms are in place?"),
94
  ("audit_frequency", "How often will the system be audited?"),
95
  ("compliance_contact", "Who is the contact person for compliance (email or name)?")
96
- ]
97
-
98
- RESPONSES = {}
99
 
100
  # === Interactive Collection Flow ===
101
  def step_by_step_agent(user_input, state):
@@ -110,15 +98,15 @@ def step_by_step_agent(user_input, state):
110
  answers[key] = user_input
111
 
112
  if step < len(QUESTIONS):
113
- next_question = QUESTIONS[step][1]
114
  state["step"] += 1
115
- return next_question, state, None # Ensure return matches expected 3 outputs
116
 
117
- filled_template = f"""
 
118
  # AI Act Compliance Register
119
 
120
  ## General Information
121
- - **Organization**: {answers['organization_name']}
122
  - **Responsible Person**: {answers['responsible_person']}
123
  - **Deployment Date**: {answers['deployment_date']}
124
  - **System Description**: {answers['ai_description']}
@@ -142,97 +130,50 @@ def step_by_step_agent(user_input, state):
142
  Generated by AI Act Assistant.
143
  """
144
 
145
-
146
 
147
- try:
148
- detected_lang = detect(filled_template)
149
- except:
150
- detected_lang = "en"
151
-
152
- flag = "🇬🇧" if detected_lang == "en" else "🇫🇷"
153
- # Save to CSV
154
  csv_file = "ai_act_registers.csv"
155
  fieldnames = [key for key, _ in QUESTIONS] + ["timestamp"]
156
  row_data = {**answers, "timestamp": datetime.datetime.now().isoformat()}
157
-
158
  file_exists = os.path.isfile(csv_file)
159
- with open(csv_file, mode="a", newline="", encoding="utf-8") as csvfile:
160
- writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
 
161
  if not file_exists:
162
  writer.writeheader()
163
  writer.writerow(row_data)
164
 
165
- pdf_path = export_text_to_pdf(filled_template, language=detected_lang)
166
- return f"""{flag} Language detected: {detected_lang.upper()}
167
- ✅ All answers received. Your PDF is ready below:
168
- 👉 Click the download button to save your AI Act compliance register.""", {"done": True, "pdf": pdf_path}, pdf_path
169
 
 
170
  def launch_step_by_step_ui():
171
- with gr.Blocks(
172
- fill_height=True,
173
- css="""
174
- footer,
175
- a[href*="gradio.app"],
176
- a[href*="huggingface.co"] {
177
- display: none !important;
178
- }
179
-
180
- /* Disable interaction with share buttons but keep visible */
181
- button[aria-label="Share"],
182
- button[data-testid="share-button"],
183
- button[title="Share"] {
184
- pointer-events: none !important;
185
- opacity: 0.4 !important;
186
- cursor: default !important;
187
- }
188
- """
189
- ) as demo:
190
-
191
- # GDPR Notice
192
- gr.Markdown("""
193
- ### 🔒 GDPR Notice
194
- This assistant does not store any personal data.
195
- All responses are processed temporarily to generate your document.
196
- You are responsible for the accuracy and legality of the information submitted.
197
- """)
198
-
199
- initial_question = QUESTIONS[0][1]
200
- initial_message = gr.ChatMessage(role="assistant", content=f"""
201
- 👋 Welcome! I will guide you through the AI Act compliance form.
202
- Let's begin with a few questions to generate your compliance register.
203
- {initial_question}
204
- """)
205
- stored_messages = [initial_message]
206
- chatbot = gr.Chatbot(type="messages", value=stored_messages)
207
  msg = gr.Textbox(label="Your answer")
208
  state = gr.State()
209
  file_output = gr.File(label="Download PDF", visible=True)
210
- restart_button = gr.Button("🔁 Restart")
211
 
212
  def chat_logic(user_msg, state):
213
  reply, updated_state, file_path = step_by_step_agent(user_msg, state)
214
  messages = [gr.ChatMessage(role="user", content=user_msg)]
215
-
216
  if isinstance(reply, str):
217
  messages.append(gr.ChatMessage(role="assistant", content=reply))
 
218
 
219
- if not file_path or not os.path.isfile(file_path):
220
- file_path = None
221
- return messages, updated_state, file_path
222
-
223
- def restart_conversation():
224
- return [initial_message], {"step": 0, "answers": {}}, None
225
 
226
  msg.submit(chat_logic, [msg, state], [chatbot, state, file_output])
227
- restart_button.click(restart_conversation, outputs=[chatbot, state, file_output])
228
 
229
  demo.launch(show_api=False)
230
 
231
-
232
-
233
-
234
  def get_questions():
235
  return QUESTIONS
236
 
237
  def run_tool():
238
- return launch_step_by_step_ui()
 
2
  # coding=utf-8
3
  import csv
4
  import datetime
 
5
  import os
6
  import re
 
 
 
 
 
 
 
 
 
7
  from fpdf import FPDF
8
  from langdetect import detect
9
 
10
+ import gradio as gr
11
  from tools.common import prepend_metadata_questions
12
 
13
  # === PDF Export Function with Language Option ===
14
+ def export_text_to_pdf(text, answers, output_path=None, language="fr"):
15
  if output_path is None:
16
  timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
17
  output_path = f"ai_act_register_{timestamp}.pdf"
 
25
  pdf.set_text_color(0, 51, 102)
26
  title = "Documentation Record for High-Risk AI Systems" if language == "en" else "Registre de Conformité AI Act"
27
  pdf.cell(0, 15, title, ln=True, align='C')
28
+ pdf.ln(5)
29
 
30
+ # Metadata below title
31
+ pdf.set_font("Arial", 'I', 11)
32
+ pdf.set_text_color(80, 80, 80)
33
+ name = answers.get("user_name", "N/A")
34
+ role = answers.get("user_role", "N/A")
35
+ org = answers.get("organization_name", "N/A")
36
+ timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
37
+ pdf.multi_cell(0, 10, f"Completed by {name} ({role}) at {org} on {timestamp}", align="C")
38
  pdf.ln(5)
39
 
40
+ # Content
41
  pdf.set_font("Arial", '', 12)
42
  pdf.set_text_color(0, 0, 0)
 
 
43
  for line in text.strip().split('\n'):
44
  line = line.strip()
45
  if line.startswith("## "):
 
48
  pdf.set_text_color(30, 30, 120)
49
  pdf.ln(8)
50
  pdf.cell(0, 10, section_title, ln=True)
 
51
  pdf.set_font("Arial", '', 12)
52
  pdf.set_text_color(0, 0, 0)
53
  elif line.startswith("- **"):
54
+ match = re.match(r"- \*\*(.+?)\*\*: (.+)", line)
55
+ if match:
56
+ label, value = match.groups()
57
  pdf.set_font("Arial", 'B', 12)
58
  pdf.cell(0, 10, f"{label}:", ln=True)
59
  pdf.set_font("Arial", '', 12)
60
+ pdf.multi_cell(0, 10, value)
61
  pdf.ln(2)
62
+ elif line == "---":
63
  pdf.line(10, pdf.get_y(), 200, pdf.get_y())
64
  pdf.ln(5)
65
  else:
 
70
  return output_path
71
 
72
  # === Sequential Questions ===
73
+ QUESTIONS = prepend_metadata_questions([
 
74
  ("responsible_person", "Who is responsible for this AI system?"),
75
  ("deployment_date", "When is the AI system scheduled to be deployed?"),
76
  ("ai_type", "What type of AI system is it?"),
 
83
  ("transparency_measures", "What transparency mechanisms are in place?"),
84
  ("audit_frequency", "How often will the system be audited?"),
85
  ("compliance_contact", "Who is the contact person for compliance (email or name)?")
86
+ ])
 
 
87
 
88
  # === Interactive Collection Flow ===
89
  def step_by_step_agent(user_input, state):
 
98
  answers[key] = user_input
99
 
100
  if step < len(QUESTIONS):
101
+ next_q = QUESTIONS[step][1]
102
  state["step"] += 1
103
+ return next_q, state, None
104
 
105
+ # Build filled template
106
+ filled = f"""
107
  # AI Act Compliance Register
108
 
109
  ## General Information
 
110
  - **Responsible Person**: {answers['responsible_person']}
111
  - **Deployment Date**: {answers['deployment_date']}
112
  - **System Description**: {answers['ai_description']}
 
130
  Generated by AI Act Assistant.
131
  """
132
 
133
+ detected_lang = detect(filled) if filled.strip() else "en"
134
 
 
 
 
 
 
 
 
135
  csv_file = "ai_act_registers.csv"
136
  fieldnames = [key for key, _ in QUESTIONS] + ["timestamp"]
137
  row_data = {**answers, "timestamp": datetime.datetime.now().isoformat()}
 
138
  file_exists = os.path.isfile(csv_file)
139
+
140
+ with open(csv_file, mode="a", newline="", encoding="utf-8") as f:
141
+ writer = csv.DictWriter(f, fieldnames=fieldnames)
142
  if not file_exists:
143
  writer.writeheader()
144
  writer.writerow(row_data)
145
 
146
+ pdf_path = export_text_to_pdf(filled, answers, language=detected_lang)
147
+ return f"✅ Your PDF is ready for download.", {"done": True, "pdf": pdf_path}, pdf_path
 
 
148
 
149
+ # === Gradio Interface ===
150
  def launch_step_by_step_ui():
151
+ with gr.Blocks(title="AI Act Assistant", css="""footer, a[href*="gradio.app"], a[href*="huggingface.co"] { display: none !important; }""") as demo:
152
+ gr.Markdown("### 🔒 GDPR Notice\nThis assistant does not store personal data. Use responsibly.")
153
+ chatbot = gr.Chatbot(type="messages", value=[])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  msg = gr.Textbox(label="Your answer")
155
  state = gr.State()
156
  file_output = gr.File(label="Download PDF", visible=True)
157
+ restart = gr.Button("🔁 Restart")
158
 
159
  def chat_logic(user_msg, state):
160
  reply, updated_state, file_path = step_by_step_agent(user_msg, state)
161
  messages = [gr.ChatMessage(role="user", content=user_msg)]
 
162
  if isinstance(reply, str):
163
  messages.append(gr.ChatMessage(role="assistant", content=reply))
164
+ return messages, updated_state, file_path if file_path else None
165
 
166
+ def reset():
167
+ first_q = QUESTIONS[0][1]
168
+ return [gr.ChatMessage(role="assistant", content=f"👋 Let's get started.\n\n{first_q}")], {"step": 0, "answers": {}}, None
 
 
 
169
 
170
  msg.submit(chat_logic, [msg, state], [chatbot, state, file_output])
171
+ restart.click(reset, outputs=[chatbot, state, file_output])
172
 
173
  demo.launch(show_api=False)
174
 
 
 
 
175
  def get_questions():
176
  return QUESTIONS
177
 
178
  def run_tool():
179
+ return launch_step_by_step_ui()