Spaces:
Running
Running
| """ | |
| MEXAR Core Engine - Explainability Generator Module | |
| Packages reasoning traces for UI display. | |
| """ | |
| import logging | |
| from typing import Dict, List, Any, Optional | |
| # Configure logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| class ExplainabilityGenerator: | |
| """ | |
| Generates structured explainability data for the UI. | |
| Prepares reasoning traces and source citations. | |
| """ | |
| def __init__(self): | |
| """Initialize the explainability generator.""" | |
| pass | |
| def generate( | |
| self, | |
| reasoning_result: Dict[str, Any] | |
| ) -> Dict[str, Any]: | |
| """ | |
| Generate comprehensive explainability data. | |
| Args: | |
| reasoning_result: Output from ReasoningEngine.reason() | |
| Returns: | |
| Structured explainability data for UI | |
| """ | |
| explainability = reasoning_result.get("explainability", {}) | |
| # Enhance the existing explainability data | |
| enhanced = { | |
| "summary": self._generate_summary(reasoning_result), | |
| "inputs": self._format_inputs(explainability.get("inputs", {})), | |
| "retrieval": self._format_retrieval(explainability.get("retrieval", {})), | |
| "reasoning_steps": self._format_reasoning_steps( | |
| explainability.get("reasoning_trace", []) | |
| ), | |
| "confidence": self._format_confidence( | |
| explainability.get("confidence_breakdown", {}) | |
| ), | |
| "sources": self._format_sources(explainability.get("sources_cited", [])) | |
| } | |
| return enhanced | |
| def _generate_summary(self, reasoning_result: Dict[str, Any]) -> Dict[str, Any]: | |
| """Generate a human-readable summary.""" | |
| confidence = reasoning_result.get("confidence", 0) | |
| in_domain = reasoning_result.get("in_domain", True) | |
| sources = reasoning_result.get("sources", []) | |
| if not in_domain: | |
| status = "rejected" | |
| message = "Query was outside the agent's domain expertise" | |
| color = "red" | |
| elif confidence >= 0.8: | |
| status = "high_confidence" | |
| message = "Answer is well-supported by the knowledge base" | |
| color = "green" | |
| elif confidence >= 0.5: | |
| status = "moderate_confidence" | |
| message = "Answer is partially supported, some uncertainty exists" | |
| color = "yellow" | |
| else: | |
| status = "low_confidence" | |
| message = "Limited support in knowledge base, treat with caution" | |
| color = "orange" | |
| return { | |
| "status": status, | |
| "message": message, | |
| "color": color, | |
| "quick_stats": { | |
| "sources_found": len(sources), | |
| "confidence_percent": f"{confidence * 100:.0f}%" | |
| } | |
| } | |
| def _format_inputs(self, inputs: Dict) -> Dict[str, Any]: | |
| """Format input information.""" | |
| return { | |
| "query": inputs.get("original_query", ""), | |
| "has_multimodal": inputs.get("has_multimodal", False), | |
| "multimodal_type": self._detect_multimodal_type(inputs), | |
| "multimodal_preview": inputs.get("multimodal_preview", "") | |
| } | |
| def _detect_multimodal_type(self, inputs: Dict) -> Optional[str]: | |
| """Detect the type of multimodal input.""" | |
| preview = inputs.get("multimodal_preview", "") | |
| if not preview: | |
| return None | |
| if "[AUDIO" in preview: | |
| return "audio" | |
| elif "[IMAGE" in preview: | |
| return "image" | |
| elif "[VIDEO" in preview: | |
| return "video" | |
| return "text" | |
| def _format_retrieval(self, retrieval: Dict) -> Dict[str, Any]: | |
| """Format retrieval information.""" | |
| return { | |
| "chunks_retrieved": retrieval.get("chunks_retrieved", 0), | |
| "previews": retrieval.get("chunk_previews", []) | |
| } | |
| def _format_reasoning_steps(self, trace: List[Dict]) -> List[Dict[str, Any]]: | |
| """Format reasoning trace into displayable steps.""" | |
| steps = [] | |
| for item in trace: | |
| step = { | |
| "step_number": item.get("step", len(steps) + 1), | |
| "action": item.get("action", "unknown"), | |
| "action_display": self._get_action_display(item.get("action", "unknown")), | |
| "explanation": item.get("explanation", ""), | |
| "icon": self._get_action_icon(item.get("action", "unknown")) | |
| } | |
| steps.append(step) | |
| return steps | |
| def _get_action_display(self, action: str) -> str: | |
| """Get display-friendly action name.""" | |
| action_map = { | |
| "domain_check": "Domain Relevance Check", | |
| "vector_retrieval": "Semantic Search", | |
| "llm_generation": "Answer Generation", | |
| "guardrail_rejection": "Domain Guardrail" | |
| } | |
| return action_map.get(action, action.replace("_", " ").title()) | |
| def _get_action_icon(self, action: str) -> str: | |
| """Get icon for reasoning action.""" | |
| icon_map = { | |
| "domain_check": "β ", | |
| "vector_retrieval": "π", | |
| "llm_generation": "π¬", | |
| "guardrail_rejection": "π«" | |
| } | |
| return icon_map.get(action, "βΆοΈ") | |
| def _format_confidence(self, breakdown: Dict) -> Dict[str, Any]: | |
| """Format confidence breakdown for display.""" | |
| overall = breakdown.get("overall", 0) | |
| # Determine confidence level | |
| if overall >= 0.8: | |
| level = "high" | |
| color = "#22c55e" # Green | |
| message = "High confidence answer" | |
| elif overall >= 0.5: | |
| level = "moderate" | |
| color = "#eab308" # Yellow | |
| message = "Moderate confidence" | |
| else: | |
| level = "low" | |
| color = "#f97316" # Orange | |
| message = "Low confidence - verify independently" | |
| return { | |
| "overall_score": overall, | |
| "overall_percent": f"{overall * 100:.0f}%", | |
| "level": level, | |
| "color": color, | |
| "message": message, | |
| "factors": [ | |
| { | |
| "name": "Domain Relevance", | |
| "score": breakdown.get("domain_relevance", 0), | |
| "percent": f"{breakdown.get('domain_relevance', 0) * 100:.0f}%", | |
| "description": "How well the query matches the agent's domain" | |
| }, | |
| { | |
| "name": "Retrieval Quality", | |
| "score": breakdown.get("retrieval_quality", 0), | |
| "percent": f"{breakdown.get('retrieval_quality', 0) * 100:.0f}%", | |
| "description": "Quality of retrieved context chunks" | |
| } | |
| ] | |
| } | |
| def _format_sources(self, sources: List[str]) -> List[Dict[str, str]]: | |
| """Format source citations.""" | |
| formatted = [] | |
| for source in sources: | |
| source_type = self._detect_source_type(source) | |
| formatted.append({ | |
| "citation": source, | |
| "type": source_type, | |
| "icon": self._get_source_icon(source_type) | |
| }) | |
| return formatted | |
| def _detect_source_type(self, source: str) -> str: | |
| """Detect the type of source citation.""" | |
| source_lower = source.lower() | |
| if ".csv" in source_lower: | |
| return "csv" | |
| elif ".pdf" in source_lower: | |
| return "pdf" | |
| elif ".json" in source_lower: | |
| return "json" | |
| elif ".docx" in source_lower or ".doc" in source_lower: | |
| return "docx" | |
| elif "entry" in source_lower or "row" in source_lower: | |
| return "entry" | |
| else: | |
| return "text" | |
| def _get_source_icon(self, source_type: str) -> str: | |
| """Get icon for source type.""" | |
| icon_map = { | |
| "csv": "π", | |
| "pdf": "π", | |
| "json": "π", | |
| "docx": "π", | |
| "txt": "π", | |
| "entry": "π" | |
| } | |
| return icon_map.get(source_type, "π") | |
| def format_for_display( | |
| self, | |
| explainability_data: Dict[str, Any], | |
| format_type: str = "full" | |
| ) -> Dict[str, Any]: | |
| """ | |
| Format explainability data for specific display contexts. | |
| Args: | |
| explainability_data: Generated explainability data | |
| format_type: 'full', 'compact', or 'minimal' | |
| Returns: | |
| Formatted data appropriate for the display context | |
| """ | |
| if format_type == "minimal": | |
| return { | |
| "summary": explainability_data.get("summary", {}), | |
| "confidence": { | |
| "score": explainability_data.get("confidence", {}).get("overall_percent", "0%"), | |
| "level": explainability_data.get("confidence", {}).get("level", "unknown") | |
| } | |
| } | |
| elif format_type == "compact": | |
| return { | |
| "summary": explainability_data.get("summary", {}), | |
| "retrieval": explainability_data.get("retrieval", {}), | |
| "confidence": explainability_data.get("confidence", {}), | |
| "sources": explainability_data.get("sources", [])[:3] | |
| } | |
| # Full format | |
| return explainability_data | |
| # Factory function | |
| def create_explainability_generator() -> ExplainabilityGenerator: | |
| """Create a new ExplainabilityGenerator instance.""" | |
| return ExplainabilityGenerator() | |