jmisak's picture
Upload 5 files
8cd2084 verified
import yaml
import os
def load_persona(path):
"""
Load a mental health persona from YAML file.
Validates required fields for OT simulation.
"""
if not os.path.exists(path):
raise FileNotFoundError(f"Persona file not found: {path}")
with open(path, "r", encoding="utf-8") as f:
persona = yaml.safe_load(f)
# Required keys for mental health personas
required_keys = [
"persona_name",
"age",
"role",
"system_prompt",
"facts",
"default_state"
]
for key in required_keys:
if key not in persona:
raise ValueError(f"Missing required key in persona: {key}")
# Ensure default_state has required emotional metrics
state = persona.get("default_state", {})
required_state_keys = ["anxiety", "trust", "openness", "mode"]
for key in required_state_keys:
if key not in state:
print(f"Warning: Missing state key '{key}' in persona. Using default value.")
if key == "mode":
state[key] = "baseline"
else:
state[key] = 0.5
# Initialize emotional_memory if not present
if "emotional_memory" not in state:
state["emotional_memory"] = []
# Ensure facts is a list
if not isinstance(persona.get("facts"), list):
print("Warning: facts should be a list. Converting.")
facts = persona.get("facts", [])
if isinstance(facts, dict):
persona["facts"] = list(facts.values())
else:
persona["facts"] = []
return persona
def validate_persona(persona):
"""
Validate that a persona has all necessary components for simulation.
Returns (is_valid, error_message)
"""
# Check persona name
if not persona.get("persona_name"):
return False, "Persona must have a name"
# Check default state
state = persona.get("default_state", {})
if not state:
return False, "Persona must have a default_state"
# Check that anxiety, trust, openness are numeric
for key in ["anxiety", "trust", "openness"]:
value = state.get(key)
if value is None:
return False, f"default_state missing required key: {key}"
if not isinstance(value, (int, float)):
return False, f"default_state.{key} must be numeric"
if not 0 <= value <= 1:
return False, f"default_state.{key} must be between 0 and 1"
# Check tone_guidance exists
if not persona.get("tone_guidance"):
return False, "Persona must have tone_guidance"
# Check that tone_guidance has mode entries
tone_guidance = persona.get("tone_guidance", {})
recommended_modes = ["baseline", "guarded", "triggered", "trusting", "decompensating"]
missing_modes = [mode for mode in recommended_modes if mode not in tone_guidance]
if missing_modes:
print(f"Warning: tone_guidance missing modes: {missing_modes}")
return True, "Persona is valid"
def save_persona(persona, path):
"""
Save a persona to YAML file.
"""
with open(path, "w", encoding="utf-8") as f:
yaml.dump(persona, f, sort_keys=False, default_flow_style=False)
return path
def create_default_persona(name, age, role):
"""
Create a basic persona template for development/testing.
"""
persona = {
"persona_name": name,
"age": age,
"role": role,
"system_prompt": f"You are {name}, a {age}-year-old {role}. Respond naturally and stay in character.",
"facts": [
f"{name} is {age} years old",
f"{name} works as a {role}"
],
"triggers": [
"criticism",
"pressure",
"isolation"
],
"reasoning_style": "Tends to analyze situations carefully before responding.",
"tone_guidance": {
"baseline": {
"voice": "Calm and thoughtful",
"example": "I'm doing okay today, thanks for asking."
},
"guarded": {
"voice": "Brief and cautious",
"example": "I'd rather not talk about that right now."
},
"triggered": {
"voice": "Defensive or withdrawn",
"example": "I don't see how that's relevant."
},
"trusting": {
"voice": "Open and reflective",
"example": "You know, I've been thinking about what you said last time..."
},
"decompensating": {
"voice": "Fragmented and overwhelmed",
"example": "I just... I can't... it's too much."
}
},
"default_state": {
"anxiety": 0.5,
"trust": 0.5,
"openness": 0.5,
"mode": "baseline",
"emotional_memory": []
},
"scripts": {
"crisis": "I'm not feeling safe right now. I need to step away.",
"deflection": "It's fine. I don't want to make a big deal out of it.",
"testing_trust": "Why are you asking about that?",
"resistance": "I don't see how talking about this helps."
},
"resilience_hooks": [
f"{name} has coping strategies they've used before",
f"{name} values certain relationships in their life"
]
}
return persona
def list_available_personas(persona_dir="./personas"):
"""
List all available persona files.
"""
if not os.path.exists(persona_dir):
return []
personas = []
for filename in os.listdir(persona_dir):
if filename.endswith(".yml") or filename.endswith(".yaml"):
path = os.path.join(persona_dir, filename)
try:
persona = load_persona(path)
personas.append({
"filename": filename,
"name": persona.get("persona_name", "Unknown"),
"age": persona.get("age", ""),
"role": persona.get("role", "")
})
except Exception as e:
print(f"Error loading {filename}: {e}")
return personas