Skip to content

Commit

Permalink
Impl [Batch Run] Model Training (#2066)
Browse files Browse the repository at this point in the history
  • Loading branch information
illia-prokopchuk authored Nov 7, 2023
1 parent 6962e87 commit 6c95a76
Show file tree
Hide file tree
Showing 19 changed files with 217 additions and 78 deletions.
4 changes: 2 additions & 2 deletions src/actions/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,13 @@ const functionsActions = {
type: FETCH_HUB_FUNCTION_TEMPLATE_FAILURE,
payload: err
}),
fetchHubFunctions: () => dispatch => {
fetchHubFunctions: allowedHubFunctions => dispatch => {
dispatch(functionsActions.fetchHubFunctionsBegin())

return functionsApi
.getHubFunctions()
.then(({ data: functionTemplates }) => {
const templatesData = generateHubCategories(functionTemplates.catalog)
const templatesData = generateHubCategories(functionTemplates.catalog, allowedHubFunctions)

dispatch(functionsActions.setHubFunctions(templatesData))

Expand Down
2 changes: 2 additions & 0 deletions src/common/NameFilter/nameFilter.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ such restriction.
*/

.name-filter {
min-width: 180px;

&__icon {
cursor: pointer;
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/TargetPath/targetPath.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ export const generateComboboxMatchesList = (
export const generateArtifactsList = artifacts => {
const generatedArtifacts = artifacts
.map(artifact => {
const key = artifact.link_iteration ? artifact.link_iteration.db_key : artifact.key ?? ''
const key = artifact.link_iteration?.db_key || artifact.db_key || artifact.key || ''
return {
label: key,
id: key
Expand Down
39 changes: 23 additions & 16 deletions src/components/ArtifactsActionBar/ArtifactsActionBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import detailsActions from '../../actions/details'
import { ReactComponent as RefreshIcon } from 'igz-controls/images/refresh.svg'

function ArtifactsActionBar({
actionButton,
actionButtons,
cancelRequest,
filterMenuName,
handleRefresh,
Expand Down Expand Up @@ -154,13 +154,18 @@ function ArtifactsActionBar({
</FilterMenuModal>
</div>
<div className="action-bar__actions">
{actionButton && !actionButton.hidden && (
<Button
variant={actionButton.variant}
label={actionButton.label}
className={actionButton.className}
onClick={actionButton.onClick}
/>
{actionButtons.map(
(actionButton, index) =>
actionButton &&
!actionButton.hidden && (
<Button
key={index}
variant={actionButton.variant}
label={actionButton.label}
className={actionButton.className}
onClick={actionButton.onClick}
/>
)
)}

<RoundedIcon tooltipText="Refresh" onClick={() => refresh(formState)} id="refresh">
Expand All @@ -174,19 +179,21 @@ function ArtifactsActionBar({
}

ArtifactsActionBar.defaultProps = {
actionButton: null,
actionButtons: [],
cancelRequest: null,
tab: ''
}

ArtifactsActionBar.propTypes = {
actionButton: PropTypes.shape({
className: PropTypes.string,
hidden: PropTypes.bool,
label: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
variant: PropTypes.string.isRequired
}),
actionButtons: PropTypes.arrayOf(
PropTypes.shape({
className: PropTypes.string,
hidden: PropTypes.bool,
label: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
variant: PropTypes.string.isRequired
})
),
cancelRequest: PropTypes.func,
filterMenuName: PropTypes.string.isRequired,
handleRefresh: PropTypes.func.isRequired,
Expand Down
8 changes: 4 additions & 4 deletions src/components/Datasets/Datasets.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,6 @@ const Datasets = () => {
const filtersStore = useSelector(store => store.filtersStore)
const datasetsRef = useRef(null)
const viewMode = getViewMode(window.location.search)
const pageData = useMemo(
() => generatePageData(selectedDataset, viewMode),
[selectedDataset, viewMode]
)
const params = useParams()
const navigate = useNavigate()
const location = useLocation()
Expand All @@ -96,6 +92,10 @@ const Datasets = () => {
() => filtersStore[FILTER_MENU_MODAL][DATASETS_FILTERS].values,
[filtersStore]
)
const pageData = useMemo(
() => generatePageData(selectedDataset, viewMode, params),
[selectedDataset, viewMode, params]
)

const detailsFormInitialValues = useMemo(
() => ({
Expand Down
14 changes: 8 additions & 6 deletions src/components/Datasets/DatasetsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,14 @@ const DatasetsView = React.forwardRef(
<div className="table-container">
<div className="content__action-bar-wrapper">
<ArtifactsActionBar
actionButton={{
variant: SECONDARY_BUTTON,
label: registerDatasetTitle,
className: 'register-button',
onClick: handleRegisterDataset
}}
actionButtons={[
{
variant: SECONDARY_BUTTON,
label: registerDatasetTitle,
className: 'action-button',
onClick: handleRegisterDataset
}
]}
filterMenuName={DATASETS_FILTERS}
handleRefresh={handleRefresh}
page={DATASETS_PAGE}
Expand Down
29 changes: 27 additions & 2 deletions src/components/Datasets/datasets.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ under the Apache 2.0 license is conditioned upon your compliance with
such restriction.
*/

import JobWizard from '../JobWizard/JobWizard'
import { openPopUp } from 'igz-controls/utils/common.util'
import { applyTagChanges } from '../../utils/artifacts.util'
import { getArtifactIdentifier } from '../../utils/getUniqueIdentifier'
import {
Expand All @@ -34,6 +36,8 @@ import { searchArtifactItem } from '../../utils/searchArtifactItem'
import { sortListByDate } from '../../utils'
import { fetchDataSet } from '../../reducers/artifactsReducer'

import { PRIMARY_BUTTON } from 'igz-controls/constants'

export const infoHeaders = [
{
label: 'Hash',
Expand Down Expand Up @@ -85,17 +89,38 @@ export const generateDataSetsDetailsMenu = selectedItem => [
}
]

export const generatePageData = (selectedItem, viewMode) => ({
export const generatePageData = (selectedItem, viewMode, params) => ({
page: DATASETS_PAGE,
details: {
menu: generateDataSetsDetailsMenu(selectedItem),
infoHeaders,
type: DATASETS,
hideBackBtn: viewMode === FULL_VIEW_MODE,
withToggleViewBtn: true
withToggleViewBtn: true,
actionButton: {
label: 'Train',
variant: PRIMARY_BUTTON,
onClick: () => handleTrainDataset(selectedItem, params)
}
}
})

const handleTrainDataset = (selectedItem, params) => {
const prePopulatedDataInputs = [{
name: selectedItem.db_key || selectedItem.key || 'dataset',
path: selectedItem.URI
}]

openPopUp(JobWizard, {
params,
isTrain: true,
wizardTitle: 'Train model',
prePopulatedData: {
dataInputs: prePopulatedDataInputs
}
})
}

export const fetchDataSetRowData = async (
dispatch,
dataSet,
Expand Down
14 changes: 8 additions & 6 deletions src/components/Files/FilesView.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,14 @@ const FilesView = React.forwardRef(
<div className="table-container">
<div className="content__action-bar-wrapper">
<ArtifactsActionBar
actionButton={{
variant: SECONDARY_BUTTON,
label: registerArtifactTitle,
className: 'register-button',
onClick: handleRegisterArtifact
}}
actionButtons={[
{
variant: SECONDARY_BUTTON,
label: registerArtifactTitle,
className: 'action-button',
onClick: handleRegisterArtifact
}
]}
filterMenuName={FILES_FILTERS}
handleRefresh={handleRefresh}
page={FILES_PAGE}
Expand Down
24 changes: 22 additions & 2 deletions src/components/JobWizard/JobWizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ const JobWizard = ({
functionsStore,
isBatchInference,
isOpen,
isTrain,
jobsStore,
mode,
onResolve,
onSuccessRequest,
onWizardClose,
params,
prePopulatedData,
removeJobFunction,
removeHubFunctions,
runNewJob,
Expand Down Expand Up @@ -286,7 +288,11 @@ const JobWizard = ({

return [
{
label: isBatchInference ? 'Schedule Infer' : 'Schedule for later',
label: isBatchInference
? 'Schedule Infer'
: isTrain
? 'Schedule training job'
: 'Schedule for later',
onClick: () => {
formState.handleSubmit()

Expand All @@ -301,7 +307,14 @@ const JobWizard = ({
ref: scheduleButtonRef
},
{
label: mode === PANEL_EDIT_MODE ? 'Save' : isBatchInference ? 'Infer now' : 'Run',
label:
mode === PANEL_EDIT_MODE
? 'Save'
: isBatchInference
? 'Infer now'
: isTrain
? 'Run training now'
: 'Run',
onClick: () => {
formState.handleSubmit()

Expand Down Expand Up @@ -435,7 +448,9 @@ const JobWizard = ({
frontendSpec={frontendSpec}
functions={functions}
isEditMode={isEditMode}
isTrain={isTrain}
params={params}
prePopulatedData={prePopulatedData}
selectedFunctionData={selectedFunctionData}
selectedFunctionTab={selectedFunctionTab}
setActiveTab={setActiveTab}
Expand All @@ -456,6 +471,7 @@ const JobWizard = ({
isBatchInference={isBatchInference}
isEditMode={isEditMode}
jobAdditionalData={jobAdditionalData}
prePopulatedData={prePopulatedData}
selectedFunctionData={selectedFunctionData}
/>
<JobWizardDataInputs formState={formState} />
Expand Down Expand Up @@ -505,21 +521,25 @@ const JobWizard = ({
JobWizard.defaultProps = {
defaultData: {},
isBatchInference: false,
isTrain: false,
mode: PANEL_CREATE_MODE,
onSuccessRequest: () => {},
onWizardClose: () => {},
prePopulatedData: {},
wizardTitle: 'Batch run'
}

JobWizard.propTypes = {
defaultData: PropTypes.shape({}),
isBatchInference: PropTypes.bool,
isOpen: PropTypes.bool.isRequired,
isTrain: PropTypes.bool,
mode: JOB_WIZARD_MODE,
onResolve: PropTypes.func.isRequired,
onSuccessRequest: PropTypes.func,
onWizardClose: PropTypes.func,
params: PropTypes.shape({}).isRequired,
prePopulatedData: PropTypes.shape({}),
wizardTitle: PropTypes.string
}

Expand Down
28 changes: 24 additions & 4 deletions src/components/JobWizard/JobWizard.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export const generateJobWizardData = (
selectedFunctionData,
defaultData,
currentProjectName,
isEditMode
isEditMode,
prePopulatedData
) => {
const functions = selectedFunctionData.functions
const functionInfo = getFunctionInfo(selectedFunctionData)
Expand Down Expand Up @@ -181,12 +182,18 @@ export const generateJobWizardData = (
jobFormData[RESOURCES_STEP].jobPriorityClassName = jobPriorityClassName
}

if (!isEmpty(functionParameters) || !isEmpty(prePopulatedData.dataInputs)) {
jobFormData[DATA_INPUTS_STEP].dataInputsTable = parseDataInputs(
functionParameters,
prePopulatedData.dataInputs
)
}

if (!isEmpty(functionParameters)) {
jobFormData[PARAMETERS_STEP].parametersTable = {
predefined: parsePredefinedParameters(functionParameters),
custom: []
}
jobFormData[DATA_INPUTS_STEP].dataInputsTable = parseDataInputs(functionParameters)
}

return [jobFormData, jobAdditionalData]
Expand Down Expand Up @@ -611,8 +618,8 @@ const getDataInputData = (dataInputName, dataInputValue, dataInputIsChecked) =>

const sortParameters = (parameter, nextParameter) => nextParameter.isRequired - parameter.isRequired

export const parseDataInputs = functionParameters => {
return functionParameters
export const parseDataInputs = (functionParameters = [], prePopulatedDataInputs) => {
const parsedDataInputs = functionParameters
.filter(dataInputs => dataInputs.type?.includes('DataItem'))
.map(dataInput => {
return {
Expand All @@ -624,6 +631,19 @@ export const parseDataInputs = functionParameters => {
}
})
.sort(sortParameters)

if (!isEmpty(prePopulatedDataInputs)) {
prePopulatedDataInputs.forEach(dataInput => {
parsedDataInputs.unshift({
data: getDataInputData(dataInput.name, dataInput.path, true),
isRequired: true,
isDefault: true,
isPredefined: true
})
})
}

return parsedDataInputs
}

export const parseDefaultDataInputs = (funcParams, runDataInputs = {}) => {
Expand Down
Loading

0 comments on commit 6c95a76

Please sign in to comment.