import AutoTooltip from '@/components/auto-tooltip'; import DropdownButtons from '@/components/drop-down-buttons'; import IconFont from '@/components/icon-font'; import RowChildren from '@/components/seal-table/components/row-children'; import SimpleTabel from '@/components/simple-table'; import StatusTag from '@/components/status-tag'; import { HandlerOptions } from '@/hooks/use-chunk-fetch'; import useDownloadStream from '@/hooks/use-download-stream'; import { ListItem as WorkerListItem } from '@/pages/resources/config/types'; import { DeleteOutlined, DownloadOutlined, HddFilled, InfoCircleOutlined, ThunderboltFilled } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; import { Button, Col, Divider, Progress, Row, Tag, Tooltip, notification } from 'antd'; import dayjs from 'dayjs'; import _ from 'lodash'; import React, { useCallback, useMemo } from 'react'; import { MODEL_INSTANCE_API } from '../apis'; import { InstanceStatusMap, InstanceStatusMapValue, status } from '../config'; import { ModelInstanceListItem } from '../config/types'; import '../style/instance-item.less'; interface InstanceItemProps { instanceData: ModelInstanceListItem; workerList: WorkerListItem[]; modelData?: any; handleChildSelect: (val: string, item: ModelInstanceListItem) => void; } const childActionList = [ { label: 'common.button.viewlog', key: 'viewlog', status: [ InstanceStatusMap.Initializing, InstanceStatusMap.Running, InstanceStatusMap.Error, InstanceStatusMap.Starting, InstanceStatusMap.Downloading ], icon: }, { label: 'common.button.downloadLog', key: 'download', status: [ InstanceStatusMap.Initializing, InstanceStatusMap.Running, InstanceStatusMap.Error, InstanceStatusMap.Starting, InstanceStatusMap.Downloading ], icon: }, { label: 'common.button.delrecreate', key: 'delete', props: { danger: true }, icon: } ]; const distributeCols = [ { title: 'Worker', key: 'worker_name' }, { title: 'IP', key: 'worker_ip', render: ({ row }: { row: ModelInstanceListItem }) => { return row.port ? `${row.worker_ip}:${row.port}` : row.worker_ip; } }, { title: 'models.table.gpuindex', locale: true, key: 'gpu_index' } ]; const renderMessage = (title: string) => { return (
{title}
); }; const InstanceItem: React.FC = ({ instanceData, workerList, modelData, handleChildSelect }) => { const [api, contextHolder] = notification.useNotification(); const { downloadStream } = useDownloadStream(); const intl = useIntl(); const actionItems = useMemo(() => { return _.filter(childActionList, (action: any) => { if (action.key === 'viewlog' || action.key === 'download') { return action.status.includes(instanceData.state); } return true; }); }, [instanceData]); const createFileName = (name: string) => { const timestamp = dayjs().format('YYYY-MM-DD_HH-mm-ss'); const fileName = `${name}_${timestamp}.txt`; return fileName; }; const downloadNotification = useCallback( (data: HandlerOptions & { filename: string; duration?: number }) => { api.open({ duration: data.duration, message: renderMessage(data.filename), key: data.filename, description: }); }, [] ); const renderWorkerInfo = useMemo(() => { let workerIp = '-'; if (instanceData.worker_ip) { workerIp = instanceData.port ? `${instanceData.worker_ip}:${instanceData.port}` : instanceData.worker_ip; } return (
{instanceData.worker_name}
{workerIp}
{intl.formatMessage({ id: 'models.table.gpuindex' })}: [ {_.join(instanceData.gpu_indexes?.sort?.(), ',')}]
{intl.formatMessage({ id: 'models.form.backend' })}:{' '} {modelData?.backend || ''} {modelData.backend_version ? `(${modelData.backend_version})` : ''}
); }, [modelData, instanceData, intl]); const renderDistributionInfo = useMemo(() => { const rpcServerList = instanceData.distributed_servers?.rpc_servers || []; const list = _.map(rpcServerList, (item: any) => { const data = _.find(workerList, { id: item.worker_id }); return { worker_name: data?.name, worker_ip: data?.ip, port: '', gpu_index: item.gpu_index }; }); const mainWorker = [ { worker_name: `${instanceData.worker_name}`, worker_ip: `${instanceData.worker_ip}`, port: '', gpu_index: `${instanceData.gpu_indexes?.sort?.()} (main)` } ]; return (

{intl.formatMessage({ id: 'models.table.backend' })}

); }, [workerList, instanceData, intl]); 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] ); return ( <> {contextHolder}
{instanceData.name} {instanceData.computed_resource_claim?.total_layers !== instanceData.computed_resource_claim?.offload_layers && ( CPU:{' '} {_.subtract( instanceData.computed_resource_claim?.total_layers, instanceData.computed_resource_claim?.offload_layers ) || 0}{' '} {intl.formatMessage({ id: 'models.table.layers' })} GPU:{' '} {instanceData.computed_resource_claim?.offload_layers}{' '} {intl.formatMessage({ id: 'models.table.layers' })} } > {intl.formatMessage({ id: 'models.table.cpuoffload' })} )} {instanceData?.distributed_servers?.rpc_servers?.length && ( {intl.formatMessage({ id: 'models.table.acrossworker' })} )} {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 }} > )} {dayjs(instanceData.created_at).format('YYYY-MM-DD HH:mm:ss')}
); }; export default React.memo(InstanceItem);