fix: deploy from model files source incorrect

This commit is contained in:
jialin
2025-03-25 16:39:03 +08:00
parent b25644c590
commit f882fe2c32
11 changed files with 113 additions and 182 deletions
+5
View File
@@ -32,6 +32,11 @@ export default {
colorBgSpotlight: '#3e3e3e' colorBgSpotlight: '#3e3e3e'
// sizePopupArrow: 0 // sizePopupArrow: 0
}, },
Button: {
primaryShadow: 'none',
defaultShadow: 'none',
dangerShadow: 'none'
},
Cascader: { Cascader: {
dropdownHeight: 240 dropdownHeight: 240
}, },
+7
View File
@@ -923,3 +923,10 @@ body {
.ant-notification .ant-notification-notice-close { .ant-notification .ant-notification-notice-close {
width: fit-content !important; width: fit-content !important;
} }
.desc-block {
border-radius: var(--border-radius-2px);
background-color: rgb(89 89 89);
font-weight: var(--font-weight-bold);
padding: 2px;
}
+9 -13
View File
@@ -106,13 +106,16 @@ export default function useTableFetch<ListItem>(options: {
} }
}; };
const handlePageChange = (page: number, pageSize: number) => { const handleQueryChange = (params: any) => {
setQueryParams({ setQueryParams({
...queryParams, ...queryParams,
page: page, ...params
perPage: pageSize || 10
}); });
fetchData({ query: { ...queryParams, page, perPage: pageSize || 10 } }); fetchData({ query: { ...queryParams, ...params } });
};
const handlePageChange = (page: number, pageSize: number) => {
handleQueryChange({ page, perPage: pageSize || 10 });
}; };
const handleTableChange = (pagination: any, filters: any, sorter: any) => { const handleTableChange = (pagination: any, filters: any, sorter: any) => {
@@ -124,18 +127,10 @@ export default function useTableFetch<ListItem>(options: {
}; };
const debounceUpdateFilter = _.debounce((e: any) => { const debounceUpdateFilter = _.debounce((e: any) => {
setQueryParams({ handleQueryChange({
...queryParams,
page: 1, page: 1,
search: e.target.value search: e.target.value
}); });
fetchData({
query: {
...queryParams,
page: 1,
search: e.target.value
}
});
createModelsChunkRequest({ createModelsChunkRequest({
...queryParams, ...queryParams,
search: e.target.value search: e.target.value
@@ -198,6 +193,7 @@ export default function useTableFetch<ListItem>(options: {
handlePageChange, handlePageChange,
handleTableChange, handleTableChange,
handleSearch, handleSearch,
handleQueryChange,
handleNameChange handleNameChange
}; };
} }
+1 -1
View File
@@ -63,7 +63,7 @@ export default {
'resources.modelfiles.selecttarget': 'Select Target', 'resources.modelfiles.selecttarget': 'Select Target',
'resources.modelfiles.form.localdir': 'Local Directory', 'resources.modelfiles.form.localdir': 'Local Directory',
'resources.modelfiles.form.localdir.tips': 'resources.modelfiles.form.localdir.tips':
'The default storage directory is /var/lib/gpustack/cache.', 'The default storage directory is <span class="desc-block">/var/lib/gpustack/cache</span> or the directory specified with <span class="desc-block">--data-dir</span>.',
'resources.modelfiles.retry.download': 'Retry Download', 'resources.modelfiles.retry.download': 'Retry Download',
'resources.modelfiles.storagePath.holder': 'resources.modelfiles.storagePath.holder':
'Waiting for download to complete...', 'Waiting for download to complete...',
+1 -1
View File
@@ -63,7 +63,7 @@ export default {
'resources.modelfiles.selecttarget': 'Select Target', 'resources.modelfiles.selecttarget': 'Select Target',
'resources.modelfiles.form.localdir': 'Local Directory', 'resources.modelfiles.form.localdir': 'Local Directory',
'resources.modelfiles.form.localdir.tips': 'resources.modelfiles.form.localdir.tips':
'The default storage directory is /var/lib/gpustack/cache.', 'The default storage directory is <span class="desc-block>/var/lib/gpustack/cache</span> or the directory specified with <span class="desc-block">--data-dir</span>.',
'resources.modelfiles.retry.download': 'Retry Download', 'resources.modelfiles.retry.download': 'Retry Download',
'resources.modelfiles.storagePath.holder': 'resources.modelfiles.storagePath.holder':
'Waiting for download to complete...', 'Waiting for download to complete...',
+1 -1
View File
@@ -62,7 +62,7 @@ export default {
'resources.modelfiles.selecttarget': '选择目标位置', 'resources.modelfiles.selecttarget': '选择目标位置',
'resources.modelfiles.form.localdir': '本地目录', 'resources.modelfiles.form.localdir': '本地目录',
'resources.modelfiles.form.localdir.tips': 'resources.modelfiles.form.localdir.tips':
'默认存储目录为 /var/lib/gpustack/cache', '默认存储目录为 <span class="desc-block">/var/lib/gpustack/cache</span>,或使用 <span class="desc-block">--data-dir</span> 指定的目录',
'resources.modelfiles.retry.download': '重新下载', 'resources.modelfiles.retry.download': '重新下载',
'resources.modelfiles.storagePath.holder': '等待下载完成...', 'resources.modelfiles.storagePath.holder': '等待下载完成...',
'resources.filter.worker': '按 worker 筛选', 'resources.filter.worker': '按 worker 筛选',
+1 -25
View File
@@ -99,6 +99,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
ref, ref,
() => { () => {
return { return {
form: form,
submit: handleSumit, submit: handleSumit,
setFieldsValue: (values: FormData) => { setFieldsValue: (values: FormData) => {
form.setFieldsValue(values); form.setFieldsValue(values);
@@ -288,30 +289,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
label={intl.formatMessage({ id: 'models.form.filePath' })} label={intl.formatMessage({ id: 'models.form.filePath' })}
description={<TooltipList list={localPathTipsList}></TooltipList>} description={<TooltipList list={localPathTipsList}></TooltipList>}
></SealAutoComplete> ></SealAutoComplete>
{/* <SealCascader
required
showSearch
description={<TooltipList list={localPathTipsList}></TooltipList>}
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={() => (
<Input
style={{
border: 'none',
outline: 'none',
width: '100%'
}}
/>
)}
></SealCascader> */}
</Form.Item> </Form.Item>
</> </>
); );
@@ -488,7 +465,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
useEffect(() => { useEffect(() => {
handleOnSelectModel(); handleOnSelectModel();
}, [props.selectedModel.name]); }, [props.selectedModel.name]);
return ( return (
<Form <Form
name="deployModel" name="deployModel"
+11 -5
View File
@@ -26,6 +26,7 @@ type AddModalProps = {
gpuOptions: any[]; gpuOptions: any[];
modelFileOptions: any[]; modelFileOptions: any[];
initialValues?: any; initialValues?: any;
deploymentType?: 'modelList' | 'modelFiles';
onOk: (values: FormData) => void; onOk: (values: FormData) => void;
onCancel: () => void; onCancel: () => void;
}; };
@@ -39,6 +40,7 @@ const AddModal: FC<AddModalProps> = (props) => {
source, source,
action, action,
width = 600, width = 600,
deploymentType = 'modelList',
initialValues initialValues
} = props || {}; } = props || {};
const SEARCH_SOURCE = [ const SEARCH_SOURCE = [
@@ -147,8 +149,10 @@ const AddModal: FC<AddModalProps> = (props) => {
} else if (source === modelSourceMap.ollama_library_value) { } else if (source === modelSourceMap.ollama_library_value) {
form.current?.setFieldValue?.('backend', backendOptionsMap.llamaBox); form.current?.setFieldValue?.('backend', backendOptionsMap.llamaBox);
setIsGGUF(true); setIsGGUF(true);
} else { }
form.current?.setFieldsValue({
if (props.deploymentType === 'modelFiles' && open) {
form.current?.form?.setFieldsValue({
...props.initialValues ...props.initialValues
}); });
setIsGGUF(props.isGGUF || false); setIsGGUF(props.isGGUF || false);
@@ -157,7 +161,7 @@ const AddModal: FC<AddModalProps> = (props) => {
return () => { return () => {
setSelectedModel({}); setSelectedModel({});
}; };
}, [open, source, props.isGGUF, props.initialValues]); }, [open, source, props.isGGUF, props.initialValues, props.deploymentType]);
return ( return (
<Drawer <Drawer
@@ -198,7 +202,8 @@ const AddModal: FC<AddModalProps> = (props) => {
footer={false} footer={false}
> >
<div style={{ display: 'flex', height: '100%' }}> <div style={{ display: 'flex', height: '100%' }}>
{SEARCH_SOURCE.includes(props.source) && ( {SEARCH_SOURCE.includes(props.source) &&
deploymentType === 'modelList' && (
<> <>
<div <div
style={{ style={{
@@ -283,7 +288,8 @@ const AddModal: FC<AddModalProps> = (props) => {
} }
> >
<> <>
{SEARCH_SOURCE.includes(source) && ( {SEARCH_SOURCE.includes(source) &&
deploymentType === 'modelList' && (
<TitleWrapper> <TitleWrapper>
{intl.formatMessage({ id: 'models.form.configurations' })} {intl.formatMessage({ id: 'models.form.configurations' })}
<span style={{ display: 'flex', height: 24 }}></span> <span style={{ display: 'flex', height: 24 }}></span>
@@ -6,64 +6,6 @@ import { ModelInstanceListItem } from '../config/types';
import '../style/instance-item.less'; import '../style/instance-item.less';
import InstanceItem from './instance-item'; import InstanceItem from './instance-item';
const testInstanceData = {
source: 'huggingface',
huggingface_repo_id: 'Qwen/Qwen2.5-3B-Instruct',
huggingface_filename: null,
ollama_library_model_name: null,
model_scope_model_id: null,
model_scope_file_path: null,
local_path: null,
name: 'qwen2.5-XVCXa',
worker_id: 1,
worker_name: 'sealgpuhost4080',
worker_ip: '192.168.50.12',
pid: 208852,
port: 40063,
download_progress: 72.11,
resolved_path: null,
state: 'downloading',
state_message: '',
computed_resource_claim: {
is_unified_memory: false,
offload_layers: null,
total_layers: null,
ram: null,
vram: {
'0': 1717148058
},
tensor_split: null
},
gpu_indexes: [0],
model_id: 1,
model_name: 'qwen2.5',
distributed_servers: {
rpc_servers: null,
ray_actors: [
{
worker_id: 2,
worker_ip: '192.168.50.13',
total_gpus: 1,
gpu_indexes: [0],
computed_resource_claim: {
is_unified_memory: false,
offload_layers: null,
total_layers: null,
ram: null,
vram: {
'0': 23181498777
},
tensor_split: null
},
download_progress: 27.49
}
]
},
id: 1,
created_at: '2025-03-24T12:06:30Z',
updated_at: '2025-03-24T12:09:01Z'
};
interface InstanceItemProps { interface InstanceItemProps {
list: ModelInstanceListItem[]; list: ModelInstanceListItem[];
workerList: WorkerListItem[]; workerList: WorkerListItem[];
+8 -2
View File
@@ -171,9 +171,15 @@ const TargetForm: React.FC<TargetFormProps> = forwardRef((props, ref) => {
]} ]}
> >
<SealInput.Input <SealInput.Input
description={intl.formatMessage({ description={
<span
dangerouslySetInnerHTML={{
__html: intl.formatMessage({
id: 'resources.modelfiles.form.localdir.tips' id: 'resources.modelfiles.form.localdir.tips'
})} })
}}
></span>
}
label={intl.formatMessage({ label={intl.formatMessage({
id: 'resources.modelfiles.form.localdir' id: 'resources.modelfiles.form.localdir'
})} })}
+19 -26
View File
@@ -15,7 +15,8 @@ import DeployModal from '@/pages/llmodels/components/deploy-modal';
import { import {
backendOptionsMap, backendOptionsMap,
getSourceRepoConfigValue, getSourceRepoConfigValue,
modelSourceMap modelSourceMap,
setSourceRepoConfigValue
} from '@/pages/llmodels/config'; } from '@/pages/llmodels/config';
import { identifyModelTask } from '@/pages/llmodels/config/audio-catalog'; import { identifyModelTask } from '@/pages/llmodels/config/audio-catalog';
import { import {
@@ -66,8 +67,7 @@ import {
ListItem as WorkerListItem ListItem as WorkerListItem
} from '../config/types'; } from '../config/types';
const pattern = /^(.*)-(\d+)-of-(\d+)\.(.*)$/; const filterPattern = /^(.*?)(?:-\d+-of-\d+)?(\.gguf)?$/;
const filterPattern = /^(.*)-\d+-of-\d+(\.gguf)?$/;
const getWorkerName = ( const getWorkerName = (
id: number, id: number,
@@ -122,7 +122,7 @@ const ModelFiles = () => {
handleTableChange, handleTableChange,
handleSearch, handleSearch,
handleNameChange, handleNameChange,
setQueryParams handleQueryChange
} = useTableFetch<ListItem>({ } = useTableFetch<ListItem>({
fetchAPI: queryModelFilesList, fetchAPI: queryModelFilesList,
deleteAPI: deleteModelFile, deleteAPI: deleteModelFile,
@@ -198,18 +198,10 @@ const ModelFiles = () => {
}; };
const handleWorkerChange = (value: number) => { const handleWorkerChange = (value: number) => {
setQueryParams({ handleQueryChange({
...queryParams,
page: 1, page: 1,
worker_id: value worker_id: value
}); });
fetchData({
query: {
...queryParams,
page: 1,
worker_id: value
}
});
}; };
const generateInitialValues = (record: ListItem) => { const generateInitialValues = (record: ListItem) => {
const isGGUF = _.includes(record.resolved_paths?.[0], 'gguf'); const isGGUF = _.includes(record.resolved_paths?.[0], 'gguf');
@@ -229,9 +221,12 @@ const ModelFiles = () => {
).pop() ).pop()
); );
const result = setSourceRepoConfigValue(record.source, record);
return { return {
source: modelSourceMap.local_path_value, ...result.values,
local_path: record.resolved_paths?.[0], source: record.source,
local_path: record.local_path,
name: extractFileName(name), name: extractFileName(name),
backend: backend:
isGGUF || isOllama isGGUF || isOllama
@@ -248,17 +243,7 @@ const ModelFiles = () => {
if (!parts.length) { if (!parts.length) {
return null; return null;
} }
const partsList = parts.map((item: string) => {
const match = item.match(pattern);
if (!match) {
return null;
}
return {
part: parseInt(match[2], 10),
total: parseInt(match[3], 10),
name: _.split(match[1], '/').pop()
};
});
return ( return (
<Tag <Tag
className="flex-center" className="flex-center"
@@ -295,8 +280,11 @@ const ModelFiles = () => {
]); ]);
const dataList = generateModelFileOptions(modelFileList, workersList); const dataList = generateModelFileOptions(modelFileList, workersList);
const initialValues = generateInitialValues(record); const initialValues = generateInitialValues(record);
console.log('initialValues:', initialValues);
setOpenDeployModal({ setOpenDeployModal({
...openDeployModal, ...openDeployModal,
source: record.source,
width: 600,
modelFileOptions: dataList, modelFileOptions: dataList,
gpuOptions: gpuList, gpuOptions: gpuList,
initialValues: initialValues, initialValues: initialValues,
@@ -393,7 +381,11 @@ const ModelFiles = () => {
dataIndex: 'source', dataIndex: 'source',
render: (text: string, record: ListItem) => ( render: (text: string, record: ListItem) => (
<span className="flex flex-column" style={{ width: '100%' }}> <span className="flex flex-column" style={{ width: '100%' }}>
{record.source === modelSourceMap.local_path_value ? (
intl.formatMessage({ id: 'models.form.localPath' })
) : (
<AutoTooltip ghost>{generateSource(record)}</AutoTooltip> <AutoTooltip ghost>{generateSource(record)}</AutoTooltip>
)}
</span> </span>
) )
}, },
@@ -581,6 +573,7 @@ const ModelFiles = () => {
workersList={workersList} workersList={workersList}
></DownloadModal> ></DownloadModal>
<DeployModal <DeployModal
deploymentType="modelFiles"
open={openDeployModal.show} open={openDeployModal.show}
action={PageAction.CREATE} action={PageAction.CREATE}
title={intl.formatMessage({ id: 'models.button.deploy' })} title={intl.formatMessage({ id: 'models.button.deploy' })}