fix: the fields for trigger checking
This commit is contained in:
@@ -27,6 +27,21 @@
|
|||||||
border-color: var(--ant-geekblue-3);
|
border-color: var(--ant-geekblue-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
border: 1px solid var(--color-progress-green);
|
||||||
|
color: var(--color-progress-green);
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
color: var(--color-progress-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content.success {
|
||||||
|
color: var(--color-progress-green);
|
||||||
|
font-weight: var(--font-weight-normal);
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -48,6 +63,10 @@
|
|||||||
&.transition {
|
&.transition {
|
||||||
color: var(--ant-geekblue-7);
|
color: var(--ant-geekblue-7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.success {
|
||||||
|
color: var(--color-progress-green);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text {
|
.text {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import styled from 'styled-components';
|
|||||||
import OverlayScroller from '../overlay-scroller';
|
import OverlayScroller from '../overlay-scroller';
|
||||||
import './block.less';
|
import './block.less';
|
||||||
interface AlertInfoProps {
|
interface AlertInfoProps {
|
||||||
type: 'danger' | 'warning' | 'transition' | 'info';
|
type: Global.MessageType;
|
||||||
message: React.ReactNode;
|
message: React.ReactNode;
|
||||||
rows?: number;
|
rows?: number;
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
@@ -62,9 +62,16 @@ const AlertInfo: React.FC<AlertInfoProps> = (props) => {
|
|||||||
{icon ?? <WarningFilled />}
|
{icon ?? <WarningFilled />}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{title && <TitleWrapper>{title}</TitleWrapper>}
|
{title && (
|
||||||
|
<TitleWrapper className="title-text">{title}</TitleWrapper>
|
||||||
|
)}
|
||||||
<OverlayScroller maxHeight={80} style={{ ...contentStyle }}>
|
<OverlayScroller maxHeight={80} style={{ ...contentStyle }}>
|
||||||
<ContentWrapper $hasTitle={!!title}>{message}</ContentWrapper>
|
<ContentWrapper
|
||||||
|
$hasTitle={!!title}
|
||||||
|
className={classNames('content', type)}
|
||||||
|
>
|
||||||
|
{message}
|
||||||
|
</ContentWrapper>
|
||||||
</OverlayScroller>
|
</OverlayScroller>
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Vendored
+2
@@ -42,6 +42,8 @@ declare namespace Global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SearchParams = Pagination & { search?: string };
|
type SearchParams = Pagination & { search?: string };
|
||||||
|
|
||||||
|
type MessageType = 'transition' | 'warning' | 'danger' | 'success' | 'info';
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
|
|||||||
@@ -126,5 +126,8 @@ export default {
|
|||||||
'models.form.restart.onerror': 'Auto-Restart On Error',
|
'models.form.restart.onerror': 'Auto-Restart On Error',
|
||||||
'models.form.restart.onerror.tips':
|
'models.form.restart.onerror.tips':
|
||||||
'When an error occurs, it will automatically attempt to restart.',
|
'When an error occurs, it will automatically attempt to restart.',
|
||||||
'models.form.check.params': 'Checking configuration...'
|
'models.form.check.params': 'Checking configuration...',
|
||||||
|
'models.form.check.passed': 'Check Compatibility Passed',
|
||||||
|
'models.form.check.claims':
|
||||||
|
'The model requires approximately {vram} VRAM and {ram} RAM.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -123,7 +123,10 @@ export default {
|
|||||||
'models.form.restart.onerror': 'Auto-Restart On Error',
|
'models.form.restart.onerror': 'Auto-Restart On Error',
|
||||||
'models.form.restart.onerror.tips':
|
'models.form.restart.onerror.tips':
|
||||||
'When an error occurs, it will automatically attempt to restart.',
|
'When an error occurs, it will automatically attempt to restart.',
|
||||||
'models.form.check.params': 'Checking configuration...'
|
'models.form.check.params': 'Checking configuration...',
|
||||||
|
'models.form.check.passed': 'Check Compatibility Passed',
|
||||||
|
'models.form.check.claims':
|
||||||
|
'The model requires approximately {vram} VRAM and {ram} RAM.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -136,5 +139,7 @@ export default {
|
|||||||
// 7. 'models.form.restart.onerror.tips',
|
// 7. 'models.form.restart.onerror.tips',
|
||||||
// 8. 'models.form.check.params',
|
// 8. 'models.form.check.params',
|
||||||
// 9. 'models.form.partialoffload.tips',
|
// 9. 'models.form.partialoffload.tips',
|
||||||
// 10. 'models.form.distribution.tips
|
// 10. 'models.form.distribution.tips,
|
||||||
|
// 11. 'models.form.check.passed',
|
||||||
|
// 12. 'models.form.check.claims',
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -126,10 +126,15 @@ export default {
|
|||||||
'models.form.restart.onerror': 'Автоперезапуск при ошибке',
|
'models.form.restart.onerror': 'Автоперезапуск при ошибке',
|
||||||
'models.form.restart.onerror.tips':
|
'models.form.restart.onerror.tips':
|
||||||
'При возникновении ошибки система автоматически попытается перезапуститься.',
|
'При возникновении ошибки система автоматически попытается перезапуститься.',
|
||||||
'models.form.check.params': 'Проверка конфигурации...'
|
'models.form.check.params': 'Проверка конфигурации...',
|
||||||
|
'models.form.check.passed': 'Check Compatibility Passed',
|
||||||
|
'models.form.check.claims':
|
||||||
|
'The model requires approximately {vram} VRAM and {ram} RAM.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'models.form.partialoffload.tips',
|
// 1. 'models.form.partialoffload.tips',
|
||||||
// 2. 'models.form.distribution.tips
|
// 2. 'models.form.distribution.tips,
|
||||||
|
// 3. 'models.form.check.passed',
|
||||||
|
// 4. 'models.form.check.claims',
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -75,5 +75,5 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'resources.filter.path'
|
// 1. 'resources.filter.path',
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -120,5 +120,7 @@ export default {
|
|||||||
'models.form.incompatible': '检测到不兼容',
|
'models.form.incompatible': '检测到不兼容',
|
||||||
'models.form.restart.onerror': '错误时重启',
|
'models.form.restart.onerror': '错误时重启',
|
||||||
'models.form.restart.onerror.tips': '当发生错误时,将自动尝试恢复',
|
'models.form.restart.onerror.tips': '当发生错误时,将自动尝试恢复',
|
||||||
'models.form.check.params': '正在校验配置...'
|
'models.form.check.params': '正在校验配置...',
|
||||||
|
'models.form.check.passed': '兼容性检查通过',
|
||||||
|
'models.form.check.claims': '该模型大约需要 {vram} 显存和 {ram} 内存.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ const Catalog: React.FC = () => {
|
|||||||
allowClear
|
allowClear
|
||||||
showSearch={false}
|
showSearch={false}
|
||||||
placeholder={intl.formatMessage({ id: 'models.filter.category' })}
|
placeholder={intl.formatMessage({ id: 'models.filter.category' })}
|
||||||
style={{ width: 230 }}
|
style={{ width: 180 }}
|
||||||
size="large"
|
size="large"
|
||||||
maxTagCount={1}
|
maxTagCount={1}
|
||||||
onChange={handleCategoryChange}
|
onChange={handleCategoryChange}
|
||||||
|
|||||||
@@ -162,14 +162,18 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
|
|
||||||
const handleSelectorOnBlur = () => {
|
const handleSelectorOnBlur = () => {
|
||||||
const workerSelector = form.getFieldValue('worker_selector');
|
const workerSelector = form.getFieldValue('worker_selector');
|
||||||
onValuesChange?.({}, form.getFieldsValue());
|
// check if all keys have values
|
||||||
|
const hasEmptyValue = _.some(_.keys(workerSelector), (k: string) => {
|
||||||
|
return !workerSelector[k];
|
||||||
|
});
|
||||||
|
if (!hasEmptyValue) {
|
||||||
|
onValuesChange?.({}, form.getFieldsValue());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackendVersionOnBlur = () => {
|
const handleBackendVersionOnBlur = () => {
|
||||||
const backendVersion = form.getFieldValue('backend_version');
|
const backendVersion = form.getFieldValue('backend_version');
|
||||||
if (backendVersion) {
|
onValuesChange?.({}, form.getFieldsValue());
|
||||||
onValuesChange?.({}, form.getFieldsValue());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const collapseItems = useMemo(() => {
|
const collapseItems = useMemo(() => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import AlertBlockInfo from '@/components/alert-info/block';
|
import AlertBlockInfo from '@/components/alert-info/block';
|
||||||
import {
|
import {
|
||||||
|
CheckCircleFilled,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
LoadingOutlined,
|
LoadingOutlined,
|
||||||
WarningFilled
|
WarningFilled
|
||||||
@@ -13,7 +14,7 @@ interface CompatibilityAlertProps {
|
|||||||
show: boolean;
|
show: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
isHtml?: boolean;
|
isHtml?: boolean;
|
||||||
type?: 'danger' | 'warning' | 'transition';
|
type?: Global.MessageType;
|
||||||
message: string | string[];
|
message: string | string[];
|
||||||
};
|
};
|
||||||
contentStyle?: React.CSSProperties;
|
contentStyle?: React.CSSProperties;
|
||||||
@@ -28,7 +29,7 @@ const DivWrapper = styled.div`
|
|||||||
|
|
||||||
const CloseWrapper = styled.div`
|
const CloseWrapper = styled.div`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 10px;
|
||||||
right: 18px;
|
right: 18px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: var(--ant-color-warning-bg);
|
background-color: var(--ant-color-warning-bg);
|
||||||
@@ -43,7 +44,7 @@ const MessageWrapper = styled.div`
|
|||||||
|
|
||||||
const CompatibilityAlert: React.FC<CompatibilityAlertProps> = (props) => {
|
const CompatibilityAlert: React.FC<CompatibilityAlertProps> = (props) => {
|
||||||
const { warningStatus, contentStyle, showClose, onClose } = props;
|
const { warningStatus, contentStyle, showClose, onClose } = props;
|
||||||
const { title, show, message, isHtml, type } = warningStatus;
|
const { title, show, message, isHtml, type = 'warning' } = warningStatus;
|
||||||
|
|
||||||
const renderMessage = useMemo(() => {
|
const renderMessage = useMemo(() => {
|
||||||
if (!message || !show) {
|
if (!message || !show) {
|
||||||
@@ -73,6 +74,16 @@ const CompatibilityAlert: React.FC<CompatibilityAlertProps> = (props) => {
|
|||||||
return '';
|
return '';
|
||||||
}, [message, show]);
|
}, [message, show]);
|
||||||
|
|
||||||
|
const renderIcon = useMemo(() => {
|
||||||
|
if (type === 'transition') {
|
||||||
|
return <LoadingOutlined />;
|
||||||
|
}
|
||||||
|
if (type === 'success') {
|
||||||
|
return <CheckCircleFilled />;
|
||||||
|
}
|
||||||
|
return <WarningFilled />;
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
show && (
|
show && (
|
||||||
<DivWrapper>
|
<DivWrapper>
|
||||||
@@ -82,9 +93,9 @@ const CompatibilityAlert: React.FC<CompatibilityAlertProps> = (props) => {
|
|||||||
title={title}
|
title={title}
|
||||||
contentStyle={contentStyle}
|
contentStyle={contentStyle}
|
||||||
type={type || 'warning'}
|
type={type || 'warning'}
|
||||||
icon={type === 'transition' ? <LoadingOutlined /> : <WarningFilled />}
|
icon={renderIcon}
|
||||||
></AlertBlockInfo>
|
></AlertBlockInfo>
|
||||||
{showClose && type !== 'transition' && (
|
{showClose && !['transition', 'success'].includes(type) && (
|
||||||
<CloseWrapper onClick={onClose}>
|
<CloseWrapper onClick={onClose}>
|
||||||
<CloseOutlined />
|
<CloseOutlined />
|
||||||
</CloseWrapper>
|
</CloseWrapper>
|
||||||
|
|||||||
@@ -79,9 +79,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
width = 600
|
width = 600
|
||||||
} = props || {};
|
} = props || {};
|
||||||
const {
|
const {
|
||||||
handleShowCompatibleAlert,
|
|
||||||
setWarningStatus,
|
setWarningStatus,
|
||||||
handleEvaluate,
|
handleDoEvalute,
|
||||||
generateGPUIds,
|
generateGPUIds,
|
||||||
cancelEvaluate,
|
cancelEvaluate,
|
||||||
submitAnyway,
|
submitAnyway,
|
||||||
@@ -228,17 +227,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleCheckCompatibility = async (formData: FormData) => {
|
const handleCheckCompatibility = async (formData: FormData) => {
|
||||||
const evalutionData = await handleEvaluate(formData);
|
handleDoEvalute(formData);
|
||||||
|
|
||||||
if (evalutionData?.compatible) {
|
|
||||||
setWarningStatus({
|
|
||||||
show: false,
|
|
||||||
message: ''
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
handleShowCompatibleAlert?.(evalutionData);
|
|
||||||
}
|
|
||||||
return evalutionData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCheckFormData = () => {
|
const handleCheckFormData = () => {
|
||||||
@@ -551,9 +540,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
|
|||||||
<ModalFooter
|
<ModalFooter
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onOk={handleSumit}
|
onOk={handleSumit}
|
||||||
showOkBtn={!warningStatus.show}
|
showOkBtn={
|
||||||
|
!warningStatus.show || warningStatus.type === 'success'
|
||||||
|
}
|
||||||
extra={
|
extra={
|
||||||
warningStatus.show && (
|
warningStatus.show &&
|
||||||
|
warningStatus.type !== 'success' && (
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSubmitAnyway}
|
onClick={handleSubmitAnyway}
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
const {
|
const {
|
||||||
handleShowCompatibleAlert,
|
handleShowCompatibleAlert,
|
||||||
setWarningStatus,
|
setWarningStatus,
|
||||||
|
handleBackendChangeBefore,
|
||||||
handleOnValuesChange,
|
handleOnValuesChange,
|
||||||
checkTokenRef,
|
checkTokenRef,
|
||||||
warningStatus,
|
warningStatus,
|
||||||
@@ -144,7 +145,12 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
setIsGGUF(false);
|
setIsGGUF(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = form.current.form.getFieldsValue?.();
|
const data = form.current.form.getFieldsValue?.();
|
||||||
|
const res = handleBackendChangeBefore(data);
|
||||||
|
if (res.show) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (data.local_path || props.source !== modelSourceMap.local_path_value) {
|
if (data.local_path || props.source !== modelSourceMap.local_path_value) {
|
||||||
handleOnValuesChange?.({
|
handleOnValuesChange?.({
|
||||||
changedValues: {},
|
changedValues: {},
|
||||||
@@ -303,9 +309,12 @@ const AddModal: FC<AddModalProps> = (props) => {
|
|||||||
<ModalFooter
|
<ModalFooter
|
||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
onOk={handleSumit}
|
onOk={handleSumit}
|
||||||
showOkBtn={!warningStatus.show}
|
showOkBtn={
|
||||||
|
!warningStatus.show || warningStatus.type === 'success'
|
||||||
|
}
|
||||||
extra={
|
extra={
|
||||||
warningStatus.show && (
|
warningStatus.show &&
|
||||||
|
warningStatus.type !== 'success' && (
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSubmitAnyway}
|
onClick={handleSubmitAnyway}
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
|
|||||||
});
|
});
|
||||||
const [sortType, setSortType] = useState<string>('size');
|
const [sortType, setSortType] = useState<string>('size');
|
||||||
const [current, setCurrent] = useState<string>('');
|
const [current, setCurrent] = useState<string>('');
|
||||||
|
const currentPathRef = useRef<string>('');
|
||||||
const modelFilesSortOptions = useRef<any[]>([
|
const modelFilesSortOptions = useRef<any[]>([
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({ id: 'models.sort.size' }),
|
label: intl.formatMessage({ id: 'models.sort.size' }),
|
||||||
@@ -100,6 +101,7 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
|
|||||||
const handleSelectModelFile = (item: any) => {
|
const handleSelectModelFile = (item: any) => {
|
||||||
props.onSelectFile?.(item);
|
props.onSelectFile?.(item);
|
||||||
setCurrent(item.path);
|
setCurrent(item.path);
|
||||||
|
currentPathRef.current = item.path;
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseFilename = (filename: string) => {
|
const parseFilename = (filename: string) => {
|
||||||
@@ -274,7 +276,13 @@ const HFModelFile: React.FC<HFModelFileProps> = forwardRef((props, ref) => {
|
|||||||
evaluateResult: evaluationList[index]
|
evaluateResult: evaluationList[index]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
handleSelectModelFile(resultList[0]);
|
const currentItem = _.find(
|
||||||
|
resultList,
|
||||||
|
(item: any) => item.path === currentPathRef.current
|
||||||
|
);
|
||||||
|
if (currentItem) {
|
||||||
|
handleSelectModelFile(currentItem);
|
||||||
|
}
|
||||||
setDataSource({ fileList: resultList, loading: false });
|
setDataSource({ fileList: resultList, loading: false });
|
||||||
setIsEvaluating(false);
|
setIsEvaluating(false);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -18,6 +18,12 @@ const CompatibleTag = styled(Tag)`
|
|||||||
background: transparent !important;
|
background: transparent !important;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ClaimTag = styled(Tag)`
|
||||||
|
margin: 0;
|
||||||
|
opacity: 0.7;
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
`;
|
||||||
|
|
||||||
const IncompatibleInfo = styled.div`
|
const IncompatibleInfo = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
|||||||
];
|
];
|
||||||
const [isEvaluating, setIsEvaluating] = useState<boolean>(false);
|
const [isEvaluating, setIsEvaluating] = useState<boolean>(false);
|
||||||
const [current, setCurrent] = useState<string>('');
|
const [current, setCurrent] = useState<string>('');
|
||||||
|
const currentRef = useRef<string>('');
|
||||||
const cacheRepoOptions = useRef<any[]>([]);
|
const cacheRepoOptions = useRef<any[]>([]);
|
||||||
const axiosTokenRef = useRef<any>(null);
|
const axiosTokenRef = useRef<any>(null);
|
||||||
const checkTokenRef = useRef<any>(null);
|
const checkTokenRef = useRef<any>(null);
|
||||||
@@ -100,6 +101,7 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
|||||||
const handleOnSelectModel = (item: any) => {
|
const handleOnSelectModel = (item: any) => {
|
||||||
onSelectModel(item);
|
onSelectModel(item);
|
||||||
setCurrent(item.id);
|
setCurrent(item.id);
|
||||||
|
currentRef.current = item.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// huggeface
|
// huggeface
|
||||||
@@ -222,7 +224,12 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
|||||||
repoOptions: resultList
|
repoOptions: resultList
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
handleOnSelectModel(resultList[0]);
|
const currentItem = resultList.find(
|
||||||
|
(item) => item.id === currentRef.current
|
||||||
|
);
|
||||||
|
if (currentItem) {
|
||||||
|
handleOnSelectModel(currentItem);
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setIsEvaluating(false);
|
setIsEvaluating(false);
|
||||||
}
|
}
|
||||||
@@ -264,9 +271,7 @@ const SearchModel: React.FC<SearchInputProps> = (props) => {
|
|||||||
handleOnSelectModel(list[0]);
|
handleOnSelectModel(list[0]);
|
||||||
setLoadingModel?.(false);
|
setLoadingModel?.(false);
|
||||||
|
|
||||||
timer.current = setTimeout(() => {
|
handleEvaluate(list);
|
||||||
handleEvaluate(list);
|
|
||||||
}, 200);
|
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
setDataSource({
|
setDataSource({
|
||||||
repoOptions: [],
|
repoOptions: [],
|
||||||
|
|||||||
@@ -740,7 +740,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
placeholder={intl.formatMessage({
|
placeholder={intl.formatMessage({
|
||||||
id: 'models.filter.category'
|
id: 'models.filter.category'
|
||||||
})}
|
})}
|
||||||
style={{ width: 230 }}
|
style={{ width: 180 }}
|
||||||
size="large"
|
size="large"
|
||||||
maxTagCount={1}
|
maxTagCount={1}
|
||||||
onChange={handleCategoryChange}
|
onChange={handleCategoryChange}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
const {
|
const {
|
||||||
setWarningStatus,
|
setWarningStatus,
|
||||||
generateGPUIds,
|
generateGPUIds,
|
||||||
handleOnValuesChange,
|
handleBackendChangeBefore,
|
||||||
checkTokenRef,
|
checkTokenRef,
|
||||||
warningStatus
|
warningStatus
|
||||||
} = useCheckCompatibility();
|
} = useCheckCompatibility();
|
||||||
@@ -68,6 +68,8 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
const localPathCache = useRef<string>('');
|
const localPathCache = useRef<string>('');
|
||||||
const submitAnyway = useRef<boolean>(false);
|
const submitAnyway = useRef<boolean>(false);
|
||||||
|
|
||||||
|
const handleOnValuesChange = (data: any) => {};
|
||||||
|
|
||||||
// voxbox is not support multi gpu
|
// voxbox is not support multi gpu
|
||||||
const handleSetGPUIds = (backend: string) => {
|
const handleSetGPUIds = (backend: string) => {
|
||||||
const gpuids = form.getFieldValue(['gpu_selector', 'gpu_ids']) || [];
|
const gpuids = form.getFieldValue(['gpu_selector', 'gpu_ids']) || [];
|
||||||
@@ -91,6 +93,10 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
handleSetGPUIds(backend);
|
handleSetGPUIds(backend);
|
||||||
|
|
||||||
const data = form.getFieldsValue?.();
|
const data = form.getFieldsValue?.();
|
||||||
|
const res = handleBackendChangeBefore(data);
|
||||||
|
if (res.show) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (data.local_path || data.source !== modelSourceMap.local_path_value) {
|
if (data.local_path || data.source !== modelSourceMap.local_path_value) {
|
||||||
handleOnValuesChange?.({
|
handleOnValuesChange?.({
|
||||||
changedValues: {},
|
changedValues: {},
|
||||||
@@ -390,9 +396,10 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
<ModalFooter
|
<ModalFooter
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onOk={handleSumit}
|
onOk={handleSumit}
|
||||||
showOkBtn={!warningStatus.show}
|
showOkBtn={!warningStatus.show || warningStatus.type === 'success'}
|
||||||
extra={
|
extra={
|
||||||
warningStatus.show && (
|
warningStatus.show &&
|
||||||
|
warningStatus.type !== 'success' && (
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSubmitAnyway}
|
onClick={handleSubmitAnyway}
|
||||||
|
|||||||
@@ -448,6 +448,7 @@ export const modelLabels = [
|
|||||||
{ label: 'Embedding', value: 'embedding_only' }
|
{ label: 'Embedding', value: 'embedding_only' }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// do not trigger form check compatibility
|
||||||
export const excludeFields = [
|
export const excludeFields = [
|
||||||
'repo_id',
|
'repo_id',
|
||||||
'file_name',
|
'file_name',
|
||||||
@@ -464,5 +465,8 @@ export const excludeFields = [
|
|||||||
'backend_parameters',
|
'backend_parameters',
|
||||||
'local_path',
|
'local_path',
|
||||||
'backend_version',
|
'backend_version',
|
||||||
'ollama_library_model_name'
|
'ollama_library_model_name',
|
||||||
|
'scheduleType',
|
||||||
|
'placement_strategy',
|
||||||
|
'backend'
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -218,4 +218,8 @@ export interface EvaluateResult {
|
|||||||
compatibility_messages: string[];
|
compatibility_messages: string[];
|
||||||
scheduling_messages: string[];
|
scheduling_messages: string[];
|
||||||
default_spec: Record<string, any>;
|
default_spec: Record<string, any>;
|
||||||
|
resource_claim?: {
|
||||||
|
ram: number;
|
||||||
|
vram: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { createAxiosToken } from '@/hooks/use-chunk-request';
|
|||||||
import { queryModelFilesList, queryWorkersList } from '@/pages/resources/apis';
|
import { queryModelFilesList, queryWorkersList } from '@/pages/resources/apis';
|
||||||
import { WorkerStatusMap } from '@/pages/resources/config';
|
import { WorkerStatusMap } from '@/pages/resources/config';
|
||||||
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
|
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
|
||||||
|
import { convertFileSize } from '@/utils';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
@@ -19,6 +20,15 @@ import {
|
|||||||
ListItem
|
ListItem
|
||||||
} from '../config/types';
|
} from '../config/types';
|
||||||
|
|
||||||
|
type MessageStatus = {
|
||||||
|
show: boolean;
|
||||||
|
title?: string;
|
||||||
|
type?: Global.MessageType;
|
||||||
|
isHtml?: boolean;
|
||||||
|
message: string | string[];
|
||||||
|
evaluateResult?: EvaluateResult;
|
||||||
|
};
|
||||||
|
|
||||||
export const useGenerateFormEditInitialValues = () => {
|
export const useGenerateFormEditInitialValues = () => {
|
||||||
const gpuDeviceList = useRef<any[]>([]);
|
const gpuDeviceList = useRef<any[]>([]);
|
||||||
const workerList = useRef<any[]>([]);
|
const workerList = useRef<any[]>([]);
|
||||||
@@ -220,12 +230,7 @@ export const useCheckCompatibility = () => {
|
|||||||
const submitAnyway = useRef<boolean>(false);
|
const submitAnyway = useRef<boolean>(false);
|
||||||
const requestIdRef = useRef(0);
|
const requestIdRef = useRef(0);
|
||||||
const updateStatusTimer = useRef<any>(null);
|
const updateStatusTimer = useRef<any>(null);
|
||||||
const [warningStatus, setWarningStatus] = useState<{
|
const [warningStatus, setWarningStatus] = useState<MessageStatus>({
|
||||||
show: boolean;
|
|
||||||
title?: string;
|
|
||||||
type?: 'transition' | 'warning' | 'danger';
|
|
||||||
message: string | string[];
|
|
||||||
}>({
|
|
||||||
show: false,
|
show: false,
|
||||||
title: '',
|
title: '',
|
||||||
message: []
|
message: []
|
||||||
@@ -269,7 +274,9 @@ export const useCheckCompatibility = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCheckCompatibility = (evaluateResult: EvaluateResult | null) => {
|
const handleCheckCompatibility = (
|
||||||
|
evaluateResult: EvaluateResult | null
|
||||||
|
): MessageStatus => {
|
||||||
if (!evaluateResult) {
|
if (!evaluateResult) {
|
||||||
return {
|
return {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -279,11 +286,13 @@ export const useCheckCompatibility = () => {
|
|||||||
const {
|
const {
|
||||||
compatible,
|
compatible,
|
||||||
compatibility_messages = [],
|
compatibility_messages = [],
|
||||||
scheduling_messages = []
|
scheduling_messages = [],
|
||||||
|
resource_claim
|
||||||
} = evaluateResult || {};
|
} = evaluateResult || {};
|
||||||
|
|
||||||
return {
|
const hasClaim = !!resource_claim?.ram || !!resource_claim?.vram;
|
||||||
show: !compatible,
|
|
||||||
|
let msgData = {
|
||||||
title:
|
title:
|
||||||
scheduling_messages?.length > 0
|
scheduling_messages?.length > 0
|
||||||
? compatibility_messages?.join(' ')
|
? compatibility_messages?.join(' ')
|
||||||
@@ -293,6 +302,24 @@ export const useCheckCompatibility = () => {
|
|||||||
? scheduling_messages
|
? scheduling_messages
|
||||||
: compatibility_messages?.join(' ')
|
: compatibility_messages?.join(' ')
|
||||||
};
|
};
|
||||||
|
if (hasClaim) {
|
||||||
|
const ram = convertFileSize(resource_claim.ram, 1);
|
||||||
|
const vram = convertFileSize(resource_claim.vram, 1);
|
||||||
|
msgData = {
|
||||||
|
title: intl.formatMessage({ id: 'models.form.check.passed' }),
|
||||||
|
message: intl.formatMessage(
|
||||||
|
{ id: 'models.form.check.claims' },
|
||||||
|
{ ram, vram }
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
show: !compatible || hasClaim,
|
||||||
|
type: !compatible ? 'warning' : 'success',
|
||||||
|
isHtml: hasClaim,
|
||||||
|
...msgData
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleShowCompatibleAlert = (evaluateResult: EvaluateResult | null) => {
|
const handleShowCompatibleAlert = (evaluateResult: EvaluateResult | null) => {
|
||||||
@@ -387,14 +414,22 @@ export const useCheckCompatibility = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDoEvalute = async (formData: FormData) => {
|
||||||
|
const currentRequestId = updateRequestId();
|
||||||
|
const evalutionData = await handleEvaluate(formData);
|
||||||
|
|
||||||
|
if (currentRequestId === requestIdRef.current) {
|
||||||
|
handleShowCompatibleAlert?.(evalutionData);
|
||||||
|
}
|
||||||
|
return evalutionData;
|
||||||
|
};
|
||||||
|
|
||||||
const handleOnValuesChange = async (params: {
|
const handleOnValuesChange = async (params: {
|
||||||
changedValues: any;
|
changedValues: any;
|
||||||
allValues: any;
|
allValues: any;
|
||||||
source: string;
|
source: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { changedValues, allValues, source } = params;
|
const { allValues, source } = params;
|
||||||
console.log('params+++++++', params);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
_.isEqual(cacheFormValuesRef.current, allValues) ||
|
_.isEqual(cacheFormValuesRef.current, allValues) ||
|
||||||
(allValues.source === modelSourceMap.local_path_value &&
|
(allValues.source === modelSourceMap.local_path_value &&
|
||||||
@@ -405,16 +440,30 @@ export const useCheckCompatibility = () => {
|
|||||||
cacheFormValuesRef.current = allValues;
|
cacheFormValuesRef.current = allValues;
|
||||||
const data = getSourceRepoConfigValue(source, allValues);
|
const data = getSourceRepoConfigValue(source, allValues);
|
||||||
const gpuSelector = generateGPUIds(data.values);
|
const gpuSelector = generateGPUIds(data.values);
|
||||||
|
await handleDoEvalute({
|
||||||
const currentRequestId = updateRequestId();
|
|
||||||
const evalutionData = await handleEvaluate({
|
|
||||||
...data.values,
|
...data.values,
|
||||||
...gpuSelector
|
...gpuSelector
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (currentRequestId === requestIdRef.current) {
|
// trigger from local_path change or backend change
|
||||||
handleShowCompatibleAlert?.(evalutionData);
|
const handleBackendChangeBefore = (params: {
|
||||||
|
local_path: string;
|
||||||
|
backend: string;
|
||||||
|
source: string;
|
||||||
|
}) => {
|
||||||
|
const { local_path, backend, source } = params;
|
||||||
|
|
||||||
|
const res = handleUpdateWarning?.({
|
||||||
|
backend,
|
||||||
|
localPath: local_path,
|
||||||
|
source: source
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.show) {
|
||||||
|
setWarningStatus?.(res);
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
const debounceHandleValuesChange = _.debounce(handleOnValuesChange, 500);
|
const debounceHandleValuesChange = _.debounce(handleOnValuesChange, 500);
|
||||||
@@ -434,13 +483,15 @@ export const useCheckCompatibility = () => {
|
|||||||
return {
|
return {
|
||||||
handleShowCompatibleAlert,
|
handleShowCompatibleAlert,
|
||||||
handleUpdateWarning,
|
handleUpdateWarning,
|
||||||
handleOnValuesChange: debounceHandleValuesChange,
|
handleDoEvalute,
|
||||||
warningStatus,
|
|
||||||
checkTokenRef,
|
|
||||||
submitAnyway,
|
|
||||||
generateGPUIds,
|
generateGPUIds,
|
||||||
handleEvaluate,
|
handleEvaluate,
|
||||||
setWarningStatus,
|
setWarningStatus,
|
||||||
cancelEvaluate
|
cancelEvaluate,
|
||||||
|
handleBackendChangeBefore,
|
||||||
|
handleOnValuesChange: debounceHandleValuesChange,
|
||||||
|
warningStatus,
|
||||||
|
checkTokenRef,
|
||||||
|
submitAnyway
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ import {
|
|||||||
ListItem as WorkerListItem
|
ListItem as WorkerListItem
|
||||||
} from '../config/types';
|
} from '../config/types';
|
||||||
|
|
||||||
|
const { Paragraph } = Typography;
|
||||||
|
|
||||||
const filterPattern = /^(.*?)(?:-\d+-of-\d+)?(\.gguf)?$/;
|
const filterPattern = /^(.*?)(?:-\d+-of-\d+)?(\.gguf)?$/;
|
||||||
|
|
||||||
const PathWrapper = styled.div`
|
const PathWrapper = styled.div`
|
||||||
@@ -115,11 +117,18 @@ const FilesTag = styled(Tag)`
|
|||||||
border-radius: var(--border-radius-base);
|
border-radius: var(--border-radius-base);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const TypographyPara = styled(Paragraph)`
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
`;
|
||||||
|
|
||||||
const TooltipTitle: React.FC<{ path: string }> = ({ path }) => {
|
const TooltipTitle: React.FC<{ path: string }> = ({ path }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
return (
|
return (
|
||||||
<Typography.Paragraph
|
<TypographyPara
|
||||||
style={{ background: 'transparent', color: 'inherit' }}
|
style={{ margin: 0 }}
|
||||||
copyable={{
|
copyable={{
|
||||||
icon: [
|
icon: [
|
||||||
<CopyOutlined key="copy-icon" />,
|
<CopyOutlined key="copy-icon" />,
|
||||||
@@ -133,7 +142,7 @@ const TooltipTitle: React.FC<{ path: string }> = ({ path }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{path}
|
{path}
|
||||||
</Typography.Paragraph>
|
</TypographyPara>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user