Skip to content

Commit 9dce65a

Browse files
committed
feat(FR-55): support ai.backend.accelerators image label's * value (#4301)
Resolves #2781 ([FR-55](https://lablup.atlassian.net/browse/FR-55)) This PR enhances accelerator selection by using the `supported_accelerators` field from images instead of relying on accelerator limits. The implementation: 1. Adds `supported_accelerators` to the GraphQL query in ImageEnvironmentSelectFormItems 2. Replaces the previous accelerator filtering logic with a new approach that: - Checks if an accelerator type is supported by the image using the `supported_accelerators` field - Supports wildcard matching with '*' or empty string to indicate all accelerators are supported - Allows prefix matching for accelerator types - Maintains backward compatibility with manual image input This change improves the user experience by showing only relevant accelerator options based on what the selected image actually supports. [FR-55]: https://lablup.atlassian.net/browse/FR-55?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 2682468 commit 9dce65a

File tree

5 files changed

+51
-35
lines changed

5 files changed

+51
-35
lines changed

react/src/components/ImageEnvironmentSelectFormItems.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ const ImageEnvironmentSelectFormItems: React.FC<
140140
value
141141
}
142142
version @since(version: "24.12.0")
143+
supported_accelerators
143144
}
144145
}
145146
`,

react/src/components/SessionFormItems/ResourceAllocationFormItems.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ describe('getAllocatablePresetNames', () => {
4949
base_image_name: undefined,
5050
tags: undefined,
5151
version: undefined,
52+
supported_accelerators: undefined,
5253
};
5354

5455
it('should return presets when currentImage has accelerator limits', () => {

react/src/components/SessionFormItems/ResourceAllocationFormItems.tsx

Lines changed: 45 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,9 @@ const ResourceAllocationFormItems: React.FC<
163163
);
164164

165165
// When undefined, it means that the resourceSlots are not loaded yet.
166-
const acceleratorSlots = resourceSlotsInRG
166+
const acceleratorSlotsInRG = resourceSlotsInRG
167167
? _.omitBy(resourceSlotsInRG, (value, key) => {
168168
if (['cpu', 'mem', 'shmem'].includes(key)) return true;
169-
170-
if (
171-
!resourceLimits.accelerators[key]?.max ||
172-
resourceLimits.accelerators[key]?.max === 0
173-
)
174-
return true;
175169
return false;
176170
})
177171
: undefined;
@@ -187,23 +181,34 @@ const ResourceAllocationFormItems: React.FC<
187181
[currentImage],
188182
);
189183

190-
// Disable accelerator input when there is no accelerator slot or no accelerator required in the selected image
191-
// TODO: use `supported_accelerators` information from the image instead of `currentImageAcceleratorLimits` (FR-55)
192-
const isAcceleratorInputDisabled =
193-
(!_.isUndefined(acceleratorSlots) && _.isEmpty(acceleratorSlots)) ||
194-
(currentImageAcceleratorLimits &&
195-
currentImageAcceleratorLimits.length === 0 &&
196-
_.isEmpty(currentEnvironmentManual));
184+
// Get supported accelerator types in resource group by image
185+
const supportedAcceleratorTypesInRGByImage = useMemo(() => {
186+
return _.keys(acceleratorSlotsInRG).filter((acceleratorTypeName) => {
187+
// '*' means all types of accelerators are supported
188+
return (
189+
_.includes(currentImage?.supported_accelerators, '*') ||
190+
(currentImage?.supported_accelerators?.length === 1 &&
191+
currentImage.supported_accelerators[0] === '') || // Before BA-2358, manage can return '' instead of '*'
192+
_.some(
193+
currentImage?.supported_accelerators,
194+
(accPrefix) =>
195+
accPrefix &&
196+
acceleratorTypeName.split('.')[0].startsWith(accPrefix),
197+
) ||
198+
!_.isEmpty(currentEnvironmentManual) // if manual image input is not empty, allow user to input any accelerator type
199+
);
200+
});
201+
}, [currentImage, acceleratorSlotsInRG, currentEnvironmentManual]);
197202

198203
useEffect(() => {
199-
if (isAcceleratorInputDisabled) {
204+
if (supportedAcceleratorTypesInRGByImage.length === 0) {
200205
form.setFieldsValue({
201206
resource: {
202207
accelerator: 0,
203208
},
204209
});
205210
}
206-
}, [isAcceleratorInputDisabled, form]);
211+
}, [supportedAcceleratorTypesInRGByImage, form]);
207212

208213
const sessionSliderLimitAndRemaining = {
209214
min: 1,
@@ -226,9 +231,9 @@ const ResourceAllocationFormItems: React.FC<
226231
]);
227232
// If the current accelerator type is not available,
228233
// change accelerator type to the first supported accelerator
229-
const nextAcceleratorType = acceleratorSlots?.[currentAcceleratorType]
234+
const nextAcceleratorType = acceleratorSlotsInRG?.[currentAcceleratorType]
230235
? currentAcceleratorType
231-
: _.keys(acceleratorSlots)[0];
236+
: _.first(_.keys(acceleratorSlotsInRG));
232237

233238
form.setFieldsValue({
234239
resource: {
@@ -360,7 +365,7 @@ const ResourceAllocationFormItems: React.FC<
360365

361366
// Select the first matched AI accelerator type and value
362367
const firstMatchedAcceleratorType = _.find(
363-
_.keys(acceleratorSlots),
368+
_.keys(acceleratorSlotsInRG),
364369
(value) => acceleratorObj[value] !== undefined,
365370
);
366371

@@ -1066,12 +1071,16 @@ const ResourceAllocationFormItems: React.FC<
10661071
formatter: (value = 0) => {
10671072
return `${value} ${mergedResourceSlots?.[currentAcceleratorType]?.display_unit || ''}`;
10681073
},
1069-
open: isAcceleratorInputDisabled
1070-
? false
1071-
: undefined,
1074+
open:
1075+
supportedAcceleratorTypesInRGByImage.length ===
1076+
0
1077+
? false
1078+
: undefined,
10721079
},
10731080
}}
1074-
disabled={isAcceleratorInputDisabled}
1081+
disabled={
1082+
supportedAcceleratorTypesInRGByImage.length === 0
1083+
}
10751084
min={0}
10761085
max={
10771086
resourceLimits.accelerators[currentAcceleratorType]
@@ -1086,35 +1095,36 @@ const ResourceAllocationFormItems: React.FC<
10861095
<Form.Item
10871096
noStyle
10881097
name={['resource', 'acceleratorType']}
1089-
initialValue={_.keys(acceleratorSlots)[0]}
1090-
hidden={isAcceleratorInputDisabled}
1098+
initialValue={_.first(
1099+
_.keys(acceleratorSlotsInRG),
1100+
)}
1101+
hidden={
1102+
supportedAcceleratorTypesInRGByImage.length ===
1103+
0
1104+
}
10911105
>
10921106
<BAISelect
10931107
autoSelectOption
10941108
tabIndex={-1}
10951109
// Do not delete disabled prop. It is necessary to prevent the user from changing the value.
10961110
suffixIcon={
1097-
_.size(acceleratorSlots) > 1
1111+
_.size(acceleratorSlotsInRG) > 1
10981112
? undefined
10991113
: null
11001114
}
11011115
popupMatchSelectWidth={false}
11021116
options={_.map(
1103-
acceleratorSlots,
1117+
acceleratorSlotsInRG,
11041118
(value, name) => {
11051119
return {
11061120
value: name,
11071121
label:
11081122
mergedResourceSlots?.[name]
11091123
?.display_unit || 'UNIT',
1110-
disabled:
1111-
currentImageAcceleratorLimits &&
1112-
currentImageAcceleratorLimits.length >
1113-
0 &&
1114-
!_.find(
1115-
currentImageAcceleratorLimits,
1116-
(limit) => limit?.key === name,
1117-
),
1124+
disabled: !_.includes(
1125+
supportedAcceleratorTypesInRGByImage,
1126+
name,
1127+
),
11181128
};
11191129
},
11201130
)}

react/src/helper/index.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ describe('getImageFullName', () => {
166166
},
167167
],
168168
base_image_name: 'def/training',
169+
supported_accelerators: undefined,
169170
tags: [
170171
{
171172
key: 'py3',
@@ -223,6 +224,7 @@ describe('getImageFullName', () => {
223224
},
224225
],
225226
base_image_name: 'def/training',
227+
supported_accelerators: undefined,
226228
tags: [
227229
{
228230
key: 'py3',
@@ -281,6 +283,7 @@ describe('getImageFullName', () => {
281283
},
282284
],
283285
base_image_name: 'def/training',
286+
supported_accelerators: undefined,
284287
tags: [
285288
{
286289
key: 'py3',

react/src/hooks/useBackendAIImageMetaData.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ describe('useBackendAIImageMetaData', () => {
148148
base_image_name: undefined,
149149
tags: undefined,
150150
version: undefined,
151+
supported_accelerators: undefined,
151152
}) || '',
152153
);
153154
expect(key).toBe('training');

0 commit comments

Comments
 (0)