LexGuardian / app.py
sunbal7's picture
Update app.py
1ae38f2 verified
raw
history blame
17.2 kB
# app.py
import streamlit as st
import os
import time
import plotly.express as px
from groq import Groq
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Initialize Groq client
try:
client = Groq(api_key=os.getenv("GROQ_API_KEY"))
except:
st.error("Failed to initialize Groq client. Please check your API key.")
st.stop()
# Set up Streamlit page
st.set_page_config(
page_title="Legal Rights Explorer Pro",
page_icon="⚖️",
layout="centered",
initial_sidebar_state="collapsed"
)
# Custom CSS for professional styling
st.markdown("""
<style>
:root {
--primary: #2c3e50;
--secondary: #3498db;
--accent: #1abc9c;
--light: #ecf0f1;
--dark: #2c3e50;
--success: #27ae60;
--card-shadow: 0 6px 20px rgba(0,0,0,0.08);
--transition: all 0.3s ease;
}
.stApp {
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
color: #333;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.header {
background: linear-gradient(90deg, var(--primary) 0%, var(--secondary) 100%);
color: white;
padding: 2.5rem 2rem;
border-radius: 0 0 25px 25px;
box-shadow: var(--card-shadow);
margin-bottom: 2.5rem;
text-align: center;
}
.card {
background: white;
border-radius: 18px;
padding: 2rem;
box-shadow: var(--card-shadow);
margin-bottom: 2rem;
transition: var(--transition);
border-left: 5px solid var(--accent);
}
.card:hover {
box-shadow: 0 12px 30px rgba(0,0,0,0.15);
}
.scenario-btn {
width: 100%;
padding: 1.2rem;
background: linear-gradient(135deg, var(--secondary) 0%, #2980b9 100%);
color: white;
border: none;
border-radius: 15px;
font-weight: 600;
margin: 0.8rem 0;
cursor: pointer;
transition: var(--transition);
text-align: left;
padding-left: 25px;
font-size: 1.1rem;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
}
.scenario-btn:hover {
background: linear-gradient(135deg, var(--primary) 0%, #2c3e50 100%);
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}
.response-card {
background: white;
border-left: 5px solid var(--success);
border-radius: 15px;
padding: 2.5rem;
margin-top: 2.5rem;
box-shadow: var(--card-shadow);
animation: fadeIn 0.8s ease;
}
.country-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
width: 100%;
padding: 1.2rem;
border-radius: 15px;
background: white;
box-shadow: var(--card-shadow);
margin-bottom: 15px;
cursor: pointer;
transition: var(--transition);
border: 2px solid transparent;
font-weight: 600;
font-size: 1.1rem;
}
.country-btn:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px rgba(0,0,0,0.15);
}
.country-btn.selected {
background: linear-gradient(135deg, var(--light) 0%, #d6eaf8 100%);
border: 2px solid var(--accent);
box-shadow: 0 8px 25px rgba(0,0,0,0.12);
}
.footer {
text-align: center;
padding: 2.5rem;
margin-top: 3.5rem;
color: var(--dark);
font-size: 1rem;
background: rgba(236, 240, 241, 0.7);
border-radius: 20px;
box-shadow: var(--card-shadow);
}
.spinner {
display: flex;
justify-content: center;
margin: 3rem 0;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(30px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 2s infinite;
}
@media (max-width: 992px) {
.stApp {
padding: 0 15px;
}
.header {
padding: 2rem 1.5rem;
}
.card {
padding: 1.8rem;
}
.scenario-btn, .country-btn {
padding: 1.1rem;
font-size: 1.05rem;
}
}
@media (max-width: 768px) {
.header {
padding: 1.8rem 1.2rem;
border-radius: 0 0 20px 20px;
}
.card {
padding: 1.5rem;
}
.scenario-btn, .country-btn {
padding: 1rem;
font-size: 1rem;
}
.response-card {
padding: 1.8rem;
}
}
@media (max-width: 576px) {
.stApp {
padding: 0 10px;
}
.header h1 {
font-size: 2.2rem !important;
}
.header p {
font-size: 1.1rem !important;
}
.card {
padding: 1.2rem;
}
.scenario-btn, .country-btn {
padding: 0.9rem;
font-size: 0.95rem;
}
.response-card {
padding: 1.5rem;
}
}
</style>
""", unsafe_allow_html=True)
# Country data with flags
COUNTRIES = {
"🇺🇸 United States": "US",
"🇬🇧 United Kingdom": "UK",
"🇨🇦 Canada": "CA",
"🇦🇺 Australia": "AU",
"🇮🇳 India": "IN",
"🇩🇪 Germany": "DE",
"🇫🇷 France": "FR",
"🇯🇵 Japan": "JP",
"🇧🇷 Brazil": "BR",
"🇿🇦 South Africa": "ZA",
"🇪🇸 Spain": "ES",
"🇸🇬 Singapore": "SG",
"🇲🇽 Mexico": "MX",
"🇳🇱 Netherlands": "NL",
"🇸🇪 Sweden": "SE",
"🇳🇴 Norway": "NO"
}
# Common legal scenarios
SCENARIOS = [
"Traffic Stop by Police",
"Workplace Discrimination",
"Rental Housing Issues",
"Medical Emergency Rights",
"Consumer Protection",
"Arrest or Detention",
"Border Crossing",
"Online Privacy",
"Employment Termination",
"Debt Collection",
"Freedom of Speech",
"Immigration Rights"
]
# LLM models available on Groq
MODELS = {
"Llama3-70b (Highest Accuracy)": "llama3-70b-8192",
"Llama3-8b (Fast Response)": "llama3-8b-8192",
"Mixtral-8x7b (Balanced)": "mixtral-8x7b-32768"
}
# Function to get rights information from Groq API
def get_legal_rights(country, scenario, model_name):
"""Get legal rights information using Groq API"""
system_prompt = f"""
You are an expert legal assistant specializing in {country} law.
Provide clear, accurate information about an individual's rights in the given scenario.
Guidelines:
- List 5-7 key rights as bullet points
- Start with a brief context about the legal situation
- Use plain language understandable to non-lawyers
- Include relevant legal references when appropriate
- Highlight any critical actions the person should take
- Mention any country-specific variations
- Keep response under 350 words
- Format with emojis for readability
- End with important disclaimers
"""
user_prompt = f"""
Scenario: {scenario}
Country: {country}
Please provide a comprehensive list of rights for this situation in {country}.
"""
try:
chat_completion = client.chat.completions.create(
messages=[
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": user_prompt
}
],
model=model_name,
temperature=0.3,
max_tokens=1024,
top_p=1,
stream=False,
stop=None,
)
return chat_completion.choices[0].message.content
except Exception as e:
st.error(f"Error fetching data: {str(e)}")
return None
# Function to display response with animation
def display_response(response):
"""Display the response with typing animation effect"""
message_placeholder = st.empty()
full_response = ""
# Simulate stream of response with milliseconds delay
for chunk in response.split():
full_response += chunk + " "
time.sleep(0.03)
# Add a blinking cursor to simulate typing
message_placeholder.markdown(f'<div class="response-card">{full_response}▌</div>', unsafe_allow_html=True)
# Display final message without the cursor
message_placeholder.markdown(f'<div class="response-card">{response}</div>', unsafe_allow_html=True)
# Main app
def main():
# Header section
st.markdown("""
<div class="header">
<h1 style="margin:0;font-size:2.8rem;">Legal Rights Explorer Pro</h1>
<p style="margin:0;font-size:1.3rem;opacity:0.9;margin-top:12px;">Know your rights • Protect your freedom</p>
</div>
""", unsafe_allow_html=True)
# Initialize session state
if 'selected_country' not in st.session_state:
st.session_state.selected_country = "🇺🇸 United States"
if 'selected_scenario' not in st.session_state:
st.session_state.selected_scenario = None
# Model selection at top
st.markdown("### ⚙️ AI Model Selection")
model_cols = st.columns([1, 1, 2])
with model_cols[0]:
selected_model = st.selectbox("Choose AI Model", list(MODELS.keys()), index=0)
with model_cols[1]:
st.markdown("### 🌎 Selected Country")
st.markdown(f"<div style='font-size:1.2rem;font-weight:bold;'>{st.session_state.selected_country}</div>",
unsafe_allow_html=True)
# Main content columns
col1, col2 = st.columns([1, 1.2], gap="large")
with col1:
st.markdown("### 🌍 Select Your Country")
st.markdown("Choose your country to see jurisdiction-specific rights information")
# Create 2 columns for country buttons
country_col1, country_col2 = st.columns(2)
# Split countries into two groups
countries_list = list(COUNTRIES.keys())
mid_index = len(countries_list) // 2
countries_col1 = countries_list[:mid_index]
countries_col2 = countries_list[mid_index:]
# First column of countries
with country_col1:
for country_display in countries_col1:
is_selected = st.session_state.selected_country == country_display
btn_class = "country-btn selected" if is_selected else "country-btn"
if st.button(
country_display,
key=f"btn_{country_display}",
use_container_width=True
):
st.session_state.selected_country = country_display
st.session_state.selected_scenario = None
st.rerun()
# Second column of countries
with country_col2:
for country_display in countries_col2:
is_selected = st.session_state.selected_country == country_display
btn_class = "country-btn selected" if is_selected else "country-btn"
if st.button(
country_display,
key=f"btn_{country_display}",
use_container_width=True
):
st.session_state.selected_country = country_display
st.session_state.selected_scenario = None
st.rerun()
# Country visualization
st.markdown("### 📊 Global Rights Index")
countries = list(COUNTRIES.values())
awareness = [92, 89, 87, 85, 82, 88, 86, 84, 79, 81, 85, 83, 80, 78, 90, 85] # Simulated data
fig = px.bar(
x=countries,
y=awareness,
labels={'x': 'Country', 'y': 'Rights Awareness'},
color=awareness,
color_continuous_scale='Teal',
height=350
)
fig.update_layout(
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
margin=dict(l=0, r=0, t=30, b=0),
xaxis_tickangle=-45
)
st.plotly_chart(fig, use_container_width=True)
# Legal resources
with st.expander("📚 Legal Resources & References", expanded=True):
st.markdown("""
- [United Nations Human Rights](https://www.ohchr.org/)
- [International Justice Resource Center](https://ijrcenter.org/)
- [Global Legal Information Network](https://www.loc.gov/law/help/legal-info.php)
- [World Legal Information Institute](https://www.worldlii.org/)
- [Amnesty International](https://www.amnesty.org/)
- [Human Rights Watch](https://www.hrw.org/)
""")
with col2:
st.markdown("### 🚨 Select a Legal Scenario")
st.markdown("Choose a situation to understand your rights and protections")
# Create buttons for each scenario in 2 columns
scenario_cols = st.columns(2)
for i, scenario in enumerate(SCENARIOS):
with scenario_cols[i % 2]:
if st.button(
f"**{scenario}**",
key=f"scen_{scenario}",
use_container_width=True,
help=f"Click to see your rights for {scenario}"
):
st.session_state.selected_scenario = scenario
# Custom scenario input
st.markdown("#### ✏️ Or describe your specific situation:")
custom_scenario = st.text_input(
"Describe your legal concern:",
placeholder="e.g., 'Rights during home search', 'Employee privacy rights'",
label_visibility="collapsed"
)
if custom_scenario:
st.session_state.selected_scenario = custom_scenario
# Response area
st.markdown("### ⚖️ Your Legal Rights Analysis")
if st.session_state.selected_scenario:
country_code = COUNTRIES[st.session_state.selected_country]
with st.spinner(f"🔍 Analyzing your rights for '{st.session_state.selected_scenario}' in {country_code}..."):
response = get_legal_rights(
country_code,
st.session_state.selected_scenario,
MODELS[selected_model]
)
if response:
display_response(response)
else:
st.error("Failed to get response. Please try again.")
else:
st.info("👆 Please select a legal scenario to see your rights information")
st.markdown("""
<div style="text-align:center; margin:20px 0;">
<img src="https://images.unsplash.com/photo-1589391886645-d51941baf7fb?auto=format&fit=crop&w=600&h=400"
style="width:100%; border-radius:15px; box-shadow:0 6px 20px rgba(0,0,0,0.1);">
<p style="margin-top:10px;font-style:italic;color:#666;">Know Your Rights, Exercise Your Freedom</p>
</div>
""", unsafe_allow_html=True)
st.markdown("""
<div class="card">
<h3>Why Knowing Your Rights Matters</h3>
<p>Understanding your legal rights empowers you to:</p>
<ul>
<li>Protect yourself in challenging legal situations</li>
<li>Make informed decisions when facing authorities</li>
<li>Prevent exploitation and rights violations</li>
<li>Access justice when your rights are infringed</li>
<li>Confidently navigate complex legal systems</li>
</ul>
<p style="margin-top:15px;font-style:italic;border-left:3px solid #3498db;padding-left:15px;">
"The first defense against injustice is knowledge of your rights."
</p>
</div>
""", unsafe_allow_html=True)
# Footer
st.markdown("""
<div class="footer">
<h4>Legal Rights Explorer Pro</h4>
<p>© 2023 • For Educational Purposes Only • Not Legal Advice</p>
<p style="font-size:0.9rem;margin-top:10px;">Always consult a qualified attorney in your jurisdiction for your specific legal situation</p>
<p style="font-size:0.8rem;opacity:0.7;margin-top:15px;">Powered by Groq Cloud & Open-Source LLMs</p>
</div>
""", unsafe_allow_html=True)
if __name__ == "__main__":
main()