inesbedar commited on
Commit
6970b1c
·
verified ·
1 Parent(s): 9ad0590

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -755
app.py DELETED
@@ -1,755 +0,0 @@
1
- import streamlit as st
2
-
3
- # ─────────────────────────────────────────────
4
- # REGMAP — AI System ID Card
5
- # ─────────────────────────────────────────────
6
-
7
- st.set_page_config(
8
- page_title="RegMap — AI System ID Card",
9
- page_icon="◈",
10
- layout="centered",
11
- )
12
-
13
- # ── Visual Identity ──
14
- st.markdown("""
15
- <style>
16
- @import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap');
17
- @import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap');
18
-
19
- html, body, [class*="css"] { font-family: 'DM Sans', sans-serif; }
20
- .stApp { background-color: #F7F8FA; }
21
-
22
- /* Global dark text override — HF Spaces renders in dark mode iframe */
23
- .stApp p, .stApp span, .stApp label, .stApp h1, .stApp h2, .stApp h3, .stApp h4,
24
- .stApp li, .stApp strong, .stApp em,
25
- [data-testid="stMarkdownContainer"] p,
26
- [data-testid="stMarkdownContainer"] h4,
27
- [data-testid="stMarkdownContainer"] strong,
28
- [data-testid="stMarkdownContainer"] li {
29
- color: #1E293B !important;
30
- }
31
- /* Restore header light text (dark background) — inline styles handle this now */
32
-
33
- /* Progress */
34
- .progress-container {
35
- background: #E2E8F0; border-radius: 8px;
36
- height: 6px; margin-bottom: 0.4rem;
37
- }
38
- .progress-fill {
39
- background: linear-gradient(90deg, #0D9488, #2DD4BF);
40
- height: 6px; border-radius: 8px;
41
- transition: width 0.4s ease;
42
- }
43
- .progress-label {
44
- color: #64748B; font-size: 0.8rem;
45
- font-weight: 500; margin-bottom: 1.5rem;
46
- }
47
-
48
- /* Screen title */
49
- .screen-title {
50
- font-family: 'Space Grotesk', sans-serif;
51
- color: #0F2B46; font-size: 1.2rem;
52
- font-weight: 700; letter-spacing: -0.01em;
53
- margin-bottom: 0.25rem;
54
- }
55
- .screen-subtitle {
56
- color: #64748B; font-size: 0.85rem;
57
- font-weight: 400; margin-bottom: 1.5rem;
58
- line-height: 1.4;
59
- }
60
-
61
- /* Buttons */
62
- .stButton > button {
63
- font-family: 'DM Sans', sans-serif;
64
- font-weight: 600; font-size: 0.85rem;
65
- border-radius: 8px; padding: 0.45rem 1.5rem;
66
- color: #FFFFFF !important;
67
- }
68
-
69
- /* Summary */
70
- .summary-section {
71
- background: #F8FAFB;
72
- border: 1px solid #E2E8F0;
73
- border-left: 3px solid #0D9488;
74
- border-radius: 8px;
75
- padding: 1rem 1.3rem;
76
- margin-bottom: 0.8rem;
77
- }
78
- .summary-section h4 {
79
- color: #0F2B46;
80
- font-family: 'Space Grotesk', sans-serif;
81
- font-size: 0.88rem; font-weight: 700;
82
- margin: 0 0 0.5rem 0;
83
- }
84
- .summary-section p {
85
- color: #334155; font-size: 0.85rem;
86
- margin: 0.15rem 0; line-height: 1.5;
87
- }
88
-
89
- /* Spacing */
90
- .stSelectbox, .stMultiSelect, .stTextInput, .stTextArea { margin-bottom: 0.6rem; }
91
-
92
- /* Force dark text on all widget labels for HF Spaces dark mode */
93
- .stSelectbox label, .stMultiSelect label, .stTextInput label, .stTextArea label,
94
- .stRadio label, .stCheckbox label, .stSlider label {
95
- color: #1E293B !important;
96
- }
97
- .stSelectbox label p, .stMultiSelect label p, .stTextInput label p, .stTextArea label p,
98
- .stRadio label p, .stCheckbox label p, .stSlider label p {
99
- color: #1E293B !important;
100
- }
101
- /* Radio button option text — multiple selector strategies */
102
- .stRadio div[role="radiogroup"] label p,
103
- .stRadio div[role="radiogroup"] label span,
104
- .stRadio div[role="radiogroup"] label,
105
- [data-testid="stRadio"] label p,
106
- [data-testid="stRadio"] label span,
107
- [data-testid="stRadio"] label,
108
- [data-testid="stWidgetLabel"] p,
109
- [data-testid="stWidgetLabel"] span {
110
- color: #1E293B !important;
111
- }
112
- /* Markdown text inside the app (h4 headers, paragraphs, bold) */
113
- .stMarkdown h4, .stMarkdown p, .stMarkdown strong, .stMarkdown em,
114
- .stMarkdown li, .stMarkdown span,
115
- [data-testid="stMarkdownContainer"] h4,
116
- [data-testid="stMarkdownContainer"] p,
117
- [data-testid="stMarkdownContainer"] strong,
118
- [data-testid="stMarkdownContainer"] span {
119
- color: #1E293B !important;
120
- }
121
- /* Info/Alert box text */
122
- .stAlert p, .stAlert span,
123
- [data-testid="stAlert"] p,
124
- [data-testid="stAlert"] span {
125
- color: #1E293B !important;
126
- }
127
- /* Caption */
128
- .stCaption, .stCaption p,
129
- [data-testid="stCaptionContainer"] p,
130
- [data-testid="stCaptionContainer"] span {
131
- color: #64748B !important;
132
- }
133
- /* Divider */
134
- .stDivider { border-color: #CBD5E1 !important; }
135
- /* Help text (tooltips) */
136
- .stTooltipIcon { color: #64748B !important; }
137
-
138
- /* Beta disclaimer */
139
- .beta-disclaimer {
140
- background: #FEF3C7;
141
- border: 1px solid #F59E0B;
142
- border-radius: 8px;
143
- padding: 0.8rem 1rem;
144
- margin-bottom: 1rem;
145
- color: #92400E;
146
- font-size: 0.82rem;
147
- line-height: 1.5;
148
- }
149
-
150
- /* Hide branding */
151
- #MainMenu {visibility: hidden;}
152
- footer {visibility: hidden;}
153
- header {visibility: hidden;}
154
- </style>
155
- """, unsafe_allow_html=True)
156
-
157
-
158
- # ── Reference Data ──
159
-
160
- INDUSTRY_SECTORS = [
161
- "Agriculture & Food", "Automotive & Transportation",
162
- "Banking & Financial Services", "Construction & Real Estate",
163
- "Consulting & Professional Services", "Defence & Security",
164
- "Education & Training", "Energy & Utilities",
165
- "Entertainment & Media", "Environmental Services",
166
- "Government & Public Administration", "Healthcare & Life Sciences",
167
- "Hospitality & Tourism", "Human Resources & Recruitment",
168
- "Insurance", "Legal Services", "Logistics & Supply Chain",
169
- "Manufacturing", "Mining & Natural Resources", "Non-Profit & NGO",
170
- "Pharmaceuticals", "Retail & E-commerce", "Telecommunications",
171
- "Technology & Software", "Other",
172
- ]
173
-
174
- US_STATES = [
175
- "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado",
176
- "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho",
177
- "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana",
178
- "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota",
179
- "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
180
- "New Hampshire", "New Jersey", "New Mexico", "New York",
181
- "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon",
182
- "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
183
- "Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington",
184
- "West Virginia", "Wisconsin", "Wyoming", "District of Columbia",
185
- ]
186
-
187
- # States with specific AI regulation (for downstream analysis)
188
- US_STATES_WITH_AI_REGULATION = [
189
- "California", "Colorado", "Connecticut", "Illinois", "Texas", "Utah",
190
- ]
191
-
192
- EU_COUNTRIES = [
193
- "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czechia",
194
- "Denmark", "Estonia", "Finland", "France", "Germany", "Greece",
195
- "Hungary", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg",
196
- "Malta", "Netherlands", "Poland", "Portugal", "Romania", "Slovakia",
197
- "Slovenia", "Spain", "Sweden",
198
- "Iceland (EEA)", "Liechtenstein (EEA)", "Norway (EEA)",
199
- ]
200
-
201
- UAE_EMIRATES = [
202
- "Dubai", "Abu Dhabi", "Sharjah", "Ajman",
203
- "Fujairah", "Ras Al Khaimah", "Umm Al Quwain",
204
- ]
205
-
206
- UAE_FREE_ZONES = {
207
- "Dubai": ["DIFC", "DMCC", "JAFZA", "Dubai Internet City",
208
- "Dubai Media City", "Dubai Silicon Oasis", "Dubai Healthcare City",
209
- "Dubai Design District (d3)", "Dubai South", "Dubai Knowledge Park",
210
- "DAFZA", "Dubai World Trade Centre", "Dubai Science Park",
211
- "Dubai Textile City", "DUCAMZ", "Dubai Maritime City",
212
- "Meydan Free Zone", "IFZA"],
213
- "Abu Dhabi": ["ADGM", "KIZAD", "Masdar City", "ADAFZ",
214
- "Khalifa Port Free Trade Zone", "Twofour54"],
215
- "Sharjah": ["Sharjah Media City (Shams)", "SAIF Zone",
216
- "Sharjah Publishing City", "Hamriyah Free Zone"],
217
- "Ras Al Khaimah": ["RAKEZ", "RAK Maritime City", "RAK Media City"],
218
- "Ajman": ["Ajman Free Zone"],
219
- "Fujairah": ["Fujairah Free Zone", "Fujairah Creative City"],
220
- "Umm Al Quwain": ["UAQ Free Trade Zone"],
221
- }
222
-
223
- ROLES_UNIVERSAL = [
224
- "Provider — You develop or commission the AI system",
225
- "Deployer — You use an AI system in your operations (you did not build it)",
226
- ]
227
-
228
- ROLES_EU_SPECIFIC = [
229
- "Authorised Representative — You are based in the EU and act on behalf of a non-EU provider to fulfill EU AI Act obligations",
230
- "Importer — You are based in the EU and place on the market an AI system from a non-EU provider",
231
- "Distributor — You make an AI system available on the EU market (you are neither the provider nor the importer)",
232
- ]
233
-
234
- AI_TYPES = ["Machine Learning (ML)", "Generative AI (GenAI)", "Agentic AI", "Rule-based", "Hybrid"]
235
-
236
- DATA_TYPE_OPTIONS = [
237
- "Personal data (name, email, ID)",
238
- "Sensitive/special category data (health, race, religion, political, sexual orientation)",
239
- "Biometric data",
240
- "Children's data (<18)",
241
- "Financial/credit data",
242
- "Employment/HR data",
243
- "Copyrighted content (text, images, audio, video)",
244
- "Publicly available data only",
245
- "No personal data",
246
- ]
247
-
248
- TRAINING_SOURCES = ["Public web", "Licensed datasets", "Proprietary data", "User-generated content"]
249
- INVOLVEMENT_LEVELS = ["Fully automated", "Human-assisted", "Human decides"]
250
-
251
- ALL_COUNTRIES = [
252
- "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina",
253
- "Armenia", "Australia", "Austria", "Azerbaijan", "Bahrain", "Bangladesh",
254
- "Belarus", "Belgium", "Bolivia", "Bosnia and Herzegovina", "Brazil",
255
- "Brunei", "Bulgaria", "Cambodia", "Cameroon", "Canada", "Chile", "China",
256
- "Colombia", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia",
257
- "Denmark", "Dominican Republic", "Ecuador", "Egypt", "El Salvador",
258
- "Estonia", "Ethiopia", "Finland", "France", "Georgia", "Germany",
259
- "Ghana", "Greece", "Guatemala", "Honduras", "Hong Kong", "Hungary",
260
- "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel",
261
- "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kuwait",
262
- "Latvia", "Lebanon", "Libya", "Liechtenstein", "Lithuania", "Luxembourg",
263
- "Malaysia", "Malta", "Mexico", "Moldova", "Monaco", "Mongolia",
264
- "Montenegro", "Morocco", "Mozambique", "Myanmar", "Nepal",
265
- "Netherlands", "New Zealand", "Nicaragua", "Nigeria", "North Korea",
266
- "North Macedonia", "Norway", "Oman", "Pakistan", "Panama",
267
- "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar",
268
- "Romania", "Russia", "Rwanda", "Saudi Arabia", "Senegal", "Serbia",
269
- "Singapore", "Slovakia", "Slovenia", "Somalia", "South Africa",
270
- "South Korea", "Spain", "Sri Lanka", "Sudan", "Sweden", "Switzerland",
271
- "Syria", "Taiwan", "Tanzania", "Thailand", "Tunisia", "Turkey",
272
- "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
273
- "United States", "Uruguay", "Uzbekistan", "Venezuela", "Vietnam",
274
- "Yemen", "Zambia", "Zimbabwe",
275
- ]
276
-
277
-
278
- # ── Session State ──
279
-
280
- TOTAL_SCREENS = 7
281
-
282
- if "screen" not in st.session_state:
283
- st.session_state.screen = 1
284
- if "data" not in st.session_state:
285
- st.session_state.data = {}
286
-
287
-
288
- def go_next():
289
- if st.session_state.screen < TOTAL_SCREENS + 1:
290
- st.session_state.screen += 1
291
-
292
- def go_back():
293
- if st.session_state.screen > 1:
294
- st.session_state.screen -= 1
295
-
296
- def go_to(n):
297
- st.session_state.screen = n
298
-
299
-
300
- # ── Header ──
301
- st.markdown("""
302
- <div style="background:#0F2B46; padding:2.2rem 2.5rem 1.8rem 2.5rem; border-radius:14px; margin-bottom:2rem; position:relative; overflow:hidden;">
303
- <div style="position:absolute; top:0; right:0; width:40%; height:100%; background:linear-gradient(135deg, transparent 0%, rgba(13,148,136,0.12) 100%);"></div>
304
- <div style="font-family:'Space Grotesk',sans-serif; font-size:1.6rem; font-weight:700; letter-spacing:-0.02em; color:#FFFFFF !important; margin:0; position:relative; z-index:1;">Reg<span style="color:#2DD4BF !important;">Map</span></div>
305
- <div style="font-family:'DM Sans',sans-serif; color:#94A3B8 !important; font-size:0.88rem; font-weight:400; letter-spacing:0.02em; margin:0.4rem 0 0 0; position:relative; z-index:1;">Navigate AI regulation across jurisdictions</div>
306
- <div style="display:flex; gap:0.5rem; margin-top:0.8rem; position:relative; z-index:1;">
307
- <span style="background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.12); border-radius:6px; padding:0.2rem 0.6rem; font-size:0.72rem; font-weight:500; color:#CBD5E1 !important; letter-spacing:0.04em;">EU</span>
308
- <span style="background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.12); border-radius:6px; padding:0.2rem 0.6rem; font-size:0.72rem; font-weight:500; color:#CBD5E1 !important; letter-spacing:0.04em;">US</span>
309
- <span style="background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.12); border-radius:6px; padding:0.2rem 0.6rem; font-size:0.72rem; font-weight:500; color:#CBD5E1 !important; letter-spacing:0.04em;">UAE</span>
310
- </div>
311
- </div>
312
- """, unsafe_allow_html=True)
313
-
314
- # ── Progress ──
315
- current = st.session_state.screen
316
- progress_pct = min((current - 1) / TOTAL_SCREENS * 100, 100)
317
- screen_labels = {
318
- 1: "Screen 1/7 — AI System Identity",
319
- 2: "Screen 2/7 — Application Domain",
320
- 3: "Screen 3/7 — Company Location",
321
- 4: "Screen 4/7 — Operating Regions",
322
- 5: "Screen 5/7 — Role in Value Chain",
323
- 6: "Screen 6/7 — Technology Profile",
324
- 7: "Screen 7/7 — Data Profile",
325
- 8: "Summary",
326
- }
327
- label = screen_labels.get(current, "")
328
-
329
- st.markdown(f"""
330
- <div class="progress-container"><div class="progress-fill" style="width:{progress_pct}%"></div></div>
331
- <div class="progress-label">{label}</div>
332
- """, unsafe_allow_html=True)
333
-
334
-
335
- # ═══════════════════════════════════════════════
336
- # SCREEN 1: AI System Identity
337
- # ═══════════════════════════════════════════════
338
-
339
- if current == 1:
340
- st.markdown('<p class="screen-title">AI System ID Card</p>', unsafe_allow_html=True)
341
- st.markdown('<p class="screen-subtitle">Basic information about your AI system</p>', unsafe_allow_html=True)
342
-
343
- st.markdown('<div class="beta-disclaimer"><strong>Beta version</strong> — This Space is public by default. We recommend not entering directly identifying data, especially in free text fields.</div>', unsafe_allow_html=True)
344
-
345
- name = st.text_input(
346
- "1.1 — AI system name",
347
- value=st.session_state.data.get("name", ""),
348
- placeholder="e.g. ResumeScreener, ChatAssist, FraudDetect",
349
- )
350
- description = st.text_area(
351
- "1.2 — Brief description",
352
- value=st.session_state.data.get("description", ""),
353
- placeholder="Describe what your AI system does in 1-2 sentences",
354
- height=100,
355
- )
356
-
357
- col1, col2 = st.columns([5, 1])
358
- with col2:
359
- if st.button("Next →", use_container_width=True, disabled=(not name.strip())):
360
- st.session_state.data["name"] = name.strip()
361
- st.session_state.data["description"] = description.strip()
362
- go_next()
363
- st.rerun()
364
-
365
-
366
- # ═══════════════════════════════════════════════
367
- # SCREEN 2: Application Domain
368
- # ═══════════════════════════════════════════════
369
-
370
- elif current == 2:
371
- st.markdown('<p class="screen-title">Application Domain</p>', unsafe_allow_html=True)
372
- st.markdown('<p class="screen-subtitle">Select all that apply</p>', unsafe_allow_html=True)
373
-
374
- prev_sector = st.session_state.data.get("sector", [])
375
- sector = st.multiselect(
376
- "2.1 — Primary industry sector(s)",
377
- INDUSTRY_SECTORS,
378
- default=[s for s in prev_sector if s in INDUSTRY_SECTORS],
379
- )
380
-
381
- col1, col2, col3 = st.columns([1, 3, 1])
382
- with col1:
383
- if st.button("← Back", use_container_width=True):
384
- go_back()
385
- st.rerun()
386
- with col3:
387
- if st.button("Next →", use_container_width=True, disabled=(not sector)):
388
- st.session_state.data["sector"] = sector
389
- go_next()
390
- st.rerun()
391
-
392
-
393
- # ═══════════════════════════════════════════════
394
- # SCREEN 3: Company Location
395
- # ═══════════════════════════════════════════════
396
-
397
- elif current == 3:
398
- st.markdown('<p class="screen-title">Company Location</p>', unsafe_allow_html=True)
399
- st.markdown('<p class="screen-subtitle">Where is your organization headquartered?</p>', unsafe_allow_html=True)
400
-
401
- prev_base = st.session_state.data.get("company_base", None)
402
- base_idx = ALL_COUNTRIES.index(prev_base) if prev_base in ALL_COUNTRIES else 0
403
- company_base = st.selectbox(
404
- "3.1 — Country where your company is legally established",
405
- ALL_COUNTRIES,
406
- index=base_idx,
407
- key="q_company_base",
408
- )
409
-
410
- col1, col2, col3 = st.columns([1, 3, 1])
411
- with col1:
412
- if st.button("← Back", use_container_width=True):
413
- go_back()
414
- st.rerun()
415
- with col3:
416
- if st.button("Next →", use_container_width=True):
417
- st.session_state.data["company_base"] = company_base
418
- go_next()
419
- st.rerun()
420
-
421
-
422
- # ═══════════════════════════════════════════════
423
- # SCREEN 4: AI System Operating Regions
424
- # ═══════════════════════════════════════════════
425
-
426
- elif current == 4:
427
- st.markdown('<p class="screen-title">AI System Operating Regions</p>', unsafe_allow_html=True)
428
- st.markdown('<p class="screen-subtitle">Where does your AI system operate, is distributed, or where are its end users located?</p>', unsafe_allow_html=True)
429
-
430
- prev_countries = st.session_state.data.get("operating_countries", [])
431
- operating_countries = st.multiselect(
432
- "4.1 — Select all countries where your AI system operates",
433
- ALL_COUNTRIES,
434
- default=[c for c in prev_countries if c in ALL_COUNTRIES],
435
- key="q_operating_countries",
436
- )
437
-
438
- # Auto-detect
439
- EU_COUNTRY_NAMES_CLEAN = [c.replace(" (EEA)", "") for c in EU_COUNTRIES]
440
- selected_eu = [c for c in operating_countries if c in EU_COUNTRY_NAMES_CLEAN or c in ["Iceland", "Liechtenstein", "Norway"]]
441
- has_us = "United States" in operating_countries
442
- has_uae = "United Arab Emirates" in operating_countries
443
-
444
- # US states — always visible when US selected
445
- us_states = []
446
- if has_us:
447
- prev_states = st.session_state.data.get("us_states", [])
448
- us_states = st.multiselect(
449
- "4.2 — United States: which states?",
450
- US_STATES,
451
- default=[s for s in prev_states if s in US_STATES],
452
- key="q_us_states",
453
- )
454
-
455
- # UAE emirates — always visible when UAE selected
456
- uae_emirates = []
457
- uae_free_zones = []
458
- if has_uae:
459
- prev_emirates = st.session_state.data.get("uae_emirates", [])
460
- uae_emirates = st.multiselect(
461
- "4.3 — UAE: which emirates?",
462
- UAE_EMIRATES,
463
- default=[e for e in prev_emirates if e in UAE_EMIRATES],
464
- key="q_uae_emirates",
465
- )
466
-
467
- # Free zones — build options from ALL emirates (not just selected)
468
- # so the widget always renders; options update based on selection
469
- all_zones = []
470
- for em in uae_emirates:
471
- all_zones.extend(UAE_FREE_ZONES.get(em, []))
472
- prev_zones = st.session_state.data.get("uae_free_zones", [])
473
- if all_zones:
474
- uae_free_zones = st.multiselect(
475
- "4.4 — UAE: free zones? (optional — only if your entity is registered in a free zone)",
476
- all_zones,
477
- default=[z for z in prev_zones if z in all_zones],
478
- key="q_uae_fz",
479
- )
480
- elif uae_emirates:
481
- st.caption("No free zones available for the selected emirates.")
482
-
483
- # Validation
484
- can_proceed = len(operating_countries) > 0
485
- if has_us and not us_states:
486
- can_proceed = False
487
- if has_uae and not uae_emirates:
488
- can_proceed = False
489
-
490
- col1, col2, col3 = st.columns([1, 3, 1])
491
- with col1:
492
- if st.button("← Back", use_container_width=True):
493
- go_back()
494
- st.rerun()
495
- with col3:
496
- if st.button("Next →", use_container_width=True, disabled=(not can_proceed)):
497
- st.session_state.data["operating_countries"] = operating_countries
498
- st.session_state.data["us_states"] = us_states if has_us else []
499
- st.session_state.data["us_states_with_regulation"] = [s for s in us_states if s in US_STATES_WITH_AI_REGULATION] if has_us else []
500
- st.session_state.data["eu_countries"] = selected_eu
501
- st.session_state.data["uae_emirates"] = uae_emirates if has_uae else []
502
- st.session_state.data["uae_free_zones"] = uae_free_zones if has_uae else []
503
- regions = []
504
- if has_us:
505
- regions.append("United States")
506
- if selected_eu:
507
- regions.append("Europe")
508
- if has_uae:
509
- regions.append("UAE")
510
- st.session_state.data["regions"] = regions
511
- go_next()
512
- st.rerun()
513
-
514
-
515
- # ═══════════════════════════════════════════════
516
- # SCREEN 5: Role in Value Chain
517
- # ═══════════════════════════════════════════════
518
-
519
- elif current == 5:
520
- st.markdown('<p class="screen-title">Role in Value Chain</p>', unsafe_allow_html=True)
521
- st.markdown('<p class="screen-subtitle">What is your current role?</p>', unsafe_allow_html=True)
522
-
523
- prev_roles = st.session_state.data.get("roles", [])
524
-
525
- # Universal roles — always shown
526
- roles_universal = st.multiselect(
527
- "5.1 — Your organization's role (select all that apply)",
528
- ROLES_UNIVERSAL,
529
- default=[r for r in prev_roles if r in ROLES_UNIVERSAL],
530
- key="q_roles_universal",
531
- )
532
-
533
- # EU-specific roles — shown if EU countries in operating regions OR company based in EU
534
- eu_operating = st.session_state.data.get("eu_countries", [])
535
- company_base = st.session_state.data.get("company_base", "")
536
- EU_BASE_NAMES = [c.replace(" (EEA)", "") for c in EU_COUNTRIES]
537
- has_eu = len(eu_operating) > 0 or company_base in EU_BASE_NAMES
538
- roles_eu = []
539
- if has_eu:
540
- roles_eu = st.multiselect(
541
- "5.2 — EU AI Act specific roles (if applicable)",
542
- ROLES_EU_SPECIFIC,
543
- default=[r for r in prev_roles if r in ROLES_EU_SPECIFIC],
544
- key="q_roles_eu",
545
- )
546
-
547
- all_roles = roles_universal + roles_eu
548
-
549
- col1, col2, col3 = st.columns([1, 3, 1])
550
- with col1:
551
- if st.button("← Back", use_container_width=True):
552
- go_back()
553
- st.rerun()
554
- with col3:
555
- if st.button("Next →", use_container_width=True, disabled=(not all_roles)):
556
- st.session_state.data["roles"] = all_roles
557
- go_next()
558
- st.rerun()
559
-
560
-
561
- # ═══════════════════════════════════════════════
562
- # SCREEN 6: Technology Profile
563
- # ═══════════════════════════════════════════════
564
-
565
- elif current == 6:
566
- st.markdown('<p class="screen-title">Technology Profile</p>', unsafe_allow_html=True)
567
- st.markdown('<p class="screen-subtitle">Describe your AI system\'s capabilities</p>', unsafe_allow_html=True)
568
-
569
- # 6.1 AI type
570
- prev_type = st.session_state.data.get("ai_type", AI_TYPES[0])
571
- type_idx = AI_TYPES.index(prev_type) if prev_type in AI_TYPES else 0
572
- ai_type = st.selectbox("6.1 — AI system type", AI_TYPES, index=type_idx, key="q_ai_type")
573
-
574
- # 6.2 Model type
575
- MODEL_TYPES = [
576
- "Foundation model — general-purpose, trained on broad data (e.g. GPT, Claude, Llama)",
577
- "Fine-tuned model — adapted from a foundation model for specific tasks",
578
- "Task-specific model — built and trained for a single purpose",
579
- ]
580
- prev_model = st.session_state.data.get("model_type", MODEL_TYPES[2])
581
- model_idx = MODEL_TYPES.index(prev_model) if prev_model in MODEL_TYPES else 2
582
- model_type = st.selectbox("6.2 — How would you describe your AI model?", MODEL_TYPES, index=model_idx, key="q_model_type")
583
-
584
- # 6.3 Capabilities
585
- CAPABILITY_OPTIONS = [
586
- "Interacts directly with end users",
587
- "Makes or supports decisions that affect individuals",
588
- "Profiles individuals (builds user profiles based on behavior, preferences, or characteristics)",
589
- "Generates synthetic content (text, images, audio, video, code)",
590
- "Performs emotion recognition",
591
- ]
592
- prev_caps = st.session_state.data.get("capabilities", [])
593
- capabilities = st.multiselect(
594
- "6.3 — What does your AI system do? (select all that apply)",
595
- CAPABILITY_OPTIONS,
596
- default=[c for c in prev_caps if c in CAPABILITY_OPTIONS],
597
- key="q_capabilities",
598
- )
599
-
600
- # 6.4 Human involvement — always shown
601
- prev_involvement = st.session_state.data.get("human_involvement", "N/A")
602
- INVOLVEMENT_WITH_NA = ["N/A — no decisions affecting individuals", "Fully automated", "Human-assisted", "Human decides"]
603
- if prev_involvement in INVOLVEMENT_LEVELS:
604
- inv_idx = INVOLVEMENT_WITH_NA.index(prev_involvement)
605
- else:
606
- inv_idx = 0
607
- human_involvement = st.selectbox(
608
- "6.4 — Level of human involvement in decisions (if applicable)",
609
- INVOLVEMENT_WITH_NA,
610
- index=inv_idx,
611
- key="q_involvement",
612
- )
613
-
614
- # 6.5 Synthetic content types — always shown
615
- SYNTHETIC_TYPES = ["Text", "Images", "Audio", "Video", "Code"]
616
- prev_content = st.session_state.data.get("synthetic_content", [])
617
- synthetic_content = st.multiselect(
618
- "6.5 — Types of synthetic content generated (if applicable, select all that apply)",
619
- SYNTHETIC_TYPES,
620
- default=[s for s in prev_content if s in SYNTHETIC_TYPES],
621
- key="q_content",
622
- )
623
-
624
- col1, col2, col3 = st.columns([1, 3, 1])
625
- with col1:
626
- if st.button("← Back", use_container_width=True):
627
- go_back()
628
- st.rerun()
629
- with col3:
630
- if st.button("Next →", use_container_width=True):
631
- st.session_state.data["ai_type"] = ai_type
632
- st.session_state.data["model_type"] = model_type
633
- st.session_state.data["gpai"] = model_type.startswith("Foundation model")
634
- st.session_state.data["capabilities"] = capabilities
635
- st.session_state.data["direct_interaction"] = "Interacts directly with end users" in capabilities
636
- st.session_state.data["decision_making"] = "Makes or supports decisions that affect individuals" in capabilities
637
- st.session_state.data["profiling"] = "Profiles individuals (builds user profiles based on behavior, preferences, or characteristics)" in capabilities
638
- is_decision = "Makes or supports decisions that affect individuals" in capabilities
639
- st.session_state.data["human_involvement"] = human_involvement if is_decision and not human_involvement.startswith("N/A") else "N/A"
640
- is_synthetic = "Generates synthetic content (text, images, audio, video, code)" in capabilities
641
- st.session_state.data["synthetic_content"] = synthetic_content if is_synthetic else []
642
- st.session_state.data["emotion_recognition"] = "Performs emotion recognition" in capabilities
643
- go_next()
644
- st.rerun()
645
-
646
-
647
- # ═══════════════════════════════════════════════
648
- # SCREEN 7: Data Profile
649
- # ═══════════════════════════════════════════════
650
-
651
- elif current == 7:
652
- st.markdown('<p class="screen-title">Data Profile</p>', unsafe_allow_html=True)
653
- st.markdown('<p class="screen-subtitle">What data does your system process and where does it come from?</p>', unsafe_allow_html=True)
654
-
655
- prev_data_types = st.session_state.data.get("data_types", [])
656
- selected_data_types = st.multiselect(
657
- "7.1 — What data types does your AI system process? (select all that apply)",
658
- DATA_TYPE_OPTIONS,
659
- default=[dt for dt in prev_data_types if dt in DATA_TYPE_OPTIONS],
660
- )
661
-
662
- st.divider()
663
-
664
- prev_sources = st.session_state.data.get("training_sources", [])
665
- training_sources = st.multiselect(
666
- "7.2 — Training data sources (select all that apply)",
667
- TRAINING_SOURCES,
668
- default=[s for s in prev_sources if s in TRAINING_SOURCES],
669
- )
670
-
671
- col1, col2, col3 = st.columns([1, 3, 1])
672
- with col1:
673
- if st.button("← Back", use_container_width=True):
674
- go_back()
675
- st.rerun()
676
- with col3:
677
- if st.button("View Summary →", use_container_width=True, disabled=(not selected_data_types)):
678
- st.session_state.data["data_types"] = selected_data_types
679
- st.session_state.data["training_sources"] = training_sources
680
- go_next()
681
- st.rerun()
682
-
683
-
684
- # ═��═════════════════════════════════════════════
685
- # SCREEN 8: Summary
686
- # ═══════════════════════════════════════════════
687
-
688
- elif current == 8:
689
- d = st.session_state.data
690
-
691
- st.markdown('<p class="screen-title">AI System ID Card — Summary</p>', unsafe_allow_html=True)
692
- st.markdown(f'<p class="screen-subtitle">Review your inputs for <strong>{d.get("name", "")}</strong></p>', unsafe_allow_html=True)
693
-
694
- # Identity
695
- st.markdown(f'<div class="summary-section"><h4>AI System Identity</h4><p><strong>Name:</strong> {d.get("name", "—")}</p><p><strong>Description:</strong> {d.get("description", "—") or "—"}</p></div>', unsafe_allow_html=True)
696
-
697
- # Domain
698
- sectors = d.get("sector", [])
699
- sectors_display = ", ".join(sectors) if sectors else "—"
700
- st.markdown(f'<div class="summary-section"><h4>Application Domain</h4><p><strong>Sector(s):</strong> {sectors_display}</p></div>', unsafe_allow_html=True)
701
-
702
- # Geography
703
- geo_lines = f'<p><strong>Company base:</strong> {d.get("company_base", "—")}</p>'
704
- op_countries = d.get("operating_countries", [])
705
- geo_lines += f'<p><strong>Operating countries:</strong> {", ".join(op_countries) if op_countries else "—"}</p>'
706
- if d.get("us_states"):
707
- regulated = d.get("us_states_with_regulation", [])
708
- non_regulated = [s for s in d["us_states"] if s not in regulated]
709
- us_line = ", ".join(d["us_states"])
710
- geo_lines += f'<p><strong>US states:</strong> {us_line}</p>'
711
- if regulated:
712
- geo_lines += f'<p><strong>States with AI regulation:</strong> {", ".join(regulated)}</p>'
713
- if non_regulated:
714
- geo_lines += f'<p><strong>States without specific AI regulation:</strong> {", ".join(non_regulated)}</p>'
715
- if d.get("eu_countries"):
716
- geo_lines += f'<p><strong>EU/EEA countries detected:</strong> {", ".join(d["eu_countries"])}</p>'
717
- if d.get("uae_emirates"):
718
- geo_lines += f'<p><strong>UAE emirates:</strong> {", ".join(d["uae_emirates"])}</p>'
719
- if d.get("uae_free_zones"):
720
- geo_lines += f'<p><strong>Free zones:</strong> {", ".join(d["uae_free_zones"])}</p>'
721
- st.markdown(f'<div class="summary-section"><h4>Geographic Scope</h4>{geo_lines}</div>', unsafe_allow_html=True)
722
-
723
- # Roles
724
- roles_display = ", ".join(d.get("roles", ["—"]))
725
- st.markdown(f'<div class="summary-section"><h4>Role in Value Chain</h4><p>{roles_display}</p></div>', unsafe_allow_html=True)
726
-
727
- # Technology
728
- model_type_display = d.get("model_type", "—")
729
- caps = d.get("capabilities", [])
730
- caps_display = ", ".join(caps) if caps else "None selected"
731
- synthetic = ", ".join(d.get("synthetic_content", [])) or "None"
732
- involvement = d.get("human_involvement", "N/A")
733
-
734
- tech_lines = f'<p><strong>AI type:</strong> {d.get("ai_type", "—")}</p>'
735
- tech_lines += f'<p><strong>Model:</strong> {model_type_display}</p>'
736
- tech_lines += f'<p><strong>Capabilities:</strong> {caps_display}</p>'
737
- if d.get("decision_making"):
738
- tech_lines += f'<p><strong>Human involvement in decisions:</strong> {involvement}</p>'
739
- if d.get("synthetic_content"):
740
- tech_lines += f'<p><strong>Synthetic content types:</strong> {synthetic}</p>'
741
- st.markdown(f'<div class="summary-section"><h4>Technology Profile</h4>{tech_lines}</div>', unsafe_allow_html=True)
742
-
743
- # Data
744
- data_types_display = ", ".join(d.get("data_types", ["—"]))
745
- sources_display = ", ".join(d.get("training_sources", ["—"]))
746
- st.markdown(f'<div class="summary-section"><h4>Data Profile</h4><p><strong>Data types:</strong> {data_types_display}</p><p><strong>Training sources:</strong> {sources_display}</p></div>', unsafe_allow_html=True)
747
-
748
- # Navigation
749
- col1, col2, col3 = st.columns([1, 2, 2])
750
- with col1:
751
- if st.button("← Edit", use_container_width=True):
752
- go_to(1)
753
- st.rerun()
754
- with col3:
755
- st.info("Regulation analysis coming in next version")