From 0fc570b138d25cb6a5b98dd22fff7964a7f6c338 Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 12 Mar 2025 10:42:27 +0800 Subject: [PATCH] chore: the backend matches the model file --- .../seal-form/components/label-info.tsx | 8 +- src/components/simple-table/cell.tsx | 0 src/locales/en-US/common.ts | 4 +- src/locales/en-US/models.ts | 7 +- src/locales/ru-RU/common.ts | 4 +- src/locales/zh-CN/common.ts | 4 +- src/locales/zh-CN/models.ts | 6 +- .../llmodels/components/advance-config.tsx | 4 +- .../llmodels/components/column-wrapper.tsx | 37 +++-- src/pages/llmodels/components/data-form.tsx | 5 +- .../llmodels/components/deploy-modal.tsx | 137 +++++++++++++----- .../llmodels/components/instance-item.tsx | 70 ++++----- src/pages/llmodels/components/table-list.tsx | 8 +- .../llmodels/components/update-modal.tsx | 117 +++++++++++---- src/pages/llmodels/style/column-wrapper.less | 2 + .../playground/components/message-input.tsx | 4 +- 16 files changed, 285 insertions(+), 132 deletions(-) create mode 100644 src/components/simple-table/cell.tsx diff --git a/src/components/seal-form/components/label-info.tsx b/src/components/seal-form/components/label-info.tsx index 831c0645..7cc77216 100644 --- a/src/components/seal-form/components/label-info.tsx +++ b/src/components/seal-form/components/label-info.tsx @@ -35,13 +35,13 @@ const NoteInfo: React.FC = (props) => { ) : ( <> {label} - - {required && ( + {required && ( + * - )} - + + )} )} {labelExtra} diff --git a/src/components/simple-table/cell.tsx b/src/components/simple-table/cell.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/locales/en-US/common.ts b/src/locales/en-US/common.ts index 35e38388..a5dacf6c 100644 --- a/src/locales/en-US/common.ts +++ b/src/locales/en-US/common.ts @@ -230,5 +230,7 @@ export default { 'common.search.empty': 'No matching results found.', 'common.button.downloadLog': 'Download Log', 'common.button.faq': 'FAQ', - 'common.button.moreInfo': 'More Info' + 'common.button.moreInfo': 'More Info', + 'common.text.warning': 'Warning', + 'common.text.error': 'Error' }; diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 89ff78fd..fe098637 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -110,5 +110,10 @@ export default { 'models.table.llamaAcrossworker': 'Llama-box Across Workers', 'models.table.vllmAcrossworker': 'vLLM Across Workers', 'models.form.releases': 'Releases', - 'models.form.moreparameters': 'More Parameters' + 'models.form.moreparameters': 'Parameter Description', + 'models.table.vram.allocated': 'Allocated VRAM', + 'models.form.backend.warning': + 'The backend for GGUF format models uses llama-box.', + 'models.form.backend.warning.llamabox': + 'Llama-box only supports GGUF format models. If your model files were downloaded from Ollama, you can ignore this warning.' }; diff --git a/src/locales/ru-RU/common.ts b/src/locales/ru-RU/common.ts index 26f9b28a..b20c3989 100644 --- a/src/locales/ru-RU/common.ts +++ b/src/locales/ru-RU/common.ts @@ -228,5 +228,7 @@ export default { 'common.search.empty': 'Ничего не найдено', 'common.button.downloadLog': 'Скачать логи', 'common.button.faq': 'TODO: Translate key "common.button.faq"', - 'common.button.moreInfo': 'TODO: Translate key "common.button.moreInfo"' + 'common.button.moreInfo': 'TODO: Translate key "common.button.moreInfo"', + 'common.text.warning': 'TODO: Translate key "common.text.warning"', + 'common.text.error': 'TODO: Translate key "common.text.error"' }; diff --git a/src/locales/zh-CN/common.ts b/src/locales/zh-CN/common.ts index 2761d6f4..f6e8cf7e 100644 --- a/src/locales/zh-CN/common.ts +++ b/src/locales/zh-CN/common.ts @@ -223,5 +223,7 @@ export default { 'common.search.empty': '未找到匹配结果', 'common.button.downloadLog': '下载日志', 'common.button.faq': '常见问题', - 'common.button.moreInfo': '更多信息' + 'common.button.moreInfo': '更多信息', + 'common.text.warning': '警告', + 'common.text.error': '错误' }; diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index 9d2dcfeb..59bc50e3 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -106,5 +106,9 @@ export default { 'models.table.llamaAcrossworker': 'Llama-box 跨节点', 'models.table.vllmAcrossworker': 'vLLM 跨节点', 'models.form.releases': '版本', - 'models.form.moreparameters': '更多参数' + 'models.form.moreparameters': '参数说明', + 'models.table.vram.allocated': '分配显存', + 'models.form.backend.warning': 'GGUF 格式模型后端用 llama-box。', + 'models.form.backend.warning.llamabox': + 'llama-box 仅支持 GGUF 格式模型,如果您的模型是从 Ollama 下载的模型文件,忽略此警告。' }; diff --git a/src/pages/llmodels/components/advance-config.tsx b/src/pages/llmodels/components/advance-config.tsx index e5742bbd..1af77f93 100644 --- a/src/pages/llmodels/components/advance-config.tsx +++ b/src/pages/llmodels/components/advance-config.tsx @@ -109,7 +109,7 @@ const AdvanceConfig: React.FC = (props) => { return { backend: 'vLLM', releases: 'https://github.com/vllm-project/vllm/releases', - link: 'https://docs.vllm.ai/en/stable/serving/openai_compatible_server.html#command-line-arguments-for-the-server' + link: 'https://docs.vllm.ai/en/stable/serving/openai_compatible_server.html#cli-reference' }; } return null; @@ -369,7 +369,7 @@ const AdvanceConfig: React.FC = (props) => { options={paramsConfig} labelExtra={ backendParamsTips?.link && ( - + ( = ({ children, footer, height }) => { - const handleOnWheel = (e: React.WheelEvent) => { - console.log('handleOnWheel', e); - e.preventDefault(); - e.stopPropagation(); - }; +const ColumnWrapper: React.FC = ({ + children, + footer, + maxHeight, + paddingBottom = 50 +}) => { + const scroller = React.useRef(null); + const { initialize } = useOverlayScroller(); + + React.useEffect(() => { + if (scroller.current) { + initialize(scroller.current); + } + }, []); return ( <> {footer ? (
-
- +
{children} - +
{
{footer}
}
) : ( -
- - {children} - +
+
{children}
)} diff --git a/src/pages/llmodels/components/data-form.tsx b/src/pages/llmodels/components/data-form.tsx index 977be401..52f4a2e0 100644 --- a/src/pages/llmodels/components/data-form.tsx +++ b/src/pages/llmodels/components/data-form.tsx @@ -635,7 +635,10 @@ const DataForm: React.FC = forwardRef((props, ref) => { label: 'vox-box', value: backendOptionsMap.voxBox, disabled: - props.source === modelSourceMap.ollama_library_value || isGGUF + props.source === modelSourceMap.local_path_value + ? false + : props.source === modelSourceMap.ollama_library_value || + isGGUF } ] } diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index 54a22e85..c640bc45 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -1,3 +1,4 @@ +import AlertBlockInfo from '@/components/alert-info/block'; import ModalFooter from '@/components/modal-footer'; import { PageActionType } from '@/config/types'; import { CloseOutlined } from '@ant-design/icons'; @@ -47,6 +48,13 @@ const AddModal: React.FC = (props) => { const [collapsed, setCollapsed] = useState(false); const [isGGUF, setIsGGUF] = useState(false); const modelFileRef = useRef(null); + const [warningStatus, setWarningStatus] = useState<{ + show: boolean; + message: string; + }>({ + show: false, + message: '' + }); const handleSelectModelFile = useCallback((item: any) => { form.current?.setFieldValue?.('file_name', item.fakeName); @@ -71,6 +79,35 @@ const AddModal: React.FC = (props) => { } }; + const updateShowWarning = () => { + const backend = form.current?.getFieldValue?.('backend'); + const localPath = form.current?.getFieldValue?.('local_path'); + + if (source !== modelSourceMap.local_path_value || !localPath) { + return; + } + + if (localPath.endsWith('.gguf') && backend !== backendOptionsMap.llamaBox) { + setWarningStatus({ + show: true, + message: 'models.form.backend.warning' + }); + } else if ( + !localPath.endsWith('.gguf') && + backend === backendOptionsMap.llamaBox + ) { + setWarningStatus({ + show: true, + message: 'models.form.backend.warning.llamabox' + }); + } else { + setWarningStatus({ + show: false, + message: '' + }); + } + }; + const handleBackendChange = (backend: string) => { if (backend === backendOptionsMap.vllm) { setIsGGUF(false); @@ -79,6 +116,7 @@ const AddModal: React.FC = (props) => { if (backend === backendOptionsMap.llamaBox) { setIsGGUF(true); } + updateShowWarning(); }; const handleCancel = useCallback(() => { @@ -92,6 +130,10 @@ const AddModal: React.FC = (props) => { useEffect(() => { if (!open) { setIsGGUF(false); + setWarningStatus({ + show: false, + message: '' + }); form.current?.setFieldValue?.('backend', backendOptionsMap.vllm); } else if (source === modelSourceMap.ollama_library_value) { form.current?.setFieldValue?.('backend', backendOptionsMap.llamaBox); @@ -144,7 +186,13 @@ const AddModal: React.FC = (props) => {
{SEARCH_SOURCE.includes(props.source) && ( <> -
+
= (props) => {
-
+
= (props) => {
)} - - } - > - <> - {SEARCH_SOURCE.includes(source) && ( - - {intl.formatMessage({ id: 'models.form.configurations' })} - - - )} - - - +
+ + {warningStatus.show && ( + + )} + + + } + > + <> + {SEARCH_SOURCE.includes(source) && ( + + {intl.formatMessage({ id: 'models.form.configurations' })} + + + )} + + + +
); diff --git a/src/pages/llmodels/components/instance-item.tsx b/src/pages/llmodels/components/instance-item.tsx index bcfbcc54..9c587007 100644 --- a/src/pages/llmodels/components/instance-item.tsx +++ b/src/pages/llmodels/components/instance-item.tsx @@ -126,20 +126,14 @@ const distributeCols: ColumnProps[] = [ key: 'gpu_index' }, { - title: 'resources.table.vram', + title: 'models.table.vram.allocated', locale: true, key: 'vram', - rowSpan: ({ row, rowIndex, colIndex, dataIndex, dataList }) => { - return rowIndex === 0 ? dataList.length : 0; - }, - render: ({ rowIndex, dataList }) => { - if (rowIndex === 0) { - return convertFileSize( - _.sumBy(dataList, (item: any) => item.vram), - 2 - ); - } - return null; + // rowSpan: ({ row, rowIndex, colIndex, dataIndex, dataList }) => { + // return rowIndex === 0 ? dataList.length : 0; + // }, + render: ({ rowIndex, row, dataList }) => { + return convertFileSize(row.vram, 1); } } ]; @@ -297,33 +291,33 @@ const InstanceItem: React.FC = ({ const renderDistributedServer = useCallback( (severList: any[]) => { - const list = _.map(severList, (item: any) => { - const data = _.find(workerList, { id: item.worker_id }); - return { - worker_name: data?.name, - worker_ip: data?.ip, - port: '', - vram: calcTotalVram(item.computed_resource_claim?.vram || {}), - gpu_index: _.keys(item.computed_resource_claim?.vram).join(',') - }; - }); + // const list = _.map(severList, (item: any) => { + // const data = _.find(workerList, { id: item.worker_id }); + // return { + // worker_name: data?.name, + // worker_ip: data?.ip, + // port: '', + // vram: calcTotalVram(item.computed_resource_claim?.vram || {}), + // gpu_index: _.keys(item.computed_resource_claim?.vram).join(',') + // }; + // }); - // const list = [ - // { - // worker_name: 'worker1', - // worker_ip: '192.168.50.23', - // port: '', - // vram: 21555525632, - // gpu_index: '0,1' - // }, - // { - // worker_name: 'worker2', - // worker_ip: '192.168.50.25', - // port: '', - // vram: 21555525632, - // gpu_index: '2,3' - // } - // ]; + const list = [ + { + worker_name: 'worker1', + worker_ip: '192.168.50.23', + port: '', + vram: 21555525632, + gpu_index: '0,1' + }, + { + worker_name: 'worker2', + worker_ip: '192.168.50.25', + port: '', + vram: 21555525632, + gpu_index: '2,3' + } + ]; const mainWorker = [ { diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index a90d9959..75c78643 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -459,7 +459,9 @@ const Models: React.FC = ({ }); setOpenAddModal(false); message.success(intl.formatMessage({ id: 'common.message.success' })); - handleSearch(); + setTimeout(() => { + handleSearch(); + }, 150); restoreScrollHeight(); } catch (error) {} }, @@ -499,7 +501,9 @@ const Models: React.FC = ({ updateExpandedRowKeys([modelData.id, ...expandedRowKeys]); }, 300); message.success(intl.formatMessage({ id: 'common.message.success' })); - handleSearch?.(); + setTimeout(() => { + handleSearch?.(); + }, 150); } catch (error) {} }, [openDeployModal] diff --git a/src/pages/llmodels/components/update-modal.tsx b/src/pages/llmodels/components/update-modal.tsx index 5daba2b8..3b4fe997 100644 --- a/src/pages/llmodels/components/update-modal.tsx +++ b/src/pages/llmodels/components/update-modal.tsx @@ -1,3 +1,4 @@ +import AlertBlockInfo from '@/components/alert-info/block'; import IconFont from '@/components/icon-font'; import ModalFooter from '@/components/modal-footer'; import SealAutoComplete from '@/components/seal-form/auto-complete'; @@ -8,9 +9,7 @@ import { PageActionType } from '@/config/types'; import { useIntl } from '@umijs/max'; import { Form, Modal, Tooltip, Typography } from 'antd'; import _ from 'lodash'; -import React, { useCallback, useEffect, useMemo, useRef } from 'react'; -import SimpleBar from 'simplebar-react'; -import 'simplebar-react/dist/simplebar.min.css'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { backendOptionsMap, modelSourceMap, @@ -18,6 +17,7 @@ import { } from '../config'; import { FormData, ListItem } from '../config/types'; import AdvanceConfig from './advance-config'; +import ColumnWrapper from './column-wrapper'; type AddModalProps = { title: string; @@ -73,6 +73,13 @@ const UpdateModal: React.FC = (props) => { const [form] = Form.useForm(); const intl = useIntl(); const localPathCache = useRef(''); + const [warningStatus, setWarningStatus] = useState<{ + show: boolean; + message: string; + }>({ + show: false, + message: '' + }); const handleSetGPUIds = (backend: string) => { if (backend === backendOptionsMap.llamaBox) { @@ -88,7 +95,36 @@ const UpdateModal: React.FC = (props) => { } }; - const handleBackendChange = useCallback((val: string) => { + const updateShowWarning = () => { + const backend = form.getFieldValue?.('backend'); + const localPath = form.getFieldValue?.('local_path'); + + if (formData?.source !== modelSourceMap.local_path_value || !localPath) { + return; + } + + if (localPath.endsWith('.gguf') && backend !== backendOptionsMap.llamaBox) { + setWarningStatus({ + show: true, + message: 'models.form.backend.warning' + }); + } else if ( + !localPath.endsWith('.gguf') && + backend === backendOptionsMap.llamaBox + ) { + setWarningStatus({ + show: true, + message: 'models.form.backend.warning.llamabox' + }); + } else { + setWarningStatus({ + show: false, + message: '' + }); + } + }; + + const handleBackendChange = (val: string) => { if (val === backendOptionsMap.llamaBox) { form.setFieldsValue({ distributed_inference_across_workers: true, @@ -97,7 +133,8 @@ const UpdateModal: React.FC = (props) => { } form.setFieldValue('backend_version', ''); handleSetGPUIds(val); - }, []); + updateShowWarning(); + }; const handleOnFocus = () => { localPathCache.current = form.getFieldValue('local_path'); @@ -188,23 +225,25 @@ const UpdateModal: React.FC = (props) => { defaultActiveFirstOption disabled={false} options={ollamaModelOptions} - label={intl.formatMessage({ id: 'model.form.ollama.model' })} placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })} - addAfter={ - - + {intl.formatMessage({ id: 'model.form.ollama.model' })}{' '} + - - - + + + + + } required > @@ -336,6 +375,12 @@ const UpdateModal: React.FC = (props) => { if (open && formData) { form.setFieldsValue(formData); } + if (!open) { + setWarningStatus({ + show: false, + message: '' + }); + } }, [open, formData]); return ( @@ -353,7 +398,7 @@ const UpdateModal: React.FC = (props) => { width={600} styles={{ content: { - padding: '0px' + padding: '0 0 16px 0' }, header: { padding: 'var(--ant-modal-content-padding)', @@ -363,17 +408,33 @@ const UpdateModal: React.FC = (props) => { padding: '0' }, footer: { - padding: '0 var(--ant-modal-content-padding)' + padding: '16px 24px', + margin: '0' } }} footer={ - + <> + + } > - + {warningStatus.show && ( + + )} + + } >
= (props) => { isGGUF={formData?.backend === backendOptionsMap.llamaBox} >
-
+ ); }; diff --git a/src/pages/llmodels/style/column-wrapper.less b/src/pages/llmodels/style/column-wrapper.less index 6e3f1024..804edbc1 100644 --- a/src/pages/llmodels/style/column-wrapper.less +++ b/src/pages/llmodels/style/column-wrapper.less @@ -1,6 +1,8 @@ .column-wrapper { flex: 1; position: relative; + height: 100%; + overflow-y: auto; } .simplebar-scrollbar::before { diff --git a/src/pages/playground/components/message-input.tsx b/src/pages/playground/components/message-input.tsx index b90a5296..fb53831d 100644 --- a/src/pages/playground/components/message-input.tsx +++ b/src/pages/playground/components/message-input.tsx @@ -1,6 +1,6 @@ import IconFont from '@/components/icon-font'; import HotKeys, { KeyMap } from '@/config/hotkeys'; -import { ClearOutlined, EnterOutlined, SwapOutlined } from '@ant-design/icons'; +import { ClearOutlined, SendOutlined, SwapOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Checkbox, Divider, Input, Tooltip } from 'antd'; import _ from 'lodash'; @@ -425,7 +425,7 @@ const MessageInput: React.FC = forwardRef( disabled={isDisabled} > {submitIcon ?? ( - + )}