fix: gpu selector issues

This commit is contained in:
jialin
2025-10-28 11:17:29 +08:00
parent 697f1f9c25
commit a86bed294e
7 changed files with 52 additions and 30 deletions
+1 -2
View File
@@ -60,8 +60,7 @@ const OptionNodes = (props: {
); );
} }
let width: any = { let width: any = {
maxWidth: 140, maxWidth: 140
minWidth: 140
}; };
if (!data.parent) { if (!data.parent) {
width = undefined; width = undefined;
+10 -4
View File
@@ -21,6 +21,12 @@ const Header = styled.div`
width: 100%; width: 100%;
`; `;
const ItemInfo = styled.div`
display: flex;
flex-wrap: wrap;
white-space: break-spaces;
`;
const Description = styled.div` const Description = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -60,7 +66,7 @@ const GPUCard: React.FC<{
description={ description={
info || ( info || (
<> <>
<span> <ItemInfo>
{intl.formatMessage({ id: 'resources.table.vram' })}( {intl.formatMessage({ id: 'resources.table.vram' })}(
{intl.formatMessage({ id: 'resources.table.used' })}/ {intl.formatMessage({ id: 'resources.table.used' })}/
{intl.formatMessage({ id: 'resources.table.total' })}):{' '} {intl.formatMessage({ id: 'resources.table.total' })}):{' '}
@@ -70,8 +76,8 @@ const GPUCard: React.FC<{
)}{' '} )}{' '}
/ {convertFileSize(data?.memory?.total || 0)} / {convertFileSize(data?.memory?.total || 0)}
</span> </span>
</span> </ItemInfo>
<span> <ItemInfo>
<span> <span>
{intl.formatMessage({ id: 'resources.table.gpuutilization' })} {intl.formatMessage({ id: 'resources.table.gpuutilization' })}
:{' '} :{' '}
@@ -80,7 +86,7 @@ const GPUCard: React.FC<{
? _.round(data?.memory?.utilization_rate || 0, 2) ? _.round(data?.memory?.utilization_rate || 0, 2)
: _.round(data.memory?.allocated / data.memory?.total, 2) * 100} : _.round(data.memory?.allocated / data.memory?.total, 2) * 100}
% %
</span> </ItemInfo>
</> </>
) )
} }
+3 -2
View File
@@ -1,6 +1,6 @@
import { PageActionType } from '@/config/types'; import { PageActionType } from '@/config/types';
import React from 'react'; import React from 'react';
import { BackendOption, DeployFormKey } from './types'; import { BackendOption, DeployFormKey, FormData } from './types';
type EmptyObject = Record<never, never>; type EmptyObject = Record<never, never>;
@@ -17,10 +17,11 @@ interface FormContextProps {
isGGUF?: boolean; isGGUF?: boolean;
formKey: DeployFormKey; formKey: DeployFormKey;
source: string; source: string;
pageAction: PageActionType; action: PageActionType;
gpuOptions: CascaderOption[]; gpuOptions: CascaderOption[];
workerLabelOptions: CascaderOption[]; workerLabelOptions: CascaderOption[];
backendOptions: BackendOption[]; backendOptions: BackendOption[];
initialValues?: FormData; // for editing model
onValuesChange?: (changedValues: any, allValues: any) => void; onValuesChange?: (changedValues: any, allValues: any) => void;
onBackendChange: (backend: string, option: any) => void; onBackendChange: (backend: string, option: any) => void;
} }
+1 -1
View File
@@ -23,7 +23,7 @@ const BackendFields: React.FC = () => {
const { const {
isGGUF, isGGUF,
formKey, formKey,
pageAction: action, action,
source, source,
gpuOptions, gpuOptions,
onValuesChange, onValuesChange,
+3 -2
View File
@@ -55,7 +55,7 @@ const SegmentedHeader = styled.div<{ $top?: number }>`
`; `;
interface DataFormProps { interface DataFormProps {
initialValues?: any; initialValues?: FormData;
ref?: any; ref?: any;
source: SourceType; source: SourceType;
action: PageActionType; action: PageActionType;
@@ -323,10 +323,11 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
isGGUF: isGGUF, isGGUF: isGGUF,
formKey: formKey, formKey: formKey,
source: props.source, source: props.source,
pageAction: action, action: action,
gpuOptions: gpuOptions, gpuOptions: gpuOptions,
backendOptions: backendOptions, backendOptions: backendOptions,
workerLabelOptions: workerLabelOptions, workerLabelOptions: workerLabelOptions,
initialValues: initialValues,
onValuesChange: onValuesChange, onValuesChange: onValuesChange,
onBackendChange: handleBackendChange onBackendChange: handleBackendChange
}} }}
+5 -5
View File
@@ -13,7 +13,7 @@ const HuggingFaceForm: React.FC = () => {
const formInstance = Form.useFormInstance(); const formInstance = Form.useFormInstance();
const formCtx = useFormContext(); const formCtx = useFormContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const { formKey, pageAction, isGGUF, onValuesChange } = formCtx; const { formKey, action, isGGUF, onValuesChange } = formCtx;
const source = Form.useWatch('source'); const source = Form.useWatch('source');
if ( if (
@@ -47,7 +47,7 @@ const HuggingFaceForm: React.FC = () => {
<SealInput.Input <SealInput.Input
label={intl.formatMessage({ id: 'models.form.repoid' })} label={intl.formatMessage({ id: 'models.form.repoid' })}
required required
disabled={pageAction === PageAction.CREATE} disabled={action === PageAction.CREATE}
onBlur={handleOnBlur} onBlur={handleOnBlur}
></SealInput.Input> ></SealInput.Input>
</Form.Item> </Form.Item>
@@ -58,7 +58,7 @@ const HuggingFaceForm: React.FC = () => {
> >
<SealInput.Input <SealInput.Input
label={intl.formatMessage({ id: 'models.form.filename' })} label={intl.formatMessage({ id: 'models.form.filename' })}
disabled={pageAction === PageAction.CREATE} disabled={action === PageAction.CREATE}
></SealInput.Input> ></SealInput.Input>
</Form.Item> </Form.Item>
)} )}
@@ -78,7 +78,7 @@ const HuggingFaceForm: React.FC = () => {
<SealInput.Input <SealInput.Input
required required
label={intl.formatMessage({ id: 'models.form.repoid' })} label={intl.formatMessage({ id: 'models.form.repoid' })}
disabled={pageAction === PageAction.CREATE} disabled={action === PageAction.CREATE}
onBlur={handleOnBlur} onBlur={handleOnBlur}
></SealInput.Input> ></SealInput.Input>
</Form.Item> </Form.Item>
@@ -89,7 +89,7 @@ const HuggingFaceForm: React.FC = () => {
> >
<SealInput.Input <SealInput.Input
label={intl.formatMessage({ id: 'models.form.filename' })} label={intl.formatMessage({ id: 'models.form.filename' })}
disabled={pageAction === PageAction.CREATE} disabled={action === PageAction.CREATE}
></SealInput.Input> ></SealInput.Input>
</Form.Item> </Form.Item>
)} )}
+29 -14
View File
@@ -4,6 +4,7 @@ import SealInputNumber from '@/components/seal-form/input-number';
import SealCascader from '@/components/seal-form/seal-cascader'; import SealCascader from '@/components/seal-form/seal-cascader';
import SealSelect from '@/components/seal-form/seal-select'; import SealSelect from '@/components/seal-form/seal-select';
import TooltipList from '@/components/tooltip-list'; import TooltipList from '@/components/tooltip-list';
import { PageAction } from '@/config';
import useAppUtils from '@/hooks/use-app-utils'; import useAppUtils from '@/hooks/use-app-utils';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Form } from 'antd'; import { Form } from 'antd';
@@ -67,7 +68,13 @@ const gpuAllocateTypeTips = [
const ScheduleTypeForm: React.FC = () => { const ScheduleTypeForm: React.FC = () => {
const intl = useIntl(); const intl = useIntl();
const { onValuesChange, gpuOptions, workerLabelOptions } = useFormContext(); const {
onValuesChange,
action,
gpuOptions,
workerLabelOptions,
initialValues
} = useFormContext();
const { getRuleMessage } = useAppUtils(); const { getRuleMessage } = useAppUtils();
const form = Form.useFormInstance(); const form = Form.useFormInstance();
const scheduleType = Form.useWatch('scheduleType', form); const scheduleType = Form.useWatch('scheduleType', form);
@@ -88,39 +95,41 @@ const ScheduleTypeForm: React.FC = () => {
onValuesChange?.({}, form.getFieldsValue()); onValuesChange?.({}, form.getFieldsValue());
}; };
const handleBeforeGpuSelectorChange = (gpuIds: any[]) => {};
const handleGpuSelectorChange = (value: any[]) => { const handleGpuSelectorChange = (value: any[]) => {
handleBeforeGpuSelectorChange(value); if (value.length > 0) {
onValuesChange?.({}, form.getFieldsValue()); onValuesChange?.({}, form.getFieldsValue());
}
}; };
const handleOnStepReplicaStep = ( const handleOnStepReplicaStep = (
value: number, value: number | string | null,
info: { offset: number; type: 'up' | 'down' } info: { offset: number | string | null; type: 'up' | 'down' }
) => { ) => {
let newValue = value; let newValue = value;
const isPowerOfTwo = (n: number) => (n & (n - 1)) === 0 && n !== 0; // check power of two const isPowerOfTwo = (n: number) => (n & (n - 1)) === 0 && n !== 0; // check power of two
if (!isPowerOfTwo(value)) { if (!isPowerOfTwo(value as number)) {
if (info.type === 'up') { if (info.type === 'up') {
newValue = Math.pow(2, Math.ceil(Math.log2(value))); newValue = Math.pow(2, Math.ceil(Math.log2(value as number)));
} else { } else {
newValue = Math.pow(2, Math.floor(Math.log2(value))); newValue = Math.pow(2, Math.floor(Math.log2(value as number)));
} }
} }
form.setFieldValue(['gpu_selector', 'gpus_per_replica'], newValue); form.setFieldValue(['gpu_selector', 'gpus_per_replica'], newValue);
onValuesChange?.({}, form.getFieldsValue()); onValuesChange?.({}, form.getFieldsValue());
}; };
const handleOnStepReplica = (value: number | null) => { const handleOnStepReplica = async (value: number | string | null) => {
if (value === null) { if (value === null) {
await new Promise((resolve) => {
setTimeout(resolve, 200);
});
form.setFieldValue(['gpu_selector', 'gpus_per_replica'], 1); form.setFieldValue(['gpu_selector', 'gpus_per_replica'], 1);
return; return;
} }
const isPowerOfTwo = (n: number) => (n & (n - 1)) === 0 && n !== 0; // check power of two const isPowerOfTwo = (n: number) => (n & (n - 1)) === 0 && n !== 0; // check power of two
if (!isPowerOfTwo(value)) { if (!isPowerOfTwo(value as number)) {
const newValue = Math.pow(2, Math.round(Math.log2(value))); const newValue = Math.pow(2, Math.round(Math.log2(value as number)));
form.setFieldValue(['gpu_selector', 'gpus_per_replica'], newValue); form.setFieldValue(['gpu_selector', 'gpus_per_replica'], newValue);
onValuesChange?.({}, form.getFieldsValue()); onValuesChange?.({}, form.getFieldsValue());
} }
@@ -212,7 +221,13 @@ const ScheduleTypeForm: React.FC = () => {
onChange={handleGpuSelectorChange} onChange={handleGpuSelectorChange}
></SealCascader> ></SealCascader>
</Form.Item> </Form.Item>
<Form.Item name="gpusCountType"> <Form.Item
name="gpusCountType"
hidden={
action === PageAction.EDIT &&
!!initialValues?.gpu_selector?.gpus_per_replica
}
>
<SealSelect <SealSelect
onChange={handleGpusCountTypeChange} onChange={handleGpusCountTypeChange}
label={intl.formatMessage({ label={intl.formatMessage({