Spaces:
Sleeping
Sleeping
# app.py | |
import streamlit as st | |
import torch | |
import random | |
import altair as alt | |
import pandas as pd | |
from datetime import datetime | |
from reportlab.lib.pagesizes import letter | |
from reportlab.pdfgen import canvas | |
import io | |
from transformers import AutoModelForSequenceClassification, AutoTokenizer | |
from groq import Groq | |
# Initialize components | |
try: | |
groq_client = Groq(api_key=st.secrets["GROQ_API_KEY"]) | |
model = AutoModelForSequenceClassification.from_pretrained("KevSun/Personality_LM", ignore_mismatched_sizes=True) | |
tokenizer = AutoTokenizer.from_pretrained("KevSun/Personality_LM") | |
except Exception as e: | |
st.error(f"Initialization error: {str(e)}") | |
st.stop() | |
# Configure Streamlit | |
st.set_page_config(page_title="π§ PersonaCraft", layout="wide", page_icon="π") | |
# Custom CSS | |
st.markdown(""" | |
<style> | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
.quote-box { | |
animation: fadeIn 1s ease-in; | |
border-left: 5px solid #4CAF50; | |
padding: 20px; | |
margin: 20px 0; | |
background: #f8fff9; | |
border-radius: 10px; | |
box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
} | |
.tip-card { | |
padding: 15px; | |
margin: 10px 0; | |
background: #fff3e0; | |
border-radius: 10px; | |
border: 1px solid #ffab40; | |
} | |
.social-post { | |
background: #e3f2fd; | |
padding: 20px; | |
border-radius: 15px; | |
margin: 15px 0; | |
} | |
.viz-box { | |
background: white; | |
padding: 20px; | |
border-radius: 15px; | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
} | |
.nav-btn { | |
margin: 8px 0; | |
width: 100%; | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Personality configuration | |
OCEAN_TRAITS = ["agreeableness", "openness", "conscientiousness", "extraversion", "neuroticism"] | |
QUESTION_BANK = [ | |
{"text": "If your personality was a pizza topping, what would it be? π", "trait": "openness"}, | |
{"text": "Describe your ideal alarm clock vs reality β°", "trait": "conscientiousness"}, | |
{"text": "How would you survive a surprise party? π", "trait": "neuroticism"}, | |
{"text": "What's your spirit animal during deadlines? πΎ", "trait": "agreeableness"}, | |
{"text": "Plan a perfect day... for your nemesis! π", "trait": "extraversion"}, | |
{"text": "If stress was a color, what's your current shade? π¨", "trait": "neuroticism"}, | |
{"text": "What would your browser history say about you? π", "trait": "openness"}, | |
{"text": "Describe your phone's home screen as a poem π±", "trait": "conscientiousness"}, | |
{"text": "React to 'Your idea is interesting, but...' π‘", "trait": "agreeableness"}, | |
{"text": "What's your superpower in awkward situations? π¦Έ", "trait": "extraversion"} | |
] | |
# Session state management | |
if 'started' not in st.session_state: | |
st.session_state.started = False | |
if 'current_q' not in st.session_state: | |
st.session_state.current_q = 0 | |
if 'responses' not in st.session_state: | |
st.session_state.responses = [] | |
if 'page' not in st.session_state: | |
st.session_state.page = "π Home" | |
# Functions | |
def generate_quote(): | |
prompt = "Generate a fresh motivational quote about self-discovery with an emoji" | |
response = groq_client.chat.completions.create( | |
model="mixtral-8x7b-32768", | |
messages=[{"role": "user", "content": prompt}], | |
temperature=0.7 | |
) | |
return response.choices[0].message.content | |
def analyze_personality(text): | |
encoded_input = tokenizer(text, return_tensors='pt', padding=True, truncation=True, max_length=64) | |
with torch.no_grad(): | |
outputs = model(**encoded_input) | |
predictions = torch.nn.functional.softmax(outputs.logits, dim=-1) | |
return {trait: score.item() for trait, score in zip(OCEAN_TRAITS, predictions[0])} | |
def create_pdf_report(traits, quote): | |
buffer = io.BytesIO() | |
p = canvas.Canvas(buffer, pagesize=letter) | |
p.setFont("Helvetica-Bold", 16) | |
p.drawString(100, 750, "π PersonaCraft Psychological Report π") | |
p.setFont("Helvetica", 12) | |
y_position = 700 | |
for trait, score in traits.items(): | |
p.drawString(100, y_position, f"{trait.upper()}: {score:.2f}") | |
y_position -= 20 | |
p.drawString(100, y_position-40, "Motivational Quote:") | |
p.drawString(100, y_position-60, quote) | |
p.save() | |
buffer.seek(0) | |
return buffer | |
def generate_social_post(platform, traits): | |
platform_formats = { | |
"LinkedIn": "professional tone with industry hashtags", | |
"Instagram": "visual storytelling with emojis", | |
"Facebook": "friendly community-oriented style", | |
"WhatsApp": "casual conversational format", | |
"Twitter": "concise with trending hashtags" | |
} | |
prompt = f"""Create a {platform} post about personal growth with these personality traits: | |
{traits} | |
Format: {platform_formats[platform]} | |
Include relevant emojis and keep under 280 characters.""" | |
response = groq_client.chat.completions.create( | |
model="mixtral-8x7b-32768", | |
messages=[{"role": "user", "content": prompt}], | |
temperature=0.7 | |
) | |
return response.choices[0].message.content | |
# Main UI | |
if not st.session_state.started: | |
st.markdown(f""" | |
<div class="quote-box"> | |
<h2>π Welcome to PersonaCraft! π</h2> | |
<h3>{generate_quote()}</h3> | |
</div> | |
""", unsafe_allow_html=True) | |
if st.button("π Start Personality Journey!", use_container_width=True): | |
st.session_state.started = True | |
st.session_state.selected_questions = random.sample(QUESTION_BANK, 5) | |
st.rerun() | |
else: | |
# Sidebar navigation | |
with st.sidebar: | |
st.title("π§ Navigation") | |
st.markdown("---") | |
if st.button("π Personality Report", key="btn1", use_container_width=True, | |
help="View your detailed personality analysis"): | |
st.session_state.page = "π Personality Report" | |
if st.button("π Visual Analysis", key="btn2", use_container_width=True, | |
help="Explore visual representations of your personality"): | |
st.session_state.page = "π Visual Analysis" | |
if st.button("π± Social Media Post", key="btn3", use_container_width=True, | |
help="Generate personalized social media posts"): | |
st.session_state.page = "π± Social Media Post" | |
if st.button("π‘ Success Tips", key="btn4", use_container_width=True, | |
help="Discover personalized improvement tips"): | |
st.session_state.page = "π‘ Success Tips" | |
if st.button("π₯ Download Report", key="btn5", use_container_width=True, | |
help="Download your complete personality report"): | |
st.session_state.page = "π₯ Download Report" | |
# Question flow | |
if st.session_state.current_q < 5: | |
q = st.session_state.selected_questions[st.session_state.current_q] | |
st.progress(st.session_state.current_q/5, text="Assessment Progress") | |
with st.chat_message("assistant"): | |
st.markdown(f"### {q['text']}") | |
user_input = st.text_input("Your response:", key=f"q{st.session_state.current_q}") | |
if st.button("Next β‘οΈ"): | |
st.session_state.responses.append(user_input) | |
st.session_state.current_q += 1 | |
st.rerun() | |
else: | |
# Process responses | |
traits = analyze_personality("\n".join(st.session_state.responses)) | |
quote = generate_quote() | |
# Current page display | |
if st.session_state.page == "π Personality Report": | |
st.header("π Personality Breakdown") | |
cols = st.columns(5) | |
for i, (trait, score) in enumerate(traits.items()): | |
cols[i].metric(label=trait.upper(), value=f"{score:.2f}") | |
st.divider() | |
st.header("π Emotional Landscape") | |
emotion_data = pd.DataFrame({ | |
"Trait": traits.keys(), | |
"Score": traits.values() | |
}) | |
st.altair_chart(alt.Chart(emotion_data).mark_bar().encode( | |
x="Trait", | |
y="Score", | |
color=alt.Color("Trait", legend=None) | |
), use_container_width=True) | |
elif st.session_state.page == "π Visual Analysis": | |
st.header("π Personality Visualization") | |
# Fix radar chart encoding | |
radar_data = pd.DataFrame({ | |
"Trait": list(traits.keys()), | |
"Score": list(traits.values()), | |
"Angle": [i*(360/5) for i in range(5)] | |
}) | |
chart = alt.Chart(radar_data).mark_line(point=True).encode( | |
theta=alt.Theta("Angle:Q", stack=True), | |
radius=alt.Radius("Score:Q", scale=alt.Scale(type='linear', zero=True)), | |
color=alt.value("#4CAF50"), | |
tooltip=["Trait", "Score"] | |
).project(type='radial') | |
st.altair_chart(chart, use_container_width=True) | |
elif st.session_state.page == "π± Social Media Post": | |
st.header("π± Create Social Post") | |
platform = st.selectbox("Select Platform:", ["LinkedIn", "Instagram", "Facebook", "WhatsApp", "Twitter"]) | |
if st.button("Generate Post π"): | |
post = generate_social_post(platform, traits) | |
st.session_state.post = post | |
if 'post' in st.session_state: | |
st.markdown(f""" | |
<div class="social-post"> | |
<p>{st.session_state.post}</p> | |
</div> | |
""", unsafe_allow_html=True) | |
st.button("π Copy to Clipboard", on_click=lambda: st.write(st.session_state.post)) | |
elif st.session_state.page == "π‘ Success Tips": | |
st.header("π‘ Personality Success Tips") | |
tips = [ | |
"π± Practice daily self-reflection journaling", | |
"π€ Seek diverse social interactions weekly", | |
"π― Set SMART goals for personal development", | |
"π§βοΈ Incorporate mindfulness practices daily", | |
"π Engage in cross-disciplinary learning", | |
"π£οΈ Practice active listening techniques", | |
"π Embrace constructive feedback regularly", | |
"βοΈ Maintain work-life harmony", | |
"π Develop emotional granularity skills", | |
"π Challenge comfort zones monthly" | |
] | |
for tip in tips: | |
st.markdown(f"<div class='tip-card'>{tip}</div>", unsafe_allow_html=True) | |
elif st.session_state.page == "π₯ Download Report": | |
st.header("π₯ Download Complete Report") | |
pdf_buffer = create_pdf_report(traits, quote) | |
st.download_button( | |
"β¬οΈ Download PDF Report", | |
data=pdf_buffer, | |
file_name="personacraft_report.pdf", | |
mime="application/pdf", | |
use_container_width=True | |
) |