1+ import json
2+ from dash .dependencies import Input , Output
3+ from dash import html , dcc
4+ import plotly .graph_objects as go
5+
6+ def register_metrics_callbacks (app ):
7+ @app .callback (
8+ [Output ('test-statistics-content' , 'children' ),
9+ Output ('accuracy-chart' , 'children' ),
10+ Output ('hallucination-rate' , 'children' ),
11+ Output ('llm-drift-rate' , 'children' ),
12+ Output ('custom-metric-1' , 'children' ),
13+ Output ('custom-metric-2' , 'children' )],
14+ [Input ('selected-file-path' , 'data' )]
15+ )
16+ def update_metrics (selected_file ):
17+ default_values = get_default_metric_values ()
18+
19+ if selected_file is None :
20+ return default_values
21+
22+ try :
23+ with open (selected_file , 'r' ) as f :
24+ data = json .load (f )
25+ metrics = data .get ('metrics' , [])
26+
27+ return process_metrics (metrics )
28+
29+ except Exception as e :
30+ print (f"Error loading metrics from { selected_file } : { e } " )
31+ return default_values
32+
33+ def get_default_metric_values ():
34+ """Return default values for all metrics."""
35+ default_stats = html .Div ([
36+ html .P (f"Total Tests: N/A" ),
37+ html .P (f"Test Cases: N/A" ),
38+ html .P (f"Paraphrased: N/A" ),
39+ html .P (f"Iterations: N/A" ),
40+ html .P (f"Passed: N/A" ),
41+ html .P (f"Failed: N/A" )
42+ ])
43+
44+ default_gauge = html .Div ([
45+ html .H3 ("N/A" , style = {'textAlign' : 'center' , 'color' : 'gray' , 'marginTop' : '20px' })
46+ ])
47+
48+ default_percentage = html .Div ([
49+ html .H3 ("N/A" , style = {'textAlign' : 'center' , 'color' : 'gray' })
50+ ])
51+
52+ return (
53+ default_stats ,
54+ default_gauge ,
55+ default_percentage ,
56+ default_percentage ,
57+ default_percentage ,
58+ default_percentage
59+ )
60+
61+ def process_metrics (metrics ):
62+ """Process metrics data and return formatted components."""
63+ statistics = get_default_metric_values ()[0 ] # Default value
64+ accuracy = get_default_metric_values ()[1 ] # Default value
65+ hallucination = get_default_metric_values ()[2 ] # Default value
66+ drift = get_default_metric_values ()[3 ] # Default value
67+ custom1 = get_default_metric_values ()[4 ] # Default value
68+ custom2 = get_default_metric_values ()[5 ] # Default value
69+
70+ for metric in metrics :
71+ metric_name = metric .get ('metric_name' , '' )
72+
73+ if metric_name == 'Statistics' :
74+ tests = metric .get ('tests' , {})
75+ statistics = html .Div ([
76+ html .P (f"Total Tests: { tests .get ('Total' , 'N/A' )} " ),
77+ html .P (f"Test Cases: { tests .get ('Test_cases' , 'N/A' )} " ),
78+ html .P (f"Paraphrased: { tests .get ('Paraphrased' , 'N/A' )} " ),
79+ html .P (f"Iterations: { tests .get ('Iteration' , 'N/A' )} " ),
80+ html .P (f"Passed: { tests .get ('Passed' , 'N/A' )} " ),
81+ html .P (f"Failed: { tests .get ('Failed' , 'N/A' )} " )
82+ ])
83+
84+ elif metric_name == 'Accuracy' :
85+ accuracy_value = metric .get ('metric_result' , 0 ) * 100
86+ accuracy = create_accuracy_gauge (accuracy_value )
87+
88+ elif metric_name == 'Hallucination_rate' :
89+ hall_rate = metric .get ('metric_result' , 0 )
90+ hallucination = html .Div ([
91+ html .H3 (f"{ hall_rate :.1f} %" ,
92+ style = {'textAlign' : 'center' ,
93+ 'color' : '#d9534f' if hall_rate > 20 else '#5cb85c' })
94+ ])
95+
96+ elif metric_name == 'LLM Drift rate' :
97+ drift_rate = metric .get ('metric_result' , 0 )
98+ drift = html .Div ([
99+ html .H3 (f"{ drift_rate :.1f} %" ,
100+ style = {'textAlign' : 'center' ,
101+ 'color' : '#d9534f' if drift_rate > 30 else '#5cb85c' })
102+ ])
103+
104+ elif metric_name == 'Custom metric - 1' :
105+ custom_rate1 = metric .get ('metric_result' , 0 )
106+ custom1 = html .Div ([
107+ html .H3 (f"{ custom_rate1 :.1f} %" ,
108+ style = {'textAlign' : 'center' ,
109+ 'color' : '#d9534f' if custom_rate1 > 50 else '#5cb85c' })
110+ ])
111+
112+ elif metric_name == 'Custom metric - 2' :
113+ custom_rate2 = metric .get ('metric_result' , 0 )
114+ custom2 = html .Div ([
115+ html .H3 (f"{ custom_rate2 :.1f} %" ,
116+ style = {'textAlign' : 'center' ,
117+ 'color' : '#d9534f' if custom_rate2 > 50 else '#5cb85c' })
118+ ])
119+
120+ return statistics , accuracy , hallucination , drift , custom1 , custom2
121+
122+ def create_accuracy_gauge (accuracy_value ):
123+ """Create an accuracy gauge figure."""
124+ fig = go .Figure (go .Indicator (
125+ mode = "gauge+number" ,
126+ value = accuracy_value ,
127+ domain = {'x' : [0 , 1 ], 'y' : [0 , 1 ]},
128+ gauge = {
129+ 'axis' : {'range' : [0 , 100 ], 'tickwidth' : 1 },
130+ 'bar' : {'color' : "#5cb85c" },
131+ 'bgcolor' : "white" ,
132+ 'borderwidth' : 2 ,
133+ 'bordercolor' : "gray" ,
134+ 'steps' : [
135+ {'range' : [0 , 30 ], 'color' : '#d9534f' },
136+ {'range' : [30 , 70 ], 'color' : '#f0ad4e' },
137+ {'range' : [70 , 100 ], 'color' : '#5cb85c' }
138+ ],
139+ 'threshold' : {
140+ 'line' : {'color' : "red" , 'width' : 4 },
141+ 'thickness' : 0.75 ,
142+ 'value' : 70
143+ }
144+ }
145+ ))
146+
147+ fig .update_layout (
148+ paper_bgcolor = '#2b2b2b' ,
149+ font = {'color' : "white" , 'family' : "Arial" },
150+ height = 200 ,
151+ margin = dict (l = 30 , r = 30 , t = 30 , b = 0 )
152+ )
153+
154+ return html .Div ([
155+ dcc .Graph (figure = fig , config = {'displayModeBar' : False })
156+ ])
0 commit comments