Skip to content

Commit 61065ee

Browse files
committed
chore: scheduling group
1 parent df65d3e commit 61065ee

File tree

7 files changed

+138
-113
lines changed

7 files changed

+138
-113
lines changed

src/locales/en-US/models.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,5 +212,6 @@ export default {
212212
'models.form.kvCache.tips':
213213
'Available only with built-in backends (vLLM / SGLang) — switch backend in <span class="bold-text">Advanced</span> to enable.',
214214
'models.form.kvCache.tips2':
215-
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).'
215+
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).',
216+
'models.form.scheduling': 'Scheduling'
216217
};

src/locales/ja-JP/models.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,8 @@ export default {
209209
'models.form.kvCache.tips':
210210
'Available only with built-in backends (vLLM / SGLang) — switch backend in <span class="bold-text">Advanced</span> to enable.',
211211
'models.form.kvCache.tips2':
212-
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).'
212+
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).',
213+
'models.form.scheduling': 'Scheduling'
213214
};
214215

215216
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -255,5 +256,6 @@ export default {
255256
// 42. 'models.mymodels.status.active': 'Active'
256257
// 43. 'models.form.remoteURL.tips': 'Refer to the <a href="https://docs.lmcache.ai/api_reference/configurations.html" target="_blank">configuration documentation</a> for details.',
257258
// 44. 'models.form.kvCache.tips': 'Available only with built-in backends (vLLM / SGLang) — switch backend in <span class="bold-text">Advanced</span> to enable.'
258-
// 45. 'models.form.kvCache.tips2': 'KV cache is only supported when using built-in inference backends (vLLM or SGLang).'
259+
// 45. 'models.form.kvCache.tips2': 'KV cache is only supported when using built-in inference backends (vLLM or SGLang).',
260+
// 46. 'models.form.scheduling': 'Scheduling'
259261
// ========== End of To-Do List ==========

src/locales/ru-RU/models.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ export default {
212212
'models.form.kvCache.tips':
213213
'Available only with built-in backends (vLLM / SGLang) — switch backend in <span class="bold-text">Advanced</span> to enable.',
214214
'models.form.kvCache.tips2':
215-
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).'
215+
'KV cache is only supported when using built-in inference backends (vLLM or SGLang).',
216+
'models.form.scheduling': 'Scheduling'
216217
};
217218

