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