Files
LivingAgents/living_agents/datatypes.py
2025-09-05 19:00:24 +02:00

90 lines
2.7 KiB
Python

from dataclasses import dataclass, field
from typing import Dict, List, Optional, Literal, TypedDict
from datetime import datetime
from uuid import uuid4
from pathlib import Path
class CharacterTemplate(TypedDict):
name: str
observations: List[str]
reflections: List[str]
plans: List[str]
yaml_file: Path
@dataclass
class Memory:
"""A single memory object with Stanford's architecture"""
description: str
creation_time: datetime = field(default_factory=datetime.now)
last_accessed: datetime = field(default_factory=datetime.now)
importance_score: int = 5 # 1-10 scale
embedding: Optional[List[float]] = None
memory_type: Literal["observation", "reflection", "plan"] = "observation"
related_memories: List['Memory'] = field(default_factory=list) # IDs of supporting memories
def __post_init__(self):
if self.last_accessed is None:
self.last_accessed = self.creation_time
@dataclass
class CharacterTrait:
name: str
description: str
strength: int = 0
updated: datetime = field(default_factory=datetime.now)
def change_by_probability(self, steepness: float = 1.0) -> float:
"""
Returns probability of trait change (0.0 to 1.0)
steepness: higher values = more resistance to change
steepness = 1.0 (moderate):
Strength 1: 90% chance
Strength 5: 50% chance
Strength 9: 10% chance
steepness = 2.0 (steep):
Strength 1: 81% chance
Strength 5: 25% chance
Strength 9: 1% chance
steepness = 0.5 (gradual):
Strength 1: 95% chance
Strength 5: 71% chance
Strength 9: 32% chance
"""
return (10 - self.strength) / 10.0 ** steepness
@dataclass
class Character:
name: str
age: Optional[int] = None
personality: str = ""
occupation: str = ""
location: str = ""
traits: List[CharacterTrait] = field(default_factory=list)
relationships: Dict[str, str] = field(default_factory=dict)
goals: List[str] = field(default_factory=list)
template_file: Optional[Path] = None
_id: str = field(default_factory=lambda: str(uuid4())[:8])
def get_trait(self, trait_name, trait_description) -> CharacterTrait:
for trait in self.traits:
if trait.name.lower() == trait_name.lower():
return trait
self.traits.append(CharacterTrait(name=trait_name.lower(), strength=0, description=trait_description))
return self.traits[-1]
def __hash__(self):
return hash(self._id)
def __eq__(self, other):
return isinstance(other, Character) and self._id == other._id