""" Persona Profile Export Service Generates beautifully formatted markdown profiles for individual personas using LLM processing. """ import os import json import logging from typing import Dict, Any, Optional from app.services.llm_service import LLMService # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class PersonaExportService: """Service for exporting individual persona profiles as formatted markdown.""" def __init__(self): """Initialize the persona export service.""" self.llm_service = LLMService() self.prompt_template = self._load_prompt_template() def _load_prompt_template(self) -> str: """Load the persona profile export prompt template.""" try: prompt_path = os.path.join( os.path.dirname(__file__), "..", "..", "prompts", "persona-profile-export.md" ) with open(prompt_path, 'r', encoding='utf-8') as f: return f.read() except Exception as e: logger.error(f"Failed to load persona export prompt template: {e}") # Fallback prompt if file loading fails return """ You are a professional documentation specialist. Transform the provided persona JSON data into a well-structured, professional markdown document with proper headers, tables, lists, and formatting. Include all available information organized logically with sections for demographics, goals, personality traits, scenarios, and additional data. """ async def generate_profile_markdown( self, persona_data: Dict[str, Any], llm_model: str = "gpt-4.1", temperature: float = 0.3 ) -> Dict[str, Any]: """ Generate a formatted markdown profile for a persona using LLM processing. Args: persona_data: Complete persona data as dictionary llm_model: LLM model to use (default: gpt-4.1 for speed) temperature: Temperature for LLM generation (lower for consistency) Returns: Dictionary containing: - success: Boolean indicating success - markdown_content: Generated markdown string - error: Error message if failed - persona_name: Name of the persona """ try: # Validate input data if not persona_data: return { "success": False, "error": "No persona data provided", "markdown_content": None, "persona_name": None } persona_name = persona_data.get('name', 'Unknown Persona') logger.info(f"🤖 Backend: Generating profile markdown for persona: {persona_name} using {llm_model}") # Prepare the full prompt persona_json = json.dumps(persona_data, indent=2, ensure_ascii=False) full_prompt = f"{self.prompt_template}\n\n## Persona Data\n```json\n{persona_json}\n```" # Generate markdown using LLM markdown_content = await LLMService.generate_content( prompt=full_prompt, model_name=llm_model, temperature=temperature, max_tokens=4000 # Allow for comprehensive profiles ) if not markdown_content: return { "success": False, "error": "LLM failed to generate markdown content", "markdown_content": None, "persona_name": persona_name } markdown_content = markdown_content.strip() # Basic validation of generated content if len(markdown_content) < 100: # Too short, likely an error logger.warning(f"Generated markdown seems too short for {persona_name}") return { "success": False, "error": "Generated markdown content appears incomplete", "markdown_content": None, "persona_name": persona_name } logger.info(f"✅ Successfully generated profile markdown for {persona_name} ({len(markdown_content)} characters)") return { "success": True, "markdown_content": markdown_content, "persona_name": persona_name, "model_used": llm_model, "content_length": len(markdown_content) } except Exception as e: logger.error(f"Error generating persona profile markdown: {str(e)}") return { "success": False, "error": f"Failed to generate markdown profile: {str(e)}", "markdown_content": None, "persona_name": persona_data.get('name', 'Unknown') if persona_data else None } def generate_fallback_markdown(self, persona_data: Dict[str, Any]) -> str: """ Generate a basic fallback markdown if LLM processing fails. Args: persona_data: Complete persona data as dictionary Returns: Basic markdown string """ try: name = persona_data.get('name', 'Unknown Persona') occupation = persona_data.get('occupation', 'Unknown') age = persona_data.get('age', 'Unknown') location = persona_data.get('location', 'Unknown') # Create basic markdown structure markdown = f"""# {name} - Complete Profile ## Overview {name} is a {age} year old {occupation} based in {location}. ## Basic Information - **Name:** {name} - **Age:** {age} - **Occupation:** {occupation} - **Location:** {location} ## Raw Data ```json {json.dumps(persona_data, indent=2, ensure_ascii=False)} ``` *This is a basic export. For enhanced formatting, please try again later.* """ return markdown except Exception as e: logger.error(f"Failed to generate fallback markdown: {e}") return f"# Persona Profile Export\n\nError generating profile. Raw data:\n\n```json\n{json.dumps(persona_data, indent=2)}\n```"