fix: deploy from model files source incorrect

main
jialin 1 year ago
parent b25644c590
commit f882fe2c32

@ -32,6 +32,11 @@ export default {
colorBgSpotlight: '#3e3e3e'
// sizePopupArrow: 0
},
Button: {
primaryShadow: 'none',
defaultShadow: 'none',
dangerShadow: 'none'
},
Cascader: {
dropdownHeight: 240
},

@ -923,3 +923,10 @@ body {
.ant-notification .ant-notification-notice-close {
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;
}

@ -106,13 +106,16 @@ export default function useTableFetch<ListItem>(options: {
}
};
const handlePageChange = (page: number, pageSize: number) => {
const handleQueryChange = (params: any) => {
setQueryParams({
...queryParams,
page: page,
perPage: pageSize || 10
...params
});
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) => {
@ -124,18 +127,10 @@ export default function useTableFetch<ListItem>(options: {
};
const debounceUpdateFilter = _.debounce((e: any) => {
setQueryParams({
...queryParams,
handleQueryChange({
page: 1,
search: e.target.value
});
fetchData({
query: {
...queryParams,
page: 1,
search: e.target.value
}
});
createModelsChunkRequest({
...queryParams,
search: e.target.value
@ -198,6 +193,7 @@ export default function useTableFetch<ListItem>(options: {
handlePageChange,
handleTableChange,
handleSearch,
handleQueryChange,
handleNameChange
};
}

@ -63,7 +63,7 @@ export default {
'resources.modelfiles.selecttarget': 'Select Target',
'resources.modelfiles.form.localdir': 'Local Directory',
'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.storagePath.holder':
'Waiting for download to complete...',

@ -63,7 +63,7 @@ export default {
'resources.modelfiles.selecttarget': 'Select Target',
'resources.modelfiles.form.localdir': 'Local Directory',
'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.storagePath.holder':
'Waiting for download to complete...',

@ -62,7 +62,7 @@ export default {
'resources.modelfiles.selecttarget': '选择目标位置',
'resources.modelfiles.form.localdir': '本地目录',
'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.storagePath.holder': '等待下载完成...',
'resources.filter.worker': '按 worker 筛选',

@ -99,6 +99,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
ref,
() => {
return {
form: form,
submit: handleSumit,
setFieldsValue: (values: FormData) => {
form.setFieldsValue(values);
@ -288,30 +289,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
label={intl.formatMessage({ id: 'models.form.filePath' })}
description={<TooltipList list={localPathTipsList}></TooltipList>}
></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>
</>
);
@ -488,7 +465,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
useEffect(() => {
handleOnSelectModel();
}, [props.selectedModel.name]);
return (
<Form
name="deployModel"

@ -26,6 +26,7 @@ type AddModalProps = {
gpuOptions: any[];
modelFileOptions: any[];
initialValues?: any;
deploymentType?: 'modelList' | 'modelFiles';
onOk: (values: FormData) => void;
onCancel: () => void;
};
@ -39,6 +40,7 @@ const AddModal: FC<AddModalProps> = (props) => {
source,
action,
width = 600,
deploymentType = 'modelList',
initialValues
} = props || {};
const SEARCH_SOURCE = [
@ -147,8 +149,10 @@ const AddModal: FC<AddModalProps> = (props) => {
} else if (source === modelSourceMap.ollama_library_value) {
form.current?.setFieldValue?.('backend', backendOptionsMap.llamaBox);
setIsGGUF(true);
} else {
form.current?.setFieldsValue({
}
if (props.deploymentType === 'modelFiles' && open) {
form.current?.form?.setFieldsValue({
...props.initialValues
});
setIsGGUF(props.isGGUF || false);
@ -157,7 +161,7 @@ const AddModal: FC<AddModalProps> = (props) => {
return () => {
setSelectedModel({});
};
}, [open, source, props.isGGUF, props.initialValues]);
}, [open, source, props.isGGUF, props.initialValues, props.deploymentType]);
return (
<Drawer
@ -198,52 +202,53 @@ const AddModal: FC<AddModalProps> = (props) => {
footer={false}
>
<div style={{ display: 'flex', height: '100%' }}>
{SEARCH_SOURCE.includes(props.source) && (
<>
<div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper>
<SearchModel
modelSource={props.source}
onSelectModel={handleOnSelectModel}
></SearchModel>
</ColumnWrapper>
<Separator></Separator>
</div>
<div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper>
<ModelCard
selectedModel={selectedModel}
onCollapse={setCollapsed}
collapsed={collapsed}
modelSource={props.source}
setIsGGUF={handleSetIsGGUF}
></ModelCard>
{isGGUF && (
<HFModelFile
ref={modelFileRef}
selectedModel={selectedModel}
{SEARCH_SOURCE.includes(props.source) &&
deploymentType === 'modelList' && (
<>
<div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper>
<SearchModel
modelSource={props.source}
onSelectFile={handleSelectModelFile}
onSelectModel={handleOnSelectModel}
></SearchModel>
</ColumnWrapper>
<Separator></Separator>
</div>
<div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper>
<ModelCard
selectedModel={selectedModel}
onCollapse={setCollapsed}
collapsed={collapsed}
></HFModelFile>
)}
</ColumnWrapper>
<Separator></Separator>
</div>
</>
)}
modelSource={props.source}
setIsGGUF={handleSetIsGGUF}
></ModelCard>
{isGGUF && (
<HFModelFile
ref={modelFileRef}
selectedModel={selectedModel}
modelSource={props.source}
onSelectFile={handleSelectModelFile}
collapsed={collapsed}
></HFModelFile>
)}
</ColumnWrapper>
<Separator></Separator>
</div>
</>
)}
<div style={{ display: 'flex', flex: 1, maxWidth: '100%' }}>
<ColumnWrapper
paddingBottom={warningStatus.show ? 125 : 50}
@ -283,12 +288,13 @@ const AddModal: FC<AddModalProps> = (props) => {
}
>
<>
{SEARCH_SOURCE.includes(source) && (
<TitleWrapper>
{intl.formatMessage({ id: 'models.form.configurations' })}
<span style={{ display: 'flex', height: 24 }}></span>
</TitleWrapper>
)}
{SEARCH_SOURCE.includes(source) &&
deploymentType === 'modelList' && (
<TitleWrapper>
{intl.formatMessage({ id: 'models.form.configurations' })}
<span style={{ display: 'flex', height: 24 }}></span>
</TitleWrapper>
)}
<DataForm
initialValues={initialValues}
source={source}

@ -6,64 +6,6 @@ import { ModelInstanceListItem } from '../config/types';
import '../style/instance-item.less';
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 {
list: ModelInstanceListItem[];
workerList: WorkerListItem[];

@ -171,9 +171,15 @@ const TargetForm: React.FC<TargetFormProps> = forwardRef((props, ref) => {
]}
>
<SealInput.Input
description={intl.formatMessage({
id: 'resources.modelfiles.form.localdir.tips'
})}
description={
<span
dangerouslySetInnerHTML={{
__html: intl.formatMessage({
id: 'resources.modelfiles.form.localdir.tips'
})
}}
></span>
}
label={intl.formatMessage({
id: 'resources.modelfiles.form.localdir'
})}

@ -15,7 +15,8 @@ import DeployModal from '@/pages/llmodels/components/deploy-modal';
import {
backendOptionsMap,
getSourceRepoConfigValue,
modelSourceMap
modelSourceMap,
setSourceRepoConfigValue
} from '@/pages/llmodels/config';
import { identifyModelTask } from '@/pages/llmodels/config/audio-catalog';
import {
@ -66,8 +67,7 @@ import {
ListItem as WorkerListItem
} from '../config/types';
const pattern = /^(.*)-(\d+)-of-(\d+)\.(.*)$/;
const filterPattern = /^(.*)-\d+-of-\d+(\.gguf)?$/;
const filterPattern = /^(.*?)(?:-\d+-of-\d+)?(\.gguf)?$/;
const getWorkerName = (
id: number,
@ -122,7 +122,7 @@ const ModelFiles = () => {
handleTableChange,
handleSearch,
handleNameChange,
setQueryParams
handleQueryChange
} = useTableFetch<ListItem>({
fetchAPI: queryModelFilesList,
deleteAPI: deleteModelFile,
@ -198,18 +198,10 @@ const ModelFiles = () => {
};
const handleWorkerChange = (value: number) => {
setQueryParams({
...queryParams,
handleQueryChange({
page: 1,
worker_id: value
});
fetchData({
query: {
...queryParams,
page: 1,
worker_id: value
}
});
};
const generateInitialValues = (record: ListItem) => {
const isGGUF = _.includes(record.resolved_paths?.[0], 'gguf');
@ -229,9 +221,12 @@ const ModelFiles = () => {
).pop()
);
const result = setSourceRepoConfigValue(record.source, record);
return {
source: modelSourceMap.local_path_value,
local_path: record.resolved_paths?.[0],
...result.values,
source: record.source,
local_path: record.local_path,
name: extractFileName(name),
backend:
isGGUF || isOllama
@ -248,17 +243,7 @@ const ModelFiles = () => {
if (!parts.length) {
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 (
<Tag
className="flex-center"
@ -295,8 +280,11 @@ const ModelFiles = () => {
]);
const dataList = generateModelFileOptions(modelFileList, workersList);
const initialValues = generateInitialValues(record);
console.log('initialValues:', initialValues);
setOpenDeployModal({
...openDeployModal,
source: record.source,
width: 600,
modelFileOptions: dataList,
gpuOptions: gpuList,
initialValues: initialValues,
@ -393,7 +381,11 @@ const ModelFiles = () => {
dataIndex: 'source',
render: (text: string, record: ListItem) => (
<span className="flex flex-column" style={{ width: '100%' }}>
<AutoTooltip ghost>{generateSource(record)}</AutoTooltip>
{record.source === modelSourceMap.local_path_value ? (
intl.formatMessage({ id: 'models.form.localPath' })
) : (
<AutoTooltip ghost>{generateSource(record)}</AutoTooltip>
)}
</span>
)
},
@ -581,6 +573,7 @@ const ModelFiles = () => {
workersList={workersList}
></DownloadModal>
<DeployModal
deploymentType="modelFiles"
open={openDeployModal.show}
action={PageAction.CREATE}
title={intl.formatMessage({ id: 'models.button.deploy' })}

Loading…
Cancel
Save