Spaces:
Sleeping
Sleeping
# 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: 1000px; | |
margin: 0 auto; | |
} | |
.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-card { | |
display: flex; | |
align-items: center; | |
gap: 15px; | |
padding: 1.5rem; | |
border-radius: 15px; | |
background: white; | |
box-shadow: var(--card-shadow); | |
margin-bottom: 18px; | |
cursor: pointer; | |
transition: var(--transition); | |
border: 2px solid transparent; | |
} | |
.country-card:hover { | |
transform: translateX(8px); | |
box-shadow: 0 10px 25px rgba(0,0,0,0.15); | |
} | |
.country-card.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: 768px) { | |
.header { | |
padding: 1.8rem 1.2rem; | |
} | |
.card { | |
padding: 1.5rem; | |
} | |
.scenario-btn { | |
padding: 1rem; | |
font-size: 1rem; | |
} | |
} | |
</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" | |
} | |
# 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 (Best)": "llama3-70b-8192", | |
"Llama3-8b (Fast)": "llama3-8b-8192", | |
"Mixtral-8x7b": "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(3) | |
with model_cols[0]: | |
selected_model = st.selectbox("Choose AI Model", list(MODELS.keys()), index=0) | |
with model_cols[1]: | |
st.markdown("### ๐ Country") | |
st.caption("Selected: " + st.session_state.selected_country) | |
# 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") | |
# Country selection cards | |
for country_display in COUNTRIES.keys(): | |
is_selected = st.session_state.selected_country == country_display | |
# Use button to capture click | |
if st.button(country_display, | |
key=f"btn_{country_display}", | |
use_container_width=True, | |
type="primary" if is_selected else "secondary"): | |
st.session_state.selected_country = country_display | |
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] # Simulated data | |
fig = px.bar( | |
x=countries, | |
y=awareness, | |
labels={'x': 'Country', 'y': 'Rights Awareness'}, | |
color=awareness, | |
color_continuous_scale='Teal', | |
height=300 | |
) | |
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) | |
) | |
st.plotly_chart(fig, use_container_width=True) | |
# Legal resources | |
with st.expander("๐ Legal Resources & References"): | |
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/) | |
""") | |
with col2: | |
st.markdown("### ๐จ Select a Legal Scenario") | |
st.markdown("Choose a situation to understand your rights and protections") | |
# Create buttons for each scenario | |
cols = st.columns(2) | |
for i, scenario in enumerate(SCENARIOS): | |
with cols[i % 2]: | |
if st.button( | |
f"**{scenario}**", | |
key=scenario, | |
use_container_width=True, | |
help=f"Click to see your rights for {scenario}" | |
): | |
st.session_state.selected_scenario = scenario | |
# Custom scenario input | |
custom_scenario = st.text_input("**Or describe your specific situation:**", placeholder="e.g., 'Rights during home search', 'Employee privacy rights'") | |
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.image("https://images.unsplash.com/photo-1589391886645-d51941baf7fb?auto=format&fit=crop&w=600&h=400", | |
caption="Know Your Rights, Exercise Your Freedom") | |
st.markdown(""" | |
<div class="card"> | |
<h3>Why Know Your Rights?</h3> | |
<p>Understanding your legal rights empowers you to:</p> | |
<ul> | |
<li>Protect yourself in difficult situations</li> | |
<li>Make informed decisions when facing legal issues</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;">"Knowledge of the law is the first defense against injustice."</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() |