fix: update open playground btn
This commit is contained in:
@@ -104,6 +104,11 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-full {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
// space-between
|
// space-between
|
||||||
.flex-between {
|
.flex-between {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
|
|||||||
// import './iconfont/iconfont.js';
|
// import './iconfont/iconfont.js';
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: '//at.alicdn.com/t/c/font_4613488_c3lajf3mdtk.js'
|
scriptUrl: '//at.alicdn.com/t/c/font_4613488_i617h54opsm.js'
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IconFont;
|
export default IconFont;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -98,7 +98,11 @@ const CommunityBackends: React.FC<{
|
|||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
{data.enabled && (
|
{data.enabled && (
|
||||||
<ThemeTag style={{ margin: 0 }} color="geekblue" variant="filled">
|
<ThemeTag
|
||||||
|
style={{ margin: 0, fontWeight: 400 }}
|
||||||
|
color="geekblue"
|
||||||
|
variant="filled"
|
||||||
|
>
|
||||||
{intl.formatMessage({ id: 'common.status.enabled' })}
|
{intl.formatMessage({ id: 'common.status.enabled' })}
|
||||||
</ThemeTag>
|
</ThemeTag>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -88,53 +88,6 @@ export const credentialActionList = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const clusterActionList = [
|
|
||||||
{
|
|
||||||
key: 'edit',
|
|
||||||
label: 'common.button.edit',
|
|
||||||
icon: icons.EditOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'resources.metrics.details',
|
|
||||||
key: 'metrics',
|
|
||||||
icon: icons.Metrics
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'add_worker',
|
|
||||||
label: 'resources.button.create',
|
|
||||||
provider: ProviderValueMap.Docker,
|
|
||||||
locale: true,
|
|
||||||
icon: icons.DockerOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'register_cluster',
|
|
||||||
label: 'clusters.button.register',
|
|
||||||
provider: ProviderValueMap.Kubernetes,
|
|
||||||
locale: true,
|
|
||||||
icon: icons.KubernetesOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'addPool',
|
|
||||||
label: 'clusters.button.addNodePool',
|
|
||||||
provider: ProviderValueMap.DigitalOcean,
|
|
||||||
locale: true,
|
|
||||||
icon: icons.Catalog1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'isDefault',
|
|
||||||
label: 'clusters.form.setDefault',
|
|
||||||
icon: icons.StarOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'delete',
|
|
||||||
label: 'common.button.delete',
|
|
||||||
icon: icons.DeleteOutlined,
|
|
||||||
props: {
|
|
||||||
danger: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const CloudOptionItems = [
|
export const CloudOptionItems = [
|
||||||
{
|
{
|
||||||
label: 'Volumes',
|
label: 'Volumes',
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
import { systemConfigAtom } from '@/atoms/system';
|
import { systemConfigAtom } from '@/atoms/system';
|
||||||
import AutoTooltip from '@/components/auto-tooltip';
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
|
import icons from '@/components/icon-font/icons';
|
||||||
import { SealColumnProps } from '@/components/seal-table/types';
|
import { SealColumnProps } from '@/components/seal-table/types';
|
||||||
import StatusTag from '@/components/status-tag';
|
import StatusTag from '@/components/status-tag';
|
||||||
import { tableSorter } from '@/config/settings';
|
import { tableSorter } from '@/config/settings';
|
||||||
|
import GrafanaIcon from '@/pages/_components/grafana-icon';
|
||||||
import { StarFilled } from '@ant-design/icons';
|
import { StarFilled } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Tooltip } from 'antd';
|
import { Tooltip } from 'antd';
|
||||||
@@ -15,10 +17,61 @@ import {
|
|||||||
ClusterStatus,
|
ClusterStatus,
|
||||||
ClusterStatusLabelMap,
|
ClusterStatusLabelMap,
|
||||||
ProviderLabelMap,
|
ProviderLabelMap,
|
||||||
clusterActionList
|
ProviderValueMap
|
||||||
} from '../config';
|
} from '../config';
|
||||||
import { ClusterListItem } from '../config/types';
|
import { ClusterListItem } from '../config/types';
|
||||||
|
|
||||||
|
const clusterActionList = [
|
||||||
|
{
|
||||||
|
key: 'edit',
|
||||||
|
label: 'common.button.edit',
|
||||||
|
icon: icons.EditOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'resources.metrics.details',
|
||||||
|
key: 'metrics',
|
||||||
|
icon: (
|
||||||
|
<span className="flex-center">
|
||||||
|
<GrafanaIcon style={{ width: 14, height: 14 }}></GrafanaIcon>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'add_worker',
|
||||||
|
label: 'resources.button.create',
|
||||||
|
provider: ProviderValueMap.Docker,
|
||||||
|
locale: true,
|
||||||
|
icon: icons.DockerOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'register_cluster',
|
||||||
|
label: 'clusters.button.register',
|
||||||
|
provider: ProviderValueMap.Kubernetes,
|
||||||
|
locale: true,
|
||||||
|
icon: icons.KubernetesOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'addPool',
|
||||||
|
label: 'clusters.button.addNodePool',
|
||||||
|
provider: ProviderValueMap.DigitalOcean,
|
||||||
|
locale: true,
|
||||||
|
icon: icons.Catalog1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'isDefault',
|
||||||
|
label: 'clusters.form.setDefault',
|
||||||
|
icon: icons.StarOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'delete',
|
||||||
|
label: 'common.button.delete',
|
||||||
|
icon: icons.DeleteOutlined,
|
||||||
|
props: {
|
||||||
|
danger: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const useClusterColumns = (
|
const useClusterColumns = (
|
||||||
handleSelect: (val: string, record: ClusterListItem) => void,
|
handleSelect: (val: string, record: ClusterListItem) => void,
|
||||||
onCellClick?: (record: ClusterListItem, dataIndex: string) => void
|
onCellClick?: (record: ClusterListItem, dataIndex: string) => void
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { HandlerOptions } from '@/hooks/use-chunk-fetch';
|
|||||||
import useDownloadStream from '@/hooks/use-download-stream';
|
import useDownloadStream from '@/hooks/use-download-stream';
|
||||||
import { useBenchmarkTargetInstance } from '@/pages/llmodels/hooks/use-run-benchmark';
|
import { useBenchmarkTargetInstance } from '@/pages/llmodels/hooks/use-run-benchmark';
|
||||||
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
|
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
|
||||||
import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
|
|
||||||
import { convertFileSize } from '@/utils';
|
import { convertFileSize } from '@/utils';
|
||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
@@ -330,12 +329,6 @@ const childActionList = [
|
|||||||
],
|
],
|
||||||
icon: <IconFont type="icon-logs" />
|
icon: <IconFont type="icon-logs" />
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'resources.metrics.details',
|
|
||||||
key: 'metrics',
|
|
||||||
status: [InstanceStatusMap.Running],
|
|
||||||
icon: <IconFont type="icon-metrics" />
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: 'common.button.downloadLog',
|
label: 'common.button.downloadLog',
|
||||||
key: 'download',
|
key: 'download',
|
||||||
@@ -438,7 +431,6 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
handleChildSelect
|
handleChildSelect
|
||||||
}) => {
|
}) => {
|
||||||
const systemConfig = useAtomValue(systemConfigAtom);
|
const systemConfig = useAtomValue(systemConfigAtom);
|
||||||
const { goToGrafana } = useGranfanaLink({ type: 'instance' });
|
|
||||||
const { runBenchmarkOnInstance } = useBenchmarkTargetInstance();
|
const { runBenchmarkOnInstance } = useBenchmarkTargetInstance();
|
||||||
const [api, contextHolder] = notification.useNotification({
|
const [api, contextHolder] = notification.useNotification({
|
||||||
stack: { threshold: 1 }
|
stack: { threshold: 1 }
|
||||||
@@ -456,9 +448,6 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
if (action.status && action.status.length > 0) {
|
if (action.status && action.status.length > 0) {
|
||||||
return action.status.includes(instanceData.state);
|
return action.status.includes(instanceData.state);
|
||||||
}
|
}
|
||||||
if (action.key === 'metrics') {
|
|
||||||
return systemConfig.showMonitoring;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}, [instanceData.state, modelData, systemConfig.showMonitoring]);
|
}, [instanceData.state, modelData, systemConfig.showMonitoring]);
|
||||||
@@ -668,25 +657,27 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
<InfoColumn fieldList={fieldList} data={offloadData}></InfoColumn>
|
<InfoColumn fieldList={fieldList} data={offloadData}></InfoColumn>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ThemeTag
|
<span>
|
||||||
opacity={0.75}
|
<ThemeTag
|
||||||
color="cyan"
|
opacity={0.75}
|
||||||
style={{
|
color="cyan"
|
||||||
display: 'flex',
|
style={{
|
||||||
alignItems: 'center',
|
display: 'flex',
|
||||||
maxWidth: '100%',
|
alignItems: 'center',
|
||||||
minWidth: 50,
|
maxWidth: '100%',
|
||||||
textOverflow: 'ellipsis',
|
minWidth: 50,
|
||||||
whiteSpace: 'nowrap',
|
textOverflow: 'ellipsis',
|
||||||
overflow: 'hidden',
|
whiteSpace: 'nowrap',
|
||||||
borderRadius: 12
|
overflow: 'hidden',
|
||||||
}}
|
borderRadius: 12
|
||||||
>
|
}}
|
||||||
<InfoCircleOutlined className="m-r-5" />
|
>
|
||||||
{intl.formatMessage({
|
<InfoCircleOutlined className="m-r-5" />
|
||||||
id: 'models.table.cpuoffload'
|
{intl.formatMessage({
|
||||||
})}
|
id: 'models.table.cpuoffload'
|
||||||
</ThemeTag>
|
})}
|
||||||
|
</ThemeTag>
|
||||||
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}, [
|
}, [
|
||||||
@@ -703,8 +694,6 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
filename: createFileName(instanceData.name),
|
filename: createFileName(instanceData.name),
|
||||||
downloadNotification
|
downloadNotification
|
||||||
});
|
});
|
||||||
} else if (val === 'metrics') {
|
|
||||||
goToGrafana(instanceData);
|
|
||||||
} else {
|
} else {
|
||||||
handleChildSelect(val, instanceData);
|
handleChildSelect(val, instanceData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,12 @@ import { PageActionType } from '@/config/types';
|
|||||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||||
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
||||||
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
||||||
|
import useWatchList from '@/hooks/use-watch-list';
|
||||||
import PageBox from '@/pages/_components/page-box';
|
import PageBox from '@/pages/_components/page-box';
|
||||||
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
|
||||||
|
import { MODEL_ROUTE_TARGETS } from '@/pages/model-routes/apis';
|
||||||
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
||||||
import useOpenPlayground from '@/pages/model-routes/hooks/use-open-playground';
|
import useOpenPlayground from '@/pages/model-routes/hooks/use-open-playground';
|
||||||
import useQueryTargets from '@/pages/model-routes/services/use-query-targets';
|
|
||||||
import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
|
import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
|
||||||
import { handleBatchRequest } from '@/utils';
|
import { handleBatchRequest } from '@/utils';
|
||||||
import { DownOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
import { DownOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
|
||||||
@@ -166,11 +167,8 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
useFilterStatus({
|
useFilterStatus({
|
||||||
onStatusChange: onStatusChange
|
onStatusChange: onStatusChange
|
||||||
});
|
});
|
||||||
const { fetchData: fetchTargets, dataList: targetList } = useQueryTargets();
|
const { watchDataList: targetList } = useWatchList(MODEL_ROUTE_TARGETS);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchTargets({});
|
|
||||||
}, []);
|
|
||||||
const { goToGrafana, ActionButton } = useGranfanaLink({
|
const { goToGrafana, ActionButton } = useGranfanaLink({
|
||||||
type: 'model',
|
type: 'model',
|
||||||
dataList: dataSource || []
|
dataList: dataSource || []
|
||||||
@@ -554,7 +552,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
sortOrder,
|
sortOrder,
|
||||||
targetList: targetList
|
targetList: targetList
|
||||||
};
|
};
|
||||||
}, [handleSelect, clusterList, sortOrder]);
|
}, [handleSelect, clusterList, sortOrder, targetList]);
|
||||||
|
|
||||||
const columns = useModelsColumns(options);
|
const columns = useModelsColumns(options);
|
||||||
|
|
||||||
|
|||||||
@@ -275,6 +275,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
initialValues={formData}
|
initialValues={formData}
|
||||||
source={formData.source || ''}
|
source={formData.source || ''}
|
||||||
action={action}
|
action={action}
|
||||||
|
realAction={realAction}
|
||||||
clusterList={clusterList}
|
clusterList={clusterList}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
ref={formRef}
|
ref={formRef}
|
||||||
|
|||||||
@@ -33,47 +33,6 @@ interface ActionItem {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ActionList: ActionItem[] = [
|
|
||||||
{
|
|
||||||
label: 'common.button.edit',
|
|
||||||
key: 'edit',
|
|
||||||
icon: icons.EditOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'models.openinplayground',
|
|
||||||
key: 'chat',
|
|
||||||
icon: icons.ExperimentOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'copy',
|
|
||||||
label: 'common.button.clone',
|
|
||||||
icon: icons.CopyOutlined
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'common.button.start',
|
|
||||||
key: 'start',
|
|
||||||
icon: icons.Play
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'common.button.stop',
|
|
||||||
key: 'stop',
|
|
||||||
icon: icons.Stop
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'resources.metrics.details',
|
|
||||||
key: 'metrics',
|
|
||||||
icon: icons.Metrics
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'common.button.delete',
|
|
||||||
key: 'delete',
|
|
||||||
props: {
|
|
||||||
danger: true
|
|
||||||
},
|
|
||||||
icon: icons.DeleteOutlined
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const ButtonList = [
|
export const ButtonList = [
|
||||||
{
|
{
|
||||||
label: 'common.button.start',
|
label: 'common.button.start',
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ interface FormContextProps {
|
|||||||
formKey: DeployFormKey;
|
formKey: DeployFormKey;
|
||||||
source: string;
|
source: string;
|
||||||
action: PageActionType;
|
action: PageActionType;
|
||||||
|
realAction?: PageActionType;
|
||||||
gpuOptions: CascaderOption[];
|
gpuOptions: CascaderOption[];
|
||||||
workerLabelOptions: CascaderOption[];
|
workerLabelOptions: CascaderOption[];
|
||||||
backendOptions: {
|
backendOptions: {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import LabelSelector from '@/components/label-selector';
|
import LabelSelector from '@/components/label-selector';
|
||||||
import CheckboxField from '@/components/seal-form/checkbox-field';
|
import CheckboxField from '@/components/seal-form/checkbox-field';
|
||||||
import SealSelect from '@/components/seal-form/seal-select';
|
import SealSelect from '@/components/seal-form/seal-select';
|
||||||
|
import { PageAction } from '@/config';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form } from 'antd';
|
import { Form } from 'antd';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -19,6 +20,8 @@ const AdvanceConfig = () => {
|
|||||||
const modelRouteEnable = Form.useWatch('enable_model_route', form);
|
const modelRouteEnable = Form.useWatch('enable_model_route', form);
|
||||||
const {
|
const {
|
||||||
onValuesChange,
|
onValuesChange,
|
||||||
|
realAction,
|
||||||
|
action,
|
||||||
backendOptions,
|
backendOptions,
|
||||||
flatBackendOptions,
|
flatBackendOptions,
|
||||||
isGGUF,
|
isGGUF,
|
||||||
@@ -133,33 +136,37 @@ const AdvanceConfig = () => {
|
|||||||
})}
|
})}
|
||||||
></CheckboxField>
|
></CheckboxField>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FormData>
|
{realAction === PageAction.COPY || action === PageAction.CREATE ? (
|
||||||
name="enable_model_route"
|
<>
|
||||||
valuePropName="checked"
|
<Form.Item<FormData>
|
||||||
style={{ marginBottom: 8 }}
|
name="enable_model_route"
|
||||||
>
|
valuePropName="checked"
|
||||||
<CheckboxField
|
style={{ marginBottom: 8 }}
|
||||||
label={intl.formatMessage({
|
>
|
||||||
id: 'models.form.enableModelRoute'
|
<CheckboxField
|
||||||
})}
|
label={intl.formatMessage({
|
||||||
></CheckboxField>
|
id: 'models.form.enableModelRoute'
|
||||||
</Form.Item>
|
})}
|
||||||
{modelRouteEnable && (
|
></CheckboxField>
|
||||||
<Form.Item<FormData>
|
</Form.Item>
|
||||||
name="generic_proxy"
|
{modelRouteEnable && (
|
||||||
valuePropName="checked"
|
<Form.Item<FormData>
|
||||||
style={{ marginBottom: 8 }}
|
name="generic_proxy"
|
||||||
>
|
valuePropName="checked"
|
||||||
<CheckboxField
|
style={{ marginBottom: 8 }}
|
||||||
description={intl.formatMessage({
|
>
|
||||||
id: 'models.form.generic_proxy.tips'
|
<CheckboxField
|
||||||
})}
|
description={intl.formatMessage({
|
||||||
label={intl.formatMessage({
|
id: 'models.form.generic_proxy.tips'
|
||||||
id: 'models.form.generic_proxy'
|
})}
|
||||||
})}
|
label={intl.formatMessage({
|
||||||
></CheckboxField>
|
id: 'models.form.generic_proxy'
|
||||||
</Form.Item>
|
})}
|
||||||
)}
|
></CheckboxField>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ interface DataFormProps {
|
|||||||
ref?: any;
|
ref?: any;
|
||||||
source: SourceType;
|
source: SourceType;
|
||||||
action: PageActionType;
|
action: PageActionType;
|
||||||
|
realAction?: PageActionType;
|
||||||
isGGUF: boolean;
|
isGGUF: boolean;
|
||||||
formKey: DeployFormKey;
|
formKey: DeployFormKey;
|
||||||
sourceDisable?: boolean;
|
sourceDisable?: boolean;
|
||||||
@@ -77,6 +78,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
|||||||
isGGUF,
|
isGGUF,
|
||||||
formKey,
|
formKey,
|
||||||
source,
|
source,
|
||||||
|
realAction,
|
||||||
initialValues,
|
initialValues,
|
||||||
sourceDisable = true,
|
sourceDisable = true,
|
||||||
sourceList,
|
sourceList,
|
||||||
@@ -392,6 +394,7 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
|||||||
formKey: formKey,
|
formKey: formKey,
|
||||||
source: props.source,
|
source: props.source,
|
||||||
action: action,
|
action: action,
|
||||||
|
realAction: realAction,
|
||||||
gpuOptions: gpuOptions,
|
gpuOptions: gpuOptions,
|
||||||
backendOptions: backendOptions,
|
backendOptions: backendOptions,
|
||||||
flatBackendOptions: flatBackendOptions,
|
flatBackendOptions: flatBackendOptions,
|
||||||
|
|||||||
@@ -271,12 +271,6 @@ export const useCheckCompatibility = () => {
|
|||||||
|
|
||||||
let compatibilityMessage = compatibility_messages.join(' ');
|
let compatibilityMessage = compatibility_messages.join(' ');
|
||||||
|
|
||||||
compatibilityMessage = compatibilityMessage.startsWith(
|
|
||||||
'The model file path you specified does not exist on the GPUStack server'
|
|
||||||
)
|
|
||||||
? intl.formatMessage({ id: 'models.form.modelfile.notfound' })
|
|
||||||
: compatibilityMessage;
|
|
||||||
|
|
||||||
let msgData = {
|
let msgData = {
|
||||||
title: scheduling_messages?.length > 0 ? compatibilityMessage : '',
|
title: scheduling_messages?.length > 0 ? compatibilityMessage : '',
|
||||||
message:
|
message:
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
import { systemConfigAtom } from '@/atoms/system';
|
import { systemConfigAtom } from '@/atoms/system';
|
||||||
import AutoTooltip from '@/components/auto-tooltip';
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
|
import icons from '@/components/icon-font/icons';
|
||||||
import { SealColumnProps } from '@/components/seal-table/types';
|
import { SealColumnProps } from '@/components/seal-table/types';
|
||||||
import { OPENAI_COMPATIBLE, tableSorter } from '@/config/settings';
|
import { OPENAI_COMPATIBLE, tableSorter } from '@/config/settings';
|
||||||
|
import GrafanaIcon from '@/pages/_components/grafana-icon';
|
||||||
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
import { TargetStatusValueMap } from '@/pages/model-routes/config';
|
||||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
@@ -14,9 +16,63 @@ import { useAtomValue } from 'jotai';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import ModelTag from '../../_components/model-tag';
|
import ModelTag from '../../_components/model-tag';
|
||||||
import { ActionList, generateSource } from '../config/button-actions';
|
import { generateSource } from '../config/button-actions';
|
||||||
import { ListItem } from '../config/types';
|
import { ListItem } from '../config/types';
|
||||||
|
|
||||||
|
interface ActionItem {
|
||||||
|
label: string;
|
||||||
|
key: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
props?: {
|
||||||
|
danger?: boolean;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActionList: ActionItem[] = [
|
||||||
|
{
|
||||||
|
label: 'common.button.edit',
|
||||||
|
key: 'edit',
|
||||||
|
icon: icons.EditOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'models.openinplayground',
|
||||||
|
key: 'chat',
|
||||||
|
icon: icons.ExperimentOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'common.button.start',
|
||||||
|
key: 'start',
|
||||||
|
icon: icons.Play
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'common.button.stop',
|
||||||
|
key: 'stop',
|
||||||
|
icon: icons.Stop
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'resources.metrics.details',
|
||||||
|
key: 'metrics',
|
||||||
|
icon: (
|
||||||
|
<span className="flex-center">
|
||||||
|
<GrafanaIcon style={{ width: 14, height: 14 }}></GrafanaIcon>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'copy',
|
||||||
|
label: 'common.button.clone',
|
||||||
|
icon: icons.CopyOutlined
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'common.button.delete',
|
||||||
|
key: 'delete',
|
||||||
|
props: {
|
||||||
|
danger: true
|
||||||
|
},
|
||||||
|
icon: icons.DeleteOutlined
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
interface ModelsColumnsHookProps {
|
interface ModelsColumnsHookProps {
|
||||||
handleSelect: (val: string, record: ListItem) => void;
|
handleSelect: (val: string, record: ListItem) => void;
|
||||||
sortOrder: string[];
|
sortOrder: string[];
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ const useGPUColumns = (props: {
|
|||||||
sorter: tableSorter(6),
|
sorter: tableSorter(6),
|
||||||
render: (text: number, record: GPUDeviceItem) => {
|
render: (text: number, record: GPUDeviceItem) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<span className="flex-center flex-full">
|
||||||
{record.core ? (
|
{record.core ? (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
percent={_.round(record.core?.utilization_rate, 2)}
|
percent={_.round(record.core?.utilization_rate, 2)}
|
||||||
@@ -110,7 +110,7 @@ const useGPUColumns = (props: {
|
|||||||
) : (
|
) : (
|
||||||
'-'
|
'-'
|
||||||
)}
|
)}
|
||||||
</>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -121,23 +121,25 @@ const useGPUColumns = (props: {
|
|||||||
sorter: tableSorter(7),
|
sorter: tableSorter(7),
|
||||||
render: (text: number, record: GPUDeviceItem, index: number) => {
|
render: (text: number, record: GPUDeviceItem, index: number) => {
|
||||||
return (
|
return (
|
||||||
<ProgressBar
|
<span className="flex-center flex-full">
|
||||||
defaultOpen={index === 0 && loadend && firstLoad}
|
<ProgressBar
|
||||||
percent={
|
defaultOpen={index === 0 && loadend && firstLoad}
|
||||||
record.memory?.used
|
percent={
|
||||||
? _.round(record.memory?.utilization_rate, 0)
|
record.memory?.used
|
||||||
: _.round(
|
? _.round(record.memory?.utilization_rate, 0)
|
||||||
record.memory?.allocated / record.memory?.total,
|
: _.round(
|
||||||
0
|
record.memory?.allocated / record.memory?.total,
|
||||||
) * 100
|
0
|
||||||
}
|
) * 100
|
||||||
label={
|
}
|
||||||
<InfoColumn
|
label={
|
||||||
fieldList={fieldList}
|
<InfoColumn
|
||||||
data={record.memory}
|
fieldList={fieldList}
|
||||||
></InfoColumn>
|
data={record.memory}
|
||||||
}
|
></InfoColumn>
|
||||||
></ProgressBar>
|
}
|
||||||
|
></ProgressBar>
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { systemConfigAtom } from '@/atoms/system';
|
import { systemConfigAtom } from '@/atoms/system';
|
||||||
import IconFont from '@/components/icon-font';
|
|
||||||
import { GPUSTACK_API_BASE_URL } from '@/config/settings';
|
import { GPUSTACK_API_BASE_URL } from '@/config/settings';
|
||||||
|
import GrafanaIcon from '@/pages/_components/grafana-icon';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button } from 'antd';
|
import { Button } from 'antd';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
|
|
||||||
const useGranfanaLink = (options: {
|
const useGranfanaLink = (options: {
|
||||||
type: 'model' | 'worker' | 'instance' | 'cluster';
|
type: 'model' | 'worker' | 'instance' | 'cluster';
|
||||||
dataList: any[];
|
dataList?: any[];
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const systemConfig = useAtomValue(systemConfigAtom);
|
const systemConfig = useAtomValue(systemConfigAtom);
|
||||||
@@ -53,7 +53,7 @@ const useGranfanaLink = (options: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (options.dataList?.length > 0) {
|
if (options.dataList && options.dataList.length > 0) {
|
||||||
goToGrafana(options.dataList?.[0]);
|
goToGrafana(options.dataList?.[0]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -63,7 +63,7 @@ const useGranfanaLink = (options: {
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
icon={<IconFont type="icon-metrics" style={{ fontSize: 16 }} />}
|
icon={<GrafanaIcon style={{ width: 16, height: 16 }}></GrafanaIcon>}
|
||||||
>
|
>
|
||||||
{intl.formatMessage({ id: 'resources.metrics.details' })}
|
{intl.formatMessage({ id: 'resources.metrics.details' })}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { systemConfigAtom } from '@/atoms/system';
|
import { systemConfigAtom } from '@/atoms/system';
|
||||||
import AutoTooltip from '@/components/auto-tooltip';
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import DropdownButtons from '@/components/drop-down-buttons';
|
import DropdownButtons from '@/components/drop-down-buttons';
|
||||||
import IconFont from '@/components/icon-font';
|
|
||||||
import LabelsCell from '@/components/label-cell';
|
import LabelsCell from '@/components/label-cell';
|
||||||
import ProgressBar from '@/components/progress-bar';
|
import ProgressBar from '@/components/progress-bar';
|
||||||
import InfoColumn from '@/components/simple-table/info-column';
|
import InfoColumn from '@/components/simple-table/info-column';
|
||||||
import StatusTag from '@/components/status-tag';
|
import StatusTag from '@/components/status-tag';
|
||||||
import { tableSorter } from '@/config/settings';
|
import { tableSorter } from '@/config/settings';
|
||||||
|
import GrafanaIcon from '@/pages/_components/grafana-icon';
|
||||||
import { convertFileSize } from '@/utils';
|
import { convertFileSize } from '@/utils';
|
||||||
import {
|
import {
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
@@ -48,7 +48,11 @@ const ActionList = [
|
|||||||
{
|
{
|
||||||
label: 'resources.metrics.details',
|
label: 'resources.metrics.details',
|
||||||
key: 'metrics',
|
key: 'metrics',
|
||||||
icon: <IconFont type="icon-metrics" />
|
icon: (
|
||||||
|
<span className="flex-center">
|
||||||
|
<GrafanaIcon style={{ width: 14, height: 14 }}></GrafanaIcon>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// label: 'common.button.detail',
|
// label: 'common.button.detail',
|
||||||
@@ -123,7 +127,10 @@ const GPUCell = ({ devices }: { devices: GPUDeviceItem[] }) => (
|
|||||||
_.sortBy(devices || [], ['index']),
|
_.sortBy(devices || [], ['index']),
|
||||||
(item: GPUDeviceItem, index: number) => (
|
(item: GPUDeviceItem, index: number) => (
|
||||||
<span className="flex-center" key={index}>
|
<span className="flex-center" key={index}>
|
||||||
<span className="m-r-5" style={{ display: 'flex', width: 25 }}>
|
<span
|
||||||
|
className="m-r-5"
|
||||||
|
style={{ display: 'flex', width: 25, lineHeight: 1 }}
|
||||||
|
>
|
||||||
[{item.index}]
|
[{item.index}]
|
||||||
</span>
|
</span>
|
||||||
{item.core ? (
|
{item.core ? (
|
||||||
@@ -155,7 +162,10 @@ const VRAMCell = ({
|
|||||||
_.sortBy(devices || [], ['index']),
|
_.sortBy(devices || [], ['index']),
|
||||||
(item: GPUDeviceItem, index: number) => (
|
(item: GPUDeviceItem, index: number) => (
|
||||||
<span key={index} className="flex-center">
|
<span key={index} className="flex-center">
|
||||||
<span className="m-r-5" style={{ display: 'flex', width: 25 }}>
|
<span
|
||||||
|
className="m-r-5"
|
||||||
|
style={{ display: 'flex', width: 25, lineHeight: 1 }}
|
||||||
|
>
|
||||||
[{item.index}]
|
[{item.index}]
|
||||||
</span>
|
</span>
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
@@ -343,33 +353,42 @@ const useWorkerColumns = ({
|
|||||||
title: 'CPU',
|
title: 'CPU',
|
||||||
dataIndex: 'status.cpu.utilization_rate',
|
dataIndex: 'status.cpu.utilization_rate',
|
||||||
sorter: tableSorter(4),
|
sorter: tableSorter(4),
|
||||||
render: (text: string, record) =>
|
render: (text: string, record) => (
|
||||||
statusAvailable(record) ? (
|
<span className="flex-center flex-full">
|
||||||
<ProgressBar
|
{statusAvailable(record) ? (
|
||||||
percent={_.round(record?.status?.cpu?.utilization_rate, 0)}
|
<ProgressBar
|
||||||
/>
|
percent={_.round(record?.status?.cpu?.utilization_rate, 0)}
|
||||||
) : (
|
/>
|
||||||
<HolderStatus />
|
) : (
|
||||||
)
|
<HolderStatus />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.memory' }),
|
title: intl.formatMessage({ id: 'resources.table.memory' }),
|
||||||
dataIndex: 'status.memory.utilization_rate',
|
dataIndex: 'status.memory.utilization_rate',
|
||||||
sorter: tableSorter(5),
|
sorter: tableSorter(5),
|
||||||
render: (_, record) =>
|
render: (_, record) => (
|
||||||
statusAvailable(record) ? (
|
<span className="flex-center flex-full">
|
||||||
<ProgressBar
|
{statusAvailable(record) ? (
|
||||||
percent={formateUtilization(
|
<ProgressBar
|
||||||
record?.status?.memory?.used,
|
percent={formateUtilization(
|
||||||
record?.status?.memory?.total
|
record?.status?.memory?.used,
|
||||||
)}
|
record?.status?.memory?.total
|
||||||
label={
|
)}
|
||||||
<InfoColumn fieldList={fieldList} data={record.status.memory} />
|
label={
|
||||||
}
|
<InfoColumn
|
||||||
/>
|
fieldList={fieldList}
|
||||||
) : (
|
data={record.status.memory}
|
||||||
<HolderStatus />
|
/>
|
||||||
)
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<HolderStatus />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'GPU',
|
title: 'GPU',
|
||||||
@@ -400,12 +419,15 @@ const useWorkerColumns = ({
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.disk' }),
|
title: intl.formatMessage({ id: 'resources.table.disk' }),
|
||||||
dataIndex: 'storage',
|
dataIndex: 'storage',
|
||||||
render: (_, record) =>
|
render: (_, record) => (
|
||||||
statusAvailable(record) ? (
|
<span className="flex-center flex-full">
|
||||||
<StorageCell files={record.status?.filesystem} />
|
{statusAvailable(record) ? (
|
||||||
) : (
|
<StorageCell files={record.status?.filesystem} />
|
||||||
<HolderStatus />
|
) : (
|
||||||
)
|
<HolderStatus />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.operation' }),
|
title: intl.formatMessage({ id: 'common.table.operation' }),
|
||||||
|
|||||||
Reference in New Issue
Block a user