Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -19,9 +19,9 @@ except:
|
|
19 |
|
20 |
# Set up Streamlit page
|
21 |
st.set_page_config(
|
22 |
-
page_title="
|
23 |
page_icon="βοΈ",
|
24 |
-
layout="
|
25 |
initial_sidebar_state="collapsed"
|
26 |
)
|
27 |
|
@@ -31,7 +31,7 @@ st.markdown("""
|
|
31 |
:root {
|
32 |
--primary: #2c3e50;
|
33 |
--secondary: #3498db;
|
34 |
-
--accent: #
|
35 |
--light: #ecf0f1;
|
36 |
--dark: #2c3e50;
|
37 |
--success: #27ae60;
|
@@ -51,201 +51,154 @@ st.markdown("""
|
|
51 |
.header {
|
52 |
background: linear-gradient(90deg, var(--primary) 0%, var(--secondary) 100%);
|
53 |
color: white;
|
54 |
-
padding:
|
55 |
border-radius: 0 0 25px 25px;
|
56 |
box-shadow: var(--card-shadow);
|
57 |
-
margin-bottom:
|
58 |
text-align: center;
|
59 |
}
|
60 |
|
61 |
.card {
|
62 |
background: white;
|
63 |
-
border-radius:
|
64 |
-
padding:
|
65 |
box-shadow: var(--card-shadow);
|
66 |
-
margin-bottom:
|
67 |
transition: var(--transition);
|
68 |
-
border-left:
|
69 |
-
}
|
70 |
-
|
71 |
-
.card:hover {
|
72 |
-
box-shadow: 0 12px 30px rgba(0,0,0,0.15);
|
73 |
}
|
74 |
|
75 |
.scenario-btn {
|
76 |
width: 100%;
|
77 |
-
padding: 1.
|
78 |
-
background:
|
79 |
-
color:
|
80 |
-
border:
|
81 |
-
border-radius:
|
82 |
font-weight: 600;
|
83 |
-
margin: 0.
|
84 |
cursor: pointer;
|
85 |
transition: var(--transition);
|
86 |
-
text-align:
|
87 |
-
|
88 |
-
|
89 |
-
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
|
90 |
}
|
91 |
|
92 |
.scenario-btn:hover {
|
93 |
-
background: linear-gradient(135deg, var(--
|
|
|
94 |
transform: translateY(-3px);
|
95 |
-
box-shadow: 0
|
96 |
}
|
97 |
|
98 |
.response-card {
|
99 |
background: white;
|
100 |
border-left: 5px solid var(--success);
|
101 |
-
border-radius:
|
102 |
-
padding:
|
103 |
-
margin-top:
|
104 |
box-shadow: var(--card-shadow);
|
105 |
animation: fadeIn 0.8s ease;
|
106 |
}
|
107 |
|
108 |
-
.country-
|
109 |
display: flex;
|
110 |
align-items: center;
|
111 |
justify-content: flex-start;
|
112 |
gap: 12px;
|
113 |
width: 100%;
|
114 |
-
padding:
|
115 |
-
border-radius:
|
116 |
background: white;
|
117 |
box-shadow: var(--card-shadow);
|
118 |
-
margin-bottom:
|
119 |
cursor: pointer;
|
120 |
transition: var(--transition);
|
121 |
-
border: 2px solid
|
122 |
-
font-weight:
|
123 |
-
font-size:
|
124 |
text-align: left;
|
125 |
}
|
126 |
|
127 |
-
.country-
|
128 |
-
transform: translateY(-
|
129 |
-
box-shadow: 0
|
|
|
130 |
}
|
131 |
|
132 |
-
.country-
|
133 |
background: linear-gradient(135deg, var(--light) 0%, #d6eaf8 100%);
|
134 |
border: 2px solid var(--accent);
|
135 |
-
box-shadow: 0
|
136 |
}
|
137 |
|
138 |
.country-flag {
|
139 |
-
font-size: 1.
|
140 |
-
min-width:
|
141 |
text-align: center;
|
142 |
}
|
143 |
|
144 |
.footer {
|
145 |
text-align: center;
|
146 |
-
padding:
|
147 |
-
margin-top:
|
148 |
color: var(--dark);
|
149 |
-
font-size:
|
150 |
background: rgba(236, 240, 241, 0.7);
|
151 |
-
border-radius:
|
152 |
box-shadow: var(--card-shadow);
|
153 |
}
|
154 |
|
155 |
-
.
|
156 |
-
|
157 |
-
|
158 |
-
margin:
|
|
|
|
|
159 |
}
|
160 |
|
161 |
-
|
162 |
-
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
164 |
}
|
165 |
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
100% { transform: scale(1); }
|
170 |
}
|
171 |
|
172 |
-
.
|
173 |
-
|
|
|
|
|
174 |
}
|
175 |
|
176 |
-
@
|
177 |
-
|
178 |
-
|
179 |
-
}
|
180 |
-
|
181 |
-
.header {
|
182 |
-
padding: 2rem 1.5rem;
|
183 |
-
}
|
184 |
-
|
185 |
-
.card {
|
186 |
-
padding: 1.8rem;
|
187 |
-
}
|
188 |
-
|
189 |
-
.scenario-btn, .country-btn {
|
190 |
-
padding: 1.1rem;
|
191 |
-
font-size: 1.05rem;
|
192 |
-
}
|
193 |
}
|
194 |
|
195 |
@media (max-width: 768px) {
|
196 |
.header {
|
197 |
-
padding: 1.
|
198 |
-
border-radius: 0 0 20px 20px;
|
199 |
-
}
|
200 |
-
|
201 |
-
.card {
|
202 |
-
padding: 1.5rem;
|
203 |
-
}
|
204 |
-
|
205 |
-
.scenario-btn, .country-btn {
|
206 |
-
padding: 1rem;
|
207 |
-
font-size: 1rem;
|
208 |
-
}
|
209 |
-
|
210 |
-
.response-card {
|
211 |
-
padding: 1.8rem;
|
212 |
-
}
|
213 |
-
|
214 |
-
.country-flag {
|
215 |
-
font-size: 1.5rem;
|
216 |
-
min-width: 35px;
|
217 |
-
}
|
218 |
-
}
|
219 |
-
|
220 |
-
@media (max-width: 576px) {
|
221 |
-
.stApp {
|
222 |
-
padding: 0 10px;
|
223 |
-
}
|
224 |
-
|
225 |
-
.header h1 {
|
226 |
-
font-size: 2.2rem !important;
|
227 |
-
}
|
228 |
-
|
229 |
-
.header p {
|
230 |
-
font-size: 1.1rem !important;
|
231 |
}
|
232 |
|
233 |
.card {
|
234 |
padding: 1.2rem;
|
235 |
}
|
236 |
|
237 |
-
.
|
238 |
-
padding: 0.
|
239 |
font-size: 0.95rem;
|
240 |
}
|
241 |
|
242 |
-
.response-card {
|
243 |
-
padding: 1.5rem;
|
244 |
-
}
|
245 |
-
|
246 |
.country-flag {
|
247 |
font-size: 1.3rem;
|
248 |
-
min-width: 30px;
|
249 |
}
|
250 |
}
|
251 |
</style>
|
@@ -264,27 +217,39 @@ COUNTRIES = {
|
|
264 |
"π§π· Brazil": "BR",
|
265 |
"πΏπ¦ South Africa": "ZA",
|
266 |
"πͺπΈ Spain": "ES",
|
267 |
-
"πΈπ¬ Singapore": "SG"
|
268 |
-
"π²π½ Mexico": "MX",
|
269 |
-
"π³π± Netherlands": "NL",
|
270 |
-
"πΈπͺ Sweden": "SE",
|
271 |
-
"π³π΄ Norway": "NO"
|
272 |
}
|
273 |
|
274 |
-
# Common legal scenarios
|
275 |
-
|
276 |
-
"
|
277 |
-
"
|
278 |
-
"
|
279 |
-
"
|
280 |
-
"
|
281 |
-
"
|
282 |
-
"
|
283 |
-
"
|
284 |
-
"Employment
|
285 |
-
"
|
286 |
-
"
|
287 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
]
|
289 |
|
290 |
# LLM models available on Groq
|
@@ -307,17 +272,17 @@ def get_legal_rights(country, scenario, model_name):
|
|
307 |
country_name = get_country_name(country)
|
308 |
|
309 |
system_prompt = f"""
|
310 |
-
You are an expert legal assistant specializing in {country_name}
|
311 |
-
Provide clear, accurate information about
|
312 |
|
313 |
Guidelines:
|
314 |
-
-
|
315 |
-
-
|
316 |
-
- Use plain language understandable to
|
317 |
- Include relevant legal references when appropriate
|
318 |
-
- Highlight
|
319 |
- Mention any country-specific variations
|
320 |
-
- Keep response under
|
321 |
- Format with emojis for readability
|
322 |
- End with important disclaimers
|
323 |
"""
|
@@ -326,7 +291,7 @@ def get_legal_rights(country, scenario, model_name):
|
|
326 |
Scenario: {scenario}
|
327 |
Country: {country_name}
|
328 |
|
329 |
-
Please provide
|
330 |
"""
|
331 |
|
332 |
try:
|
@@ -376,8 +341,8 @@ def main():
|
|
376 |
# Header section
|
377 |
st.markdown("""
|
378 |
<div class="header">
|
379 |
-
<h1 style="margin:0;font-size:2.
|
380 |
-
<p style="margin:0;font-size:1.
|
381 |
</div>
|
382 |
""", unsafe_allow_html=True)
|
383 |
|
@@ -387,175 +352,216 @@ def main():
|
|
387 |
|
388 |
if 'selected_scenario' not in st.session_state:
|
389 |
st.session_state.selected_scenario = None
|
|
|
|
|
|
|
390 |
|
391 |
-
#
|
392 |
-
st.
|
393 |
-
model_cols = st.columns([1, 1, 2])
|
394 |
-
with model_cols[0]:
|
395 |
-
selected_model = st.selectbox("Choose AI Model", list(MODELS.keys()), index=0)
|
396 |
-
|
397 |
-
with model_cols[1]:
|
398 |
-
st.markdown("### π Selected Country")
|
399 |
-
st.markdown(f"<div style='font-size:1.2rem;font-weight:bold;'>{st.session_state.selected_country}</div>",
|
400 |
-
unsafe_allow_html=True)
|
401 |
-
|
402 |
-
# Main content columns
|
403 |
-
col1, col2 = st.columns([1, 1.2], gap="large")
|
404 |
|
405 |
-
with
|
406 |
-
st.markdown("###
|
407 |
-
st.markdown("
|
408 |
|
409 |
-
#
|
410 |
-
|
|
|
|
|
|
|
|
|
411 |
|
412 |
-
#
|
413 |
-
|
414 |
-
mid_index = len(countries_list) // 2
|
415 |
-
countries_col1 = countries_list[:mid_index]
|
416 |
-
countries_col2 = countries_list[mid_index:]
|
417 |
|
418 |
-
|
419 |
-
|
420 |
-
|
|
|
|
|
421 |
is_selected = st.session_state.selected_country == country_display
|
422 |
-
|
423 |
flag, name = country_display.split(" ", 1)
|
424 |
|
425 |
if st.button(
|
426 |
-
f'
|
427 |
key=f"btn_{country_display}",
|
428 |
use_container_width=True
|
429 |
):
|
430 |
st.session_state.selected_country = country_display
|
431 |
st.session_state.selected_scenario = None
|
432 |
st.rerun()
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
440 |
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
449 |
|
450 |
-
#
|
451 |
-
st.
|
452 |
-
|
453 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
454 |
|
455 |
-
|
456 |
-
|
457 |
-
y=awareness,
|
458 |
-
labels={'x': 'Country', 'y': 'Rights Awareness'},
|
459 |
-
color=awareness,
|
460 |
-
color_continuous_scale='Teal',
|
461 |
-
height=350
|
462 |
-
)
|
463 |
-
fig.update_layout(
|
464 |
-
plot_bgcolor='rgba(0,0,0,0)',
|
465 |
-
paper_bgcolor='rgba(0,0,0,0)',
|
466 |
-
margin=dict(l=0, r=0, t=30, b=0),
|
467 |
-
xaxis_tickangle=-45
|
468 |
-
)
|
469 |
-
st.plotly_chart(fig, use_container_width=True)
|
470 |
|
471 |
-
|
472 |
-
with
|
473 |
st.markdown("""
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
- [Human Rights Watch](https://www.hrw.org/)
|
480 |
""")
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
|
|
|
|
485 |
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
497 |
|
498 |
-
#
|
499 |
-
st.
|
500 |
-
|
501 |
-
"
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
|
|
507 |
|
508 |
-
|
509 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
510 |
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
country_code,
|
517 |
-
st.session_state.selected_scenario,
|
518 |
-
MODELS[selected_model]
|
519 |
-
)
|
520 |
-
|
521 |
-
if response:
|
522 |
-
display_response(response)
|
523 |
-
else:
|
524 |
-
st.error("Failed to get response. Please try again.")
|
525 |
-
else:
|
526 |
-
st.info("π Please select a legal scenario to see your rights information")
|
527 |
st.markdown("""
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
""", unsafe_allow_html=True)
|
534 |
-
|
535 |
st.markdown("""
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
<p style="margin-top:15px;font-style:italic;border-left:3px solid #3498db;padding-left:15px;">
|
547 |
-
"The first defense against injustice is knowledge of your rights."
|
548 |
-
</p>
|
549 |
-
</div>
|
550 |
-
""", unsafe_allow_html=True)
|
551 |
|
552 |
# Footer
|
553 |
st.markdown("""
|
554 |
<div class="footer">
|
555 |
-
<h4>
|
556 |
-
<p>Β©
|
557 |
-
<p style="font-size:0.9rem;margin-top:10px;">Always consult
|
558 |
-
<p style="font-size:0.8rem;opacity:0.7;margin-top:15px;">Powered by Groq Cloud & Open-Source LLMs</p>
|
559 |
</div>
|
560 |
""", unsafe_allow_html=True)
|
561 |
|
|
|
19 |
|
20 |
# Set up Streamlit page
|
21 |
st.set_page_config(
|
22 |
+
page_title="LexGuardian",
|
23 |
page_icon="βοΈ",
|
24 |
+
layout="wide",
|
25 |
initial_sidebar_state="collapsed"
|
26 |
)
|
27 |
|
|
|
31 |
:root {
|
32 |
--primary: #2c3e50;
|
33 |
--secondary: #3498db;
|
34 |
+
--accent: #e74c3c;
|
35 |
--light: #ecf0f1;
|
36 |
--dark: #2c3e50;
|
37 |
--success: #27ae60;
|
|
|
51 |
.header {
|
52 |
background: linear-gradient(90deg, var(--primary) 0%, var(--secondary) 100%);
|
53 |
color: white;
|
54 |
+
padding: 2rem 1.5rem;
|
55 |
border-radius: 0 0 25px 25px;
|
56 |
box-shadow: var(--card-shadow);
|
57 |
+
margin-bottom: 2rem;
|
58 |
text-align: center;
|
59 |
}
|
60 |
|
61 |
.card {
|
62 |
background: white;
|
63 |
+
border-radius: 15px;
|
64 |
+
padding: 1.8rem;
|
65 |
box-shadow: var(--card-shadow);
|
66 |
+
margin-bottom: 1.8rem;
|
67 |
transition: var(--transition);
|
68 |
+
border-left: 4px solid var(--accent);
|
|
|
|
|
|
|
|
|
69 |
}
|
70 |
|
71 |
.scenario-btn {
|
72 |
width: 100%;
|
73 |
+
padding: 1.1rem;
|
74 |
+
background: white;
|
75 |
+
color: var(--primary);
|
76 |
+
border: 2px solid var(--secondary);
|
77 |
+
border-radius: 12px;
|
78 |
font-weight: 600;
|
79 |
+
margin: 0.7rem 0;
|
80 |
cursor: pointer;
|
81 |
transition: var(--transition);
|
82 |
+
text-align: center;
|
83 |
+
font-size: 1rem;
|
84 |
+
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
|
85 |
}
|
86 |
|
87 |
.scenario-btn:hover {
|
88 |
+
background: linear-gradient(135deg, var(--secondary) 0%, #2980b9 100%);
|
89 |
+
color: white;
|
90 |
transform: translateY(-3px);
|
91 |
+
box-shadow: 0 6px 15px rgba(0,0,0,0.15);
|
92 |
}
|
93 |
|
94 |
.response-card {
|
95 |
background: white;
|
96 |
border-left: 5px solid var(--success);
|
97 |
+
border-radius: 12px;
|
98 |
+
padding: 2rem;
|
99 |
+
margin-top: 2rem;
|
100 |
box-shadow: var(--card-shadow);
|
101 |
animation: fadeIn 0.8s ease;
|
102 |
}
|
103 |
|
104 |
+
.country-card {
|
105 |
display: flex;
|
106 |
align-items: center;
|
107 |
justify-content: flex-start;
|
108 |
gap: 12px;
|
109 |
width: 100%;
|
110 |
+
padding: 1rem;
|
111 |
+
border-radius: 12px;
|
112 |
background: white;
|
113 |
box-shadow: var(--card-shadow);
|
114 |
+
margin-bottom: 12px;
|
115 |
cursor: pointer;
|
116 |
transition: var(--transition);
|
117 |
+
border: 2px solid #e0e0e0;
|
118 |
+
font-weight: 500;
|
119 |
+
font-size: 1rem;
|
120 |
text-align: left;
|
121 |
}
|
122 |
|
123 |
+
.country-card:hover {
|
124 |
+
transform: translateY(-3px);
|
125 |
+
box-shadow: 0 8px 20px rgba(0,0,0,0.12);
|
126 |
+
border-color: var(--secondary);
|
127 |
}
|
128 |
|
129 |
+
.country-card.selected {
|
130 |
background: linear-gradient(135deg, var(--light) 0%, #d6eaf8 100%);
|
131 |
border: 2px solid var(--accent);
|
132 |
+
box-shadow: 0 6px 15px rgba(0,0,0,0.1);
|
133 |
}
|
134 |
|
135 |
.country-flag {
|
136 |
+
font-size: 1.5rem;
|
137 |
+
min-width: 35px;
|
138 |
text-align: center;
|
139 |
}
|
140 |
|
141 |
.footer {
|
142 |
text-align: center;
|
143 |
+
padding: 2rem;
|
144 |
+
margin-top: 3rem;
|
145 |
color: var(--dark);
|
146 |
+
font-size: 0.9rem;
|
147 |
background: rgba(236, 240, 241, 0.7);
|
148 |
+
border-radius: 15px;
|
149 |
box-shadow: var(--card-shadow);
|
150 |
}
|
151 |
|
152 |
+
.section-title {
|
153 |
+
font-size: 1.4rem;
|
154 |
+
color: var(--primary);
|
155 |
+
margin-bottom: 1.2rem;
|
156 |
+
padding-bottom: 0.5rem;
|
157 |
+
border-bottom: 2px solid var(--accent);
|
158 |
}
|
159 |
|
160 |
+
.feature-card {
|
161 |
+
background: white;
|
162 |
+
border-radius: 12px;
|
163 |
+
padding: 1.5rem;
|
164 |
+
box-shadow: var(--card-shadow);
|
165 |
+
margin-bottom: 1.5rem;
|
166 |
+
transition: var(--transition);
|
167 |
+
text-align: center;
|
168 |
}
|
169 |
|
170 |
+
.feature-card:hover {
|
171 |
+
transform: translateY(-5px);
|
172 |
+
box-shadow: 0 10px 25px rgba(0,0,0,0.12);
|
|
|
173 |
}
|
174 |
|
175 |
+
.feature-icon {
|
176 |
+
font-size: 2.5rem;
|
177 |
+
color: var(--accent);
|
178 |
+
margin-bottom: 1rem;
|
179 |
}
|
180 |
|
181 |
+
@keyframes fadeIn {
|
182 |
+
from { opacity: 0; transform: translateY(20px); }
|
183 |
+
to { opacity: 1; transform: translateY(0); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
}
|
185 |
|
186 |
@media (max-width: 768px) {
|
187 |
.header {
|
188 |
+
padding: 1.5rem 1rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
}
|
190 |
|
191 |
.card {
|
192 |
padding: 1.2rem;
|
193 |
}
|
194 |
|
195 |
+
.country-card {
|
196 |
+
padding: 0.8rem;
|
197 |
font-size: 0.95rem;
|
198 |
}
|
199 |
|
|
|
|
|
|
|
|
|
200 |
.country-flag {
|
201 |
font-size: 1.3rem;
|
|
|
202 |
}
|
203 |
}
|
204 |
</style>
|
|
|
217 |
"π§π· Brazil": "BR",
|
218 |
"πΏπ¦ South Africa": "ZA",
|
219 |
"πͺπΈ Spain": "ES",
|
220 |
+
"πΈπ¬ Singapore": "SG"
|
|
|
|
|
|
|
|
|
221 |
}
|
222 |
|
223 |
+
# Common legal scenarios for students
|
224 |
+
STUDENT_SCENARIOS = [
|
225 |
+
"Academic Rights & Responsibilities",
|
226 |
+
"Campus Housing Issues",
|
227 |
+
"Discrimination & Harassment",
|
228 |
+
"Freedom of Speech on Campus",
|
229 |
+
"Student Privacy Rights",
|
230 |
+
"Disciplinary Proceedings",
|
231 |
+
"Financial Aid & Scholarships",
|
232 |
+
"Intellectual Property Rights",
|
233 |
+
"Internship & Employment Rights",
|
234 |
+
"Student Loan Concerns",
|
235 |
+
"Campus Safety & Security",
|
236 |
+
"Consumer Protection as a Student"
|
237 |
+
]
|
238 |
+
|
239 |
+
# Student legal topics
|
240 |
+
LEGAL_TOPICS = [
|
241 |
+
"Academic Integrity Policies",
|
242 |
+
"Title IX & Gender Equity",
|
243 |
+
"Disability Accommodations",
|
244 |
+
"Student Privacy (FERPA)",
|
245 |
+
"Campus Free Speech",
|
246 |
+
"Student Organization Rights",
|
247 |
+
"Financial Aid Regulations",
|
248 |
+
"Plagiarism & Copyright",
|
249 |
+
"Tenant Rights for Students",
|
250 |
+
"Student Employment Laws",
|
251 |
+
"Campus Police Interactions",
|
252 |
+
"Student Loan Borrower Rights"
|
253 |
]
|
254 |
|
255 |
# LLM models available on Groq
|
|
|
272 |
country_name = get_country_name(country)
|
273 |
|
274 |
system_prompt = f"""
|
275 |
+
You are an expert legal assistant specializing in student rights in {country_name}.
|
276 |
+
Provide clear, accurate information about student rights in the given scenario.
|
277 |
|
278 |
Guidelines:
|
279 |
+
- Focus specifically on student rights and responsibilities
|
280 |
+
- List 5-7 key points as bullet points
|
281 |
+
- Use plain language understandable to students
|
282 |
- Include relevant legal references when appropriate
|
283 |
+
- Highlight practical steps students can take
|
284 |
- Mention any country-specific variations
|
285 |
+
- Keep response under 300 words
|
286 |
- Format with emojis for readability
|
287 |
- End with important disclaimers
|
288 |
"""
|
|
|
291 |
Scenario: {scenario}
|
292 |
Country: {country_name}
|
293 |
|
294 |
+
Please provide student-specific rights information for this situation in {country_name}.
|
295 |
"""
|
296 |
|
297 |
try:
|
|
|
341 |
# Header section
|
342 |
st.markdown("""
|
343 |
<div class="header">
|
344 |
+
<h1 style="margin:0;font-size:2.5rem;">LexGuardian</h1>
|
345 |
+
<p style="margin:0;font-size:1.2rem;opacity:0.9;margin-top:10px;">Empowering Students with Legal Knowledge</p>
|
346 |
</div>
|
347 |
""", unsafe_allow_html=True)
|
348 |
|
|
|
352 |
|
353 |
if 'selected_scenario' not in st.session_state:
|
354 |
st.session_state.selected_scenario = None
|
355 |
+
|
356 |
+
if 'active_tab' not in st.session_state:
|
357 |
+
st.session_state.active_tab = "explorer"
|
358 |
|
359 |
+
# Navigation tabs
|
360 |
+
tab1, tab2, tab3 = st.tabs(["Rights Explorer", "Legal Topics", "Student Resources"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
361 |
|
362 |
+
with tab1:
|
363 |
+
st.markdown("### βοΈ Know Your Rights")
|
364 |
+
st.markdown("Select your country and a situation to understand your legal rights as a student")
|
365 |
|
366 |
+
# Model selection
|
367 |
+
model_col = st.columns([1,1,2])
|
368 |
+
with model_col[0]:
|
369 |
+
selected_model = st.selectbox("Choose AI Model", list(MODELS.keys()), index=0)
|
370 |
+
with model_col[1]:
|
371 |
+
st.markdown(f"**Selected Country:** {st.session_state.selected_country}")
|
372 |
|
373 |
+
# Main content columns
|
374 |
+
col1, col2 = st.columns([1, 1.3], gap="large")
|
|
|
|
|
|
|
375 |
|
376 |
+
with col1:
|
377 |
+
st.markdown("#### π Select Your Country")
|
378 |
+
|
379 |
+
# Country selection cards
|
380 |
+
for country_display in COUNTRIES.keys():
|
381 |
is_selected = st.session_state.selected_country == country_display
|
382 |
+
card_class = "country-card selected" if is_selected else "country-card"
|
383 |
flag, name = country_display.split(" ", 1)
|
384 |
|
385 |
if st.button(
|
386 |
+
f'{flag} {name}',
|
387 |
key=f"btn_{country_display}",
|
388 |
use_container_width=True
|
389 |
):
|
390 |
st.session_state.selected_country = country_display
|
391 |
st.session_state.selected_scenario = None
|
392 |
st.rerun()
|
393 |
+
|
394 |
+
st.markdown("#### π Student Rights Awareness")
|
395 |
+
countries = list(COUNTRIES.values())
|
396 |
+
awareness = [85, 82, 80, 78, 75, 83, 81, 79, 76, 74, 80, 77] # Simulated data
|
397 |
+
|
398 |
+
fig = px.pie(
|
399 |
+
names=[get_country_name(code) for code in countries],
|
400 |
+
values=awareness,
|
401 |
+
title="Global Student Rights Awareness",
|
402 |
+
height=300
|
403 |
+
)
|
404 |
+
fig.update_layout(
|
405 |
+
plot_bgcolor='rgba(0,0,0,0)',
|
406 |
+
paper_bgcolor='rgba(0,0,0,0)',
|
407 |
+
margin=dict(l=0, r=0, t=40, b=0),
|
408 |
+
showlegend=False
|
409 |
+
)
|
410 |
+
fig.update_traces(textposition='inside', textinfo='percent+label')
|
411 |
+
st.plotly_chart(fig, use_container_width=True)
|
412 |
+
|
413 |
+
with col2:
|
414 |
+
st.markdown("#### π Student Scenarios")
|
415 |
+
st.markdown("Select a situation relevant to student life")
|
416 |
+
|
417 |
+
# Create buttons for each scenario in 2 columns
|
418 |
+
scenario_cols = st.columns(2)
|
419 |
+
for i, scenario in enumerate(STUDENT_SCENARIOS):
|
420 |
+
with scenario_cols[i % 2]:
|
421 |
+
if st.button(
|
422 |
+
f"{scenario}",
|
423 |
+
key=f"scen_{scenario}",
|
424 |
+
use_container_width=True,
|
425 |
+
help=f"Click to see student rights for {scenario}"
|
426 |
+
):
|
427 |
+
st.session_state.selected_scenario = scenario
|
428 |
+
|
429 |
+
# Custom scenario input
|
430 |
+
custom_scenario = st.text_input(
|
431 |
+
"**Describe your specific concern:**",
|
432 |
+
placeholder="e.g., 'Rights during campus protest', 'Academic appeal process'"
|
433 |
+
)
|
434 |
+
if custom_scenario:
|
435 |
+
st.session_state.selected_scenario = custom_scenario
|
436 |
+
|
437 |
+
# Response area
|
438 |
+
if st.session_state.selected_scenario:
|
439 |
+
country_code = COUNTRIES[st.session_state.selected_country]
|
440 |
|
441 |
+
with st.spinner(f"π Analyzing student rights for '{st.session_state.selected_scenario}'..."):
|
442 |
+
response = get_legal_rights(
|
443 |
+
country_code,
|
444 |
+
st.session_state.selected_scenario,
|
445 |
+
MODELS[selected_model]
|
446 |
+
)
|
447 |
+
|
448 |
+
if response:
|
449 |
+
display_response(response)
|
450 |
+
else:
|
451 |
+
st.error("Failed to get response. Please try again.")
|
452 |
+
else:
|
453 |
+
st.info("π Select a student scenario to see your rights information")
|
454 |
+
st.markdown("""
|
455 |
+
<div style="text-align:center; margin:20px 0;">
|
456 |
+
<img src="https://images.unsplash.com/photo-1523050854058-8df90110c9f1?auto=format&fit=crop&w=600&h=400"
|
457 |
+
style="width:100%; border-radius:15px; box-shadow:0 6px 20px rgba(0,0,0,0.1);">
|
458 |
+
<p style="margin-top:10px;font-style:italic;color:#666;">Knowledge is your best legal defense</p>
|
459 |
+
</div>
|
460 |
+
""", unsafe_allow_html=True)
|
461 |
+
|
462 |
+
with tab2:
|
463 |
+
st.markdown("### π Essential Legal Topics for Students")
|
464 |
+
st.markdown("Explore key legal concepts every student should understand")
|
465 |
|
466 |
+
# Topics in 3 columns
|
467 |
+
cols = st.columns(3)
|
468 |
+
for i, topic in enumerate(LEGAL_TOPICS):
|
469 |
+
with cols[i % 3]:
|
470 |
+
with st.expander(f"**{topic}**", expanded=True):
|
471 |
+
st.info(f"Learn about your rights and responsibilities regarding {topic.lower()}")
|
472 |
+
if st.button("Explore Topic", key=f"topic_{topic}"):
|
473 |
+
st.session_state.active_tab = "explorer"
|
474 |
+
st.session_state.selected_scenario = topic
|
475 |
+
st.rerun()
|
476 |
|
477 |
+
st.markdown("### π§ Legal Knowledge Quiz")
|
478 |
+
st.markdown("Test your understanding of student rights")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
479 |
|
480 |
+
quiz_cols = st.columns(2)
|
481 |
+
with quiz_cols[0]:
|
482 |
st.markdown("""
|
483 |
+
**Question 1:** Can your college share your academic records without permission?
|
484 |
+
A) Always
|
485 |
+
B) Only with parents
|
486 |
+
C) Only with your consent
|
487 |
+
D) Only in emergencies
|
|
|
488 |
""")
|
489 |
+
|
490 |
+
answer1 = st.radio("Select answer:", ["A", "B", "C", "D"], key="q1", index=None)
|
491 |
+
if answer1 == "C":
|
492 |
+
st.success("Correct! FERPA requires your consent for most record disclosures.")
|
493 |
+
elif answer1:
|
494 |
+
st.error("Incorrect. The correct answer is C - Only with your consent.")
|
495 |
|
496 |
+
with quiz_cols[1]:
|
497 |
+
st.markdown("""
|
498 |
+
**Question 2:** What should you do if you face discrimination on campus?
|
499 |
+
A) Ignore it
|
500 |
+
B) Report to Title IX coordinator
|
501 |
+
C) Post about it on social media
|
502 |
+
D) Confront the person directly
|
503 |
+
""")
|
504 |
+
|
505 |
+
answer2 = st.radio("Select answer:", ["A", "B", "C", "D"], key="q2", index=None)
|
506 |
+
if answer2 == "B":
|
507 |
+
st.success("Correct! Reporting to the Title IX coordinator is the proper step.")
|
508 |
+
elif answer2:
|
509 |
+
st.error("Incorrect. The correct answer is B - Report to Title IX coordinator.")
|
510 |
+
|
511 |
+
with tab3:
|
512 |
+
st.markdown("### π‘οΈ Student Legal Resources")
|
513 |
+
st.markdown("Essential tools and information for student legal matters")
|
514 |
|
515 |
+
# Resources in cards
|
516 |
+
resource_cols = st.columns(3)
|
517 |
+
resources = [
|
518 |
+
{"icon": "π", "title": "Legal Templates", "desc": "Downloadable templates for common student legal documents"},
|
519 |
+
{"icon": "π", "title": "Legal Glossary", "desc": "Understand legal terminology with our student-friendly dictionary"},
|
520 |
+
{"icon": "π±", "title": "Campus Legal Apps", "desc": "Mobile applications for legal assistance on campus"},
|
521 |
+
{"icon": "π¨ββοΈ", "title": "Find Legal Aid", "desc": "Locate free or low-cost legal services for students"},
|
522 |
+
{"icon": "π
", "title": "Workshops & Events", "desc": "Upcoming legal education sessions on campus"},
|
523 |
+
{"icon": "π", "title": "Legal Handbook", "desc": "Comprehensive guide to student rights and responsibilities"}
|
524 |
+
]
|
525 |
|
526 |
+
for i, resource in enumerate(resources):
|
527 |
+
with resource_cols[i % 3]:
|
528 |
+
st.markdown(f"""
|
529 |
+
<div class="feature-card">
|
530 |
+
<div class="feature-icon">{resource['icon']}</div>
|
531 |
+
<h3>{resource['title']}</h3>
|
532 |
+
<p>{resource['desc']}</p>
|
533 |
+
</div>
|
534 |
+
""", unsafe_allow_html=True)
|
535 |
|
536 |
+
st.markdown("### π Emergency Contacts")
|
537 |
+
st.markdown("Important contacts for immediate legal assistance")
|
538 |
+
|
539 |
+
contacts = st.columns(3)
|
540 |
+
with contacts[0]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
st.markdown("""
|
542 |
+
**Campus Security**
|
543 |
+
Emergency: (555) 123-4567
|
544 |
+
Non-emergency: (555) 123-4000
|
545 |
+
""")
|
546 |
+
with contacts[1]:
|
|
|
|
|
547 |
st.markdown("""
|
548 |
+
**Student Legal Services**
|
549 |
+
Phone: (555) 987-6543
|
550 |
+
Email: legal@university.edu
|
551 |
+
""")
|
552 |
+
with contacts[2]:
|
553 |
+
st.markdown("""
|
554 |
+
**National Legal Aid**
|
555 |
+
Hotline: 1-800-LEGAL-AID
|
556 |
+
Website: legalaid.org
|
557 |
+
""")
|
|
|
|
|
|
|
|
|
|
|
558 |
|
559 |
# Footer
|
560 |
st.markdown("""
|
561 |
<div class="footer">
|
562 |
+
<h4>LexGuardian - Student Legal Empowerment</h4>
|
563 |
+
<p>Β© 2025 β’ For Educational Purposes Only β’ Not Legal Advice</p>
|
564 |
+
<p style="font-size:0.9rem;margin-top:10px;">Always consult qualified legal counsel for your specific situation</p>
|
|
|
565 |
</div>
|
566 |
""", unsafe_allow_html=True)
|
567 |
|