chore: the backend matches the model file

This commit is contained in:
jialin
2025-03-12 10:43:59 +08:00
parent 5edbc1a7b5
commit 0fc570b138
16 changed files with 285 additions and 132 deletions
@@ -35,13 +35,13 @@ const NoteInfo: React.FC<NoteInfoProps> = (props) => {
) : ( ) : (
<> <>
<span>{label}</span> <span>{label}</span>
<span className="note-info"> {required && (
{required && ( <span className="note-info">
<span style={{ color: 'red' }} className="star"> <span style={{ color: 'red' }} className="star">
* *
</span> </span>
)} </span>
</span> )}
</> </>
)} )}
{labelExtra} {labelExtra}
+3 -1
View File
@@ -230,5 +230,7 @@ export default {
'common.search.empty': 'No matching results found.', 'common.search.empty': 'No matching results found.',
'common.button.downloadLog': 'Download Log', 'common.button.downloadLog': 'Download Log',
'common.button.faq': 'FAQ', 'common.button.faq': 'FAQ',
'common.button.moreInfo': 'More Info' 'common.button.moreInfo': 'More Info',
'common.text.warning': 'Warning',
'common.text.error': 'Error'
}; };
+6 -1
View File
@@ -110,5 +110,10 @@ export default {
'models.table.llamaAcrossworker': 'Llama-box Across Workers', 'models.table.llamaAcrossworker': 'Llama-box Across Workers',
'models.table.vllmAcrossworker': 'vLLM Across Workers', 'models.table.vllmAcrossworker': 'vLLM Across Workers',
'models.form.releases': 'Releases', '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.'
}; };
+3 -1
View File
@@ -228,5 +228,7 @@ export default {
'common.search.empty': 'Ничего не найдено', 'common.search.empty': 'Ничего не найдено',
'common.button.downloadLog': 'Скачать логи', 'common.button.downloadLog': 'Скачать логи',
'common.button.faq': 'TODO: Translate key "common.button.faq"', '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"'
}; };
+3 -1
View File
@@ -223,5 +223,7 @@ export default {
'common.search.empty': '未找到匹配结果', 'common.search.empty': '未找到匹配结果',
'common.button.downloadLog': '下载日志', 'common.button.downloadLog': '下载日志',
'common.button.faq': '常见问题', 'common.button.faq': '常见问题',
'common.button.moreInfo': '更多信息' 'common.button.moreInfo': '更多信息',
'common.text.warning': '警告',
'common.text.error': '错误'
}; };
+5 -1
View File
@@ -106,5 +106,9 @@ export default {
'models.table.llamaAcrossworker': 'Llama-box 跨节点', 'models.table.llamaAcrossworker': 'Llama-box 跨节点',
'models.table.vllmAcrossworker': 'vLLM 跨节点', 'models.table.vllmAcrossworker': 'vLLM 跨节点',
'models.form.releases': '版本', '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 下载的模型文件,忽略此警告。'
}; };
@@ -109,7 +109,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
return { return {
backend: 'vLLM', backend: 'vLLM',
releases: 'https://github.com/vllm-project/vllm/releases', 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; return null;
@@ -369,7 +369,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
options={paramsConfig} options={paramsConfig}
labelExtra={ labelExtra={
backendParamsTips?.link && ( backendParamsTips?.link && (
<span style={{ marginLeft: 2 }}> <span style={{ marginLeft: 5 }}>
( (
<Typography.Link <Typography.Link
style={{ lineHeight: 1 }} style={{ lineHeight: 1 }}
@@ -1,36 +1,41 @@
import useOverlayScroller from '@/hooks/use-overlay-scroller';
import React from 'react'; import React from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css'; import 'simplebar-react/dist/simplebar.min.css';
import '../style/column-wrapper.less'; import '../style/column-wrapper.less';
const ColumnWrapper: React.FC<any> = ({ children, footer, height }) => { const ColumnWrapper: React.FC<any> = ({
const handleOnWheel = (e: React.WheelEvent) => { children,
console.log('handleOnWheel', e); footer,
e.preventDefault(); maxHeight,
e.stopPropagation(); paddingBottom = 50
}; }) => {
const scroller = React.useRef<any>(null);
const { initialize } = useOverlayScroller();
React.useEffect(() => {
if (scroller.current) {
initialize(scroller.current);
}
}, []);
return ( return (
<> <>
{footer ? ( {footer ? (
<div className="column-wrapper-footer"> <div className="column-wrapper-footer">
<div className="column-wrapper"> <div className="column-wrapper" ref={scroller} style={{ maxHeight }}>
<SimpleBar <div
style={{ style={{
maxHeight: height || 'calc(100vh - 89px)', paddingBottom: paddingBottom
paddingBottom: '50px'
}} }}
> >
{children} {children}
</SimpleBar> </div>
</div> </div>
{<div className="footer">{footer}</div>} {<div className="footer">{footer}</div>}
</div> </div>
) : ( ) : (
<div className="column-wrapper"> <div className="column-wrapper" ref={scroller} style={{ maxHeight }}>
<SimpleBar style={{ maxHeight: height || 'calc(100vh - 89px)' }}> <div>{children}</div>
{children}
</SimpleBar>
</div> </div>
)} )}
</> </>
+4 -1
View File
@@ -635,7 +635,10 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
label: 'vox-box', label: 'vox-box',
value: backendOptionsMap.voxBox, value: backendOptionsMap.voxBox,
disabled: disabled:
props.source === modelSourceMap.ollama_library_value || isGGUF props.source === modelSourceMap.local_path_value
? false
: props.source === modelSourceMap.ollama_library_value ||
isGGUF
} }
] ]
} }
+103 -34
View File
@@ -1,3 +1,4 @@
import AlertBlockInfo from '@/components/alert-info/block';
import ModalFooter from '@/components/modal-footer'; import ModalFooter from '@/components/modal-footer';
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import { CloseOutlined } from '@ant-design/icons'; import { CloseOutlined } from '@ant-design/icons';
@@ -47,6 +48,13 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const [collapsed, setCollapsed] = useState<boolean>(false); const [collapsed, setCollapsed] = useState<boolean>(false);
const [isGGUF, setIsGGUF] = useState<boolean>(false); const [isGGUF, setIsGGUF] = useState<boolean>(false);
const modelFileRef = useRef<any>(null); const modelFileRef = useRef<any>(null);
const [warningStatus, setWarningStatus] = useState<{
show: boolean;
message: string;
}>({
show: false,
message: ''
});
const handleSelectModelFile = useCallback((item: any) => { const handleSelectModelFile = useCallback((item: any) => {
form.current?.setFieldValue?.('file_name', item.fakeName); form.current?.setFieldValue?.('file_name', item.fakeName);
@@ -71,6 +79,35 @@ const AddModal: React.FC<AddModalProps> = (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) => { const handleBackendChange = (backend: string) => {
if (backend === backendOptionsMap.vllm) { if (backend === backendOptionsMap.vllm) {
setIsGGUF(false); setIsGGUF(false);
@@ -79,6 +116,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
if (backend === backendOptionsMap.llamaBox) { if (backend === backendOptionsMap.llamaBox) {
setIsGGUF(true); setIsGGUF(true);
} }
updateShowWarning();
}; };
const handleCancel = useCallback(() => { const handleCancel = useCallback(() => {
@@ -92,6 +130,10 @@ const AddModal: React.FC<AddModalProps> = (props) => {
useEffect(() => { useEffect(() => {
if (!open) { if (!open) {
setIsGGUF(false); setIsGGUF(false);
setWarningStatus({
show: false,
message: ''
});
form.current?.setFieldValue?.('backend', backendOptionsMap.vllm); form.current?.setFieldValue?.('backend', backendOptionsMap.vllm);
} 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);
@@ -144,7 +186,13 @@ const AddModal: React.FC<AddModalProps> = (props) => {
<div style={{ display: 'flex', height: '100%' }}> <div style={{ display: 'flex', height: '100%' }}>
{SEARCH_SOURCE.includes(props.source) && ( {SEARCH_SOURCE.includes(props.source) && (
<> <>
<div style={{ display: 'flex', flex: 1 }}> <div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper> <ColumnWrapper>
<SearchModel <SearchModel
modelSource={props.source} modelSource={props.source}
@@ -153,7 +201,13 @@ const AddModal: React.FC<AddModalProps> = (props) => {
</ColumnWrapper> </ColumnWrapper>
<Separator></Separator> <Separator></Separator>
</div> </div>
<div style={{ display: 'flex', flex: 1 }}> <div
style={{
display: 'flex',
flex: 1,
maxWidth: '33.33%'
}}
>
<ColumnWrapper> <ColumnWrapper>
<ModelCard <ModelCard
selectedModel={selectedModel} selectedModel={selectedModel}
@@ -176,38 +230,53 @@ const AddModal: React.FC<AddModalProps> = (props) => {
</div> </div>
</> </>
)} )}
<ColumnWrapper <div style={{ display: 'flex', flex: 1, maxWidth: '100%' }}>
footer={ <ColumnWrapper
<ModalFooter paddingBottom={warningStatus.show ? 125 : 50}
onCancel={handleCancel} footer={
onOk={handleSumit} <>
style={{ {warningStatus.show && (
padding: '16px 24px', <AlertBlockInfo
display: 'flex', ellipsis={false}
justifyContent: 'flex-end' message={intl.formatMessage({ id: warningStatus.message })}
}} title={intl.formatMessage({
></ModalFooter> id: 'common.text.warning'
} })}
> type="warning"
<> ></AlertBlockInfo>
{SEARCH_SOURCE.includes(source) && ( )}
<TitleWrapper> <ModalFooter
{intl.formatMessage({ id: 'models.form.configurations' })} onCancel={handleCancel}
<span style={{ display: 'flex', height: 24 }}></span> onOk={handleSumit}
</TitleWrapper> style={{
)} padding: '16px 24px',
<DataForm display: 'flex',
source={source} justifyContent: 'flex-end'
action={action} }}
selectedModel={selectedModel} ></ModalFooter>
onOk={onOk} </>
ref={form} }
isGGUF={isGGUF} >
gpuOptions={props.gpuOptions} <>
onBackendChange={handleBackendChange} {SEARCH_SOURCE.includes(source) && (
></DataForm> <TitleWrapper>
</> {intl.formatMessage({ id: 'models.form.configurations' })}
</ColumnWrapper> <span style={{ display: 'flex', height: 24 }}></span>
</TitleWrapper>
)}
<DataForm
source={source}
action={action}
selectedModel={selectedModel}
onOk={onOk}
ref={form}
isGGUF={isGGUF}
gpuOptions={props.gpuOptions}
onBackendChange={handleBackendChange}
></DataForm>
</>
</ColumnWrapper>
</div>
</div> </div>
</Drawer> </Drawer>
); );
+32 -38
View File
@@ -126,20 +126,14 @@ const distributeCols: ColumnProps[] = [
key: 'gpu_index' key: 'gpu_index'
}, },
{ {
title: 'resources.table.vram', title: 'models.table.vram.allocated',
locale: true, locale: true,
key: 'vram', key: 'vram',
rowSpan: ({ row, rowIndex, colIndex, dataIndex, dataList }) => { // rowSpan: ({ row, rowIndex, colIndex, dataIndex, dataList }) => {
return rowIndex === 0 ? dataList.length : 0; // return rowIndex === 0 ? dataList.length : 0;
}, // },
render: ({ rowIndex, dataList }) => { render: ({ rowIndex, row, dataList }) => {
if (rowIndex === 0) { return convertFileSize(row.vram, 1);
return convertFileSize(
_.sumBy(dataList, (item: any) => item.vram),
2
);
}
return null;
} }
} }
]; ];
@@ -297,33 +291,33 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
const renderDistributedServer = useCallback( const renderDistributedServer = useCallback(
(severList: any[]) => { (severList: any[]) => {
const list = _.map(severList, (item: any) => { // const list = _.map(severList, (item: any) => {
const data = _.find(workerList, { id: item.worker_id }); // const data = _.find(workerList, { id: item.worker_id });
return { // return {
worker_name: data?.name, // worker_name: data?.name,
worker_ip: data?.ip, // worker_ip: data?.ip,
port: '', // port: '',
vram: calcTotalVram(item.computed_resource_claim?.vram || {}), // vram: calcTotalVram(item.computed_resource_claim?.vram || {}),
gpu_index: _.keys(item.computed_resource_claim?.vram).join(',') // gpu_index: _.keys(item.computed_resource_claim?.vram).join(',')
}; // };
}); // });
// const list = [ const list = [
// { {
// worker_name: 'worker1', worker_name: 'worker1',
// worker_ip: '192.168.50.23', worker_ip: '192.168.50.23',
// port: '', port: '',
// vram: 21555525632, vram: 21555525632,
// gpu_index: '0,1' gpu_index: '0,1'
// }, },
// { {
// worker_name: 'worker2', worker_name: 'worker2',
// worker_ip: '192.168.50.25', worker_ip: '192.168.50.25',
// port: '', port: '',
// vram: 21555525632, vram: 21555525632,
// gpu_index: '2,3' gpu_index: '2,3'
// } }
// ]; ];
const mainWorker = [ const mainWorker = [
{ {
+6 -2
View File
@@ -459,7 +459,9 @@ const Models: React.FC<ModelsProps> = ({
}); });
setOpenAddModal(false); setOpenAddModal(false);
message.success(intl.formatMessage({ id: 'common.message.success' })); message.success(intl.formatMessage({ id: 'common.message.success' }));
handleSearch(); setTimeout(() => {
handleSearch();
}, 150);
restoreScrollHeight(); restoreScrollHeight();
} catch (error) {} } catch (error) {}
}, },
@@ -499,7 +501,9 @@ const Models: React.FC<ModelsProps> = ({
updateExpandedRowKeys([modelData.id, ...expandedRowKeys]); updateExpandedRowKeys([modelData.id, ...expandedRowKeys]);
}, 300); }, 300);
message.success(intl.formatMessage({ id: 'common.message.success' })); message.success(intl.formatMessage({ id: 'common.message.success' }));
handleSearch?.(); setTimeout(() => {
handleSearch?.();
}, 150);
} catch (error) {} } catch (error) {}
}, },
[openDeployModal] [openDeployModal]
+89 -28
View File
@@ -1,3 +1,4 @@
import AlertBlockInfo from '@/components/alert-info/block';
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import ModalFooter from '@/components/modal-footer'; import ModalFooter from '@/components/modal-footer';
import SealAutoComplete from '@/components/seal-form/auto-complete'; import SealAutoComplete from '@/components/seal-form/auto-complete';
@@ -8,9 +9,7 @@ import { PageActionType } from '@/config/types';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form, Modal, Tooltip, Typography } from 'antd'; import { Form, Modal, Tooltip, Typography } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
import SimpleBar from 'simplebar-react';
import 'simplebar-react/dist/simplebar.min.css';
import { import {
backendOptionsMap, backendOptionsMap,
modelSourceMap, modelSourceMap,
@@ -18,6 +17,7 @@ import {
} from '../config'; } from '../config';
import { FormData, ListItem } from '../config/types'; import { FormData, ListItem } from '../config/types';
import AdvanceConfig from './advance-config'; import AdvanceConfig from './advance-config';
import ColumnWrapper from './column-wrapper';
type AddModalProps = { type AddModalProps = {
title: string; title: string;
@@ -73,6 +73,13 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const intl = useIntl(); const intl = useIntl();
const localPathCache = useRef<string>(''); const localPathCache = useRef<string>('');
const [warningStatus, setWarningStatus] = useState<{
show: boolean;
message: string;
}>({
show: false,
message: ''
});
const handleSetGPUIds = (backend: string) => { const handleSetGPUIds = (backend: string) => {
if (backend === backendOptionsMap.llamaBox) { if (backend === backendOptionsMap.llamaBox) {
@@ -88,7 +95,36 @@ const UpdateModal: React.FC<AddModalProps> = (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) { if (val === backendOptionsMap.llamaBox) {
form.setFieldsValue({ form.setFieldsValue({
distributed_inference_across_workers: true, distributed_inference_across_workers: true,
@@ -97,7 +133,8 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
} }
form.setFieldValue('backend_version', ''); form.setFieldValue('backend_version', '');
handleSetGPUIds(val); handleSetGPUIds(val);
}, []); updateShowWarning();
};
const handleOnFocus = () => { const handleOnFocus = () => {
localPathCache.current = form.getFieldValue('local_path'); localPathCache.current = form.getFieldValue('local_path');
@@ -188,23 +225,25 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
defaultActiveFirstOption defaultActiveFirstOption
disabled={false} disabled={false}
options={ollamaModelOptions} options={ollamaModelOptions}
label={intl.formatMessage({ id: 'model.form.ollama.model' })}
placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })} placeholder={intl.formatMessage({ id: 'model.form.ollamaholder' })}
addAfter={ label={
<Typography.Link <>
href="https://www.ollama.com/library" {intl.formatMessage({ id: 'model.form.ollama.model' })}{' '}
target="_blank" <Typography.Link
> href="https://www.ollama.com/library"
<Tooltip target="_blank"
title={intl.formatMessage({ id: 'models.form.ollamalink' })}
placement="topRight"
> >
<IconFont <Tooltip
type="icon-external-link" title={intl.formatMessage({ id: 'models.form.ollamalink' })}
className="font-size-14" placement="topRight"
></IconFont> >
</Tooltip> <IconFont
</Typography.Link> type="icon-external-link"
className="font-size-14"
></IconFont>
</Tooltip>
</Typography.Link>
</>
} }
required required
></SealAutoComplete> ></SealAutoComplete>
@@ -336,6 +375,12 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
if (open && formData) { if (open && formData) {
form.setFieldsValue(formData); form.setFieldsValue(formData);
} }
if (!open) {
setWarningStatus({
show: false,
message: ''
});
}
}, [open, formData]); }, [open, formData]);
return ( return (
@@ -353,7 +398,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
width={600} width={600}
styles={{ styles={{
content: { content: {
padding: '0px' padding: '0 0 16px 0'
}, },
header: { header: {
padding: 'var(--ant-modal-content-padding)', padding: 'var(--ant-modal-content-padding)',
@@ -363,17 +408,33 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
padding: '0' padding: '0'
}, },
footer: { footer: {
padding: '0 var(--ant-modal-content-padding)' padding: '16px 24px',
margin: '0'
} }
}} }}
footer={ footer={
<ModalFooter onCancel={onCancel} onOk={handleSumit}></ModalFooter> <>
<ModalFooter onCancel={onCancel} onOk={handleSumit}></ModalFooter>
</>
} }
> >
<SimpleBar <ColumnWrapper
style={{ maxHeight={550}
maxHeight: '550px' paddingBottom={warningStatus.show ? 85 : 0}
}} footer={
<>
{warningStatus.show && (
<AlertBlockInfo
ellipsis={false}
message={intl.formatMessage({ id: warningStatus.message })}
title={intl.formatMessage({
id: 'common.text.warning'
})}
type="warning"
></AlertBlockInfo>
)}
</>
}
> >
<Form <Form
name="addModalForm" name="addModalForm"
@@ -519,7 +580,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
isGGUF={formData?.backend === backendOptionsMap.llamaBox} isGGUF={formData?.backend === backendOptionsMap.llamaBox}
></AdvanceConfig> ></AdvanceConfig>
</Form> </Form>
</SimpleBar> </ColumnWrapper>
</Modal> </Modal>
); );
}; };
@@ -1,6 +1,8 @@
.column-wrapper { .column-wrapper {
flex: 1; flex: 1;
position: relative; position: relative;
height: 100%;
overflow-y: auto;
} }
.simplebar-scrollbar::before { .simplebar-scrollbar::before {
@@ -1,6 +1,6 @@
import IconFont from '@/components/icon-font'; import IconFont from '@/components/icon-font';
import HotKeys, { KeyMap } from '@/config/hotkeys'; 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 { useIntl } from '@umijs/max';
import { Button, Checkbox, Divider, Input, Tooltip } from 'antd'; import { Button, Checkbox, Divider, Input, Tooltip } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
@@ -425,7 +425,7 @@ const MessageInput: React.FC<MessageInputProps> = forwardRef(
disabled={isDisabled} disabled={isDisabled}
> >
{submitIcon ?? ( {submitIcon ?? (
<EnterOutlined rotate={0} className="font-size-14" /> <SendOutlined rotate={0} className="font-size-14" />
)} )}
</Button> </Button>
</Tooltip> </Tooltip>