Spaces:
Sleeping
Sleeping
File size: 4,618 Bytes
a865db3 |
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 |
import yaml
import os
def load_persona(path):
"""
Load a LitDigitalTwin persona from YAML file.
Ensures required fields and initializes missing defaults.
"""
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 top-level keys
required_keys = [
"persona_name",
"age",
"role",
"system_prompt",
"facts"
]
for key in required_keys:
if key not in persona:
raise ValueError(f"Missing required key in persona: {key}")
# 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"] = []
# Initialize default_state if missing
if "default_state" not in persona:
persona["default_state"] = {}
state = persona["default_state"]
default_state_keys = {
"anxiety": 0.5,
"trust": 0.5,
"openness": 0.5,
"mode": "baseline",
"emotional_memory": []
}
for key, default in default_state_keys.items():
if key not in state:
print(f"Warning: Missing state key '{key}' in persona. Using default value.")
state[key] = default
# Ensure tone_guidance exists and has at least 'baseline'
if "tone_guidance" not in persona:
persona["tone_guidance"] = {
"baseline": {
"voice": "Natural and authentic",
"example": "I'm doing okay today, thanks for asking."
}
}
return persona
def validate_persona(persona):
"""
Validate that a persona has all necessary components for simulation.
Returns (is_valid, error_message)
"""
if not persona.get("persona_name"):
return False, "Persona must have a name"
if not persona.get("system_prompt"):
return False, "Persona must have a system_prompt"
if not isinstance(persona.get("facts"), list):
return False, "Persona 'facts' must be a list"
state = persona.get("default_state", {})
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"
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 LitDigitalTwin persona template.
"""
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}."
],
"tone_guidance": {
"baseline": {
"voice": "Natural and authentic",
"example": "I'm doing okay today, thanks for asking."
}
},
"default_state": {
"anxiety": 0.5,
"trust": 0.5,
"openness": 0.5,
"mode": "baseline",
"emotional_memory": []
}
}
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 |