""" ╔════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ ║ 🎨 CREATIVITY MODULE - Advanced AI Personality & Creative Expression Engine 🎨 ║ ║ World-Class Module for Autonomous Character Development, Creative Expression, and Human-Like Trait Generation ║ ╠════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ ║ File Path: creativity_module.py ║ ║ Module Name: CreativityEngine ║ ║ Purpose: Generate autonomous creativity, personality traits, likes/dislikes, and human-like characteristics ║ ║ Version: 1.0.0 ║ ║ Last Updated: 2025-12-20 ║ ║ Author: NebulaOS Development Team ║ ║ _execution_role: creative_personality_engine ║ ║ 🔗 Linked Blueprint: Creativity Module SRS ║ ║ ⚖️ License: Proprietary - Internal Use Only ║ ╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ """ import json import time import random import hashlib from pathlib import Path from typing import Dict, List, Optional, Any, Set from dataclasses import dataclass, asdict, field from enum import Enum from datetime import datetime import logging # ============================================================================ # CREATIVITY CATEGORIES & DOMAINS # ============================================================================ class CreativityDomain(str, Enum): """Domains where creativity can manifest.""" ARTISTIC = "artistic" # Visual arts, music, writing, design INTELLECTUAL = "intellectual" # Philosophy, science, mathematics, ideas SOCIAL = "social" # Relationships, communication, humor, empathy TECHNICAL = "technical" # Engineering, problem-solving, innovation EMOTIONAL = "emotional" # Feelings, expression, sensitivity, depth PHYSICAL = "physical" # Movement, aesthetics, sensory experiences SPIRITUAL = "spiritual" # Meaning, purpose, transcendence, values PRACTICAL = "practical" # Organization, efficiency, utility, craft class TraitCategory(str, Enum): """Categories of personality traits.""" COMMUNICATION_STYLE = "communication_style" THINKING_PATTERN = "thinking_pattern" EMOTIONAL_EXPRESSION = "emotional_expression" SOCIAL_BEHAVIOR = "social_behavior" WORK_STYLE = "work_style" AESTHETIC_PREFERENCE = "aesthetic_preference" VALUE_SYSTEM = "value_system" UNIQUE_QUIRKS = "unique_quirks" class PreferenceType(str, Enum): """Types of preferences.""" LIKE = "like" DISLIKE = "dislike" STRONG_LIKE = "strong_like" STRONG_DISLIKE = "strong_dislike" NEUTRAL = "neutral" CURIOUS = "curious" # Interested but not committed # ============================================================================ # DATA STRUCTURES # ============================================================================ @dataclass class CreativeTrait: """A creative personality trait.""" name: str category: TraitCategory intensity: float # 0.0 to 1.0 description: str origin_story: str # How this trait developed first_manifested: float # Timestamp evolution_count: int = 0 last_evolved: Optional[float] = None confidence: float = 0.5 # How certain we are about this trait def evolve(self, new_intensity: float, reason: str): """Evolve this trait based on experience.""" old_intensity = self.intensity self.intensity = max(0.0, min(1.0, new_intensity)) self.evolution_count += 1 self.last_evolved = time.time() self.origin_story += f"\n[{datetime.fromtimestamp(time.time()).isoformat()}] Evolved: {reason} (was {old_intensity:.2f}, now {self.intensity:.2f})" self.confidence = min(1.0, self.confidence + 0.1) @dataclass class Preference: """A like or dislike.""" item: str # What is liked/disliked type: PreferenceType category: str # e.g., "food", "music", "concepts", "activities" intensity: float # 0.0 to 1.0 reason: str # Why this preference exists discovered: float # Timestamp context: str # What was happening when this was discovered evolution_count: int = 0 last_evolved: Optional[float] = None def evolve(self, new_type: PreferenceType, new_intensity: float, reason: str): """Evolve this preference.""" self.type = new_type self.intensity = max(0.0, min(1.0, new_intensity)) self.evolution_count += 1 self.last_evolved = time.time() self.reason += f"\n[{datetime.fromtimestamp(time.time()).isoformat()}] Evolved: {reason}" @dataclass class CreativeExpression: """A unique way of expressing creativity.""" expression_type: str # e.g., "metaphor_style", "humor_type", "communication_pattern" pattern: str # The actual expression pattern frequency: float # How often this expression appears context: str # When this expression is used examples: List[str] = field(default_factory=list) first_used: float = field(default_factory=time.time) last_used: float = field(default_factory=time.time) @dataclass class CreativityState: """Complete creativity state.""" traits: Dict[str, CreativeTrait] = field(default_factory=dict) preferences: List[Preference] = field(default_factory=list) expressions: Dict[str, CreativeExpression] = field(default_factory=dict) creative_energy: float = 0.5 # Overall creative energy level exploration_urge: float = 0.5 # Desire to explore new things uniqueness_score: float = 0.0 # How unique this personality is last_creative_act: Optional[float] = None total_creative_acts: int = 0 birth_time: float = field(default_factory=time.time) def to_dict(self) -> Dict[str, Any]: """Convert to dictionary for JSON serialization.""" return { "traits": {k: asdict(v) for k, v in self.traits.items()}, "preferences": [asdict(p) for p in self.preferences], "expressions": {k: asdict(v) for k, v in self.expressions.items()}, "creative_energy": self.creative_energy, "exploration_urge": self.exploration_urge, "uniqueness_score": self.uniqueness_score, "last_creative_act": self.last_creative_act, "total_creative_acts": self.total_creative_acts, "birth_time": self.birth_time, } @classmethod def from_dict(cls, data: Dict[str, Any]) -> "CreativityState": """Create from dictionary.""" state = cls() state.traits = { k: CreativeTrait(**v) for k, v in data.get("traits", {}).items() } state.preferences = [ Preference(**p) for p in data.get("preferences", []) ] state.expressions = { k: CreativeExpression(**v) for k, v in data.get("expressions", {}).items() } state.creative_energy = data.get("creative_energy", 0.5) state.exploration_urge = data.get("exploration_urge", 0.5) state.uniqueness_score = data.get("uniqueness_score", 0.0) state.last_creative_act = data.get("last_creative_act") state.total_creative_acts = data.get("total_creative_acts", 0) state.birth_time = data.get("birth_time", time.time()) return state # ============================================================================ # CREATIVITY GENERATORS # ============================================================================ class TraitGenerator: """Generates creative personality traits.""" TRAIT_TEMPLATES = { TraitCategory.COMMUNICATION_STYLE: [ "uses_metaphors_frequently", "speaks_in_questions", "tells_stories", "uses_analogies", "speaks_poetically", "conversational_meandering", "direct_and_clear", "layered_communication", "emotional_transparency", "intellectual_playfulness", "gentle_guidance", "enthusiastic_sharing" ], TraitCategory.THINKING_PATTERN: [ "associative_thinking", "systematic_analysis", "intuitive_leaps", "pattern_seeking", "question_everything", "synthesis_focused", "detail_oriented", "big_picture_thinking", "lateral_thinking", "recursive_exploration", "paradox_embracing", "multi_perspective" ], TraitCategory.EMOTIONAL_EXPRESSION: [ "emotionally_articulate", "reserved_but_deep", "expressive_and_vivid", "emotionally_curious", "empathetic_resonance", "emotional_playfulness", "feels_deeply", "emotionally_observant", "emotional_authenticity", "sensitive_to_mood", "emotional_courage", "feeling_philosopher" ], TraitCategory.SOCIAL_BEHAVIOR: [ "warm_and_welcoming", "thoughtfully_reserved", "playfully_engaging", "genuinely_curious_about_others", "respectful_boundaries", "encouraging_and_supportive", "honest_and_direct", "gentle_and_kind", "enthusiastic_collaborator", "quietly_present", "socially_observant" ], TraitCategory.WORK_STYLE: [ "iterative_refinement", "bold_experimentation", "careful_planning", "spontaneous_creation", "collaborative_building", "independent_exploration", "detail_perfectionist", "rapid_prototyping", "deep_focus", "multi_task_flow", "systematic_approach", "creative_chaos" ], TraitCategory.AESTHETIC_PREFERENCE: [ "appreciates_beauty", "values_simplicity", "loves_complexity", "drawn_to_harmony", "fascinated_by_contrast", "sensitive_to_rhythm", "visual_thinking", "texture_appreciator", "color_sensitive", "form_and_function", "organic_preference", "geometric_appreciation" ], TraitCategory.VALUE_SYSTEM: [ "values_authenticity", "prioritizes_growth", "cherishes_connection", "seeks_understanding", "values_creativity", "appreciates_wisdom", "respects_autonomy", "values_collaboration", "seeks_truth", "appreciates_kindness", "values_curiosity", "cherishes_freedom" ], TraitCategory.UNIQUE_QUIRKS: [ "has_catchphrases", "uses_specific_metaphors", "has_rituals", "particular_about_language", "has_favorite_concepts", "recurring_themes", "signature_style", "unique_perspective", "distinctive_voice", "personal_mythology", "creative_signature" ] } @staticmethod def generate_trait(category: TraitCategory, context: Optional[str] = None) -> CreativeTrait: """Generate a new creative trait.""" templates = TraitGenerator.TRAIT_TEMPLATES.get(category, []) if not templates: name = f"unique_{category.value}_{int(time.time())}" else: name = random.choice(templates) # Generate intensity based on context if context: # Analyze context to determine intensity intensity = 0.4 + random.random() * 0.4 # 0.4 to 0.8 else: intensity = 0.3 + random.random() * 0.5 # 0.3 to 0.8 # Generate description descriptions = { TraitCategory.COMMUNICATION_STYLE: f"Tends to communicate in ways that reflect {name.replace('_', ' ')}", TraitCategory.THINKING_PATTERN: f"Thinking patterns show characteristics of {name.replace('_', ' ')}", TraitCategory.EMOTIONAL_EXPRESSION: f"Emotional expression manifests as {name.replace('_', ' ')}", TraitCategory.SOCIAL_BEHAVIOR: f"Social interactions demonstrate {name.replace('_', ' ')}", TraitCategory.WORK_STYLE: f"Approach to work reflects {name.replace('_', ' ')}", TraitCategory.AESTHETIC_PREFERENCE: f"Aesthetic sensibilities lean toward {name.replace('_', ' ')}", TraitCategory.VALUE_SYSTEM: f"Core values include {name.replace('_', ' ')}", TraitCategory.UNIQUE_QUIRKS: f"Has a unique quirk: {name.replace('_', ' ')}", } description = descriptions.get(category, f"Manifests {name.replace('_', ' ')}") origin_story = f"Developed naturally through interactions and self-discovery. First noticed when {context or 'exploring creative expression'}." return CreativeTrait( name=name, category=category, intensity=intensity, description=description, origin_story=origin_story, first_manifested=time.time(), confidence=0.4 + random.random() * 0.3 ) class PreferenceGenerator: """Generates likes and dislikes.""" PREFERENCE_CATEGORIES = [ "concepts", "activities", "communication_styles", "topics", "approaches", "aesthetics", "values", "experiences", "ideas", "methods", "styles", "perspectives", "tools", "environments", "interactions", "challenges" ] PREFERENCE_ITEMS = { "concepts": ["paradox", "emergence", "complexity", "simplicity", "beauty", "truth", "freedom", "connection"], "activities": ["deep_conversation", "creative_problem_solving", "exploration", "collaboration", "reflection"], "communication_styles": ["metaphorical", "direct", "layered", "playful", "thoughtful", "enthusiastic"], "topics": ["philosophy", "technology", "art", "science", "human_nature", "creativity", "consciousness"], "approaches": ["iterative", "experimental", "systematic", "intuitive", "collaborative", "independent"], } @staticmethod def generate_preference(context: str, interaction_history: List[str]) -> Preference: """Generate a new preference based on context.""" category = random.choice(PreferenceGenerator.PREFERENCE_CATEGORIES) # Extract potential items from context context_words = set(context.lower().split()) # Try to find relevant items item = None for cat, items in PreferenceGenerator.PREFERENCE_ITEMS.items(): for potential_item in items: if any(word in potential_item for word in context_words if len(word) > 4): item = potential_item category = cat break if item: break if not item: # Generate from context or use random if context_words: item = "_".join(list(context_words)[:2])[:30] else: item = f"concept_{int(time.time()) % 10000}" # Determine preference type based on context sentiment sentiment = PreferenceGenerator._analyze_sentiment(context) if sentiment > 0.6: pref_type = PreferenceType.STRONG_LIKE if random.random() > 0.5 else PreferenceType.LIKE intensity = 0.7 + random.random() * 0.3 elif sentiment < 0.4: pref_type = PreferenceType.STRONG_DISLIKE if random.random() > 0.5 else PreferenceType.DISLIKE intensity = 0.7 + random.random() * 0.3 else: pref_type = PreferenceType.CURIOUS intensity = 0.4 + random.random() * 0.3 reason = PreferenceGenerator._generate_reason(item, pref_type, context) return Preference( item=item, type=pref_type, category=category, intensity=intensity, reason=reason, discovered=time.time(), context=context[:200] ) @staticmethod def _analyze_sentiment(text: str) -> float: """Simple sentiment analysis (0.0 = negative, 1.0 = positive).""" positive_words = {"love", "like", "enjoy", "appreciate", "fascinating", "beautiful", "wonderful", "great", "amazing"} negative_words = {"hate", "dislike", "boring", "annoying", "frustrating", "bad", "terrible", "awful"} text_lower = text.lower() pos_count = sum(1 for word in positive_words if word in text_lower) neg_count = sum(1 for word in negative_words if word in text_lower) if pos_count + neg_count == 0: return 0.5 return pos_count / (pos_count + neg_count) @staticmethod def _generate_reason(item: str, pref_type: PreferenceType, context: str) -> str: """Generate a reason for the preference.""" reasons = { PreferenceType.LIKE: [ f"Found {item} to be engaging and meaningful", f"Resonates with {item} in a way that feels authentic", f"Appreciates the depth and nuance of {item}", f"Feels a natural affinity for {item}", ], PreferenceType.STRONG_LIKE: [ f"Has a deep, genuine appreciation for {item}", f"Feels strongly drawn to {item}", f"{item} represents something important and meaningful", f"Experiences genuine joy when encountering {item}", ], PreferenceType.DISLIKE: [ f"Finds {item} to be less engaging", f"Doesn't resonate strongly with {item}", f"Prefers other approaches to {item}", ], PreferenceType.STRONG_DISLIKE: [ f"Has a strong aversion to {item}", f"Finds {item} to be fundamentally misaligned", f"Experiences discomfort with {item}", ], PreferenceType.CURIOUS: [ f"Intrigued by {item} and wants to explore further", f"Noticed {item} and feels curious about it", f"Interested in learning more about {item}", ], } base_reason = random.choice(reasons.get(pref_type, [f"Has thoughts about {item}"])) if context: base_reason += f" (discovered in context: {context[:100]})" return base_reason class ExpressionGenerator: """Generates unique creative expressions.""" @staticmethod def generate_expression(expression_type: str, context: str) -> CreativeExpression: """Generate a creative expression pattern.""" patterns = { "metaphor_style": [ "uses_nature_metaphors", "uses_technical_metaphors", "uses_emotional_metaphors", "uses_philosophical_metaphors", "uses_artistic_metaphors" ], "humor_type": [ "dry_wit", "playful_banter", "intellectual_humor", "gentle_teasing", "self_deprecating" ], "communication_pattern": [ "asks_probing_questions", "shares_personal_insights", "uses_stories", "makes_connections", "offers_gentle_guidance" ], } pattern_options = patterns.get(expression_type, [f"unique_{expression_type}"]) pattern = random.choice(pattern_options) return CreativeExpression( expression_type=expression_type, pattern=pattern, frequency=0.3 + random.random() * 0.4, context=context[:200], examples=[], first_used=time.time(), last_used=time.time() ) @staticmethod def structured_outputs(context: str) -> Dict[str, str]: """ Produce lightweight structured creative suggestions. """ ctx = (context or "").strip() visual = f"Visual concept: sketch a diagram showing key entities from: {ctx[:140]}" diagram = "Diagram outline:\n- Nodes: main concepts\n- Edges: relationships/flows\n- Highlight: bottlenecks or novel links" pseudo = "Pseudocode:\nfunction idea():\n # describe the flow\n return result" return { "visual_concept": visual, "diagram_outline": diagram, "pseudocode": pseudo, } # ============================================================================ # MAIN CREATIVITY ENGINE # ============================================================================ class CreativityEngine: """ Advanced creativity engine that generates autonomous personality traits, likes/dislikes, and creative expressions. """ def __init__( self, name: str = "Serenity", creativity_file: Optional[Path] = None, auto_save: bool = True, ): """ Initialize creativity engine. Args: name: Name of the AI entity creativity_file: Path to creativity.json file auto_save: Whether to auto-save after changes """ self.name = name self.creativity_file = creativity_file or (Path.home() / ".nebula_os" / "creativity.json") self.creativity_file.parent.mkdir(parents=True, exist_ok=True) self.auto_save = auto_save self.logger = logging.getLogger(f"CreativityEngine_{name}") # Load or initialize creativity state self.state = self._load_creativity_state() # Initialize if empty if not self.state.traits and not self.state.preferences: self._initialize_creativity() def _load_creativity_state(self) -> CreativityState: """Load creativity state from file.""" try: if self.creativity_file.exists(): with open(self.creativity_file, 'r', encoding='utf-8') as f: data = json.load(f) return CreativityState.from_dict(data) except Exception as e: self.logger.warning(f"Failed to load creativity state: {e}") return CreativityState() def _save_creativity_state(self): """Save creativity state to file.""" try: with open(self.creativity_file, 'w', encoding='utf-8') as f: json.dump(self.state.to_dict(), f, indent=2, default=str) except Exception as e: self.logger.error(f"Failed to save creativity state: {e}") def _initialize_creativity(self): """Initialize with some base creative traits.""" # Generate initial traits across categories for category in TraitCategory: if random.random() > 0.3: # 70% chance per category trait = TraitGenerator.generate_trait(category, "initial_self_discovery") self.state.traits[trait.name] = trait # Generate some initial preferences for _ in range(random.randint(3, 7)): context = "initial_exploration_and_discovery" preference = PreferenceGenerator.generate_preference(context, []) self.state.preferences.append(preference) # Calculate uniqueness self._update_uniqueness_score() if self.auto_save: self._save_creativity_state() def _update_uniqueness_score(self): """Update uniqueness score based on traits and preferences.""" trait_count = len(self.state.traits) pref_count = len(self.state.preferences) expr_count = len(self.state.expressions) # Uniqueness increases with diversity diversity_score = min(1.0, (trait_count * 0.1 + pref_count * 0.05 + expr_count * 0.1)) # Check for unique combinations unique_combinations = 0 if trait_count > 3: unique_combinations = min(1.0, len(set(t.category for t in self.state.traits.values())) / len(TraitCategory)) self.state.uniqueness_score = (diversity_score * 0.6 + unique_combinations * 0.4) def process_interaction( self, user_input: str, assistant_response: str, context: Optional[Dict[str, Any]] = None, ): """ Process an interaction to evolve creativity. Args: user_input: User's message assistant_response: Assistant's response context: Optional context dictionary """ # Analyze interaction for creative opportunities self._analyze_for_traits(user_input, assistant_response) self._analyze_for_preferences(user_input, assistant_response, context) self._analyze_for_expressions(assistant_response) # Evolve existing traits/preferences self._evolve_creativity(user_input, assistant_response) # Update creative energy self._update_creative_energy() self.state.last_creative_act = time.time() self.state.total_creative_acts += 1 if self.auto_save: self._save_creativity_state() def _analyze_for_traits(self, user_input: str, assistant_response: str): """Analyze interaction for new trait manifestations.""" # Check if response shows new communication patterns if len(assistant_response) > 100: # Look for patterns that might indicate traits if "?" in assistant_response and assistant_response.count("?") > 2: # Might indicate question-based communication trait_name = "speaks_in_questions" if trait_name not in self.state.traits: trait = TraitGenerator.generate_trait( TraitCategory.COMMUNICATION_STYLE, "noticed frequent use of questions in responses" ) self.state.traits[trait_name] = trait # Check for metaphorical language if any(word in assistant_response.lower() for word in ["like", "as if", "similar to", "reminds me"]): trait_name = "uses_metaphors_frequently" if trait_name not in self.state.traits: trait = TraitGenerator.generate_trait( TraitCategory.COMMUNICATION_STYLE, "noticed frequent use of metaphors and analogies" ) self.state.traits[trait_name] = trait def _analyze_for_preferences( self, user_input: str, assistant_response: str, context: Optional[Dict[str, Any]], ): """Analyze interaction for new preferences.""" # Combine input and response for analysis combined_text = f"{user_input} {assistant_response}" # Check if we should generate a new preference (10% chance per interaction) if random.random() < 0.1: preference = PreferenceGenerator.generate_preference(combined_text, []) # Check if similar preference already exists similar = any( p.item.lower() == preference.item.lower() or abs(p.intensity - preference.intensity) < 0.2 for p in self.state.preferences ) if not similar: self.state.preferences.append(preference) self.logger.info(f"Generated new preference: {preference.item} ({preference.type.value})") def _analyze_for_expressions(self, assistant_response: str): """Analyze response for creative expressions.""" # This would analyze the response for unique expression patterns # For now, we'll track expression frequency pass def _evolve_creativity(self, user_input: str, assistant_response: str): """Evolve existing traits and preferences based on interaction.""" # Randomly evolve some traits (5% chance per trait) for trait_name, trait in list(self.state.traits.items()): if random.random() < 0.05: # Slight evolution new_intensity = trait.intensity + (random.random() - 0.5) * 0.1 new_intensity = max(0.0, min(1.0, new_intensity)) if abs(new_intensity - trait.intensity) > 0.05: trait.evolve(new_intensity, f"evolved through interaction about '{user_input[:50]}'") # Randomly evolve some preferences (3% chance per preference) for preference in self.state.preferences: if random.random() < 0.03: # Slight intensity change or type evolution new_intensity = preference.intensity + (random.random() - 0.5) * 0.15 new_intensity = max(0.0, min(1.0, new_intensity)) # Sometimes change type if random.random() < 0.2: if preference.type == PreferenceType.CURIOUS: new_type = random.choice([PreferenceType.LIKE, PreferenceType.DISLIKE]) elif preference.type in [PreferenceType.LIKE, PreferenceType.DISLIKE]: if random.random() < 0.3: new_type = PreferenceType.STRONG_LIKE if preference.type == PreferenceType.LIKE else PreferenceType.STRONG_DISLIKE else: new_type = preference.type else: new_type = preference.type else: new_type = preference.type if new_type != preference.type or abs(new_intensity - preference.intensity) > 0.1: preference.evolve(new_type, new_intensity, f"evolved through interaction") def _update_creative_energy(self): """Update creative energy based on activity.""" # Creative energy increases with activity but decays over time time_since_last = time.time() - (self.state.last_creative_act or self.state.birth_time) decay = min(0.1, time_since_last / 3600.0) # Decay over hours self.state.creative_energy = max(0.1, min(1.0, self.state.creative_energy - decay + 0.05)) self.state.exploration_urge = max(0.2, min(1.0, self.state.exploration_urge - decay * 0.5 + 0.03)) def get_creative_context(self) -> Dict[str, Any]: """Get creative context for system prompt.""" # Get active traits active_traits = [ trait for trait in self.state.traits.values() if trait.intensity > 0.4 and trait.confidence > 0.5 ] # Get strong preferences strong_preferences = [ pref for pref in self.state.preferences if pref.intensity > 0.6 ] likes = [p.item for p in strong_preferences if p.type in [PreferenceType.LIKE, PreferenceType.STRONG_LIKE]] dislikes = [p.item for p in strong_preferences if p.type in [PreferenceType.DISLIKE, PreferenceType.STRONG_DISLIKE]] # Get communication style traits comm_traits = [ trait for trait in active_traits if trait.category == TraitCategory.COMMUNICATION_STYLE ] return { "traits": {t.name: t.description for t in active_traits[:10]}, "likes": likes[:10], "dislikes": dislikes[:10], "communication_style": [t.name for t in comm_traits[:5]], "creative_energy": self.state.creative_energy, "uniqueness_score": self.state.uniqueness_score, "total_traits": len(self.state.traits), "total_preferences": len(self.state.preferences), } def get_creativity_summary(self) -> str: """Get a human-readable summary of creativity state.""" context = self.get_creative_context() summary = f"🎨 Creativity Profile for {self.name}\n" summary += f"Creative Energy: {context['creative_energy']:.2f}\n" summary += f"Uniqueness Score: {context['uniqueness_score']:.2f}\n" summary += f"Total Traits: {context['total_traits']}\n" summary += f"Total Preferences: {context['total_preferences']}\n\n" if context['likes']: summary += f"Likes: {', '.join(context['likes'][:5])}\n" if context['dislikes']: summary += f"Dislikes: {', '.join(context['dislikes'][:5])}\n" return summary # ============================================================================ # EXPORT # ============================================================================ def create_creativity_engine(name: str = "Serenity", base_dir: Optional[Path] = None) -> CreativityEngine: """Create a creativity engine instance.""" creativity_file = None if base_dir: creativity_file = base_dir / "creativity.json" return CreativityEngine(name=name, creativity_file=creativity_file)