218219
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -222,4 +223,5 @@ export default {
222223
// 5. 'models.form.remoteURL.tips': 'Refer to the <a href="https://docs.lmcache.ai/api_reference/configurations.html" target="_blank">configuration documentation</a> for details.',
223224
// 6. 'models.form.kvCache.tips': 'Available only with built-in backends (vLLM / SGLang) — switch backend in <span class="bold-text">Advanced</span> to enable.'
224225
// 7. 'models.form.kvCache.tips2': 'KV cache is only supported when using built-in inference backends (vLLM or SGLang).';
226+
// 8. 'models.form.scheduling': 'Scheduling'
225227
// ========== End of To-Do List ==========

src/locales/zh-CN/models.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,5 +200,6 @@ export default {
200200
'models.form.kvCache.tips':
201201
'仅在内置后端(vLLM / SGLang)可用 —— 请在<span class="bold-text">高级</span>配置中切换后端以启用。',
202202
'models.form.kvCache.tips2':
203-
'仅在使用内置推理后端(vLLM 或 SGLang)时支持 KV 缓存。'
203+
'仅在使用内置推理后端(vLLM 或 SGLang)时支持 KV 缓存。',
204+
'models.form.scheduling': '调度'
204205
};

src/pages/llmodels/forms/advance-config.tsx

Lines changed: 2 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,25 @@
11
import LabelSelector from '@/components/label-selector';
2-
import { LabelSelectorContext } from '@/components/label-selector/context';
32
import CheckboxField from '@/components/seal-form/checkbox-field';
43
import SealSelect from '@/components/seal-form/seal-select';
5-
import TooltipList from '@/components/tooltip-list';
64
import { useIntl } from '@umijs/max';
75
import { Form } from 'antd';
86
import _ from 'lodash';
97
import { useCallback } from 'react';
10-
import {
11-
modelCategories,
12-
placementStrategyOptions,
13-
ScheduleValueMap
14-
} from '../config';
8+
import { modelCategories, ScheduleValueMap } from '../config';
159
import { backendOptionsMap } from '../config/backend-parameters';
1610
import { useFormContext } from '../config/form-context';
1711
import { FormData } from '../config/types';
1812
import Backend from '../forms/backend';
1913
import BackendParametersList from '../forms/backend-parameters-list';
20-
import ScheduleTypeForm from '../forms/schedule-type';
21-
22-
const placementStrategyTips = [
23-
{
24-
title: 'Spread',
25-
tips: 'resources.form.spread.tips'
26-
},
27-
{
28-
title: 'Binpack',
29-
tips: 'resources.form.binpack.tips'
30-
}
31-
];
3214

3315
const AdvanceConfig = () => {
3416
const intl = useIntl();
3517
const form = Form.useFormInstance();
36-
const wokerSelector = Form.useWatch('worker_selector', form);
3718
const EnviromentVars = Form.useWatch('env', form);
3819
const scheduleType = Form.useWatch('scheduleType', form);
3920
const backend = Form.useWatch('backend', form);
40-
const { onValuesChange, workerLabelOptions } = useFormContext();
21+
const { onValuesChange } = useFormContext();
4122

42-
const handleWorkerLabelsChange = useCallback(
43-
(labels: Record<string, any>) => {
44-
form.setFieldValue('worker_selector', labels);
45-
},
46-
[]
47-
);
4823
const handleEnviromentVarsChange = useCallback(
4924
(labels: Record<string, any>) => {
5025
form.setFieldValue('env', labels);
@@ -63,14 +38,6 @@ const AdvanceConfig = () => {
6338
}
6439
};
6540

66-
const handleSelectorOnBlur = () => {
67-
onSelectorChange('worker_selector');
68-
};
69-
70-
const handleDeleteWorkerSelector = (index: number) => {
71-
onValuesChange?.({}, form.getFieldsValue());
72-
};
73-
7441
const handleEnvSelectorOnBlur = () => {
7542
onSelectorChange('env', true);
7643
};
@@ -96,75 +63,7 @@ const AdvanceConfig = () => {
9663
options={modelCategories}
9764
></SealSelect>
9865
</Form.Item>
99-
<ScheduleTypeForm></ScheduleTypeForm>
10066
<Backend></Backend>
101-
{scheduleType === ScheduleValueMap.Auto && (
102-
<>
103-
<Form.Item<FormData> name="placement_strategy">
104-
<SealSelect
105-
label={intl.formatMessage({
106-
id: 'resources.form.placementStrategy'
107-
})}
108-
options={placementStrategyOptions}
109-
description={
110-
<TooltipList list={placementStrategyTips}></TooltipList>
111-
}
112-
></SealSelect>
113-
</Form.Item>
114-
<LabelSelectorContext.Provider
115-
value={{ options: workerLabelOptions }}
116-
>
117-
<Form.Item<FormData>
118-
name="worker_selector"
119-
rules={[
120-
({ getFieldValue }) => ({
121-
validator(rule, value) {
122-
if (
123-
getFieldValue('scheduleType') === ScheduleValueMap.Auto &&
124-
_.keys(value).length > 0
125-
) {
126-
if (_.some(_.keys(value), (k: string) => !value[k])) {
127-
return Promise.reject(
128-
intl.formatMessage(
129-
{
130-
id: 'common.validate.value'
131-
},
132-
{
133-
name: intl.formatMessage({
134-
id: 'models.form.selector'
135-
})
136-
}
137-
)
138-
);
139-
}
140-
}
141-
return Promise.resolve();
142-
}
143-
})
144-
]}
145-
>
146-
<LabelSelector
147-
isAutoComplete
148-
label={intl.formatMessage({
149-
id: 'resources.form.workerSelector'
150-
})}
151-
labels={wokerSelector}
152-
onChange={handleWorkerLabelsChange}
153-
onBlur={handleSelectorOnBlur}
154-
onDelete={handleDeleteWorkerSelector}
155-
description={
156-
<span>
157-
{intl.formatMessage({
158-
id: 'resources.form.workerSelector.description'
159-
})}
160-
</span>
161-
}
162-
></LabelSelector>
163-
</Form.Item>
164-
</LabelSelectorContext.Provider>
165-
</>
166-
)}
167-
16867
<BackendParametersList></BackendParametersList>
16968
<Form.Item<FormData> name="env">
17069
<LabelSelector

src/pages/llmodels/forms/index.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import useQueryBackends from '../hooks/use-query-backends';
2828
import AdvanceConfig from './advance-config';
2929
import BasicForm from './basic';
3030
import Performance from './performance';
31+
import ScheduleTypeForm from './schedule-type';
3132

3233
const advancedRequiredFields = [
3334
'gpu_selector',
@@ -103,6 +104,11 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
103104
label: intl.formatMessage({ id: 'common.title.basicInfo' }),
104105
field: 'name'
105106
},
107+
{
108+
value: 'scheduling',
109+
label: intl.formatMessage({ id: 'models.form.scheduling' }),
110+
field: 'scheduleType'
111+
},
106112
{
107113
value: 'performance',
108114
label: intl.formatMessage({ id: 'models.form.performance' }),
@@ -378,18 +384,22 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
378384
accordion={false}
379385
onChange={handleOnCollapseChange}
380386
items={[
387+
{
388+
key: 'scheduling',
389+
label: intl.formatMessage({ id: 'models.form.scheduling' }),
390+
forceRender: true,
391+
children: <ScheduleTypeForm></ScheduleTypeForm>
392+
},
381393
{
382394
key: 'performance',
383395
label: intl.formatMessage({ id: 'models.form.performance' }),
384396
forceRender: true,
385-
extra: <div ref={performanceRef}></div>,
386397
children: <Performance></Performance>
387398
},
388399
{
389400
key: 'advanced',
390401
label: intl.formatMessage({ id: 'resources.form.advanced' }),
391402
forceRender: true,
392-
extra: <div ref={advanceRef}></div>,
393403
children: <AdvanceConfig></AdvanceConfig>
394404
}
395405
]}

src/pages/llmodels/forms/schedule-type.tsx

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
1+
import LabelSelector from '@/components/label-selector';
2+
import { LabelSelectorContext } from '@/components/label-selector/context';
13
import SealInputNumber from '@/components/seal-form/input-number';
24
import SealCascader from '@/components/seal-form/seal-cascader';
35
import SealSelect from '@/components/seal-form/seal-select';
46
import TooltipList from '@/components/tooltip-list';
57
import useAppUtils from '@/hooks/use-app-utils';
68
import { useIntl } from '@umijs/max';
79
import { Form } from 'antd';
10+
import _ from 'lodash';
811
import React from 'react';
912
import GPUCard from '../components/gpu-card';
10-
import { gpusCountTypeMap, scheduleList, ScheduleValueMap } from '../config';
13+
import {
14+
gpusCountTypeMap,
15+
placementStrategyOptions,
16+
scheduleList,
17+
ScheduleValueMap
18+
} from '../config';
1119
import { backendOptionsMap } from '../config/backend-parameters';
1220
import { useFormContext } from '../config/form-context';
21+
import { FormData } from '../config/types';
22+
23+
const placementStrategyTips = [
24+
{
25+
title: 'Spread',
26+
tips: 'resources.form.spread.tips'
27+
},
28+
{
29+
title: 'Binpack',
30+
tips: 'resources.form.binpack.tips'
31+
}
32+
];
1333

1434
const scheduleTypeTips = [
1535
{
@@ -47,11 +67,12 @@ const gpuAllocateTypeTips = [
4767

4868
const ScheduleTypeForm: React.FC = () => {
4969
const intl = useIntl();
50-
const { onValuesChange, gpuOptions } = useFormContext();
70+
const { onValuesChange, gpuOptions, workerLabelOptions } = useFormContext();
5171
const { getRuleMessage } = useAppUtils();
5272
const form = Form.useFormInstance();
5373
const scheduleType = Form.useWatch('scheduleType', form);
5474
const gpusCountType = Form.useWatch('gpusCountType', form);
75+
const wokerSelector = Form.useWatch('worker_selector', form);
5576

5677
const handleScheduleTypeChange = (value: string) => {
5778
if (value === ScheduleValueMap.Auto) {
@@ -105,9 +126,32 @@ const ScheduleTypeForm: React.FC = () => {
105126
}
106127
};
107128

129+
const onSelectorChange = (field: string, allowEmpty?: boolean) => {
130+
const workerSelector = form.getFieldValue(field);
131+
// check if all keys have values
132+
const hasEmptyValue = _.some(_.keys(workerSelector), (k: string) => {
133+
return !workerSelector[k];
134+
});
135+
if (!hasEmptyValue || allowEmpty) {
136+
onValuesChange?.({}, form.getFieldsValue());
137+
}
138+
};
139+
140+
const handleWorkerLabelsChange = (labels: Record<string, any>) => {
141+
form.setFieldValue('worker_selector', labels);
142+
};
143+
144+
const handleSelectorOnBlur = () => {
145+
onSelectorChange('worker_selector');
146+
};
147+
148+
const handleDeleteWorkerSelector = (index: number) => {
149+
onValuesChange?.({}, form.getFieldsValue());
150+
};
151+
108152
return (
109153
<>
110-
<Form.Item name="scheduleType">
154+
<Form.Item name="scheduleType" data-field="scheduleType">
111155
<SealSelect
112156
onChange={handleScheduleTypeChange}
113157
label={intl.formatMessage({ id: 'models.form.scheduletype' })}
@@ -208,6 +252,72 @@ const ScheduleTypeForm: React.FC = () => {
208252
)}
209253
</>
210254
)}
255+
{scheduleType === ScheduleValueMap.Auto && (
256+
<>
257+
<Form.Item<FormData> name="placement_strategy">
258+
<SealSelect
259+
label={intl.formatMessage({
260+
id: 'resources.form.placementStrategy'
261+
})}
262+
options={placementStrategyOptions}
263+
description={
264+
<TooltipList list={placementStrategyTips}></TooltipList>
265+
}
266+
></SealSelect>
267+
</Form.Item>
268+
<LabelSelectorContext.Provider
269+
value={{ options: workerLabelOptions }}
270+
>
271+
<Form.Item<FormData>
272+
name="worker_selector"
273+
rules={[
274+
({ getFieldValue }) => ({
275+
validator(rule, value) {
276+
if (
277+
scheduleType === ScheduleValueMap.Auto &&
278+
_.keys(value).length > 0
279+
) {
280+
if (_.some(_.keys(value), (k: string) => !value[k])) {
281+
return Promise.reject(
282+
intl.formatMessage(
283+
{
284+
id: 'common.validate.value'
285+
},
286+
{
287+
name: intl.formatMessage({
288+
id: 'models.form.selector'
289+
})
290+
}
291+
)
292+
);
293+
}
294+
}
295+
return Promise.resolve();
296+
}
297+
})
298+
]}
299+
>
300+
<LabelSelector
301+
isAutoComplete
302+
label={intl.formatMessage({
303+
id: 'resources.form.workerSelector'
304+
})}
305+
labels={wokerSelector}
306+
onChange={handleWorkerLabelsChange}
307+
onBlur={handleSelectorOnBlur}
308+
onDelete={handleDeleteWorkerSelector}
309+
description={
310+
<span>
311+
{intl.formatMessage({
312+
id: 'resources.form.workerSelector.description'
313+
})}
314+
</span>
315+
}
316+
></LabelSelector>
317+
</Form.Item>
318+
</LabelSelectorContext.Provider>
319+
</>
320+
)}
211321
</>
212322
);
213323
};

0 commit comments

Comments
 (0)