fix: miss gpu_selector value in catalog

This commit is contained in:
jialin
2025-04-03 13:36:09 +08:00
parent dd8059693d
commit 939f46c7e6
14 changed files with 156 additions and 64 deletions
+9 -5
View File
@@ -2,7 +2,7 @@ import { CheckCircleFilled, CopyOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Button, Tooltip, message } from 'antd'; import { Button, Tooltip, message } from 'antd';
import ClipboardJS from 'clipboard'; import ClipboardJS from 'clipboard';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useMemo, useRef, useState } from 'react';
type CopyButtonProps = { type CopyButtonProps = {
children?: React.ReactNode; children?: React.ReactNode;
@@ -63,6 +63,13 @@ const CopyButton: React.FC<CopyButtonProps> = ({
} }
}; };
const tipTitle = useMemo(() => {
if (copied) {
return intl.formatMessage({ id: 'common.button.copied' });
}
return tips ?? intl.formatMessage({ id: 'common.button.copy' });
}, [copied, intl, tips]);
useEffect(() => { useEffect(() => {
initClipboard(); initClipboard();
return () => { return () => {
@@ -71,10 +78,7 @@ const CopyButton: React.FC<CopyButtonProps> = ({
}, [buttonRef]); }, [buttonRef]);
return ( return (
<Tooltip <Tooltip title={tipTitle} placement={placement}>
title={tips ?? intl.formatMessage({ id: 'common.button.copy' })}
placement={placement}
>
<Button <Button
className="copy-button" className="copy-button"
ref={buttonRef} ref={buttonRef}
+1
View File
@@ -15,6 +15,7 @@ export default {
'common.button.run': 'Run', 'common.button.run': 'Run',
'common.button.viewcode': 'View Code', 'common.button.viewcode': 'View Code',
'common.button.copy': 'Copy', 'common.button.copy': 'Copy',
'common.button.copied': 'Copied',
'common.button.collapse': 'Collapse', 'common.button.collapse': 'Collapse',
'common.button.expand': 'Expand', 'common.button.expand': 'Expand',
'common.button.cancel': 'Cancel', 'common.button.cancel': 'Cancel',
+5
View File
@@ -15,6 +15,7 @@ export default {
'common.button.run': '実行', 'common.button.run': '実行',
'common.button.viewcode': 'コードを表示', 'common.button.viewcode': 'コードを表示',
'common.button.copy': 'コピー', 'common.button.copy': 'コピー',
'common.button.copied': 'Copied',
'common.button.collapse': '折りたたむ', 'common.button.collapse': '折りたたむ',
'common.button.expand': '展開', 'common.button.expand': '展開',
'common.button.cancel': 'キャンセル', 'common.button.cancel': 'キャンセル',
@@ -235,3 +236,7 @@ export default {
'common.text.error': 'エラー', 'common.text.error': 'エラー',
'common.text.tips': 'ヒント' 'common.text.tips': 'ヒント'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'common.button.copied',
// ========== End of To-Do List ==========
+5
View File
@@ -15,6 +15,7 @@ export default {
'common.button.run': 'Запустить', 'common.button.run': 'Запустить',
'common.button.viewcode': 'Посмотреть код', 'common.button.viewcode': 'Посмотреть код',
'common.button.copy': 'Копировать', 'common.button.copy': 'Копировать',
'common.button.copied': 'Copied',
'common.button.collapse': 'Свернуть', 'common.button.collapse': 'Свернуть',
'common.button.expand': 'Развернуть', 'common.button.expand': 'Развернуть',
'common.button.cancel': 'Отмена', 'common.button.cancel': 'Отмена',
@@ -233,3 +234,7 @@ export default {
'common.text.error': 'Ошибка', 'common.text.error': 'Ошибка',
'common.text.tips': 'Советы' 'common.text.tips': 'Советы'
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ==========
// 1. 'common.button.copied',
// ========== End of To-Do List ==========
+1
View File
@@ -15,6 +15,7 @@ export default {
'common.button.run': '运行', 'common.button.run': '运行',
'common.button.viewcode': '查看代码', 'common.button.viewcode': '查看代码',
'common.button.copy': '复制', 'common.button.copy': '复制',
'common.button.copied': '复制成功',
'common.button.collapse': '折叠', 'common.button.collapse': '折叠',
'common.button.expand': '展开', 'common.button.expand': '展开',
'common.button.submit': '提交', 'common.button.submit': '提交',
@@ -157,32 +157,18 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
const handleBackendParametersOnBlur = () => { const handleBackendParametersOnBlur = () => {
const backendParams = form.getFieldValue('backend_parameters'); const backendParams = form.getFieldValue('backend_parameters');
console.log('backendParams==', backendParams); onValuesChange?.({}, form.getFieldsValue());
onValuesChange?.({
source: source,
allValues: form.getFieldsValue(),
changedValues: {}
});
}; };
const handleSelectorOnBlur = () => { const handleSelectorOnBlur = () => {
const workerSelector = form.getFieldValue('worker_selector'); const workerSelector = form.getFieldValue('worker_selector');
console.log('workerSelector==', workerSelector); onValuesChange?.({}, form.getFieldsValue());
onValuesChange?.({
source: source,
allValues: form.getFieldsValue(),
changedValues: {}
});
}; };
const handleBackendVersionOnBlur = () => { const handleBackendVersionOnBlur = () => {
const backendVersion = form.getFieldValue('backend_version'); const backendVersion = form.getFieldValue('backend_version');
if (backendVersion) { if (backendVersion) {
onValuesChange?.({ onValuesChange?.({}, form.getFieldsValue());
source: source,
allValues: form.getFieldsValue(),
changedValues: {}
});
} }
}; };
@@ -111,6 +111,11 @@ const AddModal: React.FC<AddModalProps> = (props) => {
form.current?.submit?.(); form.current?.submit?.();
}; };
const pickSomeFieldsValue = () => {
const formData = form.current?.getFieldsValue();
return _.pick(formData, ['worker_selector', 'gpu_selector', 'env']);
};
const generateSubmitData = (formData: FormData) => { const generateSubmitData = (formData: FormData) => {
const gpuSelector = generateGPUIds(formData); const gpuSelector = generateGPUIds(formData);
const data = { const data = {
@@ -285,13 +290,32 @@ const AddModal: React.FC<AddModalProps> = (props) => {
}; };
const onValuesChange = async (changedValues: any, allValues: any) => { const onValuesChange = async (changedValues: any, allValues: any) => {
const data = {
..._.omit(selectSpecRef.current, ['name']),
...allValues
};
handleOnValuesChange?.({ handleOnValuesChange?.({
changedValues, changedValues,
allValues: generateSubmitData(allValues), allValues: data,
source: props.source source: props.source
}); });
}; };
const handleAdvanceOnValuesChange = (data: {
changedValues: any;
allValues: any;
source: string;
}) => {
handleOnValuesChange?.({
changedValues: data.changedValues,
allValues: {
..._.omit(selectSpecRef.current, ['name']),
...data.allValues
},
source: data.source
});
};
const handleBackendChange = (backend: string) => { const handleBackendChange = (backend: string) => {
if (backend === backendOptionsMap.vllm) { if (backend === backendOptionsMap.vllm) {
setIsGGUF(false); setIsGGUF(false);
@@ -392,7 +416,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
quantization: val quantization: val
}); });
form.current.setFieldsValue({ form.current.setFieldsValue({
...data ...data,
...pickSomeFieldsValue()
}); });
handleCheckFormData(); handleCheckFormData();
}; };
@@ -413,7 +438,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
// set form data // set form data
form.current.setFieldsValue({ form.current.setFieldsValue({
...data ...data,
...pickSomeFieldsValue()
}); });
handleCheckFormData(); handleCheckFormData();
}; };
@@ -497,7 +523,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
quantizationOptions: quantizationOptions, quantizationOptions: quantizationOptions,
onSizeChange: handleOnSizeChange, onSizeChange: handleOnSizeChange,
onQuantizationChange: handleOnQuantizationChange, onQuantizationChange: handleOnQuantizationChange,
onValuesChange: handleOnValuesChange onValuesChange: onValuesChange
}} }}
> >
<FormWrapper> <FormWrapper>
@@ -275,7 +275,7 @@ const AddModal: FC<AddModalProps> = (props) => {
value={{ value={{
isGGUF: isGGUF, isGGUF: isGGUF,
modelFileOptions: props.modelFileOptions, modelFileOptions: props.modelFileOptions,
onValuesChange: handleOnValuesChange onValuesChange: onValuesChange
}} }}
> >
<FormWrapper> <FormWrapper>
@@ -331,6 +331,14 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
}); });
}; };
const handleManulOnValuesChange = (changedValues: any, allValues: any) => {
handleOnValuesChange({
changedValues,
allValues,
source: formData?.source as string
});
};
const handleOnClose = () => { const handleOnClose = () => {
onCancel?.(); onCancel?.();
}; };
@@ -425,7 +433,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
> >
<FormContext.Provider <FormContext.Provider
value={{ value={{
onValuesChange: handleOnValuesChange onValuesChange: handleManulOnValuesChange
}} }}
> >
<Form <Form
+1 -1
View File
@@ -8,7 +8,7 @@ interface FormContextProps {
modelFileOptions?: any[]; modelFileOptions?: any[];
onSizeChange?: (val: number) => void; onSizeChange?: (val: number) => void;
onQuantizationChange?: (val: string) => void; onQuantizationChange?: (val: string) => void;
onValuesChange?: (val: any) => void; onValuesChange?: (changedValues: any, allValues: any) => void;
} }
interface FormInnerContextProps { interface FormInnerContextProps {
-1
View File
@@ -366,7 +366,6 @@ export const getSourceRepoConfigValue = (
omits.push(key); omits.push(key);
} }
}); });
return { return {
values: { ...result, ..._.omit(data, omits) } values: { ...result, ..._.omit(data, omits) }
}; };
+2 -1
View File
@@ -382,7 +382,7 @@ export const useCheckCompatibility = () => {
return { return {
gpu_selector: { gpu_selector: {
gpu_ids: result gpu_ids: result || []
} }
}; };
}; };
@@ -393,6 +393,7 @@ export const useCheckCompatibility = () => {
source: string; source: string;
}) => { }) => {
const { changedValues, allValues, source } = params; const { changedValues, allValues, source } = params;
console.log('params+++++++', params);
if ( if (
_.isEqual(cacheFormValuesRef.current, allValues) || _.isEqual(cacheFormValuesRef.current, allValues) ||
+86 -31
View File
@@ -1,8 +1,8 @@
import { modelsExpandKeysAtom } from '@/atoms/models'; import { modelsExpandKeysAtom } from '@/atoms/models';
import AutoTooltip from '@/components/auto-tooltip'; import AutoTooltip from '@/components/auto-tooltip';
import CopyButton from '@/components/copy-button';
import DeleteModal from '@/components/delete-modal'; import DeleteModal from '@/components/delete-modal';
import DropdownButtons from '@/components/drop-down-buttons'; import DropdownButtons from '@/components/drop-down-buttons';
import OverlayScroller from '@/components/overlay-scroller';
import { FilterBar } from '@/components/page-tools'; import { FilterBar } from '@/components/page-tools';
import StatusTag from '@/components/status-tag'; import StatusTag from '@/components/status-tag';
import { PageAction } from '@/config'; import { PageAction } from '@/config';
@@ -25,12 +25,25 @@ import {
import { SourceType } from '@/pages/llmodels/config/types'; import { SourceType } from '@/pages/llmodels/config/types';
import DownloadModal from '@/pages/llmodels/download'; import DownloadModal from '@/pages/llmodels/download';
import { convertFileSize } from '@/utils'; import { convertFileSize } from '@/utils';
import {
CheckCircleFilled,
CopyOutlined,
InfoCircleOutlined
} from '@ant-design/icons';
import { useIntl, useNavigate } from '@umijs/max'; import { useIntl, useNavigate } from '@umijs/max';
import { ConfigProvider, Empty, Table, Tag, message } from 'antd'; import {
ConfigProvider,
Empty,
Table,
Tag,
Tooltip,
Typography,
message
} from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import _ from 'lodash'; import _ from 'lodash';
import { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {
useGenerateFormEditInitialValues, useGenerateFormEditInitialValues,
@@ -86,6 +99,44 @@ const PathWrapper = styled.div`
} }
`; `;
const ItemWrapper = styled.ul`
max-width: 300px;
margin: 0;
padding-inline: 8px 0;
word-break: break-word;
`;
const FilesTag = styled(Tag)`
cursor: pointer;
display: flex;
align-items: center;
margin-inline: 4px 0;
height: 22px;
border-radius: var(--border-radius-base);
`;
const TooltipTitle: React.FC<{ path: string }> = ({ path }) => {
const intl = useIntl();
return (
<Typography.Paragraph
style={{ background: 'transparent', color: 'inherit' }}
copyable={{
icon: [
<CopyOutlined key="copy-icon" />,
<CheckCircleFilled key="copied-icon" />
],
text: path,
tooltips: [
intl.formatMessage({ id: 'common.button.copy' }),
intl.formatMessage({ id: 'common.button.copied' })
]
}}
>
{path}
</Typography.Paragraph>
);
};
const getWorkerName = ( const getWorkerName = (
id: number, id: number,
workersList: Global.BaseOption<number>[] workersList: Global.BaseOption<number>[]
@@ -260,27 +311,33 @@ const ModelFiles = () => {
}; };
const renderParts = (record: ListItem) => { const renderParts = (record: ListItem) => {
const parts = _.tail(record.resolved_paths); const parts = record.resolved_paths || [];
if (!parts.length) { if (parts.length <= 1) {
return null; return null;
} }
const renderItem = () => {
return (
<ItemWrapper>
{parts.map((item: string, index: number) => {
return <li key={index}>{_.split(item, /[\\/]/).pop()}</li>;
})}
</ItemWrapper>
);
};
return ( return (
<Tag <Tooltip
className="flex-center" title={<OverlayScroller>{renderItem()}</OverlayScroller>}
color="purple" overlayInnerStyle={{ width: 'max-content', maxWidth: 300 }}
style={{
marginRight: 0,
marginLeft: 4,
height: 22,
borderRadius: 'var(--border-radius-base)'
}}
> >
<span style={{ opacity: 1 }}> <FilesTag color="purple" icon={<InfoCircleOutlined />}>
{record.resolved_paths?.length}{' '} <span style={{ opacity: 1 }}>
{intl.formatMessage({ id: 'models.form.files' })} {record.resolved_paths?.length}{' '}
</span> {intl.formatMessage({ id: 'models.form.files' })}
</Tag> </span>
</FilesTag>
</Tooltip>
); );
}; };
@@ -467,19 +524,17 @@ const ModelFiles = () => {
return ( return (
record.resolved_paths?.length > 0 && ( record.resolved_paths?.length > 0 && (
<PathWrapper> <PathWrapper>
<AutoTooltip ghost title={record.resolved_paths?.[0]} showTitle> <AutoTooltip
ghost
showTitle
title={
<TooltipTitle
path={record.resolved_paths?.[0]}
></TooltipTitle>
}
>
<span>{getResolvedPath(record.resolved_paths)}</span> <span>{getResolvedPath(record.resolved_paths)}</span>
</AutoTooltip> </AutoTooltip>
<span className="btn-wrapper">
<CopyButton
text={record.resolved_paths?.[0]}
type="link"
btnStyle={{ width: 18, paddingInline: 2 }}
tips={intl.formatMessage({
id: 'resources.modelfiles.copy.tips'
})}
></CopyButton>
</span>
{renderParts(record)} {renderParts(record)}
</PathWrapper> </PathWrapper>
) )
@@ -493,7 +548,7 @@ const ModelFiles = () => {
render: (text: string, record: ListItem) => { render: (text: string, record: ListItem) => {
return ( return (
<AutoTooltip ghost maxWidth={100}> <AutoTooltip ghost maxWidth={100}>
<span>{convertFileSize(record.size, 1)}</span> <span>{convertFileSize(record.size, 1, true)}</span>
</AutoTooltip> </AutoTooltip>
); );
} }
+3 -2
View File
@@ -21,11 +21,12 @@ export const handleBatchRequest = async (
export const convertFileSize = ( export const convertFileSize = (
sizeInBytes: number | undefined, sizeInBytes: number | undefined,
prec?: number prec?: number,
allowEmpty = false
) => { ) => {
const precision = prec ?? 1; const precision = prec ?? 1;
if (!sizeInBytes) { if (!sizeInBytes) {
return '0'; return allowEmpty ? '' : '0';
} }
if (sizeInBytes < 1024) { if (sizeInBytes < 1024) {
return `${sizeInBytes.toFixed(precision)} B`; return `${sizeInBytes.toFixed(precision)} B`;