chore: select multiple gpus by manual
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { CloseOutlined } from '@ant-design/icons';
|
||||||
import { Tag, Tooltip, type TagProps } from 'antd';
|
import { Tag, Tooltip, type TagProps } from 'antd';
|
||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
import React, {
|
import React, {
|
||||||
@@ -20,6 +21,7 @@ interface AutoTooltipProps extends Omit<TagProps, 'title'> {
|
|||||||
ghost?: boolean;
|
ghost?: boolean;
|
||||||
title?: React.ReactNode;
|
title?: React.ReactNode;
|
||||||
showTitle?: boolean;
|
showTitle?: boolean;
|
||||||
|
closable?: boolean;
|
||||||
tooltipProps?: React.ComponentProps<typeof Tooltip>;
|
tooltipProps?: React.ComponentProps<typeof Tooltip>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +37,6 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const contentRef = useRef<HTMLDivElement>(null);
|
const contentRef = useRef<HTMLDivElement>(null);
|
||||||
const [isOverflowing, setIsOverflowing] = useState(false);
|
const [isOverflowing, setIsOverflowing] = useState(false);
|
||||||
const resizeObserver = useRef<ResizeObserver>();
|
|
||||||
|
|
||||||
const checkOverflow = useCallback(() => {
|
const checkOverflow = useCallback(() => {
|
||||||
if (contentRef.current) {
|
if (contentRef.current) {
|
||||||
@@ -44,6 +45,22 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
|
|||||||
}
|
}
|
||||||
}, [contentRef.current]);
|
}, [contentRef.current]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const element = contentRef.current;
|
||||||
|
if (!element) return;
|
||||||
|
|
||||||
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
|
checkOverflow();
|
||||||
|
});
|
||||||
|
|
||||||
|
resizeObserver.observe(element);
|
||||||
|
|
||||||
|
// Initial check
|
||||||
|
checkOverflow();
|
||||||
|
|
||||||
|
return () => resizeObserver.disconnect();
|
||||||
|
}, [checkOverflow]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const debouncedCheckOverflow = throttle(checkOverflow, 200);
|
const debouncedCheckOverflow = throttle(checkOverflow, 200);
|
||||||
window.addEventListener('resize', debouncedCheckOverflow);
|
window.addEventListener('resize', debouncedCheckOverflow);
|
||||||
@@ -89,11 +106,28 @@ const AutoTooltip: React.FC<AutoTooltipProps> = ({
|
|||||||
{...tooltipProps}
|
{...tooltipProps}
|
||||||
>
|
>
|
||||||
{ghost ? (
|
{ghost ? (
|
||||||
<div ref={contentRef} style={tagStyle}>
|
<div ref={contentRef} style={tagStyle} data-overflow={isOverflowing}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Tag {...tagProps} ref={contentRef} style={tagStyle}>
|
<Tag
|
||||||
|
{...tagProps}
|
||||||
|
ref={contentRef}
|
||||||
|
style={{
|
||||||
|
...tagStyle,
|
||||||
|
paddingInline: tagProps.closable ? '8px 22px' : 8,
|
||||||
|
borderRadius: 12
|
||||||
|
}}
|
||||||
|
closeIcon={
|
||||||
|
<CloseOutlined
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
right: 8,
|
||||||
|
top: 8
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -81,7 +81,11 @@ const LineChart: React.FC<ChartProps> = (props) => {
|
|||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
...options.yAxis,
|
...options.yAxis,
|
||||||
name: yAxisName
|
name: yAxisName,
|
||||||
|
nameTextStyle: {
|
||||||
|
fontSize: 12,
|
||||||
|
align: 'right'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
...options.xAxis,
|
...options.xAxis,
|
||||||
|
|||||||
@@ -247,6 +247,11 @@ const useSetChunkRequest = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(
|
||||||
|
'chunkrequest===retryCount.current==',
|
||||||
|
requestReadyState,
|
||||||
|
retryCount.current
|
||||||
|
);
|
||||||
if (requestReadyState === 4 && retryCount.current > 0) {
|
if (requestReadyState === 4 && retryCount.current > 0) {
|
||||||
requestConfig.current.beforeReconnect?.();
|
requestConfig.current.beforeReconnect?.();
|
||||||
clearTimeout(timer.current);
|
clearTimeout(timer.current);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import AutoTooltip from '@/components/auto-tooltip';
|
||||||
import LabelSelector from '@/components/label-selector';
|
import LabelSelector from '@/components/label-selector';
|
||||||
import ListInput from '@/components/list-input';
|
import ListInput from '@/components/list-input';
|
||||||
import SealInput from '@/components/seal-form/seal-input';
|
import SealInput from '@/components/seal-form/seal-input';
|
||||||
@@ -5,13 +6,11 @@ import SealSelect from '@/components/seal-form/seal-select';
|
|||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
import { InfoCircleOutlined, RightOutlined } from '@ant-design/icons';
|
import { InfoCircleOutlined, RightOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Collapse,
|
Collapse,
|
||||||
Form,
|
Form,
|
||||||
FormInstance,
|
FormInstance,
|
||||||
Select,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Typography
|
Typography
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
@@ -252,7 +251,7 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
id: 'common.form.rule.select'
|
id: 'common.form.rule.select'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'gpu_selector'
|
name: intl.formatMessage({ id: 'models.form.gpuselector' })
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -262,14 +261,24 @@ const AdvanceConfig: React.FC<AdvanceConfigProps> = (props) => {
|
|||||||
label={intl.formatMessage({ id: 'models.form.gpuselector' })}
|
label={intl.formatMessage({ id: 'models.form.gpuselector' })}
|
||||||
required
|
required
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
maxLength={1}
|
maxTagCount={1}
|
||||||
>
|
tagRender={(props) => {
|
||||||
{gpuOptions.map((item) => (
|
return (
|
||||||
<Select.Option key={item.value} value={item.value}>
|
<AutoTooltip
|
||||||
<GPUCard data={item}></GPUCard>
|
className="m-r-0"
|
||||||
</Select.Option>
|
closable={true}
|
||||||
))}
|
onClose={props.onClose}
|
||||||
</SealSelect>
|
maxWidth={240}
|
||||||
|
>
|
||||||
|
{props.label}
|
||||||
|
</AutoTooltip>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
options={gpuOptions}
|
||||||
|
optionRender={(props) => {
|
||||||
|
return <GPUCard data={props.data}></GPUCard>;
|
||||||
|
}}
|
||||||
|
></SealSelect>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
<Form.Item name="backend_version">
|
<Form.Item name="backend_version">
|
||||||
|
|||||||
@@ -85,11 +85,12 @@ const DataForm: React.FC<DataFormProps> = forwardRef((props, ref) => {
|
|||||||
const list = _.map(data.items, (item: GPUListItem) => {
|
const list = _.map(data.items, (item: GPUListItem) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
label: item.name,
|
title: '',
|
||||||
|
label: ` ${item.name}(${item.worker_name})[
|
||||||
|
${intl.formatMessage({ id: 'resources.table.index' })}:${item.index}]`,
|
||||||
value: item.id
|
value: item.id
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
console.log('queryGPUList========', list);
|
|
||||||
setGpuOptions(list);
|
setGpuOptions(list);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,7 @@ const GPUCard: React.FC<{
|
|||||||
return (
|
return (
|
||||||
<div className="gpu-card">
|
<div className="gpu-card">
|
||||||
<div className="header" style={{ width: '100%' }}>
|
<div className="header" style={{ width: '100%' }}>
|
||||||
{header ?? (
|
{header ?? <AutoTooltip ghost>{data.label}</AutoTooltip>}
|
||||||
<AutoTooltip ghost>
|
|
||||||
{data.label}({data.worker_name})[
|
|
||||||
{intl.formatMessage({ id: 'resources.table.index' })}:{data.index}]
|
|
||||||
</AutoTooltip>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="info">
|
<div className="info">
|
||||||
{info ?? (
|
{info ?? (
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
const handleLogModalCancel = useCallback(() => {
|
const handleLogModalCancel = useCallback(() => {
|
||||||
setOpenLogModal(false);
|
setOpenLogModal(false);
|
||||||
onCancelViewLogs();
|
onCancelViewLogs();
|
||||||
}, []);
|
}, [onCancelViewLogs]);
|
||||||
|
|
||||||
const handleDelete = async (row: any) => {
|
const handleDelete = async (row: any) => {
|
||||||
modalRef.current.show({
|
modalRef.current.show({
|
||||||
@@ -437,23 +437,23 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleOpenPlayGround = (row: any) => {
|
const handleOpenPlayGround = (row: any) => {
|
||||||
if (row.image_only) {
|
if (row.categories?.includes(modelCategoriesMap.image)) {
|
||||||
navigate(`/playground/text-to-image?model=${row.name}`);
|
navigate(`/playground/text-to-image?model=${row.name}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row.text_to_speech) {
|
if (row.categories?.includes(modelCategoriesMap.text_to_speech)) {
|
||||||
navigate(`/playground/speech?model=${row.name}&type=tts`);
|
navigate(`/playground/speech?model=${row.name}&type=tts`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row.speech_to_text) {
|
if (row.categories?.includes(modelCategoriesMap.speech_to_text)) {
|
||||||
navigate(`/playground/speech?model=${row.name}&type=stt`);
|
navigate(`/playground/speech?model=${row.name}&type=stt`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row.reranker) {
|
if (row.categories?.includes(modelCategoriesMap.reranker)) {
|
||||||
navigate(`/playground/rerank?model=${row.name}`);
|
navigate(`/playground/rerank?model=${row.name}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (row.embedding_only) {
|
if (row.categories?.includes(modelCategoriesMap.embedding)) {
|
||||||
navigate(`/playground/embedding?model=${row.name}`);
|
navigate(`/playground/embedding?model=${row.name}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,10 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
const list = _.map(data.items, (item: GPUListItem) => {
|
const list = _.map(data.items, (item: GPUListItem) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
label: item.name,
|
title: '',
|
||||||
value: `${item.worker_name}-${item.name}-${item.index}`
|
label: ` ${item.name}(${item.worker_name})[
|
||||||
|
${intl.formatMessage({ id: 'resources.table.index' })}:${item.index}]`,
|
||||||
|
value: item.id
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
setGpuOptions(list);
|
setGpuOptions(list);
|
||||||
@@ -92,9 +94,9 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
? props.data.categories[0]
|
? props.data.categories[0]
|
||||||
: null,
|
: null,
|
||||||
scheduleType: props.data?.gpu_selector ? 'manual' : 'auto',
|
scheduleType: props.data?.gpu_selector ? 'manual' : 'auto',
|
||||||
gpu_selector: props.data?.gpu_selector
|
gpu_selector: props.data?.gpu_selector || {
|
||||||
? `${props.data?.gpu_selector.worker_name}-${props.data?.gpu_selector.gpu_name}-${props.data?.gpu_selector.gpu_index}`
|
gpu_ids: []
|
||||||
: null
|
}
|
||||||
};
|
};
|
||||||
form.setFieldsValue(formData);
|
form.setFieldsValue(formData);
|
||||||
}
|
}
|
||||||
@@ -300,19 +302,13 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (formdata.scheduleType === 'manual') {
|
if (formdata.scheduleType === 'manual') {
|
||||||
const gpu = _.find(gpuOptions, (item: any) => {
|
|
||||||
return item.value === formdata.gpu_selector;
|
|
||||||
});
|
|
||||||
|
|
||||||
onOk({
|
onOk({
|
||||||
..._.omit(formdata, ['scheduleType']),
|
..._.omit(formdata, ['scheduleType']),
|
||||||
categories: formdata.categories ? [formdata.categories] : [],
|
categories: formdata.categories ? [formdata.categories] : [],
|
||||||
worker_selector: null,
|
worker_selector: null,
|
||||||
gpu_selector: gpu
|
gpu_selector: formdata.gpu_selector?.gpu_ids?.length
|
||||||
? {
|
? {
|
||||||
gpu_name: gpu.name,
|
gpu_ids: formdata.gpu_selector.gpu_ids
|
||||||
gpu_index: gpu.index,
|
|
||||||
worker_name: gpu.worker_name
|
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
...obj
|
...obj
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import TableList from './components/table-list';
|
|||||||
import { ListItem } from './config/types';
|
import { ListItem } from './config/types';
|
||||||
|
|
||||||
const Models: React.FC = () => {
|
const Models: React.FC = () => {
|
||||||
console.log('model list====1');
|
|
||||||
|
|
||||||
const { setChunkRequest, createAxiosToken } = useSetChunkRequest();
|
const { setChunkRequest, createAxiosToken } = useSetChunkRequest();
|
||||||
const { setChunkRequest: setModelInstanceChunkRequest } =
|
const { setChunkRequest: setModelInstanceChunkRequest } =
|
||||||
useSetChunkRequest();
|
useSetChunkRequest();
|
||||||
@@ -33,6 +31,7 @@ const Models: React.FC = () => {
|
|||||||
const [firstLoad, setFirstLoad] = useState(true);
|
const [firstLoad, setFirstLoad] = useState(true);
|
||||||
const chunkRequedtRef = useRef<any>();
|
const chunkRequedtRef = useRef<any>();
|
||||||
const chunkInstanceRequedtRef = useRef<any>();
|
const chunkInstanceRequedtRef = useRef<any>();
|
||||||
|
const isPageHidden = useRef(false);
|
||||||
let axiosToken = createAxiosToken();
|
let axiosToken = createAxiosToken();
|
||||||
const [queryParams, setQueryParams] = useState({
|
const [queryParams, setQueryParams] = useState({
|
||||||
page: 1,
|
page: 1,
|
||||||
@@ -83,11 +82,13 @@ const Models: React.FC = () => {
|
|||||||
total: res.pagination.total
|
total: res.pagination.total
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setDataSource({
|
if (!isPageHidden.current) {
|
||||||
dataList: [],
|
setDataSource({
|
||||||
loading: false,
|
dataList: [],
|
||||||
total: dataSource.total
|
loading: false,
|
||||||
});
|
total: dataSource.total
|
||||||
|
});
|
||||||
|
}
|
||||||
console.log('error+++', error);
|
console.log('error+++', error);
|
||||||
} finally {
|
} finally {
|
||||||
setFirstLoad(false);
|
setFirstLoad(false);
|
||||||
@@ -115,7 +116,7 @@ const Models: React.FC = () => {
|
|||||||
setModelInstances(list);
|
setModelInstances(list);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createModelsChunkRequest = () => {
|
const createModelsChunkRequest = useCallback(async () => {
|
||||||
chunkRequedtRef.current?.current?.cancel?.();
|
chunkRequedtRef.current?.current?.cancel?.();
|
||||||
try {
|
try {
|
||||||
chunkRequedtRef.current = setChunkRequest({
|
chunkRequedtRef.current = setChunkRequest({
|
||||||
@@ -128,8 +129,8 @@ const Models: React.FC = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
};
|
}, [queryParams]);
|
||||||
const createModelsInstanceChunkRequest = () => {
|
const createModelsInstanceChunkRequest = useCallback(async () => {
|
||||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||||
try {
|
try {
|
||||||
chunkInstanceRequedtRef.current = setModelInstanceChunkRequest({
|
chunkInstanceRequedtRef.current = setModelInstanceChunkRequest({
|
||||||
@@ -140,7 +141,7 @@ const Models: React.FC = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
};
|
}, []);
|
||||||
|
|
||||||
const handleSearch = useCallback(
|
const handleSearch = useCallback(
|
||||||
(e: any) => {
|
(e: any) => {
|
||||||
@@ -160,15 +161,22 @@ const Models: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleOnViewLogs = useCallback(() => {
|
const handleOnViewLogs = useCallback(() => {
|
||||||
|
isPageHidden.current = true;
|
||||||
chunkRequedtRef.current?.current?.cancel?.();
|
chunkRequedtRef.current?.current?.cancel?.();
|
||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleOnCancelViewLogs = useCallback(() => {
|
const handleOnCancelViewLogs = useCallback(async () => {
|
||||||
createModelsChunkRequest();
|
isPageHidden.current = false;
|
||||||
createModelsInstanceChunkRequest();
|
await Promise.all([
|
||||||
}, []);
|
createModelsChunkRequest(),
|
||||||
|
createModelsInstanceChunkRequest()
|
||||||
|
]);
|
||||||
|
setTimeout(() => {
|
||||||
|
fetchData();
|
||||||
|
}, 100);
|
||||||
|
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
@@ -193,22 +201,32 @@ const Models: React.FC = () => {
|
|||||||
createModelsChunkRequest();
|
createModelsChunkRequest();
|
||||||
createModelsInstanceChunkRequest();
|
createModelsInstanceChunkRequest();
|
||||||
}, 100);
|
}, 100);
|
||||||
document.addEventListener('visibilitychange', () => {
|
|
||||||
if (document.visibilityState === 'visible') {
|
|
||||||
createModelsChunkRequest();
|
|
||||||
createModelsInstanceChunkRequest();
|
|
||||||
} else {
|
|
||||||
chunkRequedtRef.current?.current?.cancel?.();
|
|
||||||
cacheDataListRef.current = [];
|
|
||||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}, [firstLoad]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleVisibilityChange = async () => {
|
||||||
|
if (document.visibilityState === 'visible') {
|
||||||
|
isPageHidden.current = false;
|
||||||
|
await Promise.all([
|
||||||
|
createModelsChunkRequest(),
|
||||||
|
createModelsInstanceChunkRequest()
|
||||||
|
]);
|
||||||
|
fetchData();
|
||||||
|
} else {
|
||||||
|
isPageHidden.current = true;
|
||||||
|
chunkRequedtRef.current?.current?.cancel?.();
|
||||||
|
cacheDataListRef.current = [];
|
||||||
|
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('visibilitychange', () => {});
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||||
};
|
};
|
||||||
}, [firstLoad]);
|
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableContext.Provider
|
<TableContext.Provider
|
||||||
|
|||||||
Reference in New Issue
Block a user