File size: 7,768 Bytes
5f61ab7
 
 
 
 
0a22466
5f61ab7
 
 
 
 
 
0a22466
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f61ab7
 
 
 
 
 
 
 
 
 
 
81fe2c9
 
5f61ab7
81fe2c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f61ab7
 
 
 
 
81fe2c9
 
 
 
 
 
 
 
 
 
 
 
 
 
5f61ab7
81fe2c9
 
 
 
 
 
 
 
 
5f61ab7
81fe2c9
 
 
 
5f61ab7
81fe2c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f61ab7
81fe2c9
5f61ab7
81fe2c9
 
5f61ab7
81fe2c9
 
 
 
5f61ab7
 
 
81fe2c9
5f61ab7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81fe2c9
 
 
 
 
 
5f61ab7
81fe2c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f61ab7
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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/)"
)