From bba86c5ba5a2cdec223183da3d72bfce610841eb Mon Sep 17 00:00:00 2001 From: dvalleri Date: Thu, 12 Dec 2024 17:31:16 +0100 Subject: [PATCH 1/4] feat(ui): add LLM model creation --- .../components/modals/add-new-model/index.jsx | 68 ++++++-- .../llm-components/form-fields.jsx | 148 ++++++++++++++++++ .../add-new-model/llm-components/index.jsx | 59 +++++++ .../llm-components/use-handle-on-submit.js | 59 +++++++ .../add-new-model/step-one/form-fields.jsx | 1 + ui/src/store/state/models/constants.js | 2 + 6 files changed, 324 insertions(+), 13 deletions(-) create mode 100644 ui/src/components/modals/add-new-model/llm-components/form-fields.jsx create mode 100644 ui/src/components/modals/add-new-model/llm-components/index.jsx create mode 100644 ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js diff --git a/ui/src/components/modals/add-new-model/index.jsx b/ui/src/components/modals/add-new-model/index.jsx index dfc5ab45..e9bc8e48 100644 --- a/ui/src/components/modals/add-new-model/index.jsx +++ b/ui/src/components/modals/add-new-model/index.jsx @@ -1,5 +1,9 @@ +import { + RbitModal, SectionTitle, Steps, +} from '@radicalbit/radicalbit-design-system'; import useModals from '@Src/hooks/use-modals'; -import { RbitModal, SectionTitle, Steps } from '@radicalbit/radicalbit-design-system'; +import { ModelTypeEnum } from '@Src/store/state/models/constants'; +import { LlmActionButton, LlmBody, LlmHeader } from './llm-components'; import ModalContextProvider, { useModalContext } from './modal-context-provider'; import ActionsStepFourth from './step-four/actions'; import BodyStepFour from './step-four/new-body'; @@ -59,7 +63,9 @@ function Header() { step, } = useModalContext(); - const { isFormInvalid: isFormInvalidStepOne } = useFormbitStepOne; + const { isFormInvalid: isFormInvalidStepOne, form } = useFormbitStepOne; + const modelType = form?.modelType; + const { isFormInvalid: isFormInvalidStepTwo } = useFormbitStepTwo; const { isFormInvalid: isFormInvalidStepThree } = useFormbitStepThree; const { isFormInvalid: isFormInvalidStepFour } = useFormbitStepFour; @@ -69,21 +75,27 @@ function Header() { || (step === 2 && isFormInvalidStepThree()) || (step === 3 && isFormInvalidStepFour()) ? 'error' : undefined; - return ( -
- + switch (modelType) { + case ModelTypeEnum.LLM: + return (); + + default: + return ( +
+ - - + + - + - + - - -
- ); + + +
+ ); + } } function Subtitles() { @@ -146,6 +158,21 @@ function Subtitles() { } function Body() { + const { useFormbitStepOne } = useModalContext(); + + const { form } = useFormbitStepOne; + const modelType = form?.modelType; + + switch (modelType) { + case ModelTypeEnum.LLM: + return ; + + default: + return ; + } +} + +function BodyInner() { const { step } = useModalContext(); switch (step) { @@ -165,6 +192,21 @@ function Body() { } function Actions() { + const { useFormbitStepOne } = useModalContext(); + + const { form } = useFormbitStepOne; + const modelType = form?.modelType; + + switch (modelType) { + case ModelTypeEnum.LLM: + return (); + + default: + return ; + } +} + +function ActionsInner() { const { step } = useModalContext(); switch (step) { diff --git a/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx b/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx new file mode 100644 index 00000000..721e7cf7 --- /dev/null +++ b/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx @@ -0,0 +1,148 @@ +import useAutoFocus from '@Src/hooks/use-auto-focus'; +import { + DataTypeEnum, DataTypeEnumLabel, GranularityEnum, GranularityEnumLabel, + ModelTypeEnum, + ModelTypeEnumLabel, +} from '@State/models/constants'; +import { + FormField, + Input, + Select, +} from '@radicalbit/radicalbit-design-system'; +import { useRef } from 'react'; +import { useModalContext } from '../modal-context-provider'; +import useHandleOnSubmit from './use-handle-on-submit'; + +function Name() { + const ref = useRef(null); + + const { handleOnSubmit } = useHandleOnSubmit(); + const { useFormbit } = useModalContext(); + const { form, error, write } = useFormbit; + + const handleOnChange = ({ target: { value } }) => { + write('name', value); + }; + + useAutoFocus(ref); + + return ( + + + + ); +} + +function ModelType() { + const { useFormbit } = useModalContext(); + const { form, write } = useFormbit; + + const handleOnChange = (value) => { + write('modelType', value); + }; + + const modelTypeSelections = [ + ModelTypeEnum.BINARY_CLASSIFICATION, + ModelTypeEnum.MULTI_CLASSIFICATION, + ModelTypeEnum.REGRESSION, + ModelTypeEnum.LLM, + ]; + + return ( + + + + ); +} + +function DataType() { + const { useFormbit } = useModalContext(); + const { error } = useFormbit; + + return ( + + {DataTypeEnumLabel[DataTypeEnum.TABULAR]} + + ); +} + +function Granularity() { + const { useFormbit } = useModalContext(); + const { form, error, write } = useFormbit; + + const handleOnChange = (value) => { + write('granularity', value); + }; + + return ( + + + + ); +} + +function Framework() { + const { handleOnSubmit } = useHandleOnSubmit(); + const { useFormbit } = useModalContext(); + const { form, error, write } = useFormbit; + + const handleOnChange = ({ target: { value } }) => { + write('frameworks', value); + }; + + return ( + + + + ); +} + +function Algorithm() { + const { handleOnSubmit } = useHandleOnSubmit(); + const { useFormbit } = useModalContext(); + const { form, error, write } = useFormbit; + + const handleOnChange = ({ target: { value } }) => { + write('algorithm', value); + }; + + return ( + + + + ); +} + +export { + Algorithm, + DataType, + Framework, + Granularity, + ModelType, + Name, +}; diff --git a/ui/src/components/modals/add-new-model/llm-components/index.jsx b/ui/src/components/modals/add-new-model/llm-components/index.jsx new file mode 100644 index 00000000..748ef9ba --- /dev/null +++ b/ui/src/components/modals/add-new-model/llm-components/index.jsx @@ -0,0 +1,59 @@ +import { Button, FormField, SectionTitle } from '@radicalbit/radicalbit-design-system'; +import { + Algorithm, DataType, Framework, Granularity, ModelType, Name, +} from './form-fields'; +import { useModalContext } from '../modal-context-provider'; +import useHandleOnSubmit from './use-handle-on-submit'; + +function LlmHeader() { + return ; +} + +function LlmBody() { + const { useFormbit } = useModalContext(); + const { error } = useFormbit; + + return ( +
+
+ + +
+ + + +
+ + + + + + + + +
+
+ + ); +} + +function LlmActionButton() { + const { handleOnSubmit, args, isSubmitDisabled } = useHandleOnSubmit(); + + return ( + <> +
+ + + + ); +} + +export { LlmHeader, LlmBody, LlmActionButton }; diff --git a/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js b/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js new file mode 100644 index 00000000..8b24cfb4 --- /dev/null +++ b/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js @@ -0,0 +1,59 @@ +import { globalConfigSliceActions } from '@State/global-configuration/slice'; +import { modelsApiSlice } from '@State/models/api'; +import { useDispatch } from 'react-redux'; +import { useNavigate } from 'react-router'; +import { useSearchParams } from 'react-router-dom'; +import { useModalContext } from '../modal-context-provider'; + +const { useAddNewModelMutation } = modelsApiSlice; + +export default () => { + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const dispatch = useDispatch(); + + const { useFormbit, useFormbitStepOne } = useModalContext(); + + const { isDirty, isFormInvalid, submitForm } = useFormbit; + const { form: formStepOne } = useFormbitStepOne; + + const [triggerAddNewModel, args] = useAddNewModelMutation(); + + const isSubmitDisabled = !isDirty || isFormInvalid(); + + const handleOnSubmit = () => { + if (isSubmitDisabled || args.isLoading) { + return; + } + + submitForm(async (_, setError) => { + const { + name, algorithm, frameworks, modelType, dataType, granularity, + } = formStepOne; + + const response = await triggerAddNewModel({ + name, + dataType, + modelType, + granularity, + algorithm, + frameworks, + }); + + if (response.error) { + console.error(response.error); + setError('silent.backed', response.error); + return; + } + + const newModelUUID = response.data.uuid; + + searchParams.delete('modal'); + dispatch(globalConfigSliceActions.addModelToShowConfettiList(newModelUUID)); + + navigate({ pathname: `models/${response.data.uuid}`, search: searchParams.toString() }); + }); + }; + + return { handleOnSubmit, args, isSubmitDisabled }; +}; diff --git a/ui/src/components/modals/add-new-model/step-one/form-fields.jsx b/ui/src/components/modals/add-new-model/step-one/form-fields.jsx index a0d7bb8f..18dcefe5 100644 --- a/ui/src/components/modals/add-new-model/step-one/form-fields.jsx +++ b/ui/src/components/modals/add-new-model/step-one/form-fields.jsx @@ -50,6 +50,7 @@ function ModelType() { ModelTypeEnum.BINARY_CLASSIFICATION, ModelTypeEnum.MULTI_CLASSIFICATION, ModelTypeEnum.REGRESSION, + ModelTypeEnum.LLM, ]; return ( diff --git a/ui/src/store/state/models/constants.js b/ui/src/store/state/models/constants.js index 51f9923c..9755e17f 100644 --- a/ui/src/store/state/models/constants.js +++ b/ui/src/store/state/models/constants.js @@ -2,6 +2,7 @@ export const ModelTypeEnum = { REGRESSION: 'REGRESSION', BINARY_CLASSIFICATION: 'BINARY', MULTI_CLASSIFICATION: 'MULTI_CLASS', + LLM: 'LLM', }; export const DataTypeEnum = { @@ -21,6 +22,7 @@ export const ModelTypeEnumLabel = { [ModelTypeEnum.REGRESSION]: 'Regression', [ModelTypeEnum.BINARY_CLASSIFICATION]: 'Binary Classification', [ModelTypeEnum.MULTI_CLASSIFICATION]: 'Multiclass Classification', + [ModelTypeEnum.LLM]: 'LLM', }; export const DataTypeEnumLabel = { From 139df063f4bcf7618159f61ce1a68ac4baa5995d Mon Sep 17 00:00:00 2001 From: dvalleri Date: Fri, 13 Dec 2024 12:21:58 +0100 Subject: [PATCH 2/4] feat(ui): add TEXT_GENERATION model create --- ui/src/components/modals/add-new-model/index.jsx | 6 +++--- .../modals/add-new-model/llm-components/form-fields.jsx | 4 ++-- .../add-new-model/llm-components/use-handle-on-submit.js | 5 +++-- .../modals/add-new-model/step-one/form-fields.jsx | 2 +- ui/src/store/state/models/constants.js | 4 ++-- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/ui/src/components/modals/add-new-model/index.jsx b/ui/src/components/modals/add-new-model/index.jsx index e9bc8e48..cecea5c7 100644 --- a/ui/src/components/modals/add-new-model/index.jsx +++ b/ui/src/components/modals/add-new-model/index.jsx @@ -76,7 +76,7 @@ function Header() { || (step === 3 && isFormInvalidStepFour()) ? 'error' : undefined; switch (modelType) { - case ModelTypeEnum.LLM: + case ModelTypeEnum.TEXT_GENERATION: return (); default: @@ -164,7 +164,7 @@ function Body() { const modelType = form?.modelType; switch (modelType) { - case ModelTypeEnum.LLM: + case ModelTypeEnum.TEXT_GENERATION: return ; default: @@ -198,7 +198,7 @@ function Actions() { const modelType = form?.modelType; switch (modelType) { - case ModelTypeEnum.LLM: + case ModelTypeEnum.TEXT_GENERATION: return (); default: diff --git a/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx b/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx index 721e7cf7..1be5b498 100644 --- a/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx +++ b/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx @@ -50,7 +50,7 @@ function ModelType() { ModelTypeEnum.BINARY_CLASSIFICATION, ModelTypeEnum.MULTI_CLASSIFICATION, ModelTypeEnum.REGRESSION, - ModelTypeEnum.LLM, + ModelTypeEnum.TEXT_GENERATION, ]; return ( @@ -72,7 +72,7 @@ function DataType() { return ( - {DataTypeEnumLabel[DataTypeEnum.TABULAR]} + {DataTypeEnumLabel[DataTypeEnum.TEXT]} ); } diff --git a/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js b/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js index 8b24cfb4..9db06eb5 100644 --- a/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js +++ b/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js @@ -3,6 +3,7 @@ import { modelsApiSlice } from '@State/models/api'; import { useDispatch } from 'react-redux'; import { useNavigate } from 'react-router'; import { useSearchParams } from 'react-router-dom'; +import { DataTypeEnum } from '@Src/store/state/models/constants'; import { useModalContext } from '../modal-context-provider'; const { useAddNewModelMutation } = modelsApiSlice; @@ -28,12 +29,12 @@ export default () => { submitForm(async (_, setError) => { const { - name, algorithm, frameworks, modelType, dataType, granularity, + name, algorithm, frameworks, modelType, granularity, } = formStepOne; const response = await triggerAddNewModel({ name, - dataType, + dataType: DataTypeEnum.TEXT, modelType, granularity, algorithm, diff --git a/ui/src/components/modals/add-new-model/step-one/form-fields.jsx b/ui/src/components/modals/add-new-model/step-one/form-fields.jsx index 18dcefe5..4266fc42 100644 --- a/ui/src/components/modals/add-new-model/step-one/form-fields.jsx +++ b/ui/src/components/modals/add-new-model/step-one/form-fields.jsx @@ -50,7 +50,7 @@ function ModelType() { ModelTypeEnum.BINARY_CLASSIFICATION, ModelTypeEnum.MULTI_CLASSIFICATION, ModelTypeEnum.REGRESSION, - ModelTypeEnum.LLM, + ModelTypeEnum.TEXT_GENERATION, ]; return ( diff --git a/ui/src/store/state/models/constants.js b/ui/src/store/state/models/constants.js index 9755e17f..cf1d5075 100644 --- a/ui/src/store/state/models/constants.js +++ b/ui/src/store/state/models/constants.js @@ -2,7 +2,7 @@ export const ModelTypeEnum = { REGRESSION: 'REGRESSION', BINARY_CLASSIFICATION: 'BINARY', MULTI_CLASSIFICATION: 'MULTI_CLASS', - LLM: 'LLM', + TEXT_GENERATION: 'TEXT_GENERATION', }; export const DataTypeEnum = { @@ -22,7 +22,7 @@ export const ModelTypeEnumLabel = { [ModelTypeEnum.REGRESSION]: 'Regression', [ModelTypeEnum.BINARY_CLASSIFICATION]: 'Binary Classification', [ModelTypeEnum.MULTI_CLASSIFICATION]: 'Multiclass Classification', - [ModelTypeEnum.LLM]: 'LLM', + [ModelTypeEnum.TEXT_GENERATION]: 'Text Generation', }; export const DataTypeEnumLabel = { From 6775cb22077562ff9ccb497f80f4ead9bc13f713 Mon Sep 17 00:00:00 2001 From: dvalleri Date: Fri, 13 Dec 2024 12:25:16 +0100 Subject: [PATCH 3/4] feat(ui): rename LLM into TextGeneration components --- ui/src/components/modals/add-new-model/index.jsx | 11 +++++++---- .../form-fields.jsx | 0 .../{llm-components => text-generation}/index.jsx | 8 ++++---- .../use-handle-on-submit.js | 0 4 files changed, 11 insertions(+), 8 deletions(-) rename ui/src/components/modals/add-new-model/{llm-components => text-generation}/form-fields.jsx (100%) rename ui/src/components/modals/add-new-model/{llm-components => text-generation}/index.jsx (86%) rename ui/src/components/modals/add-new-model/{llm-components => text-generation}/use-handle-on-submit.js (100%) diff --git a/ui/src/components/modals/add-new-model/index.jsx b/ui/src/components/modals/add-new-model/index.jsx index cecea5c7..4e0109d7 100644 --- a/ui/src/components/modals/add-new-model/index.jsx +++ b/ui/src/components/modals/add-new-model/index.jsx @@ -3,7 +3,6 @@ import { } from '@radicalbit/radicalbit-design-system'; import useModals from '@Src/hooks/use-modals'; import { ModelTypeEnum } from '@Src/store/state/models/constants'; -import { LlmActionButton, LlmBody, LlmHeader } from './llm-components'; import ModalContextProvider, { useModalContext } from './modal-context-provider'; import ActionsStepFourth from './step-four/actions'; import BodyStepFour from './step-four/new-body'; @@ -13,6 +12,10 @@ import ActionsStepThree from './step-three/actions'; import BodyStepThree from './step-three/body'; import ActionsStepTwo from './step-two/actions'; import BodyStepTwo from './step-two/body'; +import { + TextGenerationActionButton, TextGenerationBody, + TextGenerationHeader, +} from './text-generation'; const { Step } = Steps; @@ -77,7 +80,7 @@ function Header() { switch (modelType) { case ModelTypeEnum.TEXT_GENERATION: - return (); + return (); default: return ( @@ -165,7 +168,7 @@ function Body() { switch (modelType) { case ModelTypeEnum.TEXT_GENERATION: - return ; + return ; default: return ; @@ -199,7 +202,7 @@ function Actions() { switch (modelType) { case ModelTypeEnum.TEXT_GENERATION: - return (); + return (); default: return ; diff --git a/ui/src/components/modals/add-new-model/llm-components/form-fields.jsx b/ui/src/components/modals/add-new-model/text-generation/form-fields.jsx similarity index 100% rename from ui/src/components/modals/add-new-model/llm-components/form-fields.jsx rename to ui/src/components/modals/add-new-model/text-generation/form-fields.jsx diff --git a/ui/src/components/modals/add-new-model/llm-components/index.jsx b/ui/src/components/modals/add-new-model/text-generation/index.jsx similarity index 86% rename from ui/src/components/modals/add-new-model/llm-components/index.jsx rename to ui/src/components/modals/add-new-model/text-generation/index.jsx index 748ef9ba..4fd95b9b 100644 --- a/ui/src/components/modals/add-new-model/llm-components/index.jsx +++ b/ui/src/components/modals/add-new-model/text-generation/index.jsx @@ -5,11 +5,11 @@ import { import { useModalContext } from '../modal-context-provider'; import useHandleOnSubmit from './use-handle-on-submit'; -function LlmHeader() { +function TextGenerationHeader() { return ; } -function LlmBody() { +function TextGenerationBody() { const { useFormbit } = useModalContext(); const { error } = useFormbit; @@ -37,7 +37,7 @@ function LlmBody() { ); } -function LlmActionButton() { +function TextGenerationActionButton() { const { handleOnSubmit, args, isSubmitDisabled } = useHandleOnSubmit(); return ( @@ -56,4 +56,4 @@ function LlmActionButton() { ); } -export { LlmHeader, LlmBody, LlmActionButton }; +export { TextGenerationHeader, TextGenerationBody, TextGenerationActionButton }; diff --git a/ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js b/ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js similarity index 100% rename from ui/src/components/modals/add-new-model/llm-components/use-handle-on-submit.js rename to ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js From 0c8d78cbefffcf40c8d287225927dc098ef1cba1 Mon Sep 17 00:00:00 2001 From: dvalleri Date: Wed, 18 Dec 2024 15:30:56 +0100 Subject: [PATCH 4/4] feat(ui): add readonly on text-geneeration createModal --- .../text-generation/form-fields.jsx | 19 ++++++++++++++----- .../text-generation/use-handle-on-submit.js | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ui/src/components/modals/add-new-model/text-generation/form-fields.jsx b/ui/src/components/modals/add-new-model/text-generation/form-fields.jsx index 1be5b498..868a9f28 100644 --- a/ui/src/components/modals/add-new-model/text-generation/form-fields.jsx +++ b/ui/src/components/modals/add-new-model/text-generation/form-fields.jsx @@ -16,7 +16,7 @@ import useHandleOnSubmit from './use-handle-on-submit'; function Name() { const ref = useRef(null); - const { handleOnSubmit } = useHandleOnSubmit(); + const { handleOnSubmit, isSubmitDisabled } = useHandleOnSubmit(); const { useFormbit } = useModalContext(); const { form, error, write } = useFormbit; @@ -31,6 +31,7 @@ function Name() { @@ -42,6 +43,8 @@ function ModelType() { const { useFormbit } = useModalContext(); const { form, write } = useFormbit; + const { isSubmitDisabled } = useHandleOnSubmit(); + const handleOnChange = (value) => { write('modelType', value); }; @@ -55,7 +58,7 @@ function ModelType() { return ( - {Object.values(modelTypeSelections).map((value) => ( {ModelTypeEnumLabel[value]} @@ -81,13 +84,15 @@ function Granularity() { const { useFormbit } = useModalContext(); const { form, error, write } = useFormbit; + const { isSubmitDisabled } = useHandleOnSubmit(); + const handleOnChange = (value) => { write('granularity', value); }; return ( - {Object.values(GranularityEnum).map((value) => ( {GranularityEnumLabel[value]} @@ -99,10 +104,11 @@ function Granularity() { } function Framework() { - const { handleOnSubmit } = useHandleOnSubmit(); const { useFormbit } = useModalContext(); const { form, error, write } = useFormbit; + const { handleOnSubmit, isSubmitDisabled } = useHandleOnSubmit(); + const handleOnChange = ({ target: { value } }) => { write('frameworks', value); }; @@ -112,6 +118,7 @@ function Framework() { @@ -119,10 +126,11 @@ function Framework() { } function Algorithm() { - const { handleOnSubmit } = useHandleOnSubmit(); const { useFormbit } = useModalContext(); const { form, error, write } = useFormbit; + const { handleOnSubmit, isSubmitDisabled } = useHandleOnSubmit(); + const handleOnChange = ({ target: { value } }) => { write('algorithm', value); }; @@ -132,6 +140,7 @@ function Algorithm() { diff --git a/ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js b/ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js index 9db06eb5..d6b07502 100644 --- a/ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js +++ b/ui/src/components/modals/add-new-model/text-generation/use-handle-on-submit.js @@ -20,7 +20,7 @@ export default () => { const [triggerAddNewModel, args] = useAddNewModelMutation(); - const isSubmitDisabled = !isDirty || isFormInvalid(); + const isSubmitDisabled = !isDirty || isFormInvalid() || args.isLoading; const handleOnSubmit = () => { if (isSubmitDisabled || args.isLoading) {