1
1
import { useState , useEffect } from 'react' ;
2
2
import chroma from "chroma-js" ;
3
3
import { format } from 'sql-formatter' ;
4
+ import EvalVisualizerSingle from './components/EvalVisualizerSingle' ;
4
5
import './App.css' ;
5
6
6
7
function App ( ) {
7
- const [ dataset , setDataset ] = useState ( "classic_new" ) ;
8
- const [ searchPattern , setSearchPattern ] = useState ( null ) ;
9
- const [ maxConfidence , setMaxConfidence ] = useState ( 1 ) ;
10
- const [ categories , setCategories ] = useState ( [ ] ) ;
11
- const [ data , setData ] = useState ( [ ] ) ;
12
- const [ siderVisible , setSiderVisible ] = useState ( false ) ;
13
- const [ selectedItem , setSelectedItem ] = useState ( null ) ;
14
- const [ showProbs , setShowProbs ] = useState ( false ) ;
15
- const [ selectedToken , setSelectedToken ] = useState ( null ) ;
16
-
17
- const getData = async ( ) => {
18
- const response = await fetch ( `/${ dataset } .json` ) ;
19
- let data = await response . json ( )
20
-
21
- if ( searchPattern ) {
22
- data = data . filter ( ( item ) => item . question . toLowerCase ( ) . includes ( searchPattern ) || item . generated_query . toLowerCase ( ) . includes ( searchPattern ) ) ;
23
- }
24
-
25
- if ( maxConfidence ) {
26
- // check if the min of all rank_1_probs is less than maxConfidence
27
- data = data . filter ( ( item ) => {
28
- return item . logprobs . reduce ( ( acc , item ) => {
29
- return Math . min ( acc , item . rank_1_prob ) ;
30
- } , 1 ) <= maxConfidence ;
31
- } ) ;
32
- }
33
-
34
- const cats = [ ] ;
35
- data . forEach ( ( item ) => {
36
- if ( ! cats . includes ( item . query_category ) ) {
37
- cats . push ( item . query_category ) ;
38
- }
39
- } ) ;
40
- setData ( data ) ;
41
- setCategories ( cats ) ;
42
- }
43
-
44
8
const getBackgroundColor = ( prob ) => {
45
9
return chroma . scale ( [ 'pink' , 'yellow' , 'lightgreen' ] ) . domain ( [ 0.15 , 0.3 , 1 ] ) ( prob ) . hex ( ) ;
46
10
}
@@ -61,240 +25,12 @@ function App() {
61
25
}
62
26
}
63
27
64
- useEffect ( ( ) => {
65
- getData ( dataset ) ;
66
- } , [ dataset , searchPattern , maxConfidence ] ) ;
67
-
68
28
return (
69
29
< div className = "App" >
70
- < h1 > Eval Visualizer</ h1 >
71
- < div className = "flex flex-padded" >
72
- < div id = "options" >
73
- < h3 > Eval Type</ h3 >
74
- < select
75
- style = { { width : 120 } }
76
- value = { dataset }
77
- onChange = {
78
- ( ev ) => {
79
- setDataset ( ev . target . value ) ;
80
- }
81
- }
82
- >
83
- < option value = "classic_new" > v1</ option >
84
- < option value = "basic_new" > Basic</ option >
85
- < option value = "advanced_new" > Advanced</ option >
86
- </ select >
87
- </ div >
88
-
89
- < div id = "search" >
90
- < h3 > Question or SQL Pattern</ h3 >
91
- < input
92
- type = "text"
93
- placeholder = "Pattern..."
94
- style = { { width : 200 } }
95
- value = { searchPattern }
96
- onChange = { ( ev ) => {
97
- setSearchPattern ( ev . target . value . toLowerCase ( ) ) ;
98
- } }
99
- />
100
- </ div >
101
-
102
- < div id = "slider-confidence" >
103
- < h3 > Min Top Prob Threshold</ h3 >
104
- < input
105
- type = "range"
106
- min = { 0 }
107
- max = { 1 }
108
- step = { 0.01 }
109
- value = { maxConfidence }
110
- style = { { width : 200 } }
111
- onChange = { ( ev ) => {
112
- setMaxConfidence ( parseFloat ( ev . target . value ) ) ;
113
- } }
114
- />
115
- < span > { maxConfidence } </ span >
116
- </ div >
117
- </ div >
118
-
119
- < div id = "summary-statistics" >
120
- < h3 > Summary Statistics</ h3 >
121
- < div className = "flex flex-padded" >
122
- < p > < b > Number of records</ b > : { data . length } </ p >
123
- < p > < b > Total Correct</ b > : { data . filter ( ( item ) => item . correct === 1 ) . length } ({ 100 * ( data . filter ( ( item ) => item . correct === 1 ) . length / data . length ) . toFixed ( 3 ) } )%</ p >
124
- < p > < b > Total Incorrect</ b > : { data . filter ( ( item ) => item . correct === 0 ) . length } ({ 100 * ( data . filter ( ( item ) => item . correct === 0 ) . length / data . length ) . toFixed ( 3 ) } )%</ p >
125
- </ div >
126
-
127
- </ div >
128
- < div id = "charts" >
129
- { categories . map ( ( category ) => {
130
- return (
131
- < >
132
- < h4 > { category } ({
133
- 100 * ( data . filter ( ( item ) => item . query_category == category ) . reduce (
134
- ( acc , item ) => {
135
- return acc + ( item . correct === 1 ? 1 : 0 ) ;
136
- } , 0
137
- ) / data . filter ( ( item ) => item . query_category == category ) . length ) . toFixed ( 2 )
138
- } %)
139
- </ h4 >
140
- < div
141
- key = { category }
142
- className = "flex"
143
- >
144
- { data . filter ( ( item ) => item . query_category === category )
145
- . sort ( ( item ) => item . correct === 1 ? - 1 : 1 )
146
- . map ( ( item ) => {
147
- return (
148
- // a table of hoverable cells with at most 10 columns
149
- // each cell is colored by the correct/incorrect status
150
- < span
151
- key = { item . question }
152
- className = { item . error_db_exec === 1 ? "cell error-cell" : "cell" }
153
- style = { {
154
- backgroundColor : item . correct === 1 ? "green" : "red" ,
155
- } }
156
- onClick = { ( ) => {
157
- selectedItem ?. question === item . question && siderVisible ?
158
- setSiderVisible ( false ) :
159
- setSiderVisible ( true )
160
- setSelectedItem ( item ) ;
161
- } }
162
- >
163
-
164
- </ span >
165
- ) ;
166
- } ) }
167
- </ div >
168
- </ >
169
- ) ; } ) }
170
- </ div >
171
- < div
172
- id = "right-sider"
173
- style = { {
174
- position : "fixed" ,
175
- right : 0 ,
176
- top : 0 ,
177
- width : 600 ,
178
- maxWidth : "100%" ,
179
- height : "100%" ,
180
- backgroundColor : "white" ,
181
- padding : 20 ,
182
- borderLeft : "1px solid black" ,
183
- boxShadow : "-2px 0 5px -1px rgba(0,0,0,0.2)" ,
184
- zIndex : 100 ,
185
- visibility : siderVisible ? "visible" : "hidden" ,
186
- overflowY : "scroll" ,
187
- } }
188
- >
189
- { /* this is closable sider on the right of the screen */ }
190
- < h3 > Details < button onClick = { ( ) => { setSiderVisible ( false ) ; } } > Close</ button > </ h3 >
191
- < p
192
- style = { {
193
- backgroundColor : selectedItem ?. correct === 1 ? "lightgreen" : "pink"
194
- } }
195
- >
196
- Question: < i > { selectedItem ?. question } </ i >
197
- </ p >
198
- < p > Database: < b > { selectedItem ?. db_name } </ b > </ p >
199
- { selectedItem ?. instructions ? < p > Instructions: < pre > { selectedItem . instructions } </ pre > </ p > : null }
200
-
201
- < div >
202
- < p > Golden Query: < pre > { formatSql ( selectedItem ?. query ) } </ pre > </ p >
203
- </ div >
204
-
205
- < p >
206
- Formatted Query
207
- < label className = "switch" style = { {
208
- marginBottom : - 8 ,
209
- marginLeft : 5 ,
210
- marginRight : 5 ,
211
- } } >
212
- < input
213
- type = "checkbox"
214
- className = "slider"
215
- id = "detail-button"
216
- checked = { showProbs }
217
- onChange = { ( ) => setShowProbs (
218
- ( prev ) => ! prev
219
- ) } />
220
- < span className = "slider round" > </ span >
221
- </ label >
222
- Probabilities
223
- </ p >
224
-
225
- < p > Generated Query:</ p >
226
- {
227
- showProbs ?
228
- < div >
229
- < div style = { {
230
- width : "80%" ,
231
- paddingBottom : 200
232
- } } >
233
- { ( selectedItem ?. logprobs || [ ] ) . map (
234
- ( item , idx ) => {
235
- return (
236
- < span
237
- key = { idx }
238
- style = { {
239
- backgroundColor : getBackgroundColor ( item ?. rank_1_prob ) ,
240
- padding : 1 ,
241
- margin : 1 ,
242
- borderRadius : 3 ,
243
- // hover pointer
244
- cursor : "pointer" ,
245
- } }
246
- // on hover, show the query in a floating div
247
- onMouseEnter = { ( ev ) => {
248
- setSelectedToken ( item ) ;
249
- const floatingDiv = document . getElementById ( "floating-div" ) ;
250
- floatingDiv . style . visibility = "visible" ;
251
- floatingDiv . style . top = ev . clientY + 10 + "px" ;
252
- floatingDiv . style . left = ev . clientX + "px" ;
253
- } }
254
- onMouseLeave = { ( ) => {
255
- const floatingDiv = document . getElementById ( "floating-div" ) ;
256
- floatingDiv . style . visibility = "hidden" ;
257
- } }
258
- >
259
- { item [ 'rank_1_token' ] }
260
- </ span >
261
- ) ;
262
- }
263
- ) }
264
- { /* floating div */ }
265
- < div
266
- id = "floating-div"
267
- style = { {
268
- position : "fixed" ,
269
- top : 0 ,
270
- left : 0 ,
271
- width : 250 ,
272
- height : 250 ,
273
- backgroundColor : "white" ,
274
- border : "1px solid black" ,
275
- zIndex : 1000 ,
276
- visibility : "hidden" ,
277
- } }
278
- >
279
- < div > Top token: < code > { selectedToken ?. rank_1_token } </ code > </ div >
280
- < div > Probability of top token: { selectedToken ?. rank_1_prob . toFixed ( 2 ) } </ div >
281
- < div > Second token: < code > { selectedToken ?. rank_2_token } </ code > </ div >
282
- < div > Probability of second token: { selectedToken ?. rank_2_prob . toFixed ( 2 ) } </ div >
283
- < div
284
- style = { {
285
- backgroundColor : getBackgroundColor ( selectedToken ?. rank_1_prob - selectedToken ?. rank_2_prob ) ,
286
- padding : 1 ,
287
- margin : 1 ,
288
- borderRadius : 3 ,
289
- } }
290
- > Probability difference: { ( selectedToken ?. rank_1_prob - selectedToken ?. rank_2_prob ) . toFixed ( 2 ) } </ div >
291
- </ div >
292
- </ div >
293
- </ div > :
294
- < pre > { formatSql ( selectedItem ?. generated_query ) } </ pre >
295
- }
296
- { selectedItem ?. error_db_exec === 1 ? < p > Error Message: < pre > { selectedItem ?. error_msg } </ pre > </ p > : null }
297
- </ div >
30
+ < EvalVisualizerSingle
31
+ getBackgroundColor = { getBackgroundColor }
32
+ formatSql = { formatSql }
33
+ />
298
34
</ div >
299
35
) ;
300
36
}
0 commit comments