fix: deploy from model files source incorrect
This commit is contained in:
@@ -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' })}
|
||||
|
||||
Reference in New Issue
Block a user