Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-rag/src/lexigram/ai/rag/synthesis/formatters/markdown.py: 13%

39 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-25 07:19 +0800

1"""Markdown formatter. 

2 

3This module implements a Markdown formatter for synthesis results with 

4structured output and citations. 

5""" 

6 

7from __future__ import annotations 

8 

9from lexigram.ai.rag.synthesis.types import SynthesisResult 

10 

11 

12class MarkdownFormatter: 

13 """Markdown response formatter. 

14 

15 This formatter outputs synthesis results as structured Markdown with 

16 headers, lists, and formatted citations. 

17 

18 Attributes: 

19 include_title: Whether to include title header 

20 include_metadata: Whether to include metadata section 

21 include_quality: Whether to include quality metrics 

22 citation_style: Citation style ("numeric" or "footnote") 

23 """ 

24 

25 def __init__( 

26 self, 

27 include_title: bool = True, 

28 include_metadata: bool = True, 

29 include_quality: bool = False, 

30 citation_style: str = "numeric", 

31 ): 

32 """Initialize the markdown formatter. 

33 

34 Args: 

35 include_title: Include title header 

36 include_metadata: Include metadata section 

37 include_quality: Include quality metrics 

38 citation_style: Citation style 

39 """ 

40 self.include_title = include_title 

41 self.include_metadata = include_metadata 

42 self.include_quality = include_quality 

43 self.citation_style = citation_style 

44 

45 def format(self, result: SynthesisResult) -> str: 

46 """Format result as Markdown. 

47 

48 Args: 

49 result: The synthesis result 

50 

51 Returns: 

52 Markdown output 

53 """ 

54 parts = [] 

55 

56 # Add title 

57 if self.include_title: 

58 parts.append("# Response\n") 

59 

60 # Add response text 

61 parts.append(result.response) 

62 parts.append("\n") 

63 

64 # Add sources/citations 

65 if result.sources or result.citations: 

66 parts.append("\n## Sources\n") 

67 

68 if result.citations: 

69 for citation in result.citations: 

70 num = citation.get("number", "?") 

71 source = citation.get("source", "Unknown") 

72 score = citation.get("score", 0.0) 

73 parts.append(f"{num}. {source} (relevance: {score:.2f})\n") 

74 else: 

75 for i, source in enumerate(result.sources, 1): 

76 parts.append(f"{i}. {source}\n") 

77 

78 # Add metadata 

79 if self.include_metadata: 

80 parts.append("\n## Metadata\n") 

81 parts.append(f"- **Strategy**: {result.strategy.value}\n") 

82 parts.append(f"- **Chunks Used**: {result.num_chunks_used}\n") 

83 parts.append(f"- **Created**: {result.created_at.isoformat()}\n") 

84 

85 # Add quality metrics 

86 if self.include_quality and result.quality_metrics: 

87 metrics = result.quality_metrics 

88 parts.append("\n## Quality Metrics\n") 

89 parts.append(f"- **Faithfulness**: {metrics.faithfulness:.2f}\n") 

90 parts.append(f"- **Relevance**: {metrics.relevance:.2f}\n") 

91 parts.append(f"- **Coherence**: {metrics.coherence:.2f}\n") 

92 parts.append(f"- **Confidence**: {metrics.confidence:.2f}\n") 

93 

94 if metrics.has_hallucinations: 

95 parts.append( 

96 f"- **Hallucinations**: {metrics.hallucination_count} detected\n", 

97 ) 

98 

99 return "".join(parts)