feat: models filter by state
This commit is contained in:
@@ -216,8 +216,8 @@ export default {
|
|||||||
'models.form.gpusAllocationType.custom.tips':
|
'models.form.gpusAllocationType.custom.tips':
|
||||||
'You can specify the exact number of GPUs per replica.',
|
'You can specify the exact number of GPUs per replica.',
|
||||||
'models.mymodels.status.inactive': 'Stopped',
|
'models.mymodels.status.inactive': 'Stopped',
|
||||||
'models.mymodels.status.degrade': 'Abnormal',
|
'models.mymodels.status.degrade': 'Not Ready',
|
||||||
'models.mymodels.status.active': 'Active',
|
'models.mymodels.status.active': 'Ready',
|
||||||
'models.form.kvCache.tips':
|
'models.form.kvCache.tips':
|
||||||
'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
||||||
'models.form.kvCache.tips2':
|
'models.form.kvCache.tips2':
|
||||||
|
|||||||
@@ -216,8 +216,8 @@ export default {
|
|||||||
'models.form.gpusAllocationType.custom.tips':
|
'models.form.gpusAllocationType.custom.tips':
|
||||||
'You can specify the exact number of GPUs per replica.',
|
'You can specify the exact number of GPUs per replica.',
|
||||||
'models.mymodels.status.inactive': 'Stopped',
|
'models.mymodels.status.inactive': 'Stopped',
|
||||||
'models.mymodels.status.degrade': 'Abnormal',
|
'models.mymodels.status.degrade': 'Not Ready',
|
||||||
'models.mymodels.status.active': 'Active',
|
'models.mymodels.status.active': 'Ready',
|
||||||
'models.form.kvCache.tips':
|
'models.form.kvCache.tips':
|
||||||
'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
||||||
'models.form.kvCache.tips2':
|
'models.form.kvCache.tips2':
|
||||||
@@ -313,8 +313,8 @@ export default {
|
|||||||
// 37. 'models.form.gpusAllocationType.auto.tips': 'The system automatically calculates the GPU count per replica, using powers of two by default and capped by the selected GPUs.',
|
// 37. 'models.form.gpusAllocationType.auto.tips': 'The system automatically calculates the GPU count per replica, using powers of two by default and capped by the selected GPUs.',
|
||||||
// 38. 'models.form.gpusAllocationType.custom.tips': 'You can specify the exact number of GPUs per replica.',
|
// 38. 'models.form.gpusAllocationType.custom.tips': 'You can specify the exact number of GPUs per replica.',
|
||||||
// 39. 'models.mymodels.status.inactive': 'Stopped',
|
// 39. 'models.mymodels.status.inactive': 'Stopped',
|
||||||
// 41. 'models.mymodels.status.degrade': 'Abnormal',
|
// 41. 'models.mymodels.status.degrade': 'Not Ready',
|
||||||
// 42. 'models.mymodels.status.active': 'Active'
|
// 42. 'models.mymodels.status.active': 'Ready',
|
||||||
// 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.',
|
// 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.',
|
||||||
// 44. 'models.form.kvCache.tips': 'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
// 44. 'models.form.kvCache.tips': 'Extended KV cache and speculative decoding are only available with built-in backends (vLLM / SGLang), Please switch the backend in the <span class="bold-text">Advanced</span> settings to enable them.',
|
||||||
// 45. 'models.form.kvCache.tips2': 'Only supported when using built-in inference backends (vLLM or SGLang).',
|
// 45. 'models.form.kvCache.tips2': 'Only supported when using built-in inference backends (vLLM or SGLang).',
|
||||||
|
|||||||
@@ -220,8 +220,8 @@ export default {
|
|||||||
'models.form.gpusAllocationType.custom.tips':
|
'models.form.gpusAllocationType.custom.tips':
|
||||||
'Вы можете указать точное количество GPU на реплику.',
|
'Вы можете указать точное количество GPU на реплику.',
|
||||||
'models.mymodels.status.inactive': 'Остановлен',
|
'models.mymodels.status.inactive': 'Остановлен',
|
||||||
'models.mymodels.status.degrade': 'Аномальный',
|
'models.mymodels.status.degrade': 'Не готов',
|
||||||
'models.mymodels.status.active': 'Активен',
|
'models.mymodels.status.active': 'Готов',
|
||||||
'models.form.kvCache.tips':
|
'models.form.kvCache.tips':
|
||||||
'Расширенный KV-кэш и спекулятивное декодирование доступны только со встроенными бэкендами (vLLM / SGLang). Переключите бэкенд в <span class="bold-text">Расширенных</span> настройках, чтобы включить их.',
|
'Расширенный KV-кэш и спекулятивное декодирование доступны только со встроенными бэкендами (vLLM / SGLang). Переключите бэкенд в <span class="bold-text">Расширенных</span> настройках, чтобы включить их.',
|
||||||
'models.form.kvCache.tips2':
|
'models.form.kvCache.tips2':
|
||||||
|
|||||||
@@ -161,21 +161,6 @@ const ModelItem: React.FC<{
|
|||||||
return _.round(max_tokens / 1024);
|
return _.round(max_tokens / 1024);
|
||||||
}, [model]);
|
}, [model]);
|
||||||
|
|
||||||
const status = useMemo(() => {
|
|
||||||
if (!model.replicas && !model.ready_replicas) {
|
|
||||||
return MyModelsStatusValueMap.Inactive;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.replicas > 0 && !model.ready_replicas) {
|
|
||||||
return MyModelsStatusValueMap.Degrade;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.replicas === model.ready_replicas && model.replicas > 0) {
|
|
||||||
return MyModelsStatusValueMap.Active;
|
|
||||||
}
|
|
||||||
return MyModelsStatusValueMap.Degrade;
|
|
||||||
}, [model]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardWrapper>
|
<CardWrapper>
|
||||||
<Card
|
<Card
|
||||||
@@ -198,7 +183,7 @@ const ModelItem: React.FC<{
|
|||||||
statusValue={{
|
statusValue={{
|
||||||
status: MyModelsStatusMap[model.status],
|
status: MyModelsStatusMap[model.status],
|
||||||
text: intl.formatMessage({
|
text: intl.formatMessage({
|
||||||
id: MyModelsStatusLabelMap[model.status]
|
id: MyModelsStatusLabelMap[model.status] || ''
|
||||||
}),
|
}),
|
||||||
message: model.state_message
|
message: model.state_message
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import {
|
|||||||
ModelInstanceListItem,
|
ModelInstanceListItem,
|
||||||
SourceType
|
SourceType
|
||||||
} from '../config/types';
|
} from '../config/types';
|
||||||
|
import useFilterStatus from '../hooks/use-filter-status';
|
||||||
import useFormInitialValues from '../hooks/use-form-initial-values';
|
import useFormInitialValues from '../hooks/use-form-initial-values';
|
||||||
import useModelsColumns from '../hooks/use-models-columns';
|
import useModelsColumns from '../hooks/use-models-columns';
|
||||||
import AccessControlModal from './access-control-modal';
|
import AccessControlModal from './access-control-modal';
|
||||||
@@ -78,6 +79,7 @@ interface ModelsProps {
|
|||||||
onStop?: (ids: number[]) => void;
|
onStop?: (ids: number[]) => void;
|
||||||
onStart?: () => void;
|
onStart?: () => void;
|
||||||
onTableSort?: (order: TableOrder | Array<TableOrder>) => void;
|
onTableSort?: (order: TableOrder | Array<TableOrder>) => void;
|
||||||
|
onStatusChange: (value?: any) => void;
|
||||||
sortOrder: string[];
|
sortOrder: string[];
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: number;
|
page: number;
|
||||||
@@ -119,6 +121,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
onStop,
|
onStop,
|
||||||
onStart,
|
onStart,
|
||||||
onTableSort,
|
onTableSort,
|
||||||
|
onStatusChange,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
deleteIds,
|
deleteIds,
|
||||||
dataSource,
|
dataSource,
|
||||||
@@ -154,6 +157,10 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
removeExpandedRowKey,
|
removeExpandedRowKey,
|
||||||
expandedRowKeys
|
expandedRowKeys
|
||||||
} = useExpandedRowKeys(expandAtom);
|
} = useExpandedRowKeys(expandAtom);
|
||||||
|
const { labelRender, optionRender, handleStatusChange, statusOptions } =
|
||||||
|
useFilterStatus({
|
||||||
|
onStatusChange: onStatusChange
|
||||||
|
});
|
||||||
|
|
||||||
const [apiAccessInfo, setAPIAccessInfo] = useState<any>({
|
const [apiAccessInfo, setAPIAccessInfo] = useState<any>({
|
||||||
show: false,
|
show: false,
|
||||||
@@ -663,6 +670,18 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
onChange={handleClusterChange}
|
onChange={handleClusterChange}
|
||||||
options={clusterList}
|
options={clusterList}
|
||||||
></BaseSelect>
|
></BaseSelect>
|
||||||
|
<BaseSelect
|
||||||
|
allowClear
|
||||||
|
showSearch={false}
|
||||||
|
placeholder={intl.formatMessage({ id: 'common.filter.status' })}
|
||||||
|
style={{ width: 180 }}
|
||||||
|
size="large"
|
||||||
|
maxTagCount={1}
|
||||||
|
optionRender={optionRender}
|
||||||
|
labelRender={labelRender}
|
||||||
|
options={statusOptions}
|
||||||
|
onChange={handleStatusChange}
|
||||||
|
></BaseSelect>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||||
|
|||||||
@@ -196,9 +196,9 @@ export const status: any = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MyModelsStatusValueMap = {
|
export const MyModelsStatusValueMap = {
|
||||||
Inactive: 'Inactive',
|
Inactive: 'stopped',
|
||||||
Degrade: 'Degrade',
|
Degrade: 'not_ready',
|
||||||
Active: 'Active'
|
Active: 'ready'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MyModelsStatusMap = {
|
export const MyModelsStatusMap = {
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { MyModelsStatusValueMap } from '../config';
|
||||||
|
|
||||||
|
const Dot = ({ color }: { color: string }) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
backgroundColor: color,
|
||||||
|
borderRadius: '50%',
|
||||||
|
height: 8,
|
||||||
|
width: 8,
|
||||||
|
display: 'flex'
|
||||||
|
}}
|
||||||
|
></span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useFilterStatus = (options: {
|
||||||
|
onStatusChange: (value?: any) => void;
|
||||||
|
}) => {
|
||||||
|
const { onStatusChange } = options;
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const statusOptions = [
|
||||||
|
{
|
||||||
|
value: MyModelsStatusValueMap.Active,
|
||||||
|
color: 'var(--ant-color-success)',
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'models.mymodels.status.active'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MyModelsStatusValueMap.Inactive,
|
||||||
|
color: 'var(--ant-color-fill)',
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'models.mymodels.status.inactive'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MyModelsStatusValueMap.Degrade,
|
||||||
|
color: 'var(--ant-color-error)',
|
||||||
|
label: intl.formatMessage({
|
||||||
|
id: 'models.mymodels.status.degrade'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const labelRender = (item: any) => {
|
||||||
|
const current = statusOptions.find((option) => option.value === item.value);
|
||||||
|
return (
|
||||||
|
<span className="flex-center gap-8">
|
||||||
|
<Dot color={current!.color}></Dot>
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionRender = (item: any) => {
|
||||||
|
return (
|
||||||
|
<span className="flex-center gap-8">
|
||||||
|
<Dot color={item.data?.color}></Dot>
|
||||||
|
{item.label}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleStatusChange = (value: string | undefined) => {
|
||||||
|
onStatusChange(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
statusOptions,
|
||||||
|
labelRender,
|
||||||
|
optionRender,
|
||||||
|
handleStatusChange
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useFilterStatus;
|
||||||
@@ -47,6 +47,7 @@ const Models: React.FC = () => {
|
|||||||
search: '',
|
search: '',
|
||||||
cluster_id: 0,
|
cluster_id: 0,
|
||||||
categories: [],
|
categories: [],
|
||||||
|
state: '',
|
||||||
sort_by: '-created_at'
|
sort_by: '-created_at'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -197,6 +198,7 @@ const Models: React.FC = () => {
|
|||||||
search: string;
|
search: string;
|
||||||
categories: any[];
|
categories: any[];
|
||||||
cluster_id: number;
|
cluster_id: number;
|
||||||
|
state?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const search = params?.search || queryParams.search;
|
const search = params?.search || queryParams.search;
|
||||||
const categories = params?.categories || queryParams.categories;
|
const categories = params?.categories || queryParams.categories;
|
||||||
@@ -287,6 +289,19 @@ const Models: React.FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnStatusChange = async (value: string | undefined) => {
|
||||||
|
handleQueryChange({
|
||||||
|
page: 1,
|
||||||
|
state: value
|
||||||
|
});
|
||||||
|
createModelsChunkRequest({
|
||||||
|
search: queryParams.search,
|
||||||
|
categories: queryParams.categories,
|
||||||
|
cluster_id: queryParams.cluster_id || 0,
|
||||||
|
state: value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleClusterChange = async (value: number) => {
|
const handleClusterChange = async (value: number) => {
|
||||||
handleQueryChange({
|
handleQueryChange({
|
||||||
page: 1,
|
page: 1,
|
||||||
@@ -408,6 +423,7 @@ const Models: React.FC = () => {
|
|||||||
>
|
>
|
||||||
<TableList
|
<TableList
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
|
onStatusChange={handleOnStatusChange}
|
||||||
handleNameChange={handleNameChange}
|
handleNameChange={handleNameChange}
|
||||||
handleCategoryChange={handleCategoryChange}
|
handleCategoryChange={handleCategoryChange}
|
||||||
handleClusterChange={handleClusterChange}
|
handleClusterChange={handleClusterChange}
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ const UserModels: React.FC = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [status, setStatus] = React.useState<string | undefined>(undefined);
|
|
||||||
|
|
||||||
const statusOptions = useMemo(() => {
|
const statusOptions = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
@@ -131,7 +130,9 @@ const UserModels: React.FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleStatusChange = (value: string) => {
|
const handleStatusChange = (value: string) => {
|
||||||
setStatus(value);
|
handleQueryChange({
|
||||||
|
state: value
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const labelRender = (item: any) => {
|
const labelRender = (item: any) => {
|
||||||
@@ -166,9 +167,8 @@ const UserModels: React.FC = () => {
|
|||||||
status: getStatus(item)
|
status: getStatus(item)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
if (!status) return result;
|
return result;
|
||||||
return result.filter((item) => item.status === status);
|
}, [dataSource.dataList]);
|
||||||
}, [dataSource.dataList, status]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageBox>
|
<PageBox>
|
||||||
@@ -242,7 +242,7 @@ const UserModels: React.FC = () => {
|
|||||||
loadend={dataSource.loadend}
|
loadend={dataSource.loadend}
|
||||||
dataSource={dataList}
|
dataSource={dataList}
|
||||||
image={<IconFont type="icon-models" />}
|
image={<IconFont type="icon-models" />}
|
||||||
filters={{ ...queryParams, status: status }}
|
filters={{ ...queryParams }}
|
||||||
noFoundText={intl.formatMessage({
|
noFoundText={intl.formatMessage({
|
||||||
id: 'noresult.mymodels.nofound'
|
id: 'noresult.mymodels.nofound'
|
||||||
})}
|
})}
|
||||||
|
|||||||
Reference in New Issue
Block a user