diff --git a/src/components/seal-form/auto-complete-cascader.tsx b/src/components/seal-form/auto-complete-cascader.tsx new file mode 100644 index 00000000..9d1f6d39 --- /dev/null +++ b/src/components/seal-form/auto-complete-cascader.tsx @@ -0,0 +1,75 @@ +import { Cascader, Input, Popover } from 'antd'; +import React, { useEffect, useRef, useState } from 'react'; + +const { Panel } = Cascader; + +const options = [ + { + value: 'fruit', + label: 'Fruit', + children: [ + { value: 'apple', label: 'Apple' }, + { value: 'banana', label: 'Banana' } + ] + }, + { + value: 'vegetable', + label: 'Vegetable', + children: [ + { value: 'carrot', label: 'Carrot' }, + { value: 'potato', label: 'Potato' } + ] + } +]; + +const CustomCascader: React.FC = () => { + const [value, setValue] = useState(''); + const [visible, setVisible] = useState(false); + const [inputWidth, setInputWidth] = useState(0); + const inputRef = useRef(null); + + useEffect(() => { + if (inputRef.current) { + setInputWidth(inputRef.current.offsetWidth); + } + }, []); + + const handleCascaderChange = (selectedValues: string[]) => { + setValue(selectedValues.join(' / ')); + setVisible(false); + }; + + const handleInputChange = (e: React.ChangeEvent) => { + setValue(e.target.value); + }; + + return ( + + + + } + arrow={false} + placement="bottomLeft" + trigger="click" + open={visible} + onOpenChange={setVisible} + > + setVisible(true)} + /> + + ); +}; + +export default CustomCascader; diff --git a/src/components/seal-form/components/wrapper.less b/src/components/seal-form/components/wrapper.less index 97c4292b..1e36fca4 100644 --- a/src/components/seal-form/components/wrapper.less +++ b/src/components/seal-form/components/wrapper.less @@ -262,7 +262,9 @@ } } - :global(.ant-select.ant-cascader .ant-select-selection-search) { + :global( + .ant-select.ant-select-multiple.ant-cascader .ant-select-selection-search + ) { top: 0 !important; } diff --git a/src/components/seal-form/seal-cascader.tsx b/src/components/seal-form/seal-cascader.tsx index b128f8b4..bc8fdc83 100644 --- a/src/components/seal-form/seal-cascader.tsx +++ b/src/components/seal-form/seal-cascader.tsx @@ -1,15 +1,78 @@ import { isNotEmptyValue } from '@/utils/index'; import { useIntl } from '@umijs/max'; import type { CascaderAutoProps } from 'antd'; -import { Cascader, Form } from 'antd'; -import { cloneDeep } from 'lodash'; -import { useEffect, useMemo, useRef, useState } from 'react'; +import { Cascader, Empty, Form } from 'antd'; +import _, { cloneDeep } from 'lodash'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import AutoTooltip from '../auto-tooltip'; import Wrapper from './components/wrapper'; import { SealFormItemProps } from './types'; -const SealCascader: React.FC = ( - props -) => { +const tag = (props: any) => { + if (props.isMaxTag) { + return props.label; + } + const parent = _.split(props.value, '__RC_CASCADER_SPLIT__')?.[0]; + return `${parent} / ${props?.label}`; +}; + +const renderTag = (props: any) => { + return ( + + {tag(props)} + + ); +}; + +const OptionNodes = (props: { + data: any; + optionNode: React.FC<{ data: any }>; +}) => { + const intl = useIntl(); + const { data, optionNode: OptionNode } = props; + if (data.value === '__EMPTY__') { + return ( + + ); + } + let width: any = { + maxWidth: 140, + minWidth: 140 + }; + if (!data.parent) { + width = undefined; + } + if (data.parent) { + return ( + + {data.label} + + ); + } + return OptionNode ? : data.label; +}; + +const SealCascader: React.FC< + CascaderAutoProps & + SealFormItemProps & { optionNode?: React.FC<{ data: any }> } +> = (props) => { const { label, placeholder, @@ -19,6 +82,8 @@ const SealCascader: React.FC = ( options, allowNull, isInFormItems = true, + optionNode, + tagRender, ...rest } = props; const intl = useIntl(); @@ -100,6 +165,14 @@ const SealCascader: React.FC = ( > ( + + ) + : undefined + } + tagRender={tagRender ?? renderTag} ref={inputRef} options={children ? null : _options} onFocus={handleOnFocus} diff --git a/src/components/status-tag/index.less b/src/components/status-tag/index.less index 4012dee1..e3cb80dd 100644 --- a/src/components/status-tag/index.less +++ b/src/components/status-tag/index.less @@ -7,7 +7,7 @@ border-radius: 20px; min-width: 76px; width: max-content; - height: 26px; + height: 24px; font-size: var(--font-size-base); overflow: hidden; diff --git a/src/hooks/use-app-utils.ts b/src/hooks/use-app-utils.ts index 7a1ec2c1..78015a1c 100644 --- a/src/hooks/use-app-utils.ts +++ b/src/hooks/use-app-utils.ts @@ -1,7 +1,9 @@ import { useIntl } from '@umijs/max'; +import { message } from 'antd'; const useAppUtils = () => { const intl = useIntl(); + const [messageApi, contextHolder] = message.useMessage(); const getRuleMessage = ( type: 'input' | 'select', @@ -22,8 +24,15 @@ const useAppUtils = () => { ); }; + const showSuccess = (msg?: string) => { + messageApi.success( + msg || intl.formatMessage({ id: 'common.message.success' }) + ); + }; + return { - getRuleMessage + getRuleMessage, + showSuccess }; }; diff --git a/src/hooks/use-table-fetch.ts b/src/hooks/use-table-fetch.ts index fd331a7c..81d9b757 100644 --- a/src/hooks/use-table-fetch.ts +++ b/src/hooks/use-table-fetch.ts @@ -1,15 +1,21 @@ +import useSetChunkRequest from '@/hooks/use-chunk-request'; import useTableRowSelection from '@/hooks/use-table-row-selection'; import useTableSort from '@/hooks/use-table-sort'; +import useUpdateChunkedList from '@/hooks/use-update-chunk-list'; import { handleBatchRequest } from '@/utils'; import _ from 'lodash'; +import qs from 'query-string'; import { useEffect, useRef, useState } from 'react'; export default function useTableFetch(options: { + API?: string; + watch?: boolean; fetchAPI: (params: any) => Promise>; deleteAPI?: (id: number) => Promise; contentForDelete?: string; }) { - const { fetchAPI, deleteAPI, contentForDelete } = options; + const { fetchAPI, deleteAPI, contentForDelete, API, watch } = options; + const chunkRequedtRef = useRef(null); const modalRef = useRef(null); const rowSelection = useTableRowSelection(); const { sortOrder, setSortOrder } = useTableSort({ @@ -33,6 +39,44 @@ export default function useTableFetch(options: { search: '' }); + const { setChunkRequest } = useSetChunkRequest(); + const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({ + events: ['UPDATE'], + dataList: dataSource.dataList, + setDataList(list, opts?: any) { + setDataSource((pre) => { + return { + total: pre.total, + loading: false, + loadend: true, + dataList: list, + deletedIds: opts?.deletedIds || [] + }; + }); + } + }); + + const updateHandler = (list: any) => { + _.each(list, (data: any) => { + updateChunkedList(data); + }); + }; + + const createModelsChunkRequest = async (params?: any) => { + if (!API || !watch) return; + chunkRequedtRef.current?.current?.cancel?.(); + try { + const query = _.omit(params || queryParams, ['page', 'perPage']); + + chunkRequedtRef.current = setChunkRequest({ + url: `${API}?${qs.stringify(_.pickBy(query, (val: any) => !!val))}`, + handler: updateHandler + }); + } catch (error) { + // ignore + } + }; + const fetchData = async (params?: { query: any }) => { const { query } = params || {}; setDataSource((pre) => { @@ -79,13 +123,12 @@ export default function useTableFetch(options: { fetchData(); }; - const handleNameChange = (e: any) => { + const debounceUpdateFilter = _.debounce((e: any) => { setQueryParams({ ...queryParams, page: 1, search: e.target.value }); - fetchData({ query: { ...queryParams, @@ -93,7 +136,13 @@ export default function useTableFetch(options: { search: e.target.value } }); - }; + createModelsChunkRequest({ + ...queryParams, + search: e.target.value + }); + }, 350); + + const handleNameChange = debounceUpdateFilter; const handleDelete = (row: ListItem & { name: string; id: number }) => { modalRef.current.show({ @@ -123,7 +172,17 @@ export default function useTableFetch(options: { }; useEffect(() => { - fetchData(); + const init = async () => { + await fetchData(); + setTimeout(() => { + createModelsChunkRequest(); + }, 200); + }; + init(); + return () => { + chunkRequedtRef.current?.cancel?.(); + cacheDataListRef.current = []; + }; }, []); return { diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index c55ccc69..e7070f60 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -55,5 +55,10 @@ export default { 'Select a label to generate the command and copy it using the copy button.', 'resources.worker.script.install': 'Script Installation', 'resources.worker.container.install': 'Container Installation(Linux Only)', - 'resources.worker.cann.tips': `Set ASCEND_VISIBLE_DEVICES to the required GPU indices. For GPU0 to GPU3, use ASCEND_VISIBLE_DEVICES=0,1,2,3 or ASCEND_VISIBLE_DEVICES=0-3.` + 'resources.worker.cann.tips': `Set ASCEND_VISIBLE_DEVICES to the required GPU indices. For GPU0 to GPU3, use ASCEND_VISIBLE_DEVICES=0,1,2,3 or ASCEND_VISIBLE_DEVICES=0-3.`, + 'resources.modelfiles.form.path': 'Storage path', + 'resources.modelfiles.modelfile': 'Model File', + 'resources.modelfiles.download': 'Download Model', + 'resources.modelfiles.size': 'Size', + 'resources.modelfiles.selecttarget': 'Select Target' }; diff --git a/src/locales/ru-RU/resources.ts b/src/locales/ru-RU/resources.ts index 95fe894f..b2f78d07 100644 --- a/src/locales/ru-RU/resources.ts +++ b/src/locales/ru-RU/resources.ts @@ -55,6 +55,18 @@ export default { 'Выберите метку для генерации команды и скопируйте её.', 'resources.worker.script.install': 'Установка скриптом', 'resources.worker.container.install': 'Установка контейнером (только Linux)', - 'resources.worker.cann.tips': - `Укажите индексы GPU через ASCEND_VISIBLE_DEVICES=0,1,2,3 или ASCEND_VISIBLE_DEVICES=0-3.` + 'resources.worker.cann.tips': `Укажите индексы GPU через ASCEND_VISIBLE_DEVICES=0,1,2,3 или ASCEND_VISIBLE_DEVICES=0-3.`, + 'resources.modelfiles.form.path': 'Storage path', + 'resources.modelfiles.modelfile': 'Model File', + 'resources.modelfiles.download': 'Add Model', + 'resources.modelfiles.size': 'Size', + 'resources.modelfiles.selecttarget': 'Select Target' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +//1. 'resources.modelfiles.form.path', +//2. 'resources.modelfiles.modelfile', +//3. 'resources.modelfiles.download', +//4. 'resources.modelfiles.size', +//5. 'resources.modelfiles.selecttarget', +// ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index aa53bc2c..7a149730 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -54,5 +54,10 @@ export default { 'resources.worker.script.install': '脚本安装', 'resources.worker.container.install': '容器安装(仅支持 Linux)', 'resources.worker.cann.tips': - '按需要挂载的 GPU index 设置 ASCEND_VISIBLE_DEVICES,如需挂载 GPU0 - GPU3,则设为 ASCEND_VISIBLE_DEVICES=0,1,2,3ASCEND_VISIBLE_DEVICES=0-3' + '按需要挂载的 GPU index 设置 ASCEND_VISIBLE_DEVICES,如需挂载 GPU0 - GPU3,则设为 ASCEND_VISIBLE_DEVICES=0,1,2,3ASCEND_VISIBLE_DEVICES=0-3', + 'resources.modelfiles.form.path': '存储路径', + 'resources.modelfiles.modelfile': '模型文件', + 'resources.modelfiles.download': '添加模型', + 'resources.modelfiles.size': '文件大小', + 'resources.modelfiles.selecttarget': '选择目标位置' }; diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index e2c494f8..58f0f471 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -1,4 +1,3 @@ -import AutoTooltip from '@/components/auto-tooltip'; import IconFont from '@/components/icon-font'; import LabelSelector from '@/components/label-selector'; import ListInput from '@/components/list-input'; @@ -13,7 +12,6 @@ import { useIntl } from '@umijs/max'; import { Checkbox, Collapse, - Empty, Form, FormInstance, Tooltip, @@ -150,49 +148,6 @@ const AdvanceConfig: React.FC = (props) => { form.setFieldValue(['gpu_selector', 'gpu_ids'], lastGroupItems); }; - const gpuOptionRender = (data: any) => { - if (data.value === '__EMPTY__') { - return ( - - ); - } - let width: any = { - maxWidth: 140, - minWidth: 140 - }; - if (!data.parent) { - width = undefined; - } - if (data.parent) { - return ( - - {data.label} - - ); - } - return ; - }; - - const tagRender = (props: any) => { - if (props.isMaxTag) { - return props.label; - } - const parent = _.split(props.value, '__RC_CASCADER_SPLIT__')?.[0]; - return `${parent} / ${props?.label}`; - }; - const collapseItems = useMemo(() => { const children = ( <> @@ -306,19 +261,7 @@ const AdvanceConfig: React.FC = (props) => { options={gpuOptions} showCheckedStrategy="SHOW_CHILD" value={form.getFieldValue(['gpu_selector', 'gpu_ids'])} - tagRender={(props) => { - return ( - - {tagRender(props)} - - ); - }} - optionRender={gpuOptionRender} + optionNode={GPUCard} getPopupContainer={(triggerNode) => triggerNode.parentNode} > diff --git a/src/pages/llmodels/components/data-form.tsx b/src/pages/llmodels/components/data-form.tsx index bd64ec84..e54fcc00 100644 --- a/src/pages/llmodels/components/data-form.tsx +++ b/src/pages/llmodels/components/data-form.tsx @@ -1,5 +1,6 @@ import IconFont from '@/components/icon-font'; import SealAutoComplete from '@/components/seal-form/auto-complete'; +import SealCascader from '@/components/seal-form/seal-cascader'; import SealInput from '@/components/seal-form/seal-input'; import SealSelect from '@/components/seal-form/seal-select'; import TooltipList from '@/components/tooltip-list'; @@ -7,7 +8,7 @@ import { PageAction } from '@/config'; import { PageActionType } from '@/config/types'; import useAppUtils from '@/hooks/use-app-utils'; import { useIntl } from '@umijs/max'; -import { Form, Typography } from 'antd'; +import { Form, Input, Typography } from 'antd'; import _ from 'lodash'; import React, { forwardRef, @@ -46,6 +47,7 @@ interface DataFormProps { backendOptions?: Global.BaseOption[]; sourceList?: Global.BaseOption[]; gpuOptions: any[]; + modelFileOptions?: any[]; onSizeChange?: (val: number) => void; onQuantizationChange?: (val: string) => void; onSourceChange?: (value: string) => void; @@ -68,12 +70,14 @@ const DataForm: React.FC = forwardRef((props, ref) => { sourceList, byBuiltIn, gpuOptions = [], + modelFileOptions = [], sizeOptions = [], quantizationOptions = [], fields = ['source'], onSourceChange, onOk } = props; + console.log('modelFileOptions--------', modelFileOptions); const { getRuleMessage } = useAppUtils(); const [form] = Form.useForm(); const intl = useIntl(); @@ -278,6 +282,11 @@ const DataForm: React.FC = forwardRef((props, ref) => { ); }; + const handleOnSearch = (value: string) => { + console.log('local_path', value); + form.setFieldValue('local_path', value); + }; + const renderLocalPathFields = () => { return ( <> @@ -291,13 +300,37 @@ const DataForm: React.FC = forwardRef((props, ref) => { } ]} > - } - > + > */} + } + expandTrigger="hover" + multiple={false} + onSearch={handleOnSearch} + popupClassName="cascader-popup-wrapper gpu-selector" + maxTagCount={1} + label={intl.formatMessage({ id: 'models.form.gpuselector' })} + options={modelFileOptions} + showCheckedStrategy="SHOW_CHILD" + value={form.getFieldValue('local_path')} + getPopupContainer={(triggerNode) => triggerNode.parentNode} + displayRender={() => ( + + )} + > ); diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index c897147a..a7128ade 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -23,6 +23,7 @@ type AddModalProps = { source: string; width?: string | number; gpuOptions: any[]; + modelFileOptions: any[]; onOk: (values: FormData) => void; onCancel: () => void; }; @@ -286,6 +287,7 @@ const AddModal: FC = (props) => { ref={form} isGGUF={isGGUF} gpuOptions={props.gpuOptions} + modelFileOptions={props.modelFileOptions} onBackendChange={handleBackendChange} > diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index 23df5aff..69971d98 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -12,10 +12,7 @@ import useBodyScroll from '@/hooks/use-body-scroll'; import useExpandedRowKeys from '@/hooks/use-expanded-row-keys'; import useTableRowSelection from '@/hooks/use-table-row-selection'; import useTableSort from '@/hooks/use-table-sort'; -import { - GPUDeviceItem, - ListItem as WorkerListItem -} from '@/pages/resources/config/types'; +import { ListItem as WorkerListItem } from '@/pages/resources/config/types'; import { handleBatchRequest } from '@/utils'; import { IS_FIRST_LOGIN, @@ -99,8 +96,8 @@ interface ModelsProps { categories?: string[]; }; deleteIds?: number[]; - gpuDeviceList: GPUDeviceItem[]; workerList: WorkerListItem[]; + modelFileOptions: any[]; catalogList?: any[]; dataSource: ListItem[]; loading: boolean; @@ -131,6 +128,7 @@ const Models: React.FC = ({ onCancelViewLogs, handleCategoryChange, handleOnToggleExpandAll, + modelFileOptions, deleteIds, dataSource, workerList, @@ -145,10 +143,12 @@ const Models: React.FC = ({ const { saveScrollHeight, restoreScrollHeight } = useBodyScroll(); const [updateFormInitials, setUpdateFormInitials] = useState<{ gpuOptions: any[]; + modelFileOptions?: any[]; data: any; isGGUF: boolean; }>({ gpuOptions: [], + modelFileOptions: [], data: {}, isGGUF: false }); @@ -176,11 +176,13 @@ const Models: React.FC = ({ width: number | string; source: string; gpuOptions: any[]; + modelFileOptions?: any[]; }>({ show: false, width: 600, source: modelSourceMap.huggingface_value, - gpuOptions: [] + gpuOptions: [], + modelFileOptions: [] }); const currentData = useRef({} as ListItem); const [currentInstance, setCurrentInstance] = useState<{ @@ -213,7 +215,10 @@ const Models: React.FC = ({ }, [deleteIds]); useEffect(() => { - getGPUList(); + const getData = async () => { + await getGPUList(); + }; + getData(); return () => { setExpandAtom([]); }; @@ -418,6 +423,7 @@ const Models: React.FC = ({ const initialValues = generateFormValues(row, gpuDeviceList.current); setUpdateFormInitials({ gpuOptions: gpuDeviceList.current, + modelFileOptions: modelFileOptions, data: initialValues, isGGUF: row.backend === backendOptionsMap.llamaBox }); @@ -497,8 +503,13 @@ const Models: React.FC = ({ } const config = modalConfig[item.key]; + console.log('modelFileOptions:', modelFileOptions); if (config) { - setOpenDeployModal({ ...config, gpuOptions: gpuDeviceList.current }); + setOpenDeployModal({ + ...config, + gpuOptions: gpuDeviceList.current, + modelFileOptions: modelFileOptions + }); } }; @@ -811,6 +822,7 @@ const Models: React.FC = ({ source={openDeployModal.source} width={openDeployModal.width} gpuOptions={openDeployModal.gpuOptions} + modelFileOptions={openDeployModal.modelFileOptions || []} onCancel={handleDeployModalCancel} onOk={handleCreateModel} > diff --git a/src/pages/llmodels/config/button-actions.ts b/src/pages/llmodels/config/button-actions.ts index fcdc7c48..565cbcc6 100644 --- a/src/pages/llmodels/config/button-actions.ts +++ b/src/pages/llmodels/config/button-actions.ts @@ -4,6 +4,7 @@ import { DeleteOutlined, EditOutlined, ExperimentOutlined, + RetweetOutlined, ThunderboltOutlined } from '@ant-design/icons'; import _ from 'lodash'; @@ -15,6 +16,7 @@ const icons = { ExperimentOutlined: React.createElement(ExperimentOutlined), DeleteOutlined: React.createElement(DeleteOutlined), ThunderboltOutlined: React.createElement(ThunderboltOutlined), + RetweetOutlined: React.createElement(RetweetOutlined), Stop: React.createElement(IconFont, { type: 'icon-stop1' }), Play: React.createElement(IconFont, { type: 'icon-outline-play' }), Catalog: React.createElement(IconFont, { type: 'icon-catalog' }), @@ -132,6 +134,13 @@ export const onLineSourceOptions = [ value: modelSourceMap.modelscope_value, key: 'modelscope', icon: icons.ModelScope + }, + { + label: 'models.form.localPath', + locale: true, + value: modelSourceMap.local_path_value, + key: 'local_path', + icon: icons.LocalPath } ]; @@ -143,14 +152,7 @@ export const sourceOptions = [ key: 'catalog', icon: icons.Catalog }, - ...onLineSourceOptions, - { - label: 'models.form.localPath', - locale: true, - value: modelSourceMap.local_path_value, - key: 'local_path', - icon: icons.LocalPath - } + ...onLineSourceOptions ]; export const generateSource = (record: any) => { @@ -187,10 +189,15 @@ export const setModelActionList = (record: any) => { }; export const modelFileActions = [ + // { + // label: 'common.button.deploy', + // key: 'deploy', + // icon: icons.ThunderboltOutlined + // }, { - label: 'common.button.deploy', - key: 'deploy', - icon: icons.ThunderboltOutlined + label: 'common.button.retry', + key: 'retry', + icon: icons.RetweetOutlined }, { label: 'common.button.delete', diff --git a/src/pages/llmodels/download/index.tsx b/src/pages/llmodels/download/index.tsx index 06e265ed..a7e1b860 100644 --- a/src/pages/llmodels/download/index.tsx +++ b/src/pages/llmodels/download/index.tsx @@ -19,12 +19,21 @@ type AddModalProps = { open: boolean; source: string; width?: string | number; + workersList: Global.BaseOption[]; onOk: (values: FormData) => void; onCancel: () => void; }; const DownloadModel: React.FC = (props) => { - const { title, open, onOk, onCancel, source, width = 600 } = props || {}; + const { + title, + workersList, + open, + onOk, + onCancel, + source, + width = 600 + } = props || {}; const SEARCH_SOURCE = [ modelSourceMap.huggingface_value, modelSourceMap.modelscope_value @@ -35,18 +44,45 @@ const DownloadModel: React.FC = (props) => { const [selectedModel, setSelectedModel] = useState({}); const [collapsed, setCollapsed] = useState(false); const [isGGUF, setIsGGUF] = useState(false); + const [fileName, setFileName] = useState(''); const modelFileRef = useRef(null); + const generateModelInfo = () => { + if (source === modelSourceMap.huggingface_value) { + const huggingFaceModel = { + huggingface_repo_id: selectedModel.name, + huggingface_filename: fileName + }; + return huggingFaceModel; + } + + if (source === modelSourceMap.modelscope_value) { + const modelScopeModel = { + model_scope_model_id: selectedModel.name, + model_scope_file_path: fileName + }; + return modelScopeModel; + } + return {}; + }; const handleSelectModelFile = useCallback((item: any) => { - form.current?.setFieldValue?.('file_name', item.fakeName); + setFileName(item.fakeName); }, []); const handleOnSelectModel = (item: any) => { setSelectedModel(item); }; + const handleOk = (values: any) => { + onOk({ + ...values, + source: source, + ...generateModelInfo() + }); + }; + const handleSumit = () => { - form.current?.submit?.(); + form.current?.form?.submit?.(); }; const debounceFetchModelFiles = debounce(() => { @@ -91,7 +127,7 @@ const DownloadModel: React.FC = (props) => { fontSize: 'var(--font-size-middle)' }} > - Download Model + {title}