diff --git a/src/components/alert-info/block.less b/src/components/alert-info/block.less index 7f1ce39b..469a1b72 100644 --- a/src/components/alert-info/block.less +++ b/src/components/alert-info/block.less @@ -32,7 +32,7 @@ border-radius: var(--border-radius-base) var(--border-radius-base) 0 0; &.danger { - background-color: var(--ant-color-error-bg-hover); + background-color: var(--ant-color-error-bg-filled-hover); } &.warning { diff --git a/src/pages/llmodels/components/deploy-modal.tsx b/src/pages/llmodels/components/deploy-modal.tsx index c640bc45..761c3c74 100644 --- a/src/pages/llmodels/components/deploy-modal.tsx +++ b/src/pages/llmodels/components/deploy-modal.tsx @@ -232,7 +232,7 @@ const AddModal: React.FC = (props) => { )}
{warningStatus.show && ( diff --git a/src/pages/llmodels/components/instance-item.tsx b/src/pages/llmodels/components/instance-item.tsx index f62ed91c..166142c4 100644 --- a/src/pages/llmodels/components/instance-item.tsx +++ b/src/pages/llmodels/components/instance-item.tsx @@ -29,7 +29,6 @@ import { import dayjs from 'dayjs'; import _ from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; -import styled from 'styled-components'; import { MODEL_INSTANCE_API } from '../apis'; import { InstanceStatusMap, InstanceStatusMapValue, status } from '../config'; import { ModelInstanceListItem } from '../config/types'; @@ -65,6 +64,52 @@ const WorkerInfo = (props: { ); }; + +const InstanceStatusTag = ( + props: Pick +) => { + const intl = useIntl(); + const { instanceData, handleChildSelect } = props; + if (!instanceData.state) { + return null; + } + return ( + handleChildSelect('viewlog', instanceData)} + > + {intl.formatMessage({ id: 'models.list.more.logs' })} + + ) : null + } + statusValue={{ + status: + instanceData.state === InstanceStatusMap.Downloading && + instanceData.download_progress === 100 + ? status[InstanceStatusMap.Running] + : status[instanceData.state], + text: InstanceStatusMapValue[instanceData.state], + message: + instanceData.state === InstanceStatusMap.Downloading && + instanceData.download_progress === 100 + ? '' + : instanceData.state_message + }} + /> + ); +}; + interface InstanceItemProps { instanceData: ModelInstanceListItem; workerList: WorkerListItem[]; @@ -129,9 +174,6 @@ const distributeCols: ColumnProps[] = [ title: 'models.table.vram.allocated', locale: true, key: 'vram', - // rowSpan: ({ row, rowIndex, colIndex, dataIndex, dataList }) => { - // return rowIndex === 0 ? dataList.length : 0; - // }, render: ({ rowIndex, row, dataList }) => { return convertFileSize(row.vram, 1); } @@ -153,40 +195,6 @@ const renderMessage = (title: string) => { ); }; -const InfoItem = (props: { label: string; value: any; width?: number }) => { - const { label, value, width } = props; - const Wrapper = styled.div` - .info-item { - width: ${width ? `${width}px` : '100%'}; - height: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - padding: 4px 8px; - background-color: var(--color-gray-fill-3); - border-radius: 4px; - .value { - display: flex; - align-items: center; - gap: 4px; - flex-wrap: wrap; - color: var(--color-white-quaternary); - .index { - color: var(--ant-color-text-light-solid); - } - } - } - `; - return ( - -
- {label} - {value} -
-
- ); -}; - const InstanceItem: React.FC = ({ instanceData, workerList, @@ -206,7 +214,7 @@ const InstanceItem: React.FC = ({ } return true; }); - }, [instanceData]); + }, [instanceData.state]); const createFileName = (name: string) => { const timestamp = dayjs().format('YYYY-MM-DD_HH-mm-ss'); @@ -239,23 +247,6 @@ const InstanceItem: React.FC = ({ [] ); - const displayGPUs = (vrams: Record) => { - return ( - - {Object.keys(vrams) - ?.sort?.() - .map((index) => { - return ( - - [{index}] {''} - {convertFileSize(vrams?.[index], 0)} - - ); - })} - - ); - }; - const renderWorkerInfo = useMemo(() => { let workerIp = '-'; if (instanceData.worker_ip) { @@ -283,85 +274,87 @@ const InstanceItem: React.FC = ({
); - }, [modelData, instanceData, intl]); + }, [ + instanceData.worker_name, + instanceData.worker_ip, + instanceData.port, + instanceData.gpu_indexes, + modelData?.backend, + modelData?.backend_version, + intl + ]); const calcTotalVram = (vram: Record) => { return _.sum(_.values(vram)); }; - const renderDistributedServer = useCallback( - (severList: any[]) => { - const list = _.map(severList, (item: any) => { - const data = _.find(workerList, { id: item.worker_id }); - return { - worker_name: data?.name, - worker_ip: data?.ip, - port: '', - vram: calcTotalVram(item.computed_resource_claim?.vram || {}), - gpu_index: _.keys(item.computed_resource_claim?.vram).join(',') - }; - }); + const renderDistributedServer = (severList: any[]) => { + const list = _.map(severList, (item: any) => { + const data = _.find(workerList, { id: item.worker_id }); + return { + worker_name: data?.name, + worker_ip: data?.ip, + port: '', + vram: calcTotalVram(item.computed_resource_claim?.vram || {}), + gpu_index: _.keys(item.computed_resource_claim?.vram).join(',') + }; + }); - const mainWorker = [ - { - worker_name: `${instanceData.worker_name}`, - worker_ip: `${instanceData.worker_ip}`, - port: '', - vram: calcTotalVram(instanceData.computed_resource_claim?.vram || {}), - gpu_index: `${instanceData.gpu_indexes?.join?.(',')}(main)` - } - ]; + const mainWorker = [ + { + worker_name: `${instanceData.worker_name}`, + worker_ip: `${instanceData.worker_ip}`, + port: '', + vram: calcTotalVram(instanceData.computed_resource_claim?.vram || {}), + gpu_index: `${instanceData.gpu_indexes?.join?.(',')}(main)` + } + ]; - return ( -
- -
- ); - }, - [workerList, instanceData, intl] - ); + return ( +
+ +
+ ); + }; - const renderDistributionInfo = useCallback( - (severList: any[]) => { - if (!severList.length) { - return null; - } - return ( - { + if (!severList.length) { + return null; + } + return ( + + - - - {intl.formatMessage({ - id: 'models.table.acrossworker' - })} - - - ); - }, - [renderDistributedServer] - ); + + {intl.formatMessage({ + id: 'models.table.acrossworker' + })} + + + ); + }; const renderOffloadInfo = useMemo(() => { const total_layers = instanceData.computed_resource_claim?.total_layers; @@ -425,21 +418,17 @@ const InstanceItem: React.FC = ({ instanceData.computed_resource_claim?.offload_layers ]); - const handleOnSelect = useCallback( - (val: string) => { - console.log('handleOnSelect', val); - if (val === 'download') { - downloadStream({ - url: `${MODEL_INSTANCE_API}/${instanceData.id}/logs`, - filename: createFileName(instanceData.name), - downloadNotification - }); - } else { - handleChildSelect(val, instanceData); - } - }, - [handleChildSelect, instanceData] - ); + const handleOnSelect = (val: string) => { + if (val === 'download') { + downloadStream({ + url: `${MODEL_INSTANCE_API}/${instanceData.id}/logs`, + filename: createFileName(instanceData.name), + downloadNotification + }); + } else { + handleChildSelect(val, instanceData); + } + }; return ( <> @@ -487,45 +476,10 @@ const InstanceItem: React.FC = ({ style={{ paddingLeft: '62px' }} className="flex justify-center" > - {instanceData.state && ( - - handleChildSelect('viewlog', instanceData) - } - > - {intl.formatMessage({ - id: 'models.list.more.logs' - })} - - ) : null - } - statusValue={{ - status: - instanceData.state === InstanceStatusMap.Downloading && - instanceData.download_progress === 100 - ? status[InstanceStatusMap.Running] - : (status[instanceData.state] as any), - text: InstanceStatusMapValue[instanceData.state], - message: - instanceData.state === InstanceStatusMap.Downloading && - instanceData.download_progress === 100 - ? '' - : instanceData.state_message - }} - > - )} + diff --git a/src/pages/llmodels/index.tsx b/src/pages/llmodels/index.tsx index 095c9cfb..2917af15 100644 --- a/src/pages/llmodels/index.tsx +++ b/src/pages/llmodels/index.tsx @@ -81,16 +81,6 @@ const Models: React.FC = () => { setDataList: setModelInstances }); - const getWorkerList = async () => { - try { - const data = await queryWorkersList({ page: 1, perPage: 100 }); - setWorkerList(data.items || []); - } catch (error) { - // ingore - setWorkerList([]); - } - }; - const getAllModelInstances = useCallback(async () => { try { instancesToken.current?.cancel?.(); @@ -110,7 +100,16 @@ const Models: React.FC = () => { }, []); const fetchData = useCallback( - async (loadingVal?: boolean) => { + async (params?: { + loadingVal?: boolean; + query?: { + page: number; + perPage: number; + search: string; + categories: any[]; + }; + }) => { + const { loadingVal, query } = params || {}; axiosToken?.cancel?.(); axiosToken = createAxiosToken(); setDataSource((pre) => { @@ -119,7 +118,7 @@ const Models: React.FC = () => { }); try { const params = { - ..._.pickBy(queryParams, (val: any) => !!val) + ..._.pickBy(query || queryParams, (val: any) => !!val) }; const res: any = await queryModelsList(params, { cancelToken: axiosToken.token @@ -153,6 +152,13 @@ const Models: React.FC = () => { page: page, perPage: pageSize || 10 }); + fetchData({ + query: { + ...queryParams, + page: page, + perPage: pageSize || 10 + } + }); }, [queryParams] ); @@ -213,7 +219,9 @@ const Models: React.FC = () => { await getAllModelInstances(); await createModelsInstanceChunkRequest(); await createModelsChunkRequest(); - fetchData(false); + fetchData({ + loadingVal: false + }); }, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]); const handleSearch = useCallback(async () => { @@ -226,29 +234,69 @@ const Models: React.FC = () => { page: 1, search: e.target.value }); + fetchData({ + query: { + ...queryParams, + page: 1, + search: e.target.value + } + }); }, 350); const handleNameChange = useCallback(debounceUpdateFilter, [queryParams]); const handleCategoryChange = useCallback( - (value: any) => { + async (value: any) => { setQueryParams({ ...queryParams, page: 1, categories: value }); + fetchData({ + query: { + ...queryParams, + page: 1, + categories: value + } + }); }, [queryParams] ); useEffect(() => { - fetchData(); - return () => { + // fetch data first time + const getTableData = async (loadingVal?: boolean) => { axiosToken?.cancel?.(); + axiosToken = createAxiosToken(); + setDataSource((pre) => { + pre.loading = loadingVal ?? true; + return { ...pre }; + }); + try { + const params = { + ..._.pickBy(queryParams, (val: any) => !!val) + }; + const res: any = await queryModelsList(params, { + cancelToken: axiosToken.token + }); + return res; + } catch (error) { + return {}; + } }; - }, [queryParams]); - useEffect(() => { + // get worker list + const getWorkerList = async (): Promise => { + try { + const data = await queryWorkersList({ page: 1, perPage: 100 }); + return data; + } catch (error) { + // ingore + return {}; + } + }; + + // get catalog list const getCataLogList = async () => { const isFirstLogin = readState(IS_FIRST_LOGIN); if (!isFirstLogin) { @@ -260,8 +308,7 @@ const Models: React.FC = () => { page: 1 }); if (!res?.items?.length) { - setCatalogList([]); - return; + return []; } const name = _.toLower(res?.items[0]?.name).replace(/\s/g, '-') || ''; const catalogSpecs: any = await queryCatalogItemSpec({ @@ -281,24 +328,36 @@ const Models: React.FC = () => { -1) ); }); - setCatalogList(resultList || []); + return resultList || []; } catch (error) { // ignore - setCatalogList([]); + return []; } }; - getCataLogList(); - }, []); - - useEffect(() => { - createModelsChunkRequest(); - }, [createModelsChunkRequest]); - useEffect(() => { - getWorkerList(); - createModelsInstanceChunkRequest(); + const init = async () => { + const [modelRes, workerRes, cList] = await Promise.all([ + getTableData(), + getWorkerList(), + getCataLogList() + ]); + setDataSource({ + dataList: modelRes.items || [], + loading: false, + loadend: true, + total: modelRes.pagination?.total || 0, + deletedIds: [] + }); + setWorkerList(workerRes.items || []); + setCatalogList(cList); + setTimeout(() => { + createModelsInstanceChunkRequest(); + }, 500); + }; + init(); return () => { + axiosToken?.cancel?.(); chunkRequedtRef.current?.current?.cancel?.(); cacheDataListRef.current = []; cacheInsDataListRef.current = []; @@ -307,10 +366,6 @@ const Models: React.FC = () => { }; }, []); - useEffect(() => { - console.log('modelInstances====', modelInstances); - }, [modelInstances]); - useEffect(() => { const handleVisibilityChange = async () => { if (document.visibilityState === 'visible') { @@ -318,7 +373,9 @@ const Models: React.FC = () => { await getAllModelInstances(); await createModelsInstanceChunkRequest(); await createModelsChunkRequest(); - fetchData(false); + fetchData({ + loadingVal: false + }); } else { isPageHidden.current = true; chunkRequedtRef.current?.current?.cancel?.();