@@ -75,6 +75,18 @@ const DashboardNative: React.FunctionComponent = () => {
7575 const [ isPublishing , setIsPublishing ] = React . useState ( false ) ;
7676 const [ expandedFiles , setExpandedFiles ] = React . useState < Record < string , boolean > > ( { } ) ;
7777
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+
7890 const router = useRouter ( ) ;
7991
8092 // Fetch branches from the API route
@@ -299,6 +311,100 @@ const DashboardNative: React.FunctionComponent = () => {
299311 } ) ) ;
300312 } ;
301313
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+
302408 return (
303409 < div >
304410 < PageBreadcrumb hasBodyWrapper = { false } >
@@ -459,6 +565,84 @@ const DashboardNative: React.FunctionComponent = () => {
459565 </ PageSection >
460566 ) }
461567
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+
462646 < Modal
463647 variant = { ModalVariant . medium }
464648 title = { `Files Contained in Branch: ${ diffData ?. branch } ` }
0 commit comments