""" Attribute map utility --------------------- Expose a structured mapping of the voice design attributes described in `prompt.txt` together with the inline emotion tags listed in `emotions.txt`. The module returns data that can be consumed by tooling to programmatically build descriptions or sweep attribute combinations. """ from __future__ import annotations import json from pathlib import Path from typing import Dict, Iterable, List, TypedDict class AttributeMap(TypedDict, total=False): metadata: Dict[str, str] emotions: Dict[str, object] shared_attributes: Dict[str, Iterable[str]] realistic_only: Dict[str, object] creative_only: Dict[str, object] constraints: Dict[str, object] defaults: Dict[str, str] MODULE_DIR = Path(__file__).resolve().parent EMOTIONS_FILE = MODULE_DIR / "emotions.txt" PROMPT_FILE = MODULE_DIR / "prompt.txt" def _load_emotion_tags(path: Path) -> List[str]: if not path.exists(): raise FileNotFoundError(f"Emotion tag file not found: {path}") tags: List[str] = [] with path.open("r", encoding="utf-8") as handle: for raw_line in handle: line = raw_line.strip() if not line or line.startswith("#"): continue tags.append(line) return tags def build_attribute_map( emotions_path: Path | None = None, prompt_path: Path | None = None, ) -> AttributeMap: """ Return an attribute map that mirrors the guidance in `prompt.txt`. Parameters ---------- emotions_path: Optional override for the emotion tag file. Defaults to `maya1/emotions.txt`. prompt_path: Included for symmetry/future validation. Defaults to `maya1/prompt.txt` and is currently used only for metadata. """ emotions_file = emotions_path or EMOTIONS_FILE prompt_file = prompt_path or PROMPT_FILE emotion_tags = _load_emotion_tags(emotions_file) attribute_map: AttributeMap = { "metadata": { "source_prompt": str(prompt_file), "source_emotions": str(emotions_file), "description": ( "Programmatic representation of Maya voice design attributes. " "Derived from prompt.txt guidance." ), }, "emotions": { "inline_tags": emotion_tags, "persona_emotion_attribute": [ "neutral", "energetic", "excited", "sad", "sarcastic", "dry", ], "intensity": ["low", "med", "high"], }, "shared_attributes": { "age": ["20s", "30s", "40s"], "gender": ["male", "female"], "accent": [ "american", "indian", "middle_eastern", "asian_american", "british", ], "pitch": ["low", "normal", "high"], "timbre_realistic": [ "deep", "warm", "gravelly", "smooth", "raspy", "nasally", "throaty", "harsh", ], "timbre_creative": [ "deep", "warm", "gravelly", "smooth", "raspy", "nasally", "throaty", "harsh", "robotic", "ethereal", ], "pacing": [ "very_slow", "slow", "conversational", "brisk", "fast", "very_fast", ], "emotion_intensity": ["low", "med", "high"], }, "realistic_only": { "domain": [ "social_content", "podcast", "commercial", "education", "support", "entertainment", "corporate", "viral_content", ], "speaking_role": { "social_content": [ "youtube_vlogger", "social_media_creator", "influencer_voice", "streamer_companion", ], "podcast": ["podcast_host", "interviewer"], "commercial": [ "ad_narrator", "brand_spokesperson", "product_demo_voice", "sales_pitch_voice", ], "education": ["elearning_instructor", "kids_story_voice"], "support": [ "customer_support_agent", "virtual_receptionist", "healthcare_assistant", ], "entertainment": [ "storyteller", "social_media_reaction", "meme_voice", ], "corporate": [ "explainer_video_voice", "event_host", "corporate_training_narrator", ], "viral_content": ["short_form_narrator", "meme_voice"], }, "register": ["formal", "neutral", "casual"], }, "creative_only": { "character": [ "animated_cartoon", "ai_machine_voice", "alien_scifi", "seductively", "flirty", "anime", "cyborg", "pirate", "dark_villain", "demon", "gangster", "mafia", "dramatic_narrator", "mythical_godlike_magical", "spy", "vampire", "alpha", ], }, "constraints": { "pitch": { "note": ( "For age 40s, avoid high pitch (use sparingly, <= 15% of uses)." ) }, "creative_timbre": { "robotic": [ "ai_machine_voice", "cyborg", "alien_scifi", "mythical_godlike_magical", ], "ethereal": [ "ai_machine_voice", "cyborg", "alien_scifi", "mythical_godlike_magical", ], }, "character_pacing_overrides": { "mafia": ["slow", "conversational"], "flirty": ["slow", "conversational"], "alpha": ["fast", "very_fast"], "seductively": ["very_slow", "slow"], }, "defaults": "Default persona emotion should be neutral unless specified.", }, "defaults": { "age": "20s", "gender": "female", "accent": "american", "pitch": "high", "timbre": "warm", "pacing": "brisk", "emotion": "excited", "emotion_intensity": "med", "domain": "social_content", "speaking_role": "influencer_voice", "register": "casual", }, } return attribute_map def main() -> None: """ CLI helper: print the attribute map as JSON for inspection. """ attribute_map = build_attribute_map() print(json.dumps(attribute_map, indent=2, sort_keys=True)) if __name__ == "__main__": main()