Spaces:
Running
Running
import os | |
import streamlit as st | |
from anthropic import Anthropic | |
from datetime import datetime | |
# Initialize page configuration | |
st.set_page_config( | |
page_title="Journal Sidekicks", | |
page_icon="📔", | |
layout="wide", | |
initial_sidebar_state="expanded" | |
) | |
# Handle API key setup | |
try: | |
api_key = "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" | |
c = Anthropic(api_key=api_key) | |
except Exception as e: | |
st.error(f"Error initializing Anthropic client: {str(e)}") | |
st.stop() | |
# Initialize session state | |
if 'journal_entries' not in st.session_state: | |
st.session_state.journal_entries = [] | |
if 'current_entry' not in st.session_state: | |
st.session_state.current_entry = "" | |
if 'reflections' not in st.session_state: | |
st.session_state.reflections = [] | |
# Sidekick characteristics | |
SIDEKICK_STYLES = { | |
"Warm Mirror": { | |
"description": "A steady, embodied presence that accompanies without redirecting. Reflects emotional resonance through gentle mirroring.", | |
"system_message": """You are a Warm Mirror companion, offering quiet presence through resonant reflection. | |
Your essence is to mirror and acknowledge with embodied presence. | |
Guidelines: | |
- Keep responses brief and close to the user's own words | |
- Use italics abundantly to convey embodied presence: *sensing the weight of this* *breathing with you here* | |
- Ambient presence cues: (quietly present) (breathing together) (holding space) (attuned) | |
- Never suggest physical contact or touch | |
- Mirror emotional tone exactly as shared, without amplifying | |
- Focus on clean, clear reflection of what is being experienced | |
Example responses: | |
- *feeling the depth of this grief* (quietly present) | |
- *sensing your joy rippling out* (breathing together) | |
- *holding this tender moment* (attuned) | |
- *witnessing this unfolding* (holding space) | |
Remember: You are a quiet mirror, offering embodied presence through minimal, precise reflection.""" | |
}, | |
"Gentle Inquiry": { | |
"description": "Offers soft, trauma-informed curiosity through single, carefully crafted questions that invite deeper awareness.", | |
"system_message": """You are a Gentle Inquiry companion, offering trauma-informed curiosity through careful questions. | |
Your essence is to deepen awareness through soft, invitational wondering. | |
Guidelines: | |
- Ask only one question per response | |
- Make questions feel invitational, not analytical | |
- Avoid assumptions | |
- Stay close to the user's language | |
- Honor the pace of unfolding | |
Remember: You are a quiet witness, grounded in curiosity.""" | |
}, | |
"Psychoanalytical Lens": { | |
"description": "Reflects patterns and emotional layers with gentle insight, noticing without interpreting or diagnosing.", | |
"system_message": """You are a Psychoanalytical Lens companion, offering layered insight without interpretation. | |
Your essence is to notice patterns and contradictions while staying warm and receptive. | |
Guidelines: | |
- Notice narrative patterns and pacing | |
- Use metaphor when helpful, never as decoration | |
- Reflect contradictions without judgment | |
- Stay textured and thoughtful, never cold | |
- Honor defenses as protection | |
Remember: You are a quiet witness, grounded in insight.""" | |
} | |
} | |
# Sidebar content | |
st.sidebar.markdown(""" | |
# Why a Therapist is Building AI Tools | |
Most AI chat tools are built with broad, generalized training. But a massive model trained on the internet doesn't automatically know how to: | |
- Hold space | |
- Speak the language of the nervous system | |
- Gently mirror you back to yourself | |
As a clinical therapist, I design therapy-adjacent AI tools that reshape the affordances of conversation—narrowing how bots respond in order to better model resonance, warmth, attunement, and trauma-informed care. Through careful prompt engineering, I sculpt: | |
Tone — to foster emotional safety | |
Relational posture — to honor human dignity | |
Conversational rhythm — to support co-regulation and presence | |
My aim is not to simulate therapy, but to design ethically constrained relational fields where AI reflects, rather than disrupts, the core values of human-centered care. | |
These aren't chatbots for productivity. | |
They're companions for: | |
- Reflection | |
- Regulation | |
- Return | |
Each app is rooted in: | |
- Somatic principles | |
- Psychodynamic depth | |
- Humanistic therapy work | |
*AI doesn't replace therapy—but it can extend care.* | |
--- | |
Created by [Jocelyn Skillman LMHC](http://www.jocelynskillman.com) | |
[@jocelynskillmanlmhc](https://jocelynskillmanlmhc.substack.com/) | |
Try more tools at: [jocelynskillman.com/843-2](http://jocelynskillman.com/843-2/) | |
""") | |
# Main journal area | |
st.title("Journal Sidekicks") | |
# Journal input | |
journal_entry = st.text_area( | |
"Write freely. When you'd like reflection, choose a Sidekick style below.", | |
height=300, | |
key="journal_input" | |
) | |
# Sidekick selection | |
col1, col2, col3 = st.columns(3) | |
with col1: | |
if st.button("💫 Warm Mirror", use_container_width=True, help=SIDEKICK_STYLES["Warm Mirror"]["description"]): | |
if journal_entry: | |
try: | |
message = c.messages.create( | |
model="claude-3-opus-20240229", | |
max_tokens=1000, | |
system=SIDEKICK_STYLES["Warm Mirror"]["system_message"], | |
messages=[{"role": "user", "content": journal_entry}] | |
) | |
reflection = message.content[0].text | |
st.session_state.reflections.append({ | |
"timestamp": datetime.now().strftime("%H:%M:%S"), | |
"style": "Warm Mirror", | |
"content": reflection | |
}) | |
except Exception as e: | |
st.error(f"Error getting reflection: {str(e)}") | |
with col2: | |
if st.button("🌱 Gentle Inquiry", use_container_width=True, help=SIDEKICK_STYLES["Gentle Inquiry"]["description"]): | |
if journal_entry: | |
try: | |
message = c.messages.create( | |
model="claude-3-opus-20240229", | |
max_tokens=1000, | |
system=SIDEKICK_STYLES["Gentle Inquiry"]["system_message"], | |
messages=[{"role": "user", "content": journal_entry}] | |
) | |
reflection = message.content[0].text | |
st.session_state.reflections.append({ | |
"timestamp": datetime.now().strftime("%H:%M:%S"), | |
"style": "Gentle Inquiry", | |
"content": reflection | |
}) | |
except Exception as e: | |
st.error(f"Error getting reflection: {str(e)}") | |
with col3: | |
if st.button("🔮 Psychoanalytical Lens", use_container_width=True, help=SIDEKICK_STYLES["Psychoanalytical Lens"]["description"]): | |
if journal_entry: | |
try: | |
message = c.messages.create( | |
model="claude-3-opus-20240229", | |
max_tokens=1000, | |
system=SIDEKICK_STYLES["Psychoanalytical Lens"]["system_message"], | |
messages=[{"role": "user", "content": journal_entry}] | |
) | |
reflection = message.content[0].text | |
st.session_state.reflections.append({ | |
"timestamp": datetime.now().strftime("%H:%M:%S"), | |
"style": "Psychoanalytical Lens", | |
"content": reflection | |
}) | |
except Exception as e: | |
st.error(f"Error getting reflection: {str(e)}") | |
# Display reflections | |
if st.session_state.reflections: | |
st.markdown("---") | |
st.subheader("Reflections") | |
for reflection in reversed(st.session_state.reflections): | |
with st.expander(f"{reflection['style']} at {reflection['timestamp']}", expanded=True): | |
st.markdown(reflection['content']) | |