Spaces:
Sleeping
Sleeping
| import os | |
| import streamlit as st | |
| from anthropic import Anthropic | |
| from dotenv import load_dotenv | |
| # Initialize page configuration first | |
| st.set_page_config( | |
| page_title="Attachment Style Roleplay Simulator", | |
| page_icon="π£οΈ", | |
| layout="wide" | |
| ) | |
| # Handle API key | |
| try: | |
| # Load from .env file for local development | |
| if os.path.exists(".env"): | |
| load_dotenv() | |
| # Get API key from environment | |
| api_key = os.getenv('ANTHROPIC_API_KEY') | |
| if not api_key: | |
| st.error(""" | |
| β οΈ Anthropic API Key not found! | |
| Please make sure you have set the ANTHROPIC_API_KEY: | |
| - For local development: in your .env file | |
| - For Hugging Face Spaces: in your Space's secrets | |
| """) | |
| st.stop() | |
| # Initialize Anthropic client | |
| c = Anthropic(api_key=api_key) | |
| except Exception as e: | |
| st.error(f""" | |
| β οΈ Error initializing Anthropic client: {str(e)} | |
| Please check: | |
| 1. Your ANTHROPIC_API_KEY is set correctly | |
| 2. You're using a valid API key from Anthropic | |
| """) | |
| st.stop() | |
| # Initialize session state variables | |
| if 'messages' not in st.session_state: | |
| st.session_state.messages = [] | |
| if 'setup_complete' not in st.session_state: | |
| st.session_state.setup_complete = False | |
| if 'system_message' not in st.session_state: | |
| st.session_state.system_message = "" | |
| # Main page header | |
| st.title("Attachment Style Roleplay Simulator") | |
| # Welcome text in main content area | |
| st.markdown(""" | |
| Welcome! | |
| Created by [Jocelyn Skillman LMHC](http://www.jocelynskillman.com), this tool is designed to help you practice and understand relational dynamics through the lens of attachment theory. | |
| To learn more about attachment theory and therapeutic approaches, check out my newsletter: [@jocelynskillmanlmhc](https://jocelynskillmanlmhc.substack.com/) | |
| """) | |
| st.markdown(""" | |
| This specific project β the Attachment Roleplay Simulator β invites users to practice emotionally difficult conversations, like setting boundaries, through roleplay tailored to their attachment style. It's designed to help people feel into relational patterns, develop language for self-advocacy, and build nervous system capacity for connection and repair. | |
| π‘ Not sure about your attachment style? | |
| You can take the free quiz by Sarah Peyton β or simply choose the one that resonates when you read it: | |
| Anxious β "I often worry I've upset people or need to explain myself." | |
| Avoidant β "I'd rather deal with things alone and not depend on anyone." | |
| Disorganized β "I want closeness, but also feel unsafe or mistrusting." | |
| Secure β "I can express needs and handle conflict without losing connection." | |
| Choose what vibes β this is a practice space, not a test. | |
| """) | |
| # Sidebar welcome and introduction | |
| with st.sidebar: | |
| st.markdown(""" | |
| Hi, I'm Jocelyn Skillman, LMHC β a clinical therapist, relational design ethicist, and creator of experimental tools that explore how AI can support (not replace) human care. | |
| Each tool in this collection is thoughtfully designed to: | |
| Extend therapeutic support between sessions | |
| Model emotional safety and relational depth | |
| Help clients and clinicians rehearse courage, regulation, and repair | |
| Stay grounded in trauma-informed, developmentally sensitive frameworks | |
| """) | |
| st.divider() | |
| # Add the moved content to the bottom of sidebar | |
| st.markdown(""" | |
| I use Claude (by Anthropic) as the primary language model for these tools, chosen for its relational tone, contextual nuance, and responsiveness to emotionally complex prompts. | |
| As a practicing therapist, I imagine these resources being especially helpful to clinicians like myself β companions in the work of tending to others with insight, warmth, and care. | |
| To learn more about my work, visit: | |
| π [jocelynskillman.com](http://www.jocelynskillman.com) | |
| π¬ [Substack: Relational Code](https://jocelynskillmanlmhc.substack.com/) | |
| """) | |
| # Simulation setup form | |
| with st.form("setup_form"): | |
| st.header("Set Up Your Simulation") | |
| attachment_style = st.selectbox( | |
| "Select your attachment style:", | |
| ["Secure", "Anxious", "Avoidant", "Disorganized"] | |
| ) | |
| scenario = st.text_area( | |
| "Describe the scenario you'd like to practice:", | |
| placeholder="Example: Having a difficult conversation with my partner about feeling disconnected" | |
| ) | |
| tone = st.text_input( | |
| "How would you like the AI to respond?", | |
| placeholder="Example: Direct but understanding" | |
| ) | |
| goals = st.text_area( | |
| "What are your practice goals?", | |
| placeholder="Example: Practice expressing needs without becoming defensive" | |
| ) | |
| submitted = st.form_submit_button("Start Simulation") | |
| if submitted: | |
| # Prepare system message with simulation parameters | |
| st.session_state.system_message = f""" | |
| You are a conversational partner helping someone practice difficult conversations. | |
| The user has a {attachment_style} attachment style and wants to practice: {scenario} | |
| Respond in a {tone} manner. Help them achieve their goals: {goals} | |
| Maintain a realistic conversation while providing gentle guidance when needed. | |
| """ | |
| # Reset message history | |
| st.session_state.messages = [] | |
| st.session_state.setup_complete = True | |
| st.rerun() | |
| # Display status or chat interface | |
| if not st.session_state.setup_complete: | |
| st.info("Please complete the simulation setup to begin.") | |
| else: | |
| # Display chat history | |
| for message in st.session_state.messages: | |
| with st.chat_message(message["role"]): | |
| st.markdown(message["content"]) | |
| # Chat input | |
| if prompt := st.chat_input("Type your message here..."): | |
| # Add user message to chat history | |
| st.session_state.messages.append({"role": "user", "content": prompt}) | |
| # Display user message | |
| with st.chat_message("user"): | |
| st.markdown(prompt) | |
| # Get AI response | |
| with st.chat_message("assistant"): | |
| with st.spinner("Thinking..."): | |
| # Construct conversation history | |
| messages = [] | |
| if st.session_state.system_message: | |
| messages.append({"role": "system", "content": st.session_state.system_message}) | |
| for msg in st.session_state.messages: | |
| messages.append({"role": msg["role"], "content": msg["content"]}) | |
| # Get completion | |
| try: | |
| message = c.messages.create( | |
| model="claude-3-opus-20240229", | |
| max_tokens=1000, | |
| system=st.session_state.system_message, | |
| messages=[ | |
| {"role": msg["role"], "content": msg["content"]} | |
| for msg in st.session_state.messages | |
| ] | |
| ) | |
| ai_response = message.content[0].text | |
| st.markdown(ai_response) | |
| # Add AI response to chat history | |
| st.session_state.messages.append( | |
| {"role": "assistant", "content": ai_response} | |
| ) | |
| except Exception as e: | |
| st.error(f"Error getting AI response: {str(e)}") | |
| st.error("Please try again or contact support if the issue persists.") | |
| # Footer | |
| st.markdown("---") | |
| st.markdown( | |
| "Created by [Jocelyn Skillman LMHC](http://www.jocelynskillman.com) | " | |
| "Learn more: [@jocelynskillmanlmhc](https://jocelynskillmanlmhc.substack.com/)" | |
| ) | |