fix: model source error in catalog

This commit is contained in:
jialin
2025-11-17 15:24:22 +08:00
parent d1c3edfd9b
commit 906f59a566
6 changed files with 85 additions and 303 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ export default {
'playground.system': '系统', 'playground.system': '系统',
'playground.systemMessage': '系统消息', 'playground.systemMessage': '系统消息',
'playground.user': '用户', 'playground.user': '用户',
'playground.assistant': 'AI助手', 'playground.assistant': 'AI 助手',
'playground.newMessage': '新消息', 'playground.newMessage': '新消息',
'playground.viewcode': '查看代码', 'playground.viewcode': '查看代码',
'playground.model': '模型', 'playground.model': '模型',
+72 -61
View File
@@ -25,15 +25,16 @@ const Catalog: React.FC = () => {
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll(); const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
const navigate = useNavigate(); const navigate = useNavigate();
const [activeId, setActiveId] = React.useState(-1); const [activeId, setActiveId] = React.useState(-1);
const [isFirst, setIsFirst] = React.useState(true);
const [dataSource, setDataSource] = useState<{ const [dataSource, setDataSource] = useState<{
dataList: CatalogItemType[]; dataList: CatalogItemType[];
loading: boolean; loading: boolean;
total: number; total: number;
loadend: boolean;
totalPage: number; totalPage: number;
}>({ }>({
dataList: [], dataList: [],
loading: false, loading: false,
loadend: false,
total: 0, total: 0,
totalPage: 0 totalPage: 0
}); });
@@ -52,67 +53,65 @@ const Catalog: React.FC = () => {
const [modelsExpandKeys, setModelsExpandKeys] = useAtom(modelsExpandKeysAtom); const [modelsExpandKeys, setModelsExpandKeys] = useAtom(modelsExpandKeysAtom);
const [, setModelsSession] = useAtom(modelsSessionAtom); const [, setModelsSession] = useAtom(modelsSessionAtom);
const cacheData = React.useRef<CatalogItemType[]>([]); const cacheData = React.useRef<CatalogItemType[]>([]);
const sourceRef = React.useRef<string>('');
const categoryOptions = [ const categoryOptions = [
...modelCategories.filter((item) => item.value) ...modelCategories.filter((item) => item.value)
] as Global.BaseOption<string>[]; ] as Global.BaseOption<string>[];
const fetchData = useCallback( const fetchData = useMemoizedFn(async (query?: any) => {
async (query?: any) => { const searchQuery = {
const searchQuery = { ...queryParams,
...query
};
if (
dataSource.loading ||
(searchQuery.page > dataSource.totalPage && dataSource.totalPage > 0)
) {
return;
}
setDataSource((pre) => {
pre.loading = true;
return { ...pre };
});
try {
const params = {
..._.pickBy(searchQuery, (val: string | number) => !!val)
};
const res: any = await queryCatalogList(params);
const dataList =
searchQuery.page === 1
? res.items
: _.concat(dataSource.dataList, res.items);
setDataSource({
dataList: dataList,
loading: false,
loadend: true,
total: res.pagination.total,
totalPage: res.pagination.totalPage
});
setQueryParams({
...queryParams, ...queryParams,
...query ...query
};
if (
dataSource.loading ||
(searchQuery.page > dataSource.totalPage && dataSource.totalPage > 0)
) {
return;
}
setDataSource((pre) => {
pre.loading = true;
return { ...pre };
}); });
try { } catch (error) {
const params = { cacheData.current = [];
..._.pickBy(searchQuery, (val: string | number) => !!val) setDataSource({
}; dataList: [],
const res: any = await queryCatalogList(params); loading: false,
loadend: true,
const dataList = total: dataSource.total,
searchQuery.page === 1 totalPage: dataSource.totalPage
? res.items });
: _.concat(dataSource.dataList, res.items); setQueryParams({
setDataSource({ ...queryParams,
dataList: dataList, ...query
loading: false, });
total: res.pagination.total, console.log('error', error);
totalPage: res.pagination.totalPage }
}); });
setQueryParams({
...queryParams,
...query
});
} catch (error) {
cacheData.current = [];
setDataSource({
dataList: [],
loading: false,
total: dataSource.total,
totalPage: dataSource.totalPage
});
setQueryParams({
...queryParams,
...query
});
console.log('error', error);
} finally {
setIsFirst(false);
}
},
[queryParams, cacheData.current]
);
const handleDeployModalCancel = () => { const handleDeployModalCancel = () => {
setOpenDeployModal({ setOpenDeployModal({
@@ -123,12 +122,12 @@ const Catalog: React.FC = () => {
setActiveId(-1); setActiveId(-1);
}; };
const handleOnDeploy = useCallback((item: CatalogItemType) => { const handleOnDeploy = useCallback(async (item: CatalogItemType) => {
saveScrollHeight(); saveScrollHeight();
setActiveId(item.id); setActiveId(item.id);
setOpenDeployModal({ setOpenDeployModal({
show: true, show: true,
source: modelSourceMap.huggingface_value, source: sourceRef.current,
current: item, current: item,
width: 600 width: 600
}); });
@@ -186,11 +185,10 @@ const Catalog: React.FC = () => {
}); });
const handleDeployFromOtherHubs = async () => { const handleDeployFromOtherHubs = async () => {
console.log('sourceRef.current', sourceRef.current);
try { try {
const id = dataSource.dataList?.[0]?.id;
const res: any = await queryCatalogItemSpec({ id });
setModelsSession({ setModelsSession({
source: res?.items?.[0]?.source source: sourceRef.current || modelSourceMap.huggingface_value
}); });
} catch (error) {} } catch (error) {}
navigate('/models/deployments'); navigate('/models/deployments');
@@ -200,6 +198,19 @@ const Catalog: React.FC = () => {
fetchData(); fetchData();
}, []); }, []);
useEffect(() => {
if (dataSource.loadend) {
const getCatalogSource = async () => {
try {
const id = dataSource.dataList?.[0]?.id;
const res: any = await queryCatalogItemSpec({ id });
sourceRef.current = res?.items?.[0]?.source;
} catch (error) {}
};
getCatalogSource();
}
}, [dataSource.loadend]);
useEffect(() => { useEffect(() => {
const handleScroll = async () => { const handleScroll = async () => {
// Determine the scrolling element // Determine the scrolling element
@@ -255,11 +266,11 @@ const Catalog: React.FC = () => {
loading={dataSource.loading} loading={dataSource.loading}
onDeploy={handleOnDeploy} onDeploy={handleOnDeploy}
activeId={-1} activeId={-1}
isFirst={isFirst} isFirst={!dataSource.loadend}
></CatalogList> ></CatalogList>
<NoResult <NoResult
loading={dataSource.loading} loading={dataSource.loading}
loadend={!isFirst} loadend={dataSource.loadend}
dataSource={dataSource.dataList} dataSource={dataSource.dataList}
image={<IconFont type="icon-layers" />} image={<IconFont type="icon-layers" />}
filters={queryParams} filters={queryParams}
@@ -10,12 +10,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import ColumnWrapper from '../../_components/column-wrapper'; import ColumnWrapper from '../../_components/column-wrapper';
import { queryCatalogItemSpec } from '../apis'; import { queryCatalogItemSpec } from '../apis';
import { import { DeployFormKeyMap, sourceOptions } from '../config';
defaultFormValues,
DeployFormKeyMap,
modelCategoriesMap,
sourceOptions
} from '../config';
import { backendOptionsMap } from '../config/backend-parameters'; import { backendOptionsMap } from '../config/backend-parameters';
import { CatalogFormContext } from '../config/form-context'; import { CatalogFormContext } from '../config/form-context';
import { CatalogSpec, FormData, ListItem, SourceType } from '../config/types'; import { CatalogSpec, FormData, ListItem, SourceType } from '../config/types';
@@ -68,36 +63,7 @@ const FormWrapper = styled.div`
maxwidth: 100%; maxwidth: 100%;
`; `;
const backendOptions = [
{
label: `llama-box`,
value: backendOptionsMap.llamaBox
},
{
label: 'vLLM',
value: backendOptionsMap.vllm
},
{
label: 'Ascend Mindie',
value: backendOptionsMap.ascendMindie
},
{
label: 'vox-box',
value: backendOptionsMap.voxBox
}
];
const quantiCapitMap: Record<string, string> = {
F16: 'FP16',
f16: 'FP16',
F32: 'FP32',
f32: 'FP32'
};
const defaultQuant = ['Q4_K_M'];
const EmbeddingRerankFirstQuant = ['FP16', 'F16'];
const AscendNPUQuant_F16 = ['F16', 'FP16']; const AscendNPUQuant_F16 = ['F16', 'FP16'];
const AscendNPUQuant_Q8 = ['Q8_0'];
const AddModal: React.FC<AddModalProps> = (props) => { const AddModal: React.FC<AddModalProps> = (props) => {
const { const {
@@ -124,13 +90,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const form = useRef<any>({}); const form = useRef<any>({});
const [isGGUF, setIsGGUF] = useState<boolean>(false); const [isGGUF, setIsGGUF] = useState<boolean>(false);
const [sourceList, setSourceList] = useState<any[]>([]); const [sourceList, setSourceList] = useState<any[]>([]);
const [backendList, setBackendList] = useState<any[]>([]);
const [sizeOptions, setSizeOptions] = useState<Global.BaseOption<number>[]>(
[]
);
const [quantizationOptions, setQuantizationOptions] = useState<
Global.BaseOption<string>[]
>([]);
const [modeList, setModeList] = useState< const [modeList, setModeList] = useState<
Global.BaseOption<string, { isBuiltIn: boolean; tips: string }>[] Global.BaseOption<string, { isBuiltIn: boolean; tips: string }>[]
>([]); >([]);
@@ -149,15 +108,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
form.current?.submit?.(); form.current?.submit?.();
}; };
// use for size change and quantization change
const pickSomeFieldsValue = (defaultSpec: CatalogSpec) => {
const formData = form.current?.getFieldsValue();
const currentData = _.pick(formData, Object.keys(defaultFormValues));
// if the backend_parameters is empty, use the defaultSpec.backend_parameters
return currentData;
};
const generateSubmitData = (formData: FormData) => { const generateSubmitData = (formData: FormData) => {
const gpuSelector = generateGPUIds(formData); const gpuSelector = generateGPUIds(formData);
const data = { const data = {
@@ -169,22 +119,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
return data; return data;
}; };
const getDefaultQuant = (data: {
category: string;
quantOption: string;
backend: string;
condidateQuant?: string[];
}) => {
if (
data.category === modelCategoriesMap.embedding ||
data.category === modelCategoriesMap.reranker
) {
return EmbeddingRerankFirstQuant.includes(_.toUpper(data.quantOption));
}
return defaultQuant.includes(_.toUpper(data.quantOption));
};
const getModelSpec = (data: { const getModelSpec = (data: {
mode?: string; mode?: string;
backend: string; backend: string;
@@ -210,59 +144,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
}); });
}; };
const handleSetSizeOptions = (data: { backend: string }) => {
const sizeGroup = _.groupBy(
_.filter(specListRef.current, (item: CatalogSpec) => {
return item.backend === data.backend;
}),
'size'
);
const sizeList = _.keys(sizeGroup)
.map((size: string) => {
return {
label: `${size}B`,
value: _.toNumber(size)
};
})
.filter((item: any) => item.value);
const result = _.sortBy(sizeList, 'value');
setSizeOptions(result);
return result;
};
const handleSetQuantizationOptions = (data: {
size: number;
backend: string;
}) => {
const sizeGroup = _.filter(specListRef.current, (item: CatalogSpec) => {
return item.size === data.size && item.backend === data.backend;
});
const quantizationList = _.map(sizeGroup, (item: CatalogSpec) => {
return {
label:
quantiCapitMap[item.quantization] ?? _.toUpper(item.quantization),
value: item.quantization
};
});
const result = _.uniqBy(quantizationList, 'value');
console.log('quantization options:', result);
setQuantizationOptions(result);
return result;
};
// TODO need check the backend is available
const handleSetBackendOptions = () => {
const backendGroup = _.groupBy(specListRef.current, 'backend');
const backendList = _.filter(backendOptions, (item: any) => {
return backendGroup[item.value];
});
setBackendList(backendList);
return backendList;
};
const handleCheckCompatibility = async (formData: FormData) => { const handleCheckCompatibility = async (formData: FormData) => {
handleDoEvalute(formData); handleDoEvalute(formData);
}; };
@@ -276,46 +157,12 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const handleSourceChange = (source: string) => { const handleSourceChange = (source: string) => {
const defaultSpec = _.get(sourceGroupMap.current, `${source}.0`, {}); const defaultSpec = _.get(sourceGroupMap.current, `${source}.0`, {});
initFormDataBySource(defaultSpec); initFormDataBySource(defaultSpec);
handleSetSizeOptions({
backend: defaultSpec.backend
});
handleSetQuantizationOptions({
size: defaultSpec.size,
backend: defaultSpec.backend
});
// set form value // set form value
initFormDataBySource(defaultSpec); initFormDataBySource(defaultSpec);
handleCheckFormData(); handleCheckFormData();
}; };
const checkSize = (list: any[]) => {
return (
_.find(
list,
(item: { label: string; value: string }) =>
item.value === form.current.getFieldValue('size')
)?.value || _.get(list, '0.value', 0)
);
};
const checkQuantization = (list: any[]) => {
return (
_.find(
list,
(item: { label: string; value: string }) =>
item.value === form.current.getFieldValue('quantization')
)?.value ||
_.find(list, (item: { label: string; value: string }) =>
getDefaultQuant({
category: _.get(current, 'categories.0', ''),
quantOption: item.value,
backend: form.current.getFieldValue('backend')
})
)?.value ||
_.get(list, '0.value', '')
);
};
const onValuesChange = async (changedValues: any, allValues: any) => { const onValuesChange = async (changedValues: any, allValues: any) => {
const data = { const data = {
..._.omit(selectSpecRef.current, ['name']), ..._.omit(selectSpecRef.current, ['name']),
@@ -329,35 +176,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
}; };
const handleBackendChange = (backend: string) => { const handleBackendChange = (backend: string) => {
// if (backend === backendOptionsMap.llamaBox) {
// setIsGGUF(true);
// } else {
// setIsGGUF(false);
// }
// const sizeList = handleSetSizeOptions({
// backend: backend
// });
// const size = checkSize(sizeList);
// const quantizaList = handleSetQuantizationOptions({
// size: size,
// backend: backend
// });
// const quantization = checkQuantization(quantizaList);
// const data = getModelSpec({
// backend: backend,
// size: size,
// quantization: quantization
// });
// form.current.setFieldsValue({
// ...defaultFormValues,
// ...data
// });
handleCheckFormData(); handleCheckFormData();
}; };
@@ -421,14 +239,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
setModeList(modeDataList); setModeList(modeDataList);
setSourceList(sources); setSourceList(sources);
handleSetBackendOptions();
handleSetSizeOptions({
backend: defaultSpec.backend
});
handleSetQuantizationOptions({
size: defaultSpec.size,
backend: defaultSpec.backend
});
initFormDataBySource({ initFormDataBySource({
...defaultSpec, ...defaultSpec,
cluster_id: initClusterId() cluster_id: initClusterId()
@@ -454,43 +264,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
} }
}; };
const handleOnQuantizationChange = (val: string) => {
const data = getModelSpec({
backend: form.current.getFieldValue('backend'),
size: form.current.getFieldValue('size'),
quantization: val
});
form.current.setFieldsValue({
...data,
...pickSomeFieldsValue(data)
});
handleCheckFormData();
};
const handleOnSizeChange = (val: number) => {
// TODO
form.current.setFieldValue(defaultFormValues);
const list = handleSetQuantizationOptions({
backend: form.current.getFieldValue('backend'),
size: val
});
const quantization = checkQuantization(list);
const data = getModelSpec({
backend: form.current.getFieldValue('backend'),
size: val,
quantization: quantization
});
// set form data
form.current.setFieldsValue({
...defaultFormValues,
...data
});
handleCheckFormData();
};
const handleOnModeChange = (val: string) => { const handleOnModeChange = (val: string) => {
const data = getModelSpec({ const data = getModelSpec({
mode: val, mode: val,
@@ -578,9 +351,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
sizeOptions: [], sizeOptions: [],
quantizationOptions: [], quantizationOptions: [],
modeList: modeList, modeList: modeList,
onModeChange: handleOnModeChange, onModeChange: handleOnModeChange
onSizeChange: handleOnSizeChange,
onQuantizationChange: handleOnQuantizationChange
}} }}
> >
<FormWrapper> <FormWrapper>
+6 -6
View File
@@ -7,17 +7,17 @@ export const modalConfig: Record<
string, string,
{ show: boolean; width: string | number; source: any; isGGUF?: boolean } { show: boolean; width: string | number; source: any; isGGUF?: boolean }
> = { > = {
huggingface: { [modelSourceMap.huggingface_value]: {
show: true, show: true,
width: 'calc(100vw - 220px)', width: 'calc(100vw - 220px)',
source: modelSourceMap.huggingface_value source: modelSourceMap.huggingface_value
}, },
modelscope: { [modelSourceMap.modelscope_value]: {
show: true, show: true,
width: 'calc(100vw - 220px)', width: 'calc(100vw - 220px)',
source: modelSourceMap.modelscope_value source: modelSourceMap.modelscope_value
}, },
local_path: { [modelSourceMap.local_path_value]: {
show: true, show: true,
width: 600, width: 600,
source: modelSourceMap.local_path_value source: modelSourceMap.local_path_value
@@ -105,21 +105,21 @@ export const onLineSourceOptions = [
label: 'Hugging Face', label: 'Hugging Face',
locale: false, locale: false,
value: modelSourceMap.huggingface_value, value: modelSourceMap.huggingface_value,
key: 'huggingface', key: modelSourceMap.huggingface_value,
icon: icons.HF icon: icons.HF
}, },
{ {
label: 'ModelScope', label: 'ModelScope',
locale: false, locale: false,
value: modelSourceMap.modelscope_value, value: modelSourceMap.modelscope_value,
key: 'modelscope', key: modelSourceMap.modelscope_value,
icon: icons.ModelScope icon: icons.ModelScope
}, },
{ {
label: 'models.form.localPath', label: 'models.form.localPath',
locale: true, locale: true,
value: modelSourceMap.local_path_value, value: modelSourceMap.local_path_value,
key: 'local_path', key: modelSourceMap.local_path_value,
icon: icons.LocalPath icon: icons.LocalPath
} }
]; ];
+2 -2
View File
@@ -32,8 +32,8 @@ interface CatalogFormContextProps {
quantizationOptions: Global.BaseOption<string>[]; quantizationOptions: Global.BaseOption<string>[];
modeList: Global.BaseOption<string, { isBuiltIn: boolean; tips: string }>[]; modeList: Global.BaseOption<string, { isBuiltIn: boolean; tips: string }>[];
onModeChange: (val: string) => void; onModeChange: (val: string) => void;
onSizeChange: (val: number) => void; onSizeChange?: (val: number) => void;
onQuantizationChange: (val: string) => void; onQuantizationChange?: (val: string) => void;
} }
interface FormOuterContextProps { interface FormOuterContextProps {
@@ -150,7 +150,7 @@ export default function useQueryDraftModels({ source }: { source: string }) {
// local path starts with / // local path starts with /
const handleOnSearch = async (value: string) => { const handleOnSearch = async (value: string) => {
if (!value || value?.trim?.().startsWith('/')) { if (!value || value?.trim?.().startsWith('/') || !source) {
setDraftModelList(presetDraftModelListRef.current); setDraftModelList(presetDraftModelListRef.current);
return; return;
} }