/********************************************************************************************************************* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of * * this software and associated documentation files (the "Software"), to deal in * * the Software without restriction, including without limitation the rights to * * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * * the Software, and to permit persons to whom the Software is furnished to do so. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * *********************************************************************************************************************/ import { FunctionComponent, useCallback, useState, useEffect } from 'react' import { Badge, Box, Button, Column, ColumnLayout, Container, Inline, KeyValuePair, Link, Stack, Text, DeleteConfirmationDialog, Tabs, Table, ButtonIcon, ExpandableSection, Form, Input, TokenGroup, } from 'aws-northstar' import { FormField } from '../../../components/NorthstarEx' import { useHistory, useParams } from 'react-router-dom' import { dayjslocal } from '../../../utils/dayjs' import NotFound from '../../../components/NotFound' import { useModelTrainingExecutionContext } from '../../../contexts/ModelTrainingExecutionContext' import { appvars } from '../../../config' import { useTrainingTemplateContext } from '../../../contexts/TrainingTemplateContext' import { columnDefinitions, execColumnDefinitions, stepColumnDefinitions } from './table-columns' import { getStatusBadge } from '../../../utils/badge-helper' import { EndpointStatus, InvokeModelEndpointPayload, TrainingTemplateData } from '../../../models' import { FEImages } from './FEImages' export const ModelTrainingExecutionDetails: FunctionComponent = () => { const history = useHistory() const { modelTrainingExecutionId } = useParams<{ modelTrainingExecutionId: string }>() const [ { items: modelTrainingExecutionItems }, { deleteItem, startModelTraining, getItem, createModelEndpoint, deleteModelEndpoint, invokeModelEndpoint }, ] = useModelTrainingExecutionContext() const [{ items: trainingTemplateItems }] = useTrainingTemplateContext() const [currentTemplateName, setCurrentTemplateName] = useState('') const currentItem = modelTrainingExecutionItems.find((x) => x.Id === modelTrainingExecutionId) const [showDeleteModal, setShowDeleteModal] = useState(false) const [tempQuantile, setTempQuantile] = useState(0.1) const [showDeleteEndpointModal, setShowDeleteEndpointModal] = useState(false) const [invokeModelEndpointPayload, setInvokeModelEndpointPayload] = useState({ executionId: '', numSamples: 100, quantiles: [], }) const [predictionLoading, setPredictionLoading] = useState(false) useEffect(() => { if (currentItem == null) { return } const initialObj: Record = {} const templateNames: Record = trainingTemplateItems.reduce( (obj: Record, curr: TrainingTemplateData) => ({ ...obj, [curr.Id]: curr.name, }), initialObj, ) setCurrentTemplateName(templateNames[currentItem.templateId]) setInvokeModelEndpointPayload({ executionId: currentItem.Id, quantiles: [0.1, 0.5, 0.9], numSamples: 100, }) }, [trainingTemplateItems, modelTrainingExecutionItems, currentItem]) const onDeleteClick = useCallback(async () => { setShowDeleteModal(true) }, []) const onRefreshClick = useCallback(async () => { if (currentItem == null) { return } getItem(currentItem.Id) }, [getItem, currentItem]) const onEditClick = useCallback(() => { if (currentItem == null) { throw new Error('ModelTrainingExecutionData is null') } history.push(`/${appvars.URL.MODEL_TRAINING_EXECUTION}/${currentItem.Id}/edit`) }, [currentItem, history]) const onCreateModelEndpointClick = useCallback(async () => { if (currentItem == null) { return } createModelEndpoint(currentItem.Id) }, [createModelEndpoint, currentItem]) const onModelEndpointDeleteClick = useCallback(() => { setShowDeleteEndpointModal(true) }, []) const onInvokeModelEndpointClick = useCallback(async () => { if (invokeModelEndpointPayload == null) { return } setPredictionLoading(true) await invokeModelEndpoint(invokeModelEndpointPayload) setPredictionLoading(false) }, [invokeModelEndpoint, invokeModelEndpointPayload]) const proceedWithDeleteEndpoint = useCallback(async () => { if (currentItem == null) { return } await deleteModelEndpoint(currentItem.Id) setShowDeleteEndpointModal(false) }, [deleteModelEndpoint, currentItem]) const onTrainModelClick = useCallback(async () => { if (currentItem == null) { throw new Error('ModelTrainingExecutionData is null') } await startModelTraining(currentItem.Id) }, [currentItem, startModelTraining]) const proceedWithDelete = useCallback(async () => { if (currentItem == null) { throw new Error('ModelTrainingExecutionData is null') } await deleteItem(currentItem.Id) history.push(`/${appvars.URL.MODEL_TRAINING_EXECUTION}`) }, [deleteItem, history, currentItem]) if (currentItem == null) { return } const actionGroup = ( {(currentItem.modelTrainingExecutionStatus == null || currentItem.modelTrainingExecutionStatus.execStatus === 'Failed') && ( )} {(currentItem.modelTrainingExecutionStatus == null || currentItem.modelTrainingExecutionStatus.execStatus === 'Failed') && ( )} ) const trainingTab = { id: 'trainingTab', label: 'Training', content: ( <> ${currentItem.modelTrainingExecutionStatus.stepStatus}` : null } /> {currentItem.pipelineExecutionArn}} /> <> {currentItem.pipelineExecStatusChanges != null && ( Pipeline Execution Changes } > )} {currentItem.pipelineStepStatusChanges != null && ( Pipeline Step Changes } >
)} {currentItem.processingStepLogs != null && ( Feature engineering logs } >
)} {currentItem.modelTrainingExecutionStatus?.execStatus === 'Succeeded' && ( Plots generated } > )} ), } const modelTab = { id: 'modelTab', label: 'Model', content: ( <> {currentItem.modelInfo != null && ( {currentItem.modelInfo.endpointStatus === EndpointStatus.InService && ( )} {currentItem.modelInfo.endpointArn == null && ( )} } > )} {currentItem.modelInfo != null && currentItem.modelInfo.endpointStatus === EndpointStatus.InService && ( } >
}> { const val = parseFloat(value) if (!isNaN(val)) { setTempQuantile(val) } }} placeholder='Add a new value' />