Source code for audify.prompts.manager

"""Prompt manager for loading and managing prompts."""

from pathlib import Path
from typing import Optional

from audify.utils.logging_utils import setup_logging

logger = setup_logging(module_name=__name__)

BUILTIN_PROMPTS_DIR = Path(__file__).parent / "builtin"


[docs] class PromptManager: """Manages loading and resolving prompts from various sources."""
[docs] def get_builtin_prompt(self, task_name: str) -> str: """Load a built-in prompt by task name. Args: task_name: Name of the built-in task (e.g., "audiobook", "podcast"). Returns: The prompt text. Raises: FileNotFoundError: If the built-in prompt file doesn't exist. """ prompt_path = BUILTIN_PROMPTS_DIR / f"{task_name}.txt" if not prompt_path.exists(): raise FileNotFoundError( f"Built-in prompt not found: {task_name}. " f"Available prompts: {self.list_builtin_prompts()}" ) return prompt_path.read_text(encoding="utf-8")
[docs] def load_prompt_file(self, path: str | Path) -> str: """Load a custom prompt from a file path. Args: path: Path to the prompt file. Returns: The prompt text. Raises: FileNotFoundError: If the prompt file doesn't exist. ValueError: If the prompt file is empty. """ prompt_path = Path(path).expanduser().resolve() if not prompt_path.exists(): raise FileNotFoundError(f"Prompt file not found: {prompt_path}") content = prompt_path.read_text(encoding="utf-8").strip() if not content: raise ValueError(f"Prompt file is empty: {prompt_path}") return content
[docs] def get_prompt( self, task: str, prompt_file: Optional[str | Path] = None, ) -> str: """Resolve the prompt for a given task. Priority: prompt_file > task's built-in prompt. Args: task: Task name (e.g., "audiobook", "podcast", "direct"). prompt_file: Optional path to a custom prompt file. Returns: The resolved prompt text. Empty string for "direct" task. """ if prompt_file: logger.info(f"Loading custom prompt from: {prompt_file}") return self.load_prompt_file(prompt_file) if task == "direct": return "" # Try to get from task registry first (avoids re-reading files) from audify.prompts.tasks import TaskRegistry task_config = TaskRegistry.get(task) if task_config: return task_config.prompt # Fallback: try loading as a builtin prompt file try: return self.get_builtin_prompt(task) except FileNotFoundError: raise ValueError( f"Unknown task '{task}' and no prompt file provided. " f"Available tasks: {TaskRegistry.list_tasks()}" )
[docs] def list_builtin_prompts(self) -> list[str]: """List available built-in prompt names.""" return sorted( p.stem for p in BUILTIN_PROMPTS_DIR.glob("*.txt") if p.stem != "__init__" )
[docs] def validate_prompt(self, prompt: str) -> tuple[bool, str]: """Validate a prompt string. Args: prompt: The prompt text to validate. Returns: A tuple of (is_valid, message) where is_valid is True if the prompt is valid, and message provides validation details. """ if not prompt or not prompt.strip(): return False, "Prompt cannot be empty." if len(prompt.strip()) < 10: return False, "Prompt is too short. Minimum 10 characters required." return True, "Prompt is valid."