From 906f59a5661a9a7ae3a89ae6ba0c60a343a6d7be Mon Sep 17 00:00:00 2001 From: jialin Date: Mon, 17 Nov 2025 15:23:11 +0800 Subject: [PATCH] fix: model source error in catalog --- src/locales/zh-CN/playground.ts | 2 +- src/pages/llmodels/catalog.tsx | 133 +++++----- .../components/deploy-builtin-modal.tsx | 235 +----------------- src/pages/llmodels/config/button-actions.ts | 12 +- src/pages/llmodels/config/form-context.ts | 4 +- .../llmodels/hooks/use-query-draftModels.ts | 2 +- 6 files changed, 85 insertions(+), 303 deletions(-) diff --git a/src/locales/zh-CN/playground.ts b/src/locales/zh-CN/playground.ts index 02598f71..acc7a69d 100644 --- a/src/locales/zh-CN/playground.ts +++ b/src/locales/zh-CN/playground.ts @@ -4,7 +4,7 @@ export default { 'playground.system': '系统', 'playground.systemMessage': '系统消息', 'playground.user': '用户', - 'playground.assistant': 'AI助手', + 'playground.assistant': 'AI 助手', 'playground.newMessage': '新消息', 'playground.viewcode': '查看代码', 'playground.model': '模型', diff --git a/src/pages/llmodels/catalog.tsx b/src/pages/llmodels/catalog.tsx index 53370058..018b6c66 100644 --- a/src/pages/llmodels/catalog.tsx +++ b/src/pages/llmodels/catalog.tsx @@ -25,15 +25,16 @@ const Catalog: React.FC = () => { const { saveScrollHeight, restoreScrollHeight } = useBodyScroll(); const navigate = useNavigate(); const [activeId, setActiveId] = React.useState(-1); - const [isFirst, setIsFirst] = React.useState(true); const [dataSource, setDataSource] = useState<{ dataList: CatalogItemType[]; loading: boolean; total: number; + loadend: boolean; totalPage: number; }>({ dataList: [], loading: false, + loadend: false, total: 0, totalPage: 0 }); @@ -52,67 +53,65 @@ const Catalog: React.FC = () => { const [modelsExpandKeys, setModelsExpandKeys] = useAtom(modelsExpandKeysAtom); const [, setModelsSession] = useAtom(modelsSessionAtom); const cacheData = React.useRef([]); + const sourceRef = React.useRef(''); const categoryOptions = [ ...modelCategories.filter((item) => item.value) ] as Global.BaseOption[]; - const fetchData = useCallback( - async (query?: any) => { - const searchQuery = { + const fetchData = useMemoizedFn(async (query?: any) => { + 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, ...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, - total: res.pagination.total, - 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] - ); + } catch (error) { + cacheData.current = []; + setDataSource({ + dataList: [], + loading: false, + loadend: true, + total: dataSource.total, + totalPage: dataSource.totalPage + }); + setQueryParams({ + ...queryParams, + ...query + }); + console.log('error', error); + } + }); const handleDeployModalCancel = () => { setOpenDeployModal({ @@ -123,12 +122,12 @@ const Catalog: React.FC = () => { setActiveId(-1); }; - const handleOnDeploy = useCallback((item: CatalogItemType) => { + const handleOnDeploy = useCallback(async (item: CatalogItemType) => { saveScrollHeight(); setActiveId(item.id); setOpenDeployModal({ show: true, - source: modelSourceMap.huggingface_value, + source: sourceRef.current, current: item, width: 600 }); @@ -186,11 +185,10 @@ const Catalog: React.FC = () => { }); const handleDeployFromOtherHubs = async () => { + console.log('sourceRef.current', sourceRef.current); try { - const id = dataSource.dataList?.[0]?.id; - const res: any = await queryCatalogItemSpec({ id }); setModelsSession({ - source: res?.items?.[0]?.source + source: sourceRef.current || modelSourceMap.huggingface_value }); } catch (error) {} navigate('/models/deployments'); @@ -200,6 +198,19 @@ const Catalog: React.FC = () => { 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(() => { const handleScroll = async () => { // Determine the scrolling element @@ -255,11 +266,11 @@ const Catalog: React.FC = () => { loading={dataSource.loading} onDeploy={handleOnDeploy} activeId={-1} - isFirst={isFirst} + isFirst={!dataSource.loadend} > } filters={queryParams} diff --git a/src/pages/llmodels/components/deploy-builtin-modal.tsx b/src/pages/llmodels/components/deploy-builtin-modal.tsx index 4555d1c6..bf28d06c 100644 --- a/src/pages/llmodels/components/deploy-builtin-modal.tsx +++ b/src/pages/llmodels/components/deploy-builtin-modal.tsx @@ -10,12 +10,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import styled from 'styled-components'; import ColumnWrapper from '../../_components/column-wrapper'; import { queryCatalogItemSpec } from '../apis'; -import { - defaultFormValues, - DeployFormKeyMap, - modelCategoriesMap, - sourceOptions -} from '../config'; +import { DeployFormKeyMap, sourceOptions } from '../config'; import { backendOptionsMap } from '../config/backend-parameters'; import { CatalogFormContext } from '../config/form-context'; import { CatalogSpec, FormData, ListItem, SourceType } from '../config/types'; @@ -68,36 +63,7 @@ const FormWrapper = styled.div` 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 = { - F16: 'FP16', - f16: 'FP16', - F32: 'FP32', - f32: 'FP32' -}; - -const defaultQuant = ['Q4_K_M']; -const EmbeddingRerankFirstQuant = ['FP16', 'F16']; const AscendNPUQuant_F16 = ['F16', 'FP16']; -const AscendNPUQuant_Q8 = ['Q8_0']; const AddModal: React.FC = (props) => { const { @@ -124,13 +90,6 @@ const AddModal: React.FC = (props) => { const form = useRef({}); const [isGGUF, setIsGGUF] = useState(false); const [sourceList, setSourceList] = useState([]); - const [backendList, setBackendList] = useState([]); - const [sizeOptions, setSizeOptions] = useState[]>( - [] - ); - const [quantizationOptions, setQuantizationOptions] = useState< - Global.BaseOption[] - >([]); const [modeList, setModeList] = useState< Global.BaseOption[] >([]); @@ -149,15 +108,6 @@ const AddModal: React.FC = (props) => { 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 gpuSelector = generateGPUIds(formData); const data = { @@ -169,22 +119,6 @@ const AddModal: React.FC = (props) => { 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: { mode?: string; backend: string; @@ -210,59 +144,6 @@ const AddModal: React.FC = (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) => { handleDoEvalute(formData); }; @@ -276,46 +157,12 @@ const AddModal: React.FC = (props) => { const handleSourceChange = (source: string) => { const defaultSpec = _.get(sourceGroupMap.current, `${source}.0`, {}); initFormDataBySource(defaultSpec); - handleSetSizeOptions({ - backend: defaultSpec.backend - }); - handleSetQuantizationOptions({ - size: defaultSpec.size, - backend: defaultSpec.backend - }); + // set form value initFormDataBySource(defaultSpec); 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 data = { ..._.omit(selectSpecRef.current, ['name']), @@ -329,35 +176,6 @@ const AddModal: React.FC = (props) => { }; 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(); }; @@ -421,14 +239,6 @@ const AddModal: React.FC = (props) => { setModeList(modeDataList); setSourceList(sources); - handleSetBackendOptions(); - handleSetSizeOptions({ - backend: defaultSpec.backend - }); - handleSetQuantizationOptions({ - size: defaultSpec.size, - backend: defaultSpec.backend - }); initFormDataBySource({ ...defaultSpec, cluster_id: initClusterId() @@ -454,43 +264,6 @@ const AddModal: React.FC = (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 data = getModelSpec({ mode: val, @@ -578,9 +351,7 @@ const AddModal: React.FC = (props) => { sizeOptions: [], quantizationOptions: [], modeList: modeList, - onModeChange: handleOnModeChange, - onSizeChange: handleOnSizeChange, - onQuantizationChange: handleOnQuantizationChange + onModeChange: handleOnModeChange }} > diff --git a/src/pages/llmodels/config/button-actions.ts b/src/pages/llmodels/config/button-actions.ts index bc3f9f25..dbd040a1 100644 --- a/src/pages/llmodels/config/button-actions.ts +++ b/src/pages/llmodels/config/button-actions.ts @@ -7,17 +7,17 @@ export const modalConfig: Record< string, { show: boolean; width: string | number; source: any; isGGUF?: boolean } > = { - huggingface: { + [modelSourceMap.huggingface_value]: { show: true, width: 'calc(100vw - 220px)', source: modelSourceMap.huggingface_value }, - modelscope: { + [modelSourceMap.modelscope_value]: { show: true, width: 'calc(100vw - 220px)', source: modelSourceMap.modelscope_value }, - local_path: { + [modelSourceMap.local_path_value]: { show: true, width: 600, source: modelSourceMap.local_path_value @@ -105,21 +105,21 @@ export const onLineSourceOptions = [ label: 'Hugging Face', locale: false, value: modelSourceMap.huggingface_value, - key: 'huggingface', + key: modelSourceMap.huggingface_value, icon: icons.HF }, { label: 'ModelScope', locale: false, value: modelSourceMap.modelscope_value, - key: 'modelscope', + key: modelSourceMap.modelscope_value, icon: icons.ModelScope }, { label: 'models.form.localPath', locale: true, value: modelSourceMap.local_path_value, - key: 'local_path', + key: modelSourceMap.local_path_value, icon: icons.LocalPath } ]; diff --git a/src/pages/llmodels/config/form-context.ts b/src/pages/llmodels/config/form-context.ts index af9ac420..e2dacdd2 100644 --- a/src/pages/llmodels/config/form-context.ts +++ b/src/pages/llmodels/config/form-context.ts @@ -32,8 +32,8 @@ interface CatalogFormContextProps { quantizationOptions: Global.BaseOption[]; modeList: Global.BaseOption[]; onModeChange: (val: string) => void; - onSizeChange: (val: number) => void; - onQuantizationChange: (val: string) => void; + onSizeChange?: (val: number) => void; + onQuantizationChange?: (val: string) => void; } interface FormOuterContextProps { diff --git a/src/pages/llmodels/hooks/use-query-draftModels.ts b/src/pages/llmodels/hooks/use-query-draftModels.ts index 9b99df57..c87b94b1 100644 --- a/src/pages/llmodels/hooks/use-query-draftModels.ts +++ b/src/pages/llmodels/hooks/use-query-draftModels.ts @@ -150,7 +150,7 @@ export default function useQueryDraftModels({ source }: { source: string }) { // local path starts with / const handleOnSearch = async (value: string) => { - if (!value || value?.trim?.().startsWith('/')) { + if (!value || value?.trim?.().startsWith('/') || !source) { setDraftModelList(presetDraftModelListRef.current); return; }