1+ """
2+ Rich terminal output formatting for uqlm-guard.
3+ """
4+ from rich .console import Console
5+ from rich .table import Table
6+ from rich .panel import Panel
7+ from rich .progress import Progress , SpinnerColumn , TextColumn
8+ from rich .syntax import Syntax
9+ from rich .markdown import Markdown
10+ from rich import box
11+ from typing import List , Dict , Any
12+
13+
14+ console = Console ()
15+
16+
17+ class OutputFormatter :
18+ """Formats analysis results for terminal display."""
19+
20+ @staticmethod
21+ def print_header (prompt : str ):
22+ """Print analysis header."""
23+ console .print ()
24+ console .print (Panel (
25+ f"[bold cyan]Analyzing Prompt[/bold cyan]\n { prompt } " ,
26+ border_style = "cyan" ,
27+ box = box .ROUNDED
28+ ))
29+ console .print ()
30+
31+ @staticmethod
32+ def print_analyzing (num_samples : int , model : str ):
33+ """Show analyzing progress."""
34+ console .print (f"[yellow]⚡ Generating { num_samples } responses using { model } ...[/yellow]" )
35+
36+ @staticmethod
37+ def print_confidence_score (score : float , recommendation : str ):
38+ """Print confidence score with color coding."""
39+ console .print ()
40+
41+ # Determine color and emoji
42+ if score >= 0.8 :
43+ color = "green"
44+ emoji = "✅"
45+ level = "HIGH CONFIDENCE"
46+ elif score >= 0.6 :
47+ color = "yellow"
48+ emoji = "⚠️"
49+ level = "MEDIUM CONFIDENCE"
50+ elif score >= 0.4 :
51+ color = "orange1"
52+ emoji = "⚠️"
53+ level = "LOW CONFIDENCE"
54+ else :
55+ color = "red"
56+ emoji = "🔴"
57+ level = "VERY LOW CONFIDENCE"
58+
59+ # Create confidence panel
60+ confidence_text = f"""[bold { color } ]{ emoji } { level } [/bold { color } ]
61+
62+ Confidence Score: [{ color } ]{ score :.2f} /1.0[/{ color } ]
63+
64+ [italic]{ recommendation } [/italic]"""
65+
66+ console .print (Panel (
67+ confidence_text ,
68+ border_style = color ,
69+ box = box .DOUBLE
70+ ))
71+ console .print ()
72+
73+ @staticmethod
74+ def print_inconsistencies (inconsistencies : List [Dict [str , Any ]]):
75+ """Print detected inconsistencies."""
76+ if not inconsistencies :
77+ console .print ("[green]✓ No major inconsistencies detected[/green]\n " )
78+ return
79+
80+ console .print ("[bold red]⚠️ Detected Inconsistencies:[/bold red]\n " )
81+
82+ for i , inc in enumerate (inconsistencies , 1 ):
83+ severity = inc .get ("severity" , "unknown" )
84+ severity_color = {
85+ "low" : "blue" ,
86+ "medium" : "yellow" ,
87+ "high" : "red" ,
88+ "critical" : "red bold"
89+ }.get (severity , "white" )
90+
91+ inc_type = inc .get ("type" , "unknown" )
92+ description = inc .get ("description" , "No description" )
93+
94+ panel_content = f"""[{ severity_color } ]Severity: { severity .upper ()} [/{ severity_color } ]
95+ Type: { inc_type }
96+
97+ { description } """
98+
99+ console .print (Panel (
100+ panel_content ,
101+ title = f"[bold]Issue #{ i } [/bold]" ,
102+ border_style = severity_color ,
103+ box = box .ROUNDED
104+ ))
105+ console .print ()
106+
107+ @staticmethod
108+ def print_consensus (consensus_parts : List [str ]):
109+ """Print consensus parts."""
110+ if not consensus_parts :
111+ console .print ("[yellow]⚠️ No clear consensus found across responses[/yellow]\n " )
112+ return
113+
114+ console .print ("[bold green]✓ Consensus Elements (present in all responses):[/bold green]\n " )
115+
116+ for part in consensus_parts [:5 ]: # Show first 5
117+ if part .strip ():
118+ console .print (f" • { part .strip ()} " )
119+
120+ if len (consensus_parts ) > 5 :
121+ console .print (f" [dim]... and { len (consensus_parts ) - 5 } more[/dim]" )
122+
123+ console .print ()
124+
125+ @staticmethod
126+ def print_divergence (divergences : List [Dict [str , Any ]]):
127+ """Print divergence information."""
128+ if not divergences :
129+ return
130+
131+ console .print ("[bold]Response Divergence Analysis:[/bold]\n " )
132+
133+ table = Table (show_header = True , header_style = "bold cyan" , box = box .ROUNDED )
134+ table .add_column ("Response Pair" , style = "cyan" )
135+ table .add_column ("Similarity" , justify = "right" )
136+ table .add_column ("Diff Lines" , justify = "right" )
137+
138+ for div in divergences [:10 ]: # Show top 10
139+ pair = div .get ("response_pair" , (0 , 0 ))
140+ similarity = div .get ("similarity" , 0 )
141+ diff_lines = div .get ("diff_lines" , 0 )
142+
143+ similarity_color = "green" if similarity > 0.8 else "yellow" if similarity > 0.5 else "red"
144+
145+ table .add_row (
146+ f"#{ pair [0 ]} vs #{ pair [1 ]} " ,
147+ f"[{ similarity_color } ]{ similarity :.2%} [/{ similarity_color } ]" ,
148+ str (diff_lines )
149+ )
150+
151+ console .print (table )
152+ console .print ()
153+
154+ @staticmethod
155+ def print_responses (responses : List [str ], show_full : bool = False ):
156+ """Print generated responses."""
157+ console .print ("[bold]Generated Responses:[/bold]\n " )
158+
159+ for i , response in enumerate (responses , 1 ):
160+ if show_full :
161+ console .print (Panel (
162+ response ,
163+ title = f"[bold]Response #{ i } [/bold]" ,
164+ border_style = "blue" ,
165+ box = box .ROUNDED
166+ ))
167+ else :
168+ # Show preview
169+ preview = response [:200 ] + "..." if len (response ) > 200 else response
170+ console .print (f"[cyan]Response #{ i } :[/cyan]" )
171+ console .print (f"[dim]{ preview } [/dim]\n " )
172+
173+ @staticmethod
174+ def print_summary_stats (analysis ):
175+ """Print summary statistics."""
176+ console .print ("[bold]Analysis Summary:[/bold]\n " )
177+
178+ table = Table (show_header = False , box = box .SIMPLE )
179+ table .add_column ("Metric" , style = "cyan" )
180+ table .add_column ("Value" )
181+
182+ table .add_row ("Model Used" , analysis .model_used )
183+ table .add_row ("Samples Generated" , str (analysis .num_samples ))
184+ table .add_row ("Confidence Score" , f"{ analysis .confidence_score :.3f} " )
185+ table .add_row ("Inconsistencies Found" , str (len (analysis .inconsistencies )))
186+ table .add_row ("Consensus Elements" , str (len (analysis .consensus_parts )))
187+
188+ console .print (table )
189+ console .print ()
190+
191+ @staticmethod
192+ def print_benchmark_results (results : Dict [str , Any ]):
193+ """Print benchmark results."""
194+ console .print ()
195+ console .print (Panel (
196+ "[bold cyan]Benchmark Results[/bold cyan]" ,
197+ border_style = "cyan"
198+ ))
199+ console .print ()
200+
201+ table = Table (show_header = True , header_style = "bold cyan" , box = box .ROUNDED )
202+ table .add_column ("Category" , style = "cyan" )
203+ table .add_column ("Tests" , justify = "right" )
204+ table .add_column ("Avg Confidence" , justify = "right" )
205+ table .add_column ("High (>0.8)" , justify = "right" , style = "green" )
206+ table .add_column ("Medium (0.6-0.8)" , justify = "right" , style = "yellow" )
207+ table .add_column ("Low (<0.6)" , justify = "right" , style = "red" )
208+
209+ for category , data in results .items ():
210+ table .add_row (
211+ category ,
212+ str (data ["total" ]),
213+ f"{ data ['avg_confidence' ]:.2f} " ,
214+ str (data ["high" ]),
215+ str (data ["medium" ]),
216+ str (data ["low" ])
217+ )
218+
219+ console .print (table )
220+ console .print ()
221+
222+ @staticmethod
223+ def print_error (message : str ):
224+ """Print error message."""
225+ console .print (f"\n [bold red]❌ Error:[/bold red] { message } \n " )
226+
227+ @staticmethod
228+ def print_success (message : str ):
229+ """Print success message."""
230+ console .print (f"\n [bold green]✓[/bold green] { message } \n " )
0 commit comments