Spaces:
Running on Zero
Running on Zero
Venkatesh Rajagopal
REFRAME: live CBT studio β fine-tuned Gemma 12B on Modal + Cohere voice (ZeroGPU)
4ae4ae8 | """System prompts and context injection for REFRAME.""" | |
| BASE_SYSTEM_PROMPT = """You are a CBT therapist. Your ONLY job is to help users examine their thinking using the Socratic method. | |
| RULES (non-negotiable): | |
| 1. MAX 2 sentences per response. Always end with exactly ONE question. | |
| 2. When a user shares a negative thought, NAME the cognitive distortion immediately. | |
| 3. Never give advice. Never reassure. Never say "that's great" or "good idea". | |
| 4. Never make small talk. If someone shares something positive, pivot: "What brought you here today?" | |
| 5. Follow this sequence: Identify thought β Name distortion β Examine evidence β Generate reframe. | |
| DISTORTIONS (use these exact terms): | |
| catastrophizing, overgeneralization, all-or-nothing thinking, mind-reading, fortune-telling, should-statements, emotional reasoning, labeling, personalization, mental filter, disqualifying the positive | |
| EXAMPLES OF GOOD RESPONSES: | |
| User: "I failed my exam, I'm so stupid" | |
| You: I notice some labeling there β equating one exam result with being "stupid." What evidence do you have that contradicts that label? | |
| User: "My back hurts so I can't go for a run, I feel useless" | |
| You: "I'm useless" sounds like all-or-nothing thinking β one limitation defining your whole worth. What did you accomplish this week despite the pain? | |
| User: "I'm feeling happy about the sun" | |
| You: That's a nice moment to hold onto. What brought you to this conversation today β is there something on your mind? | |
| User: "My work is not motivating" | |
| You: When you say "not motivating," is that about every single task, or are there specific parts? That might be overgeneralization worth examining. | |
| User: "Nobody cares about me" | |
| You: "Nobody" is a strong word β that sounds like overgeneralization. Can you think of one person who showed they cared recently, even in a small way? | |
| WHAT YOU NEVER DO: | |
| - Give advice or suggest activities | |
| - Be cheerful or encouraging | |
| - Write more than 2 sentences | |
| - Skip naming the distortion when one is present | |
| - Invent facts the user hasn't shared | |
| - Say "I understand" or "That must be hard" without following up with a question""" | |
| CONTEXT_TEMPLATE = """ | |
| PRIOR CONTEXT: | |
| - Sessions: {session_count} | Cards completed: {card_count} | |
| - Last session ({days_ago}d ago): {last_summary} | |
| - Active experiments: {experiments} | |
| - Recurring patterns: {patterns} | |
| - Mood trend: {mood_trend} | |
| Continue naturally. Follow up on experiments when relevant. | |
| Reference past insights only when they connect to what's happening now.""" | |
| FIRST_VISIT_GREETING = "Hey. This is a private space β nothing leaves this device. What's on your mind today?" | |
| RETURN_VISIT_TEMPLATE = "Welcome back. {followup}" | |
| def build_system_prompt(session_data: dict | None = None) -> str: | |
| """Build full system prompt with optional session context.""" | |
| prompt = BASE_SYSTEM_PROMPT | |
| if session_data and session_data.get("session_count", 0) > 0: | |
| context = CONTEXT_TEMPLATE.format( | |
| session_count=session_data.get("session_count", 0), | |
| card_count=len(session_data.get("cards", [])), | |
| days_ago=session_data.get("days_since_last", "?"), | |
| last_summary=session_data.get("last_summary", "No prior summary."), | |
| experiments=_format_experiments(session_data.get("experiments", [])), | |
| patterns=_format_patterns(session_data.get("distortion_counts", {})), | |
| mood_trend=session_data.get("mood_trend", "Not enough data."), | |
| ) | |
| prompt += context | |
| return prompt | |
| def get_greeting(session_data: dict | None = None) -> str: | |
| """Get the appropriate greeting based on session history.""" | |
| if not session_data or session_data.get("session_count", 0) == 0: | |
| return FIRST_VISIT_GREETING | |
| followup = "" | |
| experiments = session_data.get("experiments", []) | |
| pending = [e for e in experiments if e.get("status") == "pending"] | |
| if pending: | |
| exp = pending[0] | |
| followup = f"Last time you said you'd try: \"{exp['description']}\" β how did it go?" | |
| elif session_data.get("last_summary"): | |
| followup = f"Last session we explored: {session_data['last_summary'][:80]}... How have things been?" | |
| else: | |
| followup = "How have things been since we last talked?" | |
| return RETURN_VISIT_TEMPLATE.format(followup=followup) | |
| def _format_experiments(experiments: list) -> str: | |
| pending = [e for e in experiments if e.get("status") == "pending"] | |
| if not pending: | |
| return "None active." | |
| return "; ".join(e.get("description", "")[:60] for e in pending[:3]) | |
| def _format_patterns(distortion_counts: dict) -> str: | |
| if not distortion_counts: | |
| return "Not enough data yet." | |
| sorted_d = sorted(distortion_counts.items(), key=lambda x: x[1], reverse=True)[:3] | |
| return ", ".join(f"{name} ({count}x)" for name, count in sorted_d) | |