@@ -75,6 +75,18 @@ const DashboardNative: React.FunctionComponent = () => {
75
75
const [ isPublishing , setIsPublishing ] = React . useState ( false ) ;
76
76
const [ expandedFiles , setExpandedFiles ] = React . useState < Record < string , boolean > > ( { } ) ;
77
77
78
+ // State Variables for Evaluate Checkpoint
79
+ const [ isEvalModalOpen , setIsEvalModalOpen ] = React . useState < boolean > ( false ) ;
80
+ const [ checkpoints , setCheckpoints ] = React . useState < string [ ] > ( [ ] ) ;
81
+ const [ isCheckpointsLoading , setIsCheckpointsLoading ] = React . useState < boolean > ( false ) ;
82
+ const [ checkpointsError , setCheckpointsError ] = React . useState < string | null > ( null ) ;
83
+ const [ isDropdownOpen , setIsDropdownOpen ] = React . useState < boolean > ( false ) ;
84
+ const [ selectedCheckpoint , setSelectedCheckpoint ] = React . useState < string | null > ( null ) ;
85
+
86
+ // QnA eval result
87
+ const [ qnaEvalResult , setQnaEvalResult ] = React . useState < string > ( '' ) ;
88
+ const [ isQnaLoading , setIsQnaLoading ] = React . useState < boolean > ( false ) ;
89
+
78
90
const router = useRouter ( ) ;
79
91
80
92
// Fetch branches from the API route
@@ -299,6 +311,100 @@ const DashboardNative: React.FunctionComponent = () => {
299
311
} ) ) ;
300
312
} ;
301
313
314
+ const handleOpenEvalModal = ( ) => {
315
+ setIsEvalModalOpen ( true ) ;
316
+ fetchCheckpoints ( ) ;
317
+ } ;
318
+
319
+ const handleCloseEvalModal = ( ) => {
320
+ setIsEvalModalOpen ( false ) ;
321
+ setCheckpoints ( [ ] ) ;
322
+ setCheckpointsError ( null ) ;
323
+ setSelectedCheckpoint ( null ) ;
324
+ setQnaEvalResult ( '' ) ;
325
+ setIsQnaLoading ( false ) ;
326
+ } ;
327
+
328
+ // **New Function to Fetch Checkpoints from API Route**
329
+ const fetchCheckpoints = async ( ) => {
330
+ setIsCheckpointsLoading ( true ) ;
331
+ setCheckpointsError ( null ) ;
332
+ try {
333
+ const response = await fetch ( '/api/native/eval/checkpoints' ) ;
334
+ console . log ( 'Response status:' , response . status ) ;
335
+ const data = await response . json ( ) ;
336
+ console . log ( 'Checkpoints data:' , data ) ;
337
+
338
+ if ( response . ok ) {
339
+ // Assuming the API returns an array of checkpoints
340
+ if ( Array . isArray ( data ) && data . length > 0 ) {
341
+ setCheckpoints ( data ) ;
342
+ console . log ( 'Checkpoints set successfully:' , data ) ;
343
+ } else {
344
+ setCheckpoints ( [ ] ) ;
345
+ console . log ( 'No checkpoints returned from API.' ) ;
346
+ }
347
+ } else {
348
+ setCheckpointsError ( data . error || 'Failed to fetch checkpoints.' ) ;
349
+ console . error ( 'Error fetching checkpoints:' , data . error || 'Failed to fetch checkpoints.' ) ;
350
+ }
351
+ } catch ( error ) {
352
+ console . error ( 'Error fetching checkpoints:' , error ) ;
353
+ setCheckpointsError ( 'Unable to reach the checkpoints endpoint.' ) ;
354
+ } finally {
355
+ setIsCheckpointsLoading ( false ) ;
356
+ }
357
+ } ;
358
+
359
+ // Checkpoint select dropdown
360
+ const onDropdownToggle = ( isOpen : boolean ) => setIsDropdownOpen ( isOpen ) ;
361
+ const onSelectCheckpoint = ( event : React . MouseEvent < Element , MouseEvent > , selection : string ) => {
362
+ setSelectedCheckpoint ( selection ) ;
363
+ setIsDropdownOpen ( false ) ;
364
+ } ;
365
+
366
+ const handleEvaluateQnA = async ( ) => {
367
+ if ( ! selectedCheckpoint ) {
368
+ addDangerAlert ( 'Please select a checkpoint to evaluate.' ) ;
369
+ return ;
370
+ }
371
+
372
+ setIsQnaLoading ( true ) ;
373
+ setQnaEvalResult ( '' ) ;
374
+
375
+ // TODO: dynamically prepend the checkpoint path
376
+ const selectedModelDir = '/var/home/cloud-user/.local/share/instructlab/checkpoints/hf_format/' + selectedCheckpoint ;
377
+
378
+ console . log ( '[CLIENT] Sending to /api/native/eval/qna:' , selectedModelDir ) ;
379
+
380
+ try {
381
+ const res = await fetch ( '/api/native/eval/qna' , {
382
+ method : 'POST' ,
383
+ headers : { 'Content-Type' : 'application/json' } ,
384
+ body : JSON . stringify ( { selectedModelDir } )
385
+ } ) ;
386
+
387
+ const data = await res . json ( ) ;
388
+ console . log ( '[CLIENT] Response from /api/native/eval/qna:' , data ) ;
389
+
390
+ if ( ! res . ok ) {
391
+ addDangerAlert ( data . error || 'Failed to evaluate QnA.' ) ;
392
+ } else {
393
+ if ( data . result ) {
394
+ setQnaEvalResult ( data . result ) ;
395
+ addSuccessAlert ( 'QnA Evaluation succeeded!' ) ;
396
+ } else {
397
+ setQnaEvalResult ( 'Evaluation completed (no result field).' ) ;
398
+ }
399
+ }
400
+ } catch ( error ) {
401
+ console . error ( 'Error evaluating QnA:' , error ) ;
402
+ addDangerAlert ( 'Error evaluating QnA.' ) ;
403
+ } finally {
404
+ setIsQnaLoading ( false ) ;
405
+ }
406
+ } ;
407
+
302
408
return (
303
409
< div >
304
410
< PageBreadcrumb hasBodyWrapper = { false } >
@@ -459,6 +565,84 @@ const DashboardNative: React.FunctionComponent = () => {
459
565
</ PageSection >
460
566
) }
461
567
568
+ { /* Evaluate Checkpoint Modal */ }
569
+ < Modal
570
+ variant = { ModalVariant . medium }
571
+ title = "Evaluate Checkpoint"
572
+ isOpen = { isEvalModalOpen }
573
+ onClose = { handleCloseEvalModal }
574
+ aria-labelledby = "evaluate-checkpoint-modal-title"
575
+ aria-describedby = "evaluate-checkpoint-modal-body"
576
+ >
577
+ < ModalHeader title = "Evaluate Checkpoint" />
578
+ < ModalBody id = "evaluate-checkpoint-modal-body" >
579
+ { isCheckpointsLoading ? (
580
+ < Spinner size = "lg" aria-label = "Loading checkpoints" />
581
+ ) : checkpointsError ? (
582
+ < Alert variant = "danger" title = { checkpointsError } isInline />
583
+ ) : (
584
+ < >
585
+ < div style = { { marginBottom : '1rem' } } >
586
+ < label style = { { display : 'block' , marginBottom : '0.4rem' } } > Select a Checkpoint:</ label >
587
+ < Dropdown
588
+ isOpen = { isDropdownOpen }
589
+ onSelect = { onSelectCheckpoint }
590
+ onOpenChange = { onDropdownToggle }
591
+ toggle = { ( toggleRef : React . Ref < MenuToggleElement > ) => (
592
+ < MenuToggle ref = { toggleRef } onClick = { ( ) => onDropdownToggle ( ! isDropdownOpen ) } isExpanded = { isDropdownOpen } >
593
+ { selectedCheckpoint || 'Select a Checkpoint' }
594
+ </ MenuToggle >
595
+ ) }
596
+ ouiaId = "EvaluateCheckpointDropdown"
597
+ shouldFocusToggleOnSelect
598
+ >
599
+ < DropdownList >
600
+ { checkpoints . length > 0 ? (
601
+ checkpoints . map ( ( checkpoint ) => (
602
+ < DropdownItem key = { checkpoint } value = { checkpoint } >
603
+ { checkpoint }
604
+ </ DropdownItem >
605
+ ) )
606
+ ) : (
607
+ < DropdownItem key = "no-checkpoints" isDisabled >
608
+ No checkpoints available
609
+ </ DropdownItem >
610
+ ) }
611
+ </ DropdownList >
612
+ </ Dropdown >
613
+ </ div >
614
+
615
+ { /* Display the evaluation result */ }
616
+ { qnaEvalResult && (
617
+ < div style = { { marginTop : '1rem' } } >
618
+ < b > Evaluation Output:</ b >
619
+ < pre
620
+ style = { {
621
+ marginTop : '0.5rem' ,
622
+ backgroundColor : '#f5f5f5' ,
623
+ padding : '1rem' ,
624
+ borderRadius : '4px' ,
625
+ maxHeight : '300px' ,
626
+ overflowY : 'auto'
627
+ } }
628
+ >
629
+ { qnaEvalResult }
630
+ </ pre >
631
+ </ div >
632
+ ) }
633
+ </ >
634
+ ) }
635
+ </ ModalBody >
636
+ < ModalFooter >
637
+ < Button key = "evaluateQnA" variant = "primary" onClick = { handleEvaluateQnA } isDisabled = { ! selectedCheckpoint || isQnaLoading } >
638
+ { isQnaLoading ? 'Evaluating...' : 'Evaluate' }
639
+ </ Button >
640
+ < Button key = "cancel" variant = "secondary" onClick = { handleCloseEvalModal } >
641
+ Cancel
642
+ </ Button >
643
+ </ ModalFooter >
644
+ </ Modal >
645
+
462
646
< Modal
463
647
variant = { ModalVariant . medium }
464
648
title = { `Files Contained in Branch: ${ diffData ?. branch } ` }
0 commit comments