diff --git a/apps/server/services/schedule.py b/apps/server/services/schedule.py index 20ae22bf3..bbcdb0c4a 100644 --- a/apps/server/services/schedule.py +++ b/apps/server/services/schedule.py @@ -1,6 +1,6 @@ from datetime import datetime, timedelta -import arrow +# import arrow from fastapi_sqlalchemy import db from models.chat import ChatModel diff --git a/apps/ui/package.json b/apps/ui/package.json index 26e6f08da..30fb248a3 100644 --- a/apps/ui/package.json +++ b/apps/ui/package.json @@ -44,6 +44,7 @@ "notistack": "^2.0.5", "npm": "^9.6.2", "openai": "^3.2.1", + "papaparse": "^5.4.1", "react": "^18.2.0", "react-avatar": "^5.0.3", "react-cookie": "^4.1.1", diff --git a/apps/ui/src/components/ImportFile/ImportFile.tsx b/apps/ui/src/components/ImportFile/ImportFile.tsx index 7dcad047f..5fc19ba05 100644 --- a/apps/ui/src/components/ImportFile/ImportFile.tsx +++ b/apps/ui/src/components/ImportFile/ImportFile.tsx @@ -14,12 +14,13 @@ import { t } from 'i18next' const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?: string }) => { const { - // handleFileChange, step, parsedData, setStep, handleUploadJson, - handleConvertData, + handleConvertJson, + handleUploadCsv, + handleConvertCSVtoJSON, fileIsLoading, } = useImportFile({ setFieldValue: setFieldValue, @@ -29,7 +30,6 @@ const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?: useEffect(() => { if (value.length > 0) { - // Replace 'fileUrl' with the actual URL of the file you want to read. const fileUrl = value fetch(fileUrl) @@ -37,10 +37,14 @@ const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?: if (!response.ok) { throw new Error(`Failed to fetch file: ${response.status} ${response.statusText}`) } - return response.text() // or response.json() for JSON files, response.blob() for binary files, etc. + return response.text() }) .then(data => { - handleConvertData(data) // Update the state with the file content + if (fileUrl.endsWith('.json')) { + handleConvertJson(data) + } else if (fileUrl.endsWith('.csv')) { + handleConvertCSVtoJSON(data) + } }) .catch(error => { console.error('Error fetching file:', error) @@ -57,7 +61,7 @@ const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?: {t('download-template')} - {/* */} + { const { handleDownloadTemplate } = useDownloadTemplate() - const { formik, keys, options, step, response, setStep } = useReviewImport(data) + const { formik, step, response, setStep } = useReviewImport(data) const columns = [ { @@ -57,9 +57,9 @@ const ReviewImport = ({ data, setStep: startOver }: { data: any[]; setStep: any {/* Save */} - startOver(0)} size={Button.sizes.SMALL}> + startOver(0)} size={Button.sizes.SMALL}> {t('start-over')} - + {/* {keys.map((item: any, index: number) => ( diff --git a/apps/ui/src/components/ImportFile/useImportFile.ts b/apps/ui/src/components/ImportFile/useImportFile.ts index b8564f411..dabd9d298 100644 --- a/apps/ui/src/components/ImportFile/useImportFile.ts +++ b/apps/ui/src/components/ImportFile/useImportFile.ts @@ -1,6 +1,7 @@ import { ToastContext } from 'contexts' import useUploadFile from 'hooks/useUploadFile' import React, { useContext } from 'react' +import Papa from 'papaparse' const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => { const { setToast } = useContext(ToastContext) @@ -11,7 +12,7 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => { const { uploadFile } = useUploadFile() - const handleConvertData = (data: any) => { + const handleConvertJson = (data: any) => { const dataArray = JSON.parse(data) const convertedData = dataArray.map((item: any) => ({ System: item.System, @@ -22,21 +23,17 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => { setStep(1) } - const handleUploadJson = async (e: any) => { - setFileIsLoading(true) - const { files } = e.target + const handleConvertCSVtoJSON = (csvString: string) => { + const { data, errors } = Papa.parse(csvString, { + header: true, // Set this to true if the CSV file has a header row + skipEmptyLines: true, // Skip empty lines in CSV + }) - if (!files) return - - const file = files[0] - - if (file.type !== 'application/json') - return setToast({ - message: 'File must be JSON!', - type: 'negative', - open: true, - }) + setParsedData(data) + setStep(1) + } + const handleUploadFile = async (files: any) => { const promises = [] for (const file of files) { @@ -55,57 +52,62 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => { const uploadedFiles = await Promise.all(promises) setFieldValue('fine_tuning_file_url', uploadedFiles?.[0].url) + } - if (file) { - const reader = new FileReader() - reader.onload = (e: any) => { - const data = e.target.result - - handleConvertData(data) - } - reader.readAsText(file) - } + const handleUploadJson = async (event: any) => { + const { files } = event.target + const file = files[0] - setFileIsLoading(false) - } + if (file.type !== 'application/json') + return setToast({ + message: 'File must be JSON!', + type: 'negative', + open: true, + }) - const handleFileChange = async (e: any) => { - const { files } = e.target + handleUploadFile(files) - if (!files) return + const reader = new FileReader() - const promises = [] + reader.onload = (event: any) => { + const data = event.target.result - for (const file of files) { - promises.push( - uploadFile( - { - name: file.name, - type: file.type, - size: file.size, - }, - file, - ), - ) + handleConvertJson(data) } + reader.readAsText(file) + } - const uploadedFiles = await Promise.all(promises) + const handleUploadCsv = async (event: any) => { + const { files } = event.target + const file = files[0] - setFieldValue('fine_tuning_file_url', uploadedFiles?.[0].url) + if (file.type !== 'text/csv') + return setToast({ + message: 'File must be CSV!', + type: 'negative', + open: true, + }) - // const response = await parseCsvToJson(files[0], []) - // console.log('response', response) - // setParsedData() - setStep(1) + handleUploadFile(files) + + const reader = new FileReader() + + reader.onload = (event: any) => { + const csvString = event.target.result + handleConvertCSVtoJSON(csvString) + } + + reader.readAsText(file) } return { - handleFileChange, + handleUploadCsv, handleUploadJson, step, parsedData, setStep, - handleConvertData, + handleConvertJson, + handleConvertCSVtoJSON, fileIsLoading, } } diff --git a/apps/ui/src/components/Table/Table.tsx b/apps/ui/src/components/Table/Table.tsx index b0c7bfee2..b271eb690 100644 --- a/apps/ui/src/components/Table/Table.tsx +++ b/apps/ui/src/components/Table/Table.tsx @@ -26,7 +26,7 @@ const Table = ({ columns, data }: TableProps) => { const defaultColumn = useMemo( () => ({ width: 300, - minWidth: 100, + // minWidth: 100, // maxWidth: 100, }), [], @@ -34,13 +34,13 @@ const Table = ({ columns, data }: TableProps) => { const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = useTable( { + defaultColumn, columns, data, - defaultColumn, }, - useResizeColumns, useFlexLayout, useBlockLayout, + useResizeColumns, ) return ( @@ -55,6 +55,7 @@ const Table = ({ columns, data }: TableProps) => { {...column.getHeaderProps()} {...column.getResizerProps()} minWidth={column.minWidth} + maxWidth={column.maxWidth} width={column.width} > ) => void @@ -27,9 +27,9 @@ const UploadButton = ({ onChange, isLoading, label }: UploadButtonProps) => { {isLoading ? ( ) : label ? ( - + {label} - + ) : ( - - = 1 ? value : `${t('please-enter-value')}`} - options={options} - onChange={onChangeFunction} - onOptionRemove={onOptionRemove} - OptionRenderer={OptionRenderer} - // menuIsOpen={true} - /> - + + {(formik: any) => { + const { meta } = formik + + return ( + + + = 1 ? value : `${t('please-enter-value')}`} + options={options} + onChange={onChangeFunction} + onOptionRemove={onOptionRemove} + OptionRenderer={OptionRenderer} + // menuIsOpen={true} + /> + + {meta?.error && {meta?.error}} + + ) + }} + ) } export default AgentDropdown //todo update dropdown styles in storybook -const StyledWrapper = styled.div` +const StyledWrapper = styled.div<{ isValidationError: boolean }>` display: flex; flex-direction: column; - gap: 10px; + gap: 5px; width: 100%; .css-xrcw8y-container { border: 3px solid ${({ theme }) => theme.body.textareaBorder}; @@ -98,6 +113,9 @@ const StyledWrapper = styled.div` .css-ugu73m-placeholder { color: ${({ theme }) => theme.body.placeHolderColor}; } + .menu { + z-index: 10; + } .menu.dropdown-menu-wrapper.css-19zapvn-menu { background: ${({ theme }) => theme.body.toolkitCardBgColorSecondary}; @@ -111,7 +129,6 @@ const StyledWrapper = styled.div` background: ${({ theme }) => theme.body.placeHolderColor}; } } - .clear-indicator.css-1rycjgo { path { fill: ${({ theme }) => theme.body.iconColor}; @@ -149,7 +166,22 @@ const StyledWrapper = styled.div` border: 3px solid ${({ theme }) => theme.body.textareaBorder}; height: auto; } + .css-ugu73m-placeholder { color: ${({ theme }) => theme.body.textColorPrimary}; } + + ${p => + p.isValidationError && + css` + .dropdown-wrapper.primary__wrapper.css-7xl64p-container { + border: 4px solid #ef5533; + } + `}; +` + +//todo we need dropdown validation styles in storybook +const StyledError = styled.div` + color: #e44258; + font-size: 14px; ` diff --git a/apps/ui/src/pages/Discover/Discover.tsx b/apps/ui/src/pages/Discover/Discover.tsx index a98a3a78c..f55181ade 100644 --- a/apps/ui/src/pages/Discover/Discover.tsx +++ b/apps/ui/src/pages/Discover/Discover.tsx @@ -84,7 +84,7 @@ const Discover = () => { export default Discover -const StyledRoot = styled.div` +export const StyledRoot = styled.div` display: flex; flex-direction: column; gap: 100px; diff --git a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/CreateFineTuningForm.tsx b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/CreateFineTuningForm.tsx index 018d41b6e..01a55523d 100644 --- a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/CreateFineTuningForm.tsx +++ b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/CreateFineTuningForm.tsx @@ -19,7 +19,15 @@ import FineTuningForm from './FineTuningForm' import { StyledFormWrapper } from 'styles/formStyles.css' const CreateFineTuningForm = () => { - const { formik, isLoading } = useCreateFineTuning() + const { formik, isLoading, handleErrorAlert } = useCreateFineTuning() + + const handleFormSubmit = () => { + if (formik?.errors?.fine_tuning_file_url) { + handleErrorAlert(`${formik?.errors?.fine_tuning_file_url}!`) + } else { + formik?.handleSubmit() + } + } return ( @@ -33,7 +41,7 @@ const CreateFineTuningForm = () => { diff --git a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/EditFineTuningForm.tsx b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/EditFineTuningForm.tsx index ead4fcc38..7e81984db 100644 --- a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/EditFineTuningForm.tsx +++ b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/EditFineTuningForm.tsx @@ -18,10 +18,18 @@ import { StyledFormWrapper } from 'styles/formStyles.css' import { useEditFineTuning } from '../useEditFineTuning' const EditFineTuningForm = () => { - const { formik, isLoading } = useEditFineTuning() + const { formik, isLoading, handleErrorAlert } = useEditFineTuning() if (!formik?.values) return
+ const handleFormSubmit = () => { + if (formik?.errors?.fine_tuning_file_url) { + handleErrorAlert(`${formik?.errors?.fine_tuning_file_url}!`) + } else { + formik?.handleSubmit() + } + } + return ( @@ -34,7 +42,7 @@ const EditFineTuningForm = () => { diff --git a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/FineTuningForm.tsx b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/FineTuningForm.tsx index 0b2f31371..749a4f9b2 100644 --- a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/FineTuningForm.tsx +++ b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/FineTuningForm.tsx @@ -1,32 +1,14 @@ -import { - StyledForm, - StyledInputWrapper, - StyledRoot, -} from 'pages/Schedule/ScheduleFrom/ScheduleForm' +import { StyledForm, StyledInputWrapper } from 'pages/Schedule/ScheduleFrom/ScheduleForm' import FormikTextField from 'components/TextFieldFormik' import ImportFile from 'components/ImportFile' -import TypographyPrimary from 'components/Typography/Primary' -import Typography from '@l3-lib/ui-core/dist/Typography' import { useFineTuningForm } from './useFineTuningForm' import { t } from 'i18next' import AgentDropdown from 'pages/Agents/AgentForm/components/AgentDropdown' -import { useState } from 'react' -import { - StyledFormTabList, - StyledFormTabsWrapper, - StyledTab, - StyledSpan, - StyledTabPanelInnerWrapper, -} from 'pages/Agents/AgentForm/AgentForm' -import { StyledFormRoot } from 'styles/formStyles.css' -import Tab from '@l3-lib/ui-core/dist/Tab' -import TabList from '@l3-lib/ui-core/dist/TabList' -import TabPanel from '@l3-lib/ui-core/dist/TabPanel' -import TabPanels from '@l3-lib/ui-core/dist/TabPanels' -import TabsContext from '@l3-lib/ui-core/dist/TabsContext' +import { StyledFormRoot } from 'styles/formStyles.css' +import { useEffect } from 'react' const FineTuningForm = ({ formik }: { formik: any }) => { const { setFieldValue, values } = formik @@ -34,47 +16,31 @@ const FineTuningForm = ({ formik }: { formik: any }) => { const { modelOptions } = useFineTuningForm() - const [activeTab, setActiveTab] = useState(0) + useEffect(() => { + if (fine_tuning_model === '' && modelOptions?.length > 0) { + setFieldValue('fine_tuning_model', modelOptions[0].value) + } + }, [fine_tuning_model]) return ( - - - setActiveTab(0)}> - General - - setActiveTab(1)}> - Data - - - - - - - - - - - { - setFieldValue('fine_tuning_model', '') - }} - optionSize={'small'} - /> - - - - - - - + + + { + setFieldValue('fine_tuning_model', '') + }} + optionSize={'small'} + /> + + diff --git a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/useFineTuningForm.ts b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/useFineTuningForm.ts index c2db12c47..6ce3a4de7 100644 --- a/apps/ui/src/pages/Models/FineTuning/FineTuningForm/useFineTuningForm.ts +++ b/apps/ui/src/pages/Models/FineTuning/FineTuningForm/useFineTuningForm.ts @@ -3,10 +3,12 @@ import { useModelsService } from 'services' export const useFineTuningForm = () => { const { data: models } = useModelsService() - const modelOptions = models?.map(({ id, name, provider }) => ({ - value: id, - label: `${name} (${provider})`, - })) + const modelOptions = models + ?.filter((model: any) => model.fine_tuning === true) + ?.map(({ id, name, provider }) => ({ + value: id, + label: `${name} (${provider})`, + })) return { modelOptions, diff --git a/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx b/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx index 6efd5159c..5557240a8 100644 --- a/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx +++ b/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx @@ -1,3 +1,6 @@ +import { useMemo } from 'react' +import styled from 'styled-components' + import ComponentsWrapper from 'components/ComponentsWrapper/ComponentsWrapper' import { useTranslation } from 'react-i18next' import { @@ -7,15 +10,23 @@ import { StyledSectionWrapper, } from 'pages/Home/homeStyle.css' -import { StyledCardsWrapper } from 'pages/Agents/Agents' import { ButtonPrimary } from 'components/Button/Button' + import Button from '@l3-lib/ui-core/dist/Button' +import IconButton from '@l3-lib/ui-core/dist/IconButton' import { useNavigate } from 'react-router-dom' -import TempCard from 'pages/Schedule/TempCard' + +import { StyledCardsWrapper } from 'pages/Agents/Agents' import { useFineTuning } from './useFineTuning' import { useFineTuningForm } from './FineTuningForm/useFineTuningForm' +import Table from 'components/Table' +import { + StyledDeleteIcon, + StyledEditIcon, +} from 'pages/TeamOfAgents/TeamOfAgentsCard/TeamOfAgentsCard' + const FineTunings = () => { const { t } = useTranslation() @@ -27,7 +38,61 @@ const FineTunings = () => { const { fineTuningData, deleteFineTuningHandler } = useFineTuning() const { modelOptions } = useFineTuningForm() - console.log('fineTuningData', fineTuningData) + + const columns = useMemo( + () => [ + { + Header: 'Name', + accessor: 'name', + }, + { + Header: 'Model', + accessor: 'model', + }, + { + Header: 'Status', + accessor: 'status', + width: 250, + }, + + { + Header: 'Actions', + accessor: 'id', + width: 250, + Cell: ({ cell }: any) => { + return ( + + deleteFineTuningHandler(cell.value)} + icon={() => } + size={IconButton.sizes.SMALL} + kind={IconButton.kinds.TERTIARY} + // ariaLabel='Delete' + /> + + navigate(`/models/${cell.value}/edit-fine-tuning`)} + icon={() => } + size={IconButton.sizes.SMALL} + kind={IconButton.kinds.TERTIARY} + // ariaLabel='Edit' + /> + + ) + }, + }, + ], + [], + ) + + const tableData = + fineTuningData?.map((fineTuning: any) => ({ + id: fineTuning.id, + name: fineTuning.name, + status: fineTuning.status, + model: modelOptions?.filter((model: any) => model.value === fineTuning.model_id)?.[0].label, + })) || [] + return ( @@ -42,29 +107,7 @@ const FineTunings = () => { - {fineTuningData?.map((fineTuning: any, index: number) => { - const handleDelete = () => { - deleteFineTuningHandler(fineTuning.id) - } - - const handleEdit = () => { - navigate(`/models/${fineTuning.id}/edit-fine-tuning`) - } - - const filteredModel = modelOptions?.filter( - (model: any) => model.value === fineTuning.model_id, - )?.[0] - - return ( - - ) - })} + @@ -72,3 +115,10 @@ const FineTunings = () => { } export default FineTunings + +const StyledTableButtons = styled.div` + display: flex; + align-items: center; + + height: 100%; +` diff --git a/apps/ui/src/pages/Models/FineTuning/useCreateFineTuning.ts b/apps/ui/src/pages/Models/FineTuning/useCreateFineTuning.ts index b6187b970..6e52fee86 100644 --- a/apps/ui/src/pages/Models/FineTuning/useCreateFineTuning.ts +++ b/apps/ui/src/pages/Models/FineTuning/useCreateFineTuning.ts @@ -5,6 +5,7 @@ import { useContext, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useCreateFineTuningService } from 'services/fineTuning/useCreateFineTuningService' import { useFineTuningsService } from 'services/fineTuning/useFIneTuningsService' +import { fineTuningValidationSchema } from 'utils/validationsSchema' export const useCreateFineTuning = () => { const navigate = useNavigate() @@ -22,6 +23,14 @@ export const useCreateFineTuning = () => { fine_tuning_model: '', } + const handleErrorAlert = (errorMessage: string) => { + setToast({ + message: errorMessage, + type: 'negative', + open: true, + }) + } + const handleSubmit = async (values: any) => { setIsLoading(true) @@ -41,11 +50,7 @@ export const useCreateFineTuning = () => { open: true, }) } catch (e) { - setToast({ - message: 'Failed to create Fine-tuning!', - type: 'negative', - open: true, - }) + handleErrorAlert('Failed to create Fine-tuning!') } setIsLoading(false) @@ -54,9 +59,9 @@ export const useCreateFineTuning = () => { const formik = useFormik({ initialValues: initialValues, onSubmit: async values => handleSubmit(values), - // validationSchema: agentValidationSchema, + validationSchema: fineTuningValidationSchema, // enableReinitialize: true, }) - return { isLoading, formik } + return { isLoading, formik, handleErrorAlert } } diff --git a/apps/ui/src/pages/Models/FineTuning/useEditFineTuning.ts b/apps/ui/src/pages/Models/FineTuning/useEditFineTuning.ts index 71dfa1dc6..86289fb5d 100644 --- a/apps/ui/src/pages/Models/FineTuning/useEditFineTuning.ts +++ b/apps/ui/src/pages/Models/FineTuning/useEditFineTuning.ts @@ -5,6 +5,7 @@ import { useNavigate, useParams } from 'react-router-dom' import { useFineTuningByIdService } from 'services/fineTuning/useFineTuningByIdService' import { useFineTuningsService } from 'services/fineTuning/useFIneTuningsService' import { useUpdateFineTuningService } from 'services/fineTuning/useUpdateFineTuningService' +import { fineTuningValidationSchema } from 'utils/validationsSchema' export const useEditFineTuning = () => { const { setToast } = useContext(ToastContext) @@ -25,6 +26,14 @@ export const useEditFineTuning = () => { fine_tuning_model: fineTuningById?.model_id, } + const handleErrorAlert = (errorMessage: string) => { + setToast({ + message: errorMessage, + type: 'negative', + open: true, + }) + } + const handleSubmit = async (values: any) => { setIsLoading(true) try { @@ -44,11 +53,7 @@ export const useEditFineTuning = () => { }) navigate('/models') } catch (e) { - setToast({ - message: 'Failed To Update Fine-Tuning!', - type: 'negative', - open: true, - }) + handleErrorAlert('Failed To Update Fine-Tuning!') } setIsLoading(false) } @@ -56,12 +61,13 @@ export const useEditFineTuning = () => { const formik = useFormik({ initialValues: defaultValues, enableReinitialize: true, - // validationSchema: groupValidationSchema, + validationSchema: fineTuningValidationSchema, onSubmit: async values => handleSubmit(values), }) return { formik, isLoading, + handleErrorAlert, } } diff --git a/apps/ui/src/pages/Models/Models.tsx b/apps/ui/src/pages/Models/Models.tsx index b13b26785..78269a116 100644 --- a/apps/ui/src/pages/Models/Models.tsx +++ b/apps/ui/src/pages/Models/Models.tsx @@ -14,7 +14,8 @@ import { MODEL_PROVIDER_LOGOS } from './constants' import { StyledCardsWrapper } from 'pages/Agents/Agents' import FineTunings from './FineTuning/FineTunings' -import styled from 'styled-components' + +import { StyledRoot } from 'pages/Discover/Discover' const Models = ({ isPublic }: { isPublic?: boolean }) => { const { t } = useTranslation() @@ -60,9 +61,3 @@ const Models = ({ isPublic }: { isPublic?: boolean }) => { } export default Models - -const StyledRoot = styled.div` - display: flex; - flex-direction: column; - gap: 30px; -` diff --git a/apps/ui/src/plugins/contact/pages/Group/Groups.tsx b/apps/ui/src/plugins/contact/pages/Group/Groups.tsx index 0378b0ffb..6bcc5a0a4 100644 --- a/apps/ui/src/plugins/contact/pages/Group/Groups.tsx +++ b/apps/ui/src/plugins/contact/pages/Group/Groups.tsx @@ -39,16 +39,17 @@ const Groups = () => { { Header: 'Name', accessor: 'name', + width: 400, }, { Header: 'Description', accessor: 'description', + width: 400, }, - { Header: 'Actions', accessor: 'id', - // maxWidth: 100, + width: 300, Cell: ({ cell }: any) => { return ( diff --git a/apps/ui/src/utils/validationsSchema.ts b/apps/ui/src/utils/validationsSchema.ts index d451d6d65..3b3645aeb 100644 --- a/apps/ui/src/utils/validationsSchema.ts +++ b/apps/ui/src/utils/validationsSchema.ts @@ -54,3 +54,13 @@ export const scheduleValidationSchema = yup.object().shape({ } }), }) + +export const fineTuningValidationSchema = yup.object().shape({ + fine_tuning_name: yup + .string() + .min(2, 'Too Short!') + .max(50, 'Too Long!') + .required('Please enter name'), + fine_tuning_model: yup.string().required('Please pick Model'), + fine_tuning_file_url: yup.string().required('Please Upload File'), +}) diff --git a/apps/ui/yarn.lock b/apps/ui/yarn.lock index 66ac11bed..49837dba6 100644 --- a/apps/ui/yarn.lock +++ b/apps/ui/yarn.lock @@ -8148,6 +8148,11 @@ pacote@^15.0.0, pacote@^15.0.8, pacote@^15.1.1: ssri "^10.0.0" tar "^6.1.11" +papaparse@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.4.1.tgz#f45c0f871853578bd3a30f92d96fdcfb6ebea127" + integrity sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"