chore: display warning message after form change in edit model

This commit is contained in:
jialin
2025-04-10 12:21:55 +08:00
parent 1182fdeb43
commit 7c79accda7
23 changed files with 126 additions and 71 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
</Button> </Button>
</Space> </Space>
); );
}, [actionItems, actionType, rowSelection?.selectedRowKeys]); }, [actionItems, actionType, rowSelection?.selectedRowKeys, intl]);
return ( return (
<PageTools <PageTools
+1 -1
View File
@@ -36,7 +36,7 @@
} }
.cell-header { .cell-header {
font-weight: var(--font-weight-bold); font-weight: var(--font-weight-medium);
} }
&.light { &.light {
-4
View File
@@ -42,16 +42,12 @@
.item { .item {
display: flex; display: flex;
font-weight: var(--font-weight-medium);
color: var(--ant-color-text);
} }
.tl { .tl {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
width: 60px; width: 60px;
font-weight: var(--font-weight-normal);
color: var(--ant-color-text-secondary);
} }
} }
} }
-11
View File
@@ -148,12 +148,6 @@ const useSetChunkRequest = () => {
} else { } else {
handler(response); handler(response);
} }
console.log('chunkrequest===', {
result: response,
url,
params
});
} }
}); });
setRequestReadyState(requestData?.readyState); setRequestReadyState(requestData?.readyState);
@@ -197,11 +191,6 @@ const useSetChunkRequest = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
console.log(
'chunkrequest===retryCount.current==',
requestReadyState,
retryCount.current
);
if (requestReadyState === 4 && retryCount.current > 0) { if (requestReadyState === 4 && retryCount.current > 0) {
requestConfig.current.beforeReconnect?.(); requestConfig.current.beforeReconnect?.();
clearTimeout(timer.current); clearTimeout(timer.current);
-5
View File
@@ -41,11 +41,6 @@ export function useUpdateChunkedList(options: {
}, 200); }, 200);
}; };
const updateChunkedList = (data: ChunkedCollection) => { const updateChunkedList = (data: ChunkedCollection) => {
console.log('updateChunkedList=====', {
ids: data?.ids,
type: data?.type,
collection: data?.collection
});
let collections = data?.collection || []; let collections = data?.collection || [];
if (options?.computedID) { if (options?.computedID) {
collections = collections?.map((item: any) => { collections = collections?.map((item: any) => {
+2 -1
View File
@@ -132,5 +132,6 @@ export default {
'The model requires approximately {vram} VRAM and {ram} RAM.', 'The model requires approximately {vram} VRAM and {ram} RAM.',
'models.form.check.claims2': 'The model requires approximately {vram} VRAM.', 'models.form.check.claims2': 'The model requires approximately {vram} VRAM.',
'models.form.update.tips': 'models.form.update.tips':
'Changes will only apply after you delete and recreate the instance.' 'Changes will only apply after you delete and recreate the instance.',
'models.table.download.progress': 'Download Progress'
}; };
+1 -1
View File
@@ -51,7 +51,7 @@ export default {
'resources.worker.container.supported': 'Do not support macOS or Windows.', 'resources.worker.container.supported': 'Do not support macOS or Windows.',
'resources.worker.current.version': 'Current version is {version}.', 'resources.worker.current.version': 'Current version is {version}.',
'resources.worker.driver.install': 'resources.worker.driver.install':
'Ensure all necessary drivers and libraries are installed on the system prior to installing GPUStack.', 'Install <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">required drivers and libraries</a> prior to GPUStack installation.',
'resources.worker.select.command': 'resources.worker.select.command':
'Select a label to generate the command and copy it using the copy button.', 'Select a label to generate the command and copy it using the copy button.',
'resources.worker.script.install': 'Script Installation', 'resources.worker.script.install': 'Script Installation',
+4 -2
View File
@@ -129,7 +129,8 @@ export default {
'The model requires approximately {vram} VRAM and {ram} RAM.', 'The model requires approximately {vram} VRAM and {ram} RAM.',
'models.form.check.claims2': 'The model requires approximately {vram} VRAM.', 'models.form.check.claims2': 'The model requires approximately {vram} VRAM.',
'models.form.update.tips': 'models.form.update.tips':
'Changes will only apply after you delete and recreate the instance.' 'Changes will only apply after you delete and recreate the instance.',
'models.table.download.progress': 'Download Progress'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -147,5 +148,6 @@ export default {
// 12. 'models.form.check.claims', // 12. 'models.form.check.claims',
// 13. 'model.deploy.search.placeholder', // 13. 'model.deploy.search.placeholder',
// 14. 'models.form.update.tips, // 14. 'models.form.update.tips,
// 15. models.form.check.claims2 // 15. models.form.check.claims2,
// 16. 'models.table.download.progress'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+2 -1
View File
@@ -52,7 +52,7 @@ export default {
'MacOSまたはWindowsはサポートされていません。', 'MacOSまたはWindowsはサポートされていません。',
'resources.worker.current.version': '現在のバージョンは {version} です。', 'resources.worker.current.version': '現在のバージョンは {version} です。',
'resources.worker.driver.install': 'resources.worker.driver.install':
'GPUStackをインストールする前に、必要なすべてのドライバーとライブラリがシステムにインストールされていることを確認してください。', 'Install <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">required drivers and libraries</a> prior to GPUStack installation.',
'resources.worker.select.command': 'resources.worker.select.command':
'ラベルを選択してコマンドを生成し、コピーを使用してコマンドをコピーします。', 'ラベルを選択してコマンドを生成し、コピーを使用してコマンドをコピーします。',
'resources.worker.script.install': 'スクリプトインストール', 'resources.worker.script.install': 'スクリプトインストール',
@@ -95,4 +95,5 @@ export default {
// 16. 'resources.filter.path', // 16. 'resources.filter.path',
// 17. 'resources.form.workerSelector.description, // 17. 'resources.form.workerSelector.description,
// 18. 'resources.worker.cann.tips', // 18. 'resources.worker.cann.tips',
// 19. 'resources.worker.driver.install'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+3 -1
View File
@@ -132,7 +132,8 @@ export default {
'Модель требует примерно {vram} VRAM и {ram} RAM.', 'Модель требует примерно {vram} VRAM и {ram} RAM.',
'models.form.check.claims2': 'Модель требует примерно {vram} VRAM.', 'models.form.check.claims2': 'Модель требует примерно {vram} VRAM.',
'models.form.update.tips': 'models.form.update.tips':
'Changes will only apply after you delete and recreate the instance.' 'Changes will only apply after you delete and recreate the instance.',
'models.table.download.progress': 'Download Progress'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -140,4 +141,5 @@ export default {
// 2. 'models.form.partialoffload.tips // 2. 'models.form.partialoffload.tips
// 3. 'model.deploy.search.placeholder', // 3. 'model.deploy.search.placeholder',
// 4. 'models.form.update.tips', // 4. 'models.form.update.tips',
// 5. 'models.table.download.progress
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+3 -2
View File
@@ -51,7 +51,7 @@ export default {
'resources.worker.container.supported': 'Только для Linux.', 'resources.worker.container.supported': 'Только для Linux.',
'resources.worker.current.version': 'Текущая версия: {version}', 'resources.worker.current.version': 'Текущая версия: {version}',
'resources.worker.driver.install': 'resources.worker.driver.install':
'Установите необходимые драйверы и библиотеки перед установкой GPUStack.', 'Install <a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">required drivers and libraries</a> prior to GPUStack installation.',
'resources.worker.select.command': 'resources.worker.select.command':
'Выберите метку для генерации команды и скопируйте её.', 'Выберите метку для генерации команды и скопируйте её.',
'resources.worker.script.install': 'Установка скриптом', 'resources.worker.script.install': 'Установка скриптом',
@@ -76,5 +76,6 @@ export default {
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'resources.worker.cann.tips', // 1. 'resources.worker.cann.tips',
// 2. 'resources.worker.add.step2.tips' // 2. 'resources.worker.add.step2.tips',
// 3. 'resources.worker.driver.install'
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+2 -1
View File
@@ -124,5 +124,6 @@ export default {
'models.form.check.passed': '兼容性检查通过', 'models.form.check.passed': '兼容性检查通过',
'models.form.check.claims': '该模型大约需要 {vram} 显存和 {ram} 内存。', 'models.form.check.claims': '该模型大约需要 {vram} 显存和 {ram} 内存。',
'models.form.check.claims2': '该模型大约需要 {vram} 显存。', 'models.form.check.claims2': '该模型大约需要 {vram} 显存。',
'models.form.update.tips': '更改仅在删除并重新创建实例后生效。' 'models.form.update.tips': '更改仅在删除并重新创建实例后生效。',
'models.table.download.progress': '下载进度'
}; };
+1 -1
View File
@@ -27,7 +27,7 @@ export default {
'playground.params.seed.tips': 'playground.params.seed.tips':
'如果指定,系统将尽最大努力进行确定性采样,以便使用相同 Seed 和参数的重复请求应返回相同的结果。', '如果指定,系统将尽最大努力进行确定性采样,以便使用相同 Seed 和参数的重复请求应返回相同的结果。',
'playground.params.stop.tips': 'playground.params.stop.tips':
'停止序列是一个预定义或用户指定的文本字符串,当这些序列出现时,它会提示 AI 停止生成后续的 Token', '停止序列是一个预定义或用户指定的文本字符串,当这些序列出现时,它会提示 AI 停止生成后续的 Token',
'playground.viewcode.tips': 'playground.viewcode.tips':
'{here} 查看 API 密钥。您应该使用环境变量或密钥管理工具将您的密钥暴露给您的应用程序。', '{here} 查看 API 密钥。您应该使用环境变量或密钥管理工具将您的密钥暴露给您的应用程序。',
'playground.viewcode.here': '这里', 'playground.viewcode.here': '这里',
+1 -1
View File
@@ -51,7 +51,7 @@ export default {
'resources.worker.current.version': '当前版本为 {version}', 'resources.worker.current.version': '当前版本为 {version}',
'resources.worker.select.command': '选择一个标签生成命令并使用复制按钮复制', 'resources.worker.select.command': '选择一个标签生成命令并使用复制按钮复制',
'resources.worker.driver.install': 'resources.worker.driver.install':
'在安装 GPUStack 之前,确保系统上安装了所有必需的驱动程序和库', '在安装 GPUStack 之前,请安装<a href="https://docs.gpustack.ai/latest/installation/installation-requirements/" target="_blank">所需的驱动程序和库</a>。',
'resources.worker.script.install': '脚本安装', 'resources.worker.script.install': '脚本安装',
'resources.worker.container.install': '容器安装(仅支持 Linux)', 'resources.worker.container.install': '容器安装(仅支持 Linux)',
'resources.worker.cann.tips': 'resources.worker.cann.tips':
@@ -63,7 +63,6 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
onValuesChange, onValuesChange,
onOk onOk
} = props; } = props;
console.log('modelFileOptions--------', modelFileOptions);
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const [form] = Form.useForm(); const [form] = Form.useForm();
const intl = useIntl(); const intl = useIntl();
@@ -96,7 +96,7 @@ const AddModal: FC<AddModalProps> = (props) => {
const intl = useIntl(); const intl = useIntl();
const [selectedModel, setSelectedModel] = useState<any>({}); const [selectedModel, setSelectedModel] = useState<any>({});
const [collapsed, setCollapsed] = useState<boolean>(false); const [collapsed, setCollapsed] = useState<boolean>(false);
const [isGGUF, setIsGGUF] = useState<boolean>(props.isGGUF || false); const [isGGUF, setIsGGUF] = useState<boolean>(false);
const modelFileRef = useRef<any>(null); const modelFileRef = useRef<any>(null);
const getDefaultSpec = (item: any) => { const getDefaultSpec = (item: any) => {
@@ -225,6 +225,7 @@ const AddModal: FC<AddModalProps> = (props) => {
? backendOptionsMap.llamaBox ? backendOptionsMap.llamaBox
: backendOptionsMap.vllm; : backendOptionsMap.vllm;
form.current?.setFieldValue?.('backend', backend); form.current?.setFieldValue?.('backend', backend);
setIsGGUF(source === modelSourceMap.ollama_library_value);
} }
}; };
@@ -46,7 +46,7 @@ const downloadList: ColumnProps[] = [
width: 200 width: 200
}, },
{ {
title: 'models.table.status', title: 'models.table.download.progress',
locale: true, locale: true,
key: 'download_progress', key: 'download_progress',
render: ({ row }) => { render: ({ row }) => {
+9 -3
View File
@@ -1,11 +1,17 @@
import { ListItem as WorkerListItem } from '@/pages/resources/config/types'; import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
import { Space } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useEffect, useMemo } from 'react'; import React, { useEffect, useMemo } from 'react';
import styled from 'styled-components';
import { ModelInstanceListItem } from '../config/types'; 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 Wrapper = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;
interface InstanceItemProps { interface InstanceItemProps {
list: ModelInstanceListItem[]; list: ModelInstanceListItem[];
workerList: WorkerListItem[]; workerList: WorkerListItem[];
@@ -39,7 +45,7 @@ const Instances: React.FC<InstanceItemProps> = ({
}, []); }, []);
return ( return (
<Space size={16} direction="vertical" style={{ width: '100%' }}> <Wrapper>
{_.map(list, (item: ModelInstanceListItem, index: number) => { {_.map(list, (item: ModelInstanceListItem, index: number) => {
return ( return (
<InstanceItem <InstanceItem
@@ -52,7 +58,7 @@ const Instances: React.FC<InstanceItemProps> = ({
></InstanceItem> ></InstanceItem>
); );
})} })}
</Space> </Wrapper>
); );
}; };
export default Instances; export default Instances;
+48 -11
View File
@@ -15,7 +15,7 @@ import {
backendLabelMap, backendLabelMap,
backendOptionsMap, backendOptionsMap,
backendTipsList, backendTipsList,
excludeFields, updateExcludeFields as excludeFields,
getSourceRepoConfigValue, getSourceRepoConfigValue,
localPathTipsList, localPathTipsList,
modelSourceMap, modelSourceMap,
@@ -69,8 +69,51 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const localPathCache = useRef<string>(''); const localPathCache = useRef<string>('');
const submitAnyway = useRef<boolean>(false); const submitAnyway = useRef<boolean>(false);
const originFormData = useRef<any>(null);
const timer0 = useRef<any>(null);
const handleOnValuesChange = (data: any) => {}; const setOriginalFormData = () => {
if (!originFormData.current) {
clearTimeout(timer0.current);
timer0.current = setTimeout(() => {
originFormData.current = form.getFieldsValue?.();
}, 200);
}
};
const handleOnValuesChange = _.debounce((data: any) => {
const formdata = form.getFieldsValue?.();
let alldata = {};
if (formdata.scheduleType === 'manual') {
alldata = {
..._.omit(formdata, ['worker_selector']),
gpu_selector:
formdata.gpu_selector?.gpu_ids?.length > 0
? originFormData.current?.gpu_selector
: null
};
} else {
alldata = {
..._.omit(formdata, ['gpu_selector']),
worker_selector: originFormData.current?.worker_selector || null
};
}
const isEqual = _.isEqual(alldata, originFormData.current);
if (isEqual) {
setWarningStatus({
show: false,
message: ''
});
} else {
setWarningStatus({
show: true,
isDefault: true,
message: intl.formatMessage({
id: 'models.form.update.tips'
})
});
}
}, 300);
// voxbox is not support multi gpu // voxbox is not support multi gpu
const handleSetGPUIds = (backend: string) => { const handleSetGPUIds = (backend: string) => {
@@ -353,17 +396,11 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
useEffect(() => { useEffect(() => {
if (open && formData) { if (open && formData) {
form.setFieldsValue(formData); setOriginalFormData();
setWarningStatus({
show: true,
isDefault: true,
message: intl.formatMessage({
id: 'models.form.update.tips'
})
});
} }
if (!open) { if (!open) {
checkTokenRef.current?.cancel?.(); checkTokenRef.current?.cancel?.();
originFormData.current = null;
setWarningStatus({ setWarningStatus({
show: false, show: false,
message: '' message: ''
@@ -456,7 +493,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
}} }}
> >
<Form <Form
name="addModalForm" name="updateModalForm"
form={form} form={form}
onFinish={handleOk} onFinish={handleOk}
onValuesChange={onValuesChange} onValuesChange={onValuesChange}
+37
View File
@@ -479,3 +479,40 @@ export const excludeFields = [
'backend', 'backend',
'gpu_selector' 'gpu_selector'
]; ];
export const updateExcludeFields = [
'repo_id',
'file_name',
'description',
'source',
'worker_selector',
'backend_parameters',
'local_path',
'backend_version',
'ollama_library_model_name',
'scheduleType',
'backend',
'gpu_selector'
];
export const formFields = [
'name',
'repo_id',
'file_name',
'local_path',
'ollama_library_model_name',
'backend',
'replicas',
'source',
'description',
'worker_selector',
'cpu_offloading',
'distributed_inference_across_workers',
'gpu_selector',
'gpu_ids',
'categories',
'backend_version',
'env',
'scheduleType',
'restart_on_error'
];
-1
View File
@@ -212,7 +212,6 @@ export const useGenerateModelFileOptions = () => {
} }
return acc; return acc;
}, []); }, []);
console.log('childrenList', childrenList);
return childrenList; return childrenList;
@@ -2,9 +2,8 @@ import { GPUStackVersionAtom } from '@/atoms/user';
import { getAtomStorage } from '@/atoms/utils'; import { getAtomStorage } from '@/atoms/utils';
import EditorWrap from '@/components/editor-wrap'; import EditorWrap from '@/components/editor-wrap';
import HighlightCode from '@/components/highlight-code'; import HighlightCode from '@/components/highlight-code';
import { WarningOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Radio } from 'antd'; import { Radio } from 'antd';
import React from 'react'; import React from 'react';
import { addWorkerGuide, containerInstallOptions } from '../config'; import { addWorkerGuide, containerInstallOptions } from '../config';
import './styles/installation.less'; import './styles/installation.less';
@@ -68,22 +67,13 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
)} )}
</li> </li>
<li> <li>
<span> <span
{intl.formatMessage({ id: 'resources.worker.driver.install' })} dangerouslySetInnerHTML={{
</span> __html: intl.formatMessage({
<WarningOutlined id: 'resources.worker.driver.install'
style={{ color: 'var(--ant-color-warning)' }} })
className="font-size-14 m-l-5 m-r-5" }}
/> ></span>
<Button
style={{ padding: 0 }}
type="link"
size="small"
href="https://docs.gpustack.ai/latest/installation/installation-requirements/"
target="_blank"
>
{intl.formatMessage({ id: 'playground.audio.enablemic.doc' })}
</Button>
</li> </li>
</ul> </ul>
<h3 className="font-size-14 font-600"> <h3 className="font-size-14 font-600">
@@ -150,7 +140,6 @@ const AddWorker: React.FC<ViewModalProps> = (props) => {
code={code} code={code}
lang="bash" lang="bash"
copyable={false} copyable={false}
height={160}
></HighlightCode> ></HighlightCode>
</EditorWrap> </EditorWrap>
) : ( ) : (
-1
View File
@@ -22,7 +22,6 @@ export const requestConfig: RequestConfig = {
history.push('/login', { replace: true }); history.push('/login', { replace: true });
} }
console.log('error==============', error);
} }
}, },
requestInterceptors: [ requestInterceptors: [