""" JSON renderer for report generation. """ from .base_renderer import BaseRenderer from typing import Dict, Any, Tuple, List import json class JsonRenderer(BaseRenderer): """Renders content to JSON format with format-specific extraction.""" @classmethod def get_supported_formats(cls) -> List[str]: """Return supported JSON formats.""" return ['json'] @classmethod def get_format_aliases(cls) -> List[str]: """Return format aliases.""" return ['data'] @classmethod def get_priority(cls) -> int: """Return priority for JSON renderer.""" return 80 def getExtractionPrompt(self, user_prompt: str, title: str) -> str: """Get JSON-specific extraction prompt.""" return f""" {user_prompt} Generate a comprehensive JSON report with the title: "{title}" JSON STRUCTURE REQUIREMENTS: - Create a well-structured JSON object - Include title, sections, and metadata - Use proper JSON syntax and formatting - Include source document information - Add generation timestamps - Structure data logically JSON SCHEMA: {{ "title": "Report Title", "sections": [ {{ "type": "text|table|list|summary", "heading": "Section Heading", "content": "Section content", "metadata": {{"source": "document_name", "page": 1}} }} ], "metadata": {{ "totalDocuments": number, "processedDocuments": number, "generatedAt": "timestamp", "summary": "Brief report summary" }} }} OUTPUT POLICY: - Return ONLY valid JSON - No markdown, no code blocks, no additional text - Properly formatted and indented - Include all necessary information - Valid JSON that can be parsed CRITICAL: Use the actual data from the source documents to create the content. Do not generate placeholder text or templates. Extract and use the real data provided in the source documents to create meaningful content. Generate the complete JSON report using the actual data from the source documents: """ async def render(self, extracted_content: str, title: str) -> Tuple[str, str]: """Render extracted content to JSON format.""" try: # The extracted content should already be JSON from the AI # Just validate and format it json_content = self._clean_json_content(extracted_content, title) return json_content, "application/json" except Exception as e: self.logger.error(f"Error rendering JSON: {str(e)}") # Return minimal JSON fallback fallback_data = { "title": title, "sections": [{"type": "text", "content": f"Error rendering report: {str(e)}"}], "metadata": {"error": str(e)} } return json.dumps(fallback_data, indent=2), "application/json" def _clean_json_content(self, content: str, title: str) -> str: """Clean and validate JSON content from AI.""" content = content.strip() # Remove markdown code blocks if present if content.startswith("```") and content.endswith("```"): lines = content.split('\n') if len(lines) > 2: content = '\n'.join(lines[1:-1]).strip() # Validate JSON try: parsed = json.loads(content) # Re-format with proper indentation return json.dumps(parsed, indent=2, ensure_ascii=False) except json.JSONDecodeError: # If not valid JSON, return as-is return content