diff --git a/react-ui/config/config.ts b/react-ui/config/config.ts index 2e9ebf64..21474da6 100644 --- a/react-ui/config/config.ts +++ b/react-ui/config/config.ts @@ -150,9 +150,9 @@ export default defineConfig({ projectName: 'swagger', }, ], - mfsu: { - strategy: 'normal', - }, + // mfsu: { + // strategy: 'normal', + // }, requestRecord: {}, icons: {}, lessLoader: { diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index 3caca59f..66de518b 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -221,14 +221,24 @@ export default [ component: './ModelDeployment/List', }, { - name: '模型部署详情', - path: 'info/:id', - component: './ModelDeployment/Info', + name: '服务详情', + path: 'serviceInfo/:id', + component: './ModelDeployment/ServiceInfo', + }, + { + name: '服务版本详情', + path: 'versionInfo/:id', + component: './ModelDeployment/VersionInfo', }, { name: '创建推理服务', - path: 'create', - component: './ModelDeployment/Create', + path: 'createService', + component: './ModelDeployment/CreateService', + }, + { + name: '新增服务版本', + path: 'addVersion/:id', + component: './ModelDeployment/CreateVersion', }, ], }, diff --git a/react-ui/src/assets/img/service-version.png b/react-ui/src/assets/img/service-version.png new file mode 100644 index 00000000..08361ac9 Binary files /dev/null and b/react-ui/src/assets/img/service-version.png differ diff --git a/react-ui/src/components/BasicInfo/index.tsx b/react-ui/src/components/BasicInfo/index.tsx index c3358af2..af56ded0 100644 --- a/react-ui/src/components/BasicInfo/index.tsx +++ b/react-ui/src/components/BasicInfo/index.tsx @@ -90,7 +90,7 @@ function BasicInfoItemValue({ value, link, url }: BasicInfoItemValueProps) { ); } else { return ( -
{value || '--'}
+
{value ?? '--'}
); } } diff --git a/react-ui/src/components/CodeSelect/index.less b/react-ui/src/components/CodeSelect/index.less new file mode 100644 index 00000000..bf84e3b8 --- /dev/null +++ b/react-ui/src/components/CodeSelect/index.less @@ -0,0 +1,11 @@ +.kf-code-select { + position: relative; + display: flex; + align-items: center; + + &__button { + position: absolute; + top: 0; + left: calc(100% + 10px); + } +} diff --git a/react-ui/src/components/CodeSelect/index.tsx b/react-ui/src/components/CodeSelect/index.tsx new file mode 100644 index 00000000..03474c00 --- /dev/null +++ b/react-ui/src/components/CodeSelect/index.tsx @@ -0,0 +1,71 @@ +/* + * @Author: 赵伟 + * @Date: 2024-10-08 15:36:08 + * @Description: 代码配置选择表单组件 + */ + +import KFIcon from '@/components/KFIcon'; +import CodeSelectorModal from '@/pages/Pipeline/components/CodeSelectorModal'; +import { openAntdModal } from '@/utils/modal'; +import { Button } from 'antd'; +import ParameterInput, { type ParameterInputProps } from '../ParameterInput'; +import './index.less'; + +export { requiredValidator, type ParameterInputObject } from '../ParameterInput'; + +type CodeSelectProps = ParameterInputProps; + +function CodeSelect({ value, onChange, disabled, ...rest }: CodeSelectProps) { + const selectResource = () => { + const { close } = openAntdModal(CodeSelectorModal, { + onOk: (res) => { + if (res) { + const { git_url, git_branch, code_repo_name } = res; + const jsonObj = { + code_path: git_url, + branch: git_branch, + }; + const jsonObjStr = JSON.stringify(jsonObj); + const showValue = code_repo_name; + onChange?.({ + value: jsonObjStr, + showValue, + fromSelect: true, + ...jsonObj, + }); + } else { + onChange?.({ + value: undefined, + showValue: undefined, + fromSelect: false, + }); + } + close(); + }, + }); + }; + + return ( +
+ + +
+ ); +} + +export default CodeSelect; diff --git a/react-ui/src/components/ParameterInput/index.tsx b/react-ui/src/components/ParameterInput/index.tsx index 8ce18830..94fdddde 100644 --- a/react-ui/src/components/ParameterInput/index.tsx +++ b/react-ui/src/components/ParameterInput/index.tsx @@ -1,3 +1,9 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 08:42:57 + * @Description: 参数输入组件 + */ + import { CloseOutlined } from '@ant-design/icons'; import { Form, Input } from 'antd'; import { RuleObject } from 'antd/es/form'; diff --git a/react-ui/src/components/ParameterSelect/index.tsx b/react-ui/src/components/ParameterSelect/index.tsx index 5b181a01..ffaf8415 100644 --- a/react-ui/src/components/ParameterSelect/index.tsx +++ b/react-ui/src/components/ParameterSelect/index.tsx @@ -1,3 +1,9 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 08:42:57 + * @Description: 参数选择组件 + */ + import { PipelineNodeModelParameter } from '@/types'; import { to } from '@/utils/promise'; import { Select } from 'antd'; diff --git a/react-ui/src/components/ResourceSelect/index.tsx b/react-ui/src/components/ResourceSelect/index.tsx index a19ee1c2..5f2142d8 100644 --- a/react-ui/src/components/ResourceSelect/index.tsx +++ b/react-ui/src/components/ResourceSelect/index.tsx @@ -1,3 +1,9 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 13:58:08 + * @Description: 数据集、模型、镜像选择表单组件 + */ + import KFIcon from '@/components/KFIcon'; import ResourceSelectorModal, { ResourceSelectorResponse, @@ -22,7 +28,7 @@ const getSelectBtnIcon = (type: ResourceSelectorType) => { return ; }; -function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps) { +function ResourceSelect({ type, value, onChange, disabled, ...rest }: ResourceSelectProps) { const [selectedResource, setSelectedResource] = useState( undefined, ); @@ -87,6 +93,7 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps)
setSelectedResource(undefined)} @@ -97,6 +104,7 @@ function ResourceSelect({ type, value, onChange, ...rest }: ResourceSelectProps) size="large" type="link" icon={getSelectBtnIcon(type)} + disabled={disabled} onClick={selectResource} > {selectorTypeConfig[type].buttontTitle} diff --git a/react-ui/src/enums/index.ts b/react-ui/src/enums/index.ts index 5585725c..4b3ded7b 100644 --- a/react-ui/src/enums/index.ts +++ b/react-ui/src/enums/index.ts @@ -44,8 +44,8 @@ export enum MirrorVersionStatus { Failed = 'failed', // 构建中 } -// 模型部署状态 -export enum ModelDeploymentStatus { +// 服务运行状态 +export enum ServiceRunStatus { Init = 'Init', // 启动中 Running = 'Running', // 运行中 Stopped = 'Stopped', // 已停止 @@ -53,14 +53,13 @@ export enum ModelDeploymentStatus { Pending = 'Pending', // 挂起中 } -// 模型部署状态选项列表 -export const modelDeploymentStatusOptions = [ - { label: '全部', value: '' }, - { label: '启动中', value: ModelDeploymentStatus.Init }, - { label: '运行中', value: ModelDeploymentStatus.Running }, - { label: '已停止', value: ModelDeploymentStatus.Stopped }, - { label: '失败', value: ModelDeploymentStatus.Failed }, - { label: '挂起中', value: ModelDeploymentStatus.Pending }, +// 服务运行状态选项列表 +export const serviceStatusOptions = [ + { label: '启动中', value: ServiceRunStatus.Init }, + { label: '运行中', value: ServiceRunStatus.Running }, + { label: '已停止', value: ServiceRunStatus.Stopped }, + { label: '失败', value: ServiceRunStatus.Failed }, + { label: '挂起中', value: ServiceRunStatus.Pending }, ]; // 开发环境编辑器状态 @@ -71,3 +70,17 @@ export enum DevEditorStatus { Failed = 'Failed', // 失败 Unknown = 'Unknown', // 未启动 } + +export enum ServiceType { + Video = 'video', + Image = 'image', + Audio = 'audio', + Text = 'text', +} + +export const serviceTypeOptions = [ + { label: '视频', value: ServiceType.Video }, + { label: '图像', value: ServiceType.Image }, + { label: '音频', value: ServiceType.Audio }, + { label: '文本', value: ServiceType.Text }, +]; diff --git a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx index e3f31796..fe1e9a86 100644 --- a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx +++ b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx @@ -80,7 +80,7 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => { }) => { const request = config.getInfo; const [res] = await to(request(params)); - if (res) { + if (res && res.data) { setInfo(res.data); } }; diff --git a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx index 7489666b..21907f63 100644 --- a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx +++ b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx @@ -85,7 +85,7 @@ const formatSource = (source?: string) => { } else if (source === DataSource.HandExport) { return '手动导入'; } else if (source === DataSource.AtuoExport) { - return '自动导入'; + return '实验自动导入'; } return source; }; @@ -120,6 +120,7 @@ const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [ { label: '处理代码', value: data.processing_code, + format: formatProject, }, { label: '数据集分类', diff --git a/react-ui/src/pages/Dataset/config.tsx b/react-ui/src/pages/Dataset/config.tsx index 9c4d6e47..2ae165bc 100644 --- a/react-ui/src/pages/Dataset/config.tsx +++ b/react-ui/src/pages/Dataset/config.tsx @@ -160,7 +160,7 @@ export interface DatasetData extends ResourceData { resourceType: ResourceType.Dataset; // 用于区别类型 data_type?: string; // 数据集分类 data_tag?: string; // 研究方向 - processing_code?: string; // 处理代码 + processing_code?: ProjectDependency; // 处理代码 dataset_source?: string; // 数据来源 dataset_version_vos?: ResourceFileData[]; } @@ -199,15 +199,15 @@ export type ResourceFileData = { // 训练任务 export type TrainTask = { - ins_id: number; - name: string; - experiment_id: number; - workflow_id: number; + ins_id: number; // 实例id + name: string; // 实验名称 + experiment_id: number; //实验 id + workflow_id: number; // 流水线 id }; // 项目依赖 export type ProjectDependency = { - url: string; - name: string; - branch: string; + url: string; // 项目地址 + name: string; // 项目名称 + branch: string; // 分支 }; diff --git a/react-ui/src/pages/Experiment/Info/index.jsx b/react-ui/src/pages/Experiment/Info/index.jsx index d02ae8f8..a958794b 100644 --- a/react-ui/src/pages/Experiment/Info/index.jsx +++ b/react-ui/src/pages/Experiment/Info/index.jsx @@ -353,7 +353,7 @@ function ExperimentText() { fitView: true, minZoom: 0.5, maxZoom: 5, - fitViewPadding: 300, + fitViewPadding: 200, modes: { default: [ // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles diff --git a/react-ui/src/pages/Experiment/components/ExperimentResult/index.tsx b/react-ui/src/pages/Experiment/components/ExperimentResult/index.tsx index 6c770618..37e6a9df 100644 --- a/react-ui/src/pages/Experiment/components/ExperimentResult/index.tsx +++ b/react-ui/src/pages/Experiment/components/ExperimentResult/index.tsx @@ -1,3 +1,4 @@ +import { ResourceType } from '@/pages/Dataset/config'; import { getNodeResult } from '@/services/experiment/index.js'; import { downLoadZip } from '@/utils/downloadfile'; import { openAntdModal } from '@/utils/modal'; @@ -34,6 +35,12 @@ function ExperimentResult({ }: ExperimentResultProps) { const { message } = App.useApp(); const [experimentResults, setExperimentResults] = useState([]); + const resourceType: ResourceType | undefined = pipelineNodeId.startsWith('general-data-process') + ? ResourceType.Dataset + : pipelineNodeId.startsWith('model-train') || + pipelineNodeId.startsWith('distributed-model-train') + ? ResourceType.Model + : undefined; useEffect(() => { getExperimentResult({ id: `${experimentInsId}`, node_id: pipelineNodeId }); @@ -42,8 +49,11 @@ function ExperimentResult({ // 获取实验结果 const getExperimentResult = async (params: any) => { const [res] = await to(getNodeResult(params)); - if (res && res.data) { - setExperimentResults(res.data); + if (res && res.data && Array.isArray(res.data)) { + const data = res.data.filter((item: ExperimentResultData) => item.value.length > 0); + setExperimentResults(data); + } else { + setExperimentResults([]); } }; @@ -52,9 +62,10 @@ function ExperimentResult({ downLoadZip(`/api/mmp/minioStorage/download`, { path }); }; - // 导出到模型库 - const exportToModel = (path: string) => { + // 导出到数据集、模型 + const exportToResource = (path: string) => { const { close } = openAntdModal(ExportModelModal, { + resourceType: resourceType!, pipelineId, experimentId, experimentName, @@ -86,17 +97,17 @@ function ExperimentResult({ > 下载 - - {/* 导出到模型库 - 导出到数据集 */} + {resourceType && ( + + )}
文件名称 diff --git a/react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx b/react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx index 5667a388..1f2e18c0 100644 --- a/react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx +++ b/react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx @@ -1,7 +1,12 @@ import editExperimentIcon from '@/assets/img/edit-experiment.png'; import KFModal from '@/components/KFModal'; -import { DataSource, ResourceVersionData, type ResourceData } from '@/pages/Dataset/config'; -import { addModelVersion, getModelList, getModelVersionList } from '@/services/dataset'; +import { + DataSource, + ResourceType, + ResourceVersionData, + resourceConfig, + type ResourceData, +} from '@/pages/Dataset/config'; import { to } from '@/utils/promise'; import { InfoCircleOutlined } from '@ant-design/icons'; import { Form, Input, ModalProps, Select } from 'antd'; @@ -15,20 +20,8 @@ type FormData = { version_desc: string; }; -// type ExportModelResponce = { -// fileName: string; -// fileSize: string; -// url: string; -// }; - -// type CreateModelVersionParams = FormData & { -// file_name: string; -// file_size: string; -// url: string; -// // name: string; -// }; - interface ExportModelModalProps extends Omit { + resourceType: ResourceType; pipelineId: number; // 流水线 id experimentId: number; // 实验 id experimentName: string; // 实验 name @@ -39,6 +32,7 @@ interface ExportModelModalProps extends Omit { } function ExportModelModal({ + resourceType, pipelineId, experimentId, experimentName, @@ -49,9 +43,9 @@ function ExportModelModal({ ...rest }: ExportModelModalProps) { const [form] = Form.useForm(); - const [models, setModels] = useState([]); + const [resources, setResources] = useState([]); const [versions, setVersions] = useState([]); - // const [uuid] = useState(Date.now()); + const config = resourceConfig[resourceType]; const layout = { labelCol: { span: 24 }, @@ -59,57 +53,57 @@ function ExportModelModal({ }; useEffect(() => { - requestModelList(); + requestResourceList(); }, []); - // 获取选中的模型 - const getSelectedModel = (id: number | undefined) => { + // 获取选中的数据集、模型 + const getSelectedResource = (id: number | undefined) => { if (id) { - return models.find((item) => item.id === id); + return resources.find((item) => item.id === id); } return undefined; }; - // 模型版本 tooltip + // 版本 tooltip const getTooltip = () => { const id = form.getFieldValue('id'); - const model = getSelectedModel(id); - const name = model?.name ?? ''; + const resource = getSelectedResource(id); + const name = resource?.name ?? ''; const versionNames = versions.map((item: ResourceVersionData) => item.name).join('、'); const tooltip = versions.length > 0 ? `${name}有以下版本:\n${versionNames}\n注意不能重复` : undefined; return tooltip; }; - // 处理模型名称变化 - const handleModelChange = (id: number | undefined) => { + // 处理数据集、模型选择变化 + const handleResourceChange = (id: number | undefined) => { if (id) { - getModelVersions(id); + getRecourceVersions(id); } else { setVersions([]); } }; - // 获取模型列表 - const requestModelList = async () => { + // 获取数据集、模型列表 + const requestResourceList = async () => { const params = { page: 0, size: 1000, is_public: false, // 个人 }; - const [res] = await to(getModelList(params)); + const [res] = await to(config.getList(params)); if (res && res.data) { - setModels(res.data.content || []); + setResources(res.data.content || []); } }; - // 获取模型版本列表 - const getModelVersions = async (id: number) => { - const model = getSelectedModel(id); - if (!model) { + // 获取数据集、模型版本列表 + const getRecourceVersions = async (id: number) => { + const resource = getSelectedResource(id); + if (!resource) { return; } - const [res] = await to(getModelVersionList(pick(model, ['identifier', 'owner']))); + const [res] = await to(config.getVersions(pick(resource, ['identifier', 'owner']))); if (res && res.data) { setVersions(res.data); } @@ -117,18 +111,18 @@ function ExportModelModal({ // 提交 const hanldeFinish = (formData: FormData) => { - exportToModel(formData); + exportToResource(formData); }; - // 导出到模型 - const exportToModel = async (formData: FormData) => { + // 导出到数据集、模型 + const exportToResource = async (formData: FormData) => { const id = form.getFieldValue('id'); - const model = getSelectedModel(id); + const resource = getSelectedResource(id); const params = { ...formData, - identifier: model?.identifier, - name: model?.name, - model_source: DataSource.HandExport, + identifier: resource?.identifier, + name: resource?.name, + [config.sourceParamKey]: DataSource.HandExport, train_task: { workflow_id: pipelineId, experiment_id: experimentId, @@ -136,13 +130,13 @@ function ExportModelModal({ ins_id: experimentInsId, task_id: pipelineNodeId, }, - model_version_vos: [ + [config.filePropKey]: [ { url: path, }, ], }; - const [res] = await to(addModelVersion(params)); + const [res] = await to(config.addVersion(params)); if (res) { onOk(); } @@ -151,7 +145,7 @@ function ExportModelModal({ return ( - + { if (value && versions.map((item) => item.name).includes(value)) { - return Promise.reject('模型版本已存在'); + return Promise.reject(`${config.name}版本已存在`); } else { return Promise.resolve(); } @@ -204,7 +202,7 @@ function ExportModelModal({ }, ]} > - + (undefined); + const { message } = App.useApp(); + + useEffect(() => { + const res = getSessionStorageItem(serviceInfoKey, true); + if (res) { + setOperationType(res.operationType); + setServiceInfo(res); + form.setFieldsValue(pick(res, ['service_name', 'service_type', 'description'])); + } + return () => { + removeSessionStorageItem(serviceInfoKey); + }; + }, []); + + // 创建、更新服务 + const createService = async (formData: FormData) => { + const request = + operationType === ServiceOperationType.Create ? createServiceReq : updateServiceReq; + const params = + operationType === ServiceOperationType.Create + ? formData + : { + id: serviceInfo?.id, + ...formData, + }; + const [res] = await to(request(params)); + if (res) { + message.success('操作成功'); + navigate(-1); + } + }; + + // 提交 + const handleSubmit = (values: FormData) => { + createService(values); + }; + + // 取消 + const cancel = () => { + navigate(-1); + }; + + const disabled = operationType !== ServiceOperationType.Create; + const title = operationType === ServiceOperationType.Create ? '创建推理服务' : '更新推理服务'; + + return ( +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + @@ -173,18 +251,18 @@ function ModelDeploymentCreate() { + + + + + + + @@ -292,12 +393,16 @@ function ModelDeploymentCreate() { - + {(fields, { add, remove }) => ( <> - + {fields.length === 0 ? ( + + ) : null} @@ -329,9 +441,16 @@ function ModelDeploymentCreate() { {...restField} name={[name, 'key']} style={{ flex: 1 }} - rules={[{ required: true, message: '请输入变量名' }]} + rules={[ + { required: true, message: '请输入变量名' }, + { + pattern: /^[a-zA-Z_][a-zA-Z0-9_-]*$/, + message: + '变量名只支持字母、数字、下划线、中横线且开头必须是字母或下划线', + }, + ]} > - + = - + ))} + {fields.length > 0 ? ( + + ) : null} )} - + - {(record.status === ModelDeploymentStatus.Failed || - record.status === ModelDeploymentStatus.Stopped) && ( - - )} - {(record.status === ModelDeploymentStatus.Running || - record.status === ModelDeploymentStatus.Init || - record.status === ModelDeploymentStatus.Pending) && ( - - )} } - onClick={() => handleModelDeployDelete(record)} + onClick={() => handleServiceDelete(record)} > 删除 @@ -289,11 +245,11 @@ function ModelDeployment() { return (
- +
setInputText(e.target.value)} style={{ width: 300 }} @@ -303,27 +259,19 @@ function ModelDeployment() { -
`共${total}条`, }} onChange={handleTableChange} - rowKey="service_id" + rowKey="id" />
diff --git a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.less b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.less new file mode 100644 index 00000000..a8c3ce14 --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.less @@ -0,0 +1,24 @@ +.service-info { + height: 100%; + &__content { + display: flex; + flex-direction: column; + height: calc(100% - 60px); + margin-top: 10px; + padding: 20px 30px 0; + background-color: white; + border-radius: 10px; + + &__filter { + display: flex; + flex: none; + align-items: center; + justify-content: space-between; + } + + &__table { + flex: 1; + margin-top: 24px; + } + } +} diff --git a/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx new file mode 100644 index 00000000..21091b5a --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx @@ -0,0 +1,431 @@ +/* + * @Author: 赵伟 + * @Date: 2024-04-16 13:58:08 + * @Description: 模型部署列表 + */ +import BasicInfo from '@/components/BasicInfo'; +import CommonTableCell from '@/components/CommonTableCell'; +import KFIcon from '@/components/KFIcon'; +import PageTitle from '@/components/PageTitle'; +import SubAreaTitle from '@/components/SubAreaTitle'; +import { ServiceRunStatus, serviceStatusOptions } from '@/enums'; +import { useCacheState } from '@/hooks/pageCacheState'; +import { useComputingResource } from '@/hooks/resource'; +import { + deleteServiceVersionReq, + getServiceInfoReq, + getServiceVersionsReq, + stopServiceVersionReq, +} from '@/services/modelDeployment'; +import themes from '@/styles/theme.less'; +import { formatDate } from '@/utils/date'; +import { to } from '@/utils/promise'; +import { serviceVersionInfoKey, setSessionStorageItem } from '@/utils/sessionStorage'; +import { modalConfirm } from '@/utils/ui'; +import { useNavigate, useParams } from '@umijs/max'; +import { + App, + Button, + ConfigProvider, + Input, + Select, + Table, + Tooltip, + type TablePaginationConfig, + type TableProps, +} from 'antd'; +import { type SearchProps } from 'antd/es/input'; +import classNames from 'classnames'; +import { useEffect, useState } from 'react'; +import ServiceRunStatusCell from '../components/ModelDeployStatusCell'; +import { ServiceData, ServiceOperationType, ServiceVersionData } from '../types'; +import styles from './index.less'; + +const allServiceStatusOptions = [{ label: '全部', value: '' }, ...serviceStatusOptions]; + +function ServiceInfo() { + const navigate = useNavigate(); + const { message } = App.useApp(); + const [cacheState, setCacheState] = useCacheState(); + const [serviceStatus, setServiceStatus] = useState(cacheState?.serviceStatus ?? ''); + const [searchText, setSearchText] = useState(cacheState?.searchText); + const [inputText, setInputText] = useState(cacheState?.searchText); + const [tableData, setTableData] = useState([]); + const [total, setTotal] = useState(0); + const [pagination, setPagination] = useState( + cacheState?.pagination ?? { + current: 1, + pageSize: 10, + }, + ); + const params = useParams(); + const id = params.id; + const [serviceInfo, setServiceInfo] = useState(undefined); + const basicInfo = [ + { + label: '服务名称', + value: serviceInfo?.service_name, + }, + { + label: '服务描述', + value: serviceInfo?.description, + }, + { + label: '版本数量', + value: serviceInfo?.version_count, + }, + { + label: '创建时间', + value: serviceInfo?.create_time, + format: formatDate, + }, + ]; + const getResourceDescription = useComputingResource()[2]; + + useEffect(() => { + getServiceInfo(); + }, []); + + useEffect(() => { + getServiceVersions(); + }, [pagination, searchText, serviceStatus]); + + // 获取服务详情 + const getServiceInfo = async () => { + const [res] = await to(getServiceInfoReq(id)); + if (res && res.data) { + setServiceInfo(res.data); + } + }; + + // 获取服务版本列表 + const getServiceVersions = async () => { + const params: Record = { + page: pagination.current! - 1, + size: pagination.pageSize, + version: searchText, + run_state: serviceStatus, + service_id: id, + }; + const [res] = await to(getServiceVersionsReq(params)); + if (res && res.data) { + const { content = [], totalElements = 0 } = res.data; + setTableData(content); + setTotal(totalElements); + } + }; + + // 删除模型部署 + const deleteServiceVersion = async (record: ServiceVersionData) => { + const [res] = await to(deleteServiceVersionReq(record.id)); + if (res) { + message.success('删除成功'); + // 如果是一页的唯一数据,删除时,请求第一页的数据 + // 否则直接刷新这一页的数据 + // 避免回到第一页 + if (tableData.length > 1) { + setPagination((prev) => ({ + ...prev, + current: 1, + })); + } else { + getServiceInfo(); + getServiceVersions(); + } + } + }; + + // 停止模型部署 + const stopServiceVersion = async (record: ServiceVersionData) => { + const [res] = await to(stopServiceVersionReq(record.id)); + if (res) { + message.success('操作成功'); + getServiceVersions(); + } + }; + + // 搜索 + const onSearch: SearchProps['onSearch'] = (value) => { + setSearchText(value); + }; + + // 处理删除 + const handleServiceVersionDelete = (record: ServiceVersionData) => { + modalConfirm({ + title: '删除后,该服务版本将不可恢复', + content: '是否确认删除?', + onOk: () => { + deleteServiceVersion(record); + }, + }); + }; + + // 处理停止 + const handleServiceVersionStop = async (record: ServiceVersionData) => { + modalConfirm({ + title: '停止', + content: '是否确认停止该服务?', + onOk: () => { + stopServiceVersion(record); + }, + }); + }; + + // 创建、更新、重启模型部署 + const createServiceVersion = (type: ServiceOperationType, record?: ServiceVersionData) => { + setSessionStorageItem( + serviceVersionInfoKey, + { + ...record, + operationType: type, + }, + true, + ); + + setCacheState({ + pagination, + searchText, + serviceStatus: serviceStatus, + }); + + navigate(`/modelDeployment/addVersion/${id}`); + }; + + // 查看详情 + const toDetail = (record: ServiceVersionData) => { + setSessionStorageItem(serviceVersionInfoKey, record, true); + + setCacheState({ + pagination, + searchText, + serviceStatus: serviceStatus, + }); + + navigate(`/modelDeployment/versionInfo/${record.id}`); + }; + + // 分页切换 + const handleTableChange: TableProps['onChange'] = (pagination, _filters, _sorter, { action }) => { + if (action === 'paginate') { + setPagination(pagination); + } + // console.log(pagination, filters, sorter, action); + }; + + const columns: TableProps['columns'] = [ + { + title: '序号', + dataIndex: 'index', + key: 'index', + width: '20%', + render(_text, _record, index) { + return {(pagination.current! - 1) * pagination.pageSize! + index + 1}; + }, + }, + { + title: '服务版本', + dataIndex: 'version', + key: 'version', + width: '20%', + render: CommonTableCell(), + }, + { + title: '模型版本', + dataIndex: 'model', + key: 'model', + width: '20%', + render: (_text: string, record: ServiceVersionData) => ( + + {record.model.show_value} + + ), + ellipsis: { showTitle: false }, + }, + { + title: '状态', + dataIndex: 'run_state', + key: 'run_state', + width: '20%', + render: ServiceRunStatusCell, + }, + { + title: '版本镜像', + dataIndex: 'image', + key: 'image', + width: '20%', + render: CommonTableCell(true), + ellipsis: { showTitle: false }, + }, + { + title: '副本数量', + dataIndex: 'replicas', + key: 'replicas', + render: CommonTableCell(), + width: '20%', + }, + { + title: '资源规格', + dataIndex: 'resource', + key: 'resource', + width: '20%', + render: (resource: string) => ( + + {resource ? getResourceDescription(resource) : '--'} + + ), + ellipsis: { showTitle: false }, + }, + { + title: '操作', + dataIndex: 'operation', + width: 320, + key: 'operation', + render: (_: any, record: ServiceVersionData) => ( +
+ + + {(record.run_state === ServiceRunStatus.Failed || + record.run_state === ServiceRunStatus.Stopped) && ( + + )} + {(record.run_state === ServiceRunStatus.Running || + record.run_state === ServiceRunStatus.Init || + record.run_state === ServiceRunStatus.Pending) && ( + + )} + + + + +
+ ), + }, + ]; + + return ( +
+ +
+ + + +
+ setInputText(e.target.value)} + style={{ width: 300 }} + value={inputText} + allowClear + /> + + + +
+
+ `共${total}条`, + }} + onChange={handleTableChange} + rowKey="id" + /> + + + + ); +} + +export default ServiceInfo; diff --git a/react-ui/src/pages/ModelDeployment/Info/index.less b/react-ui/src/pages/ModelDeployment/VersionInfo/index.less similarity index 96% rename from react-ui/src/pages/ModelDeployment/Info/index.less rename to react-ui/src/pages/ModelDeployment/VersionInfo/index.less index 4dcf90d9..b54cfbed 100644 --- a/react-ui/src/pages/ModelDeployment/Info/index.less +++ b/react-ui/src/pages/ModelDeployment/VersionInfo/index.less @@ -1,4 +1,4 @@ -.model-deployment-info { +.service-version-info { height: 100%; &__content { diff --git a/react-ui/src/pages/ModelDeployment/Info/index.tsx b/react-ui/src/pages/ModelDeployment/VersionInfo/index.tsx similarity index 56% rename from react-ui/src/pages/ModelDeployment/Info/index.tsx rename to react-ui/src/pages/ModelDeployment/VersionInfo/index.tsx index 4f73f46f..cce8a1b8 100644 --- a/react-ui/src/pages/ModelDeployment/Info/index.tsx +++ b/react-ui/src/pages/ModelDeployment/VersionInfo/index.tsx @@ -1,19 +1,20 @@ /* * @Author: 赵伟 * @Date: 2024-04-16 13:58:08 - * @Description: 镜像详情 + * @Description: 服务版本详情 */ import KFIcon from '@/components/KFIcon'; import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; -import { useSessionStorage } from '@/hooks/sessionStorage'; -import { modelDeploymentInfoKey } from '@/utils/sessionStorage'; +import { getServiceVersionInfoReq } from '@/services/modelDeployment'; +import { to } from '@/utils/promise'; +import { useParams } from '@umijs/max'; import { Tabs, type TabsProps } from 'antd'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import BasicInfo from '../components/BasicInfo'; import ServerLog from '../components/ServerLog'; import UserGuide from '../components/UserGuide'; -import { ModelDeploymentData } from '../types'; +import { ServiceVersionData } from '../types'; import styles from './index.less'; export enum ModelDeploymentTabKey { @@ -22,13 +23,23 @@ export enum ModelDeploymentTabKey { Log = 'Log', // 服务日志 } -function ModelDeploymentInfo() { +function ServiceVersionInfo() { const [activeTab, setActiveTab] = useState(ModelDeploymentTabKey.Predict); - const [modelDeployementInfo] = useSessionStorage( - modelDeploymentInfoKey, - true, - undefined, - ); + const [versionInfo, setVersionInfo] = useState(undefined); + const params = useParams(); + const id = params.id; + + useEffect(() => { + getServiceVersionInfo(); + }, []); + + // 获取服务版本详情 + const getServiceVersionInfo = async () => { + const [res] = await to(getServiceVersionInfoReq(id)); + if (res && res.data) { + setVersionInfo(res.data); + } + }; const tabItems = [ { @@ -40,13 +51,13 @@ function ModelDeploymentInfo() { key: ModelDeploymentTabKey.Guide, label: '调用指南', icon: , - children: , + children: , }, { key: ModelDeploymentTabKey.Log, label: '服务日志', icon: , - children: , + children: , }, ]; @@ -56,16 +67,16 @@ function ModelDeploymentInfo() { }; return ( -
- -
+
+ +
- -
+ +
@@ -73,4 +84,4 @@ function ModelDeploymentInfo() { ); } -export default ModelDeploymentInfo; +export default ServiceVersionInfo; diff --git a/react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx b/react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx index 73beba6f..e6f62cae 100644 --- a/react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/BasicInfo/index.tsx @@ -1,12 +1,13 @@ import LabelValue from '@/components/LabelValue'; import { useComputingResource } from '@/hooks/resource'; -import { ModelDeploymentData } from '@/pages/ModelDeployment/types'; +import { ServiceVersionData } from '@/pages/ModelDeployment/types'; import { formatDate } from '@/utils/date'; +import { Link } from '@umijs/max'; import { Col, Row } from 'antd'; -import ModelDeploymentStatusCell from '../ModelDeployStatusCell'; +import ServiceRunStatusCell from '../ModelDeployStatusCell'; type BasicInfoProps = { - info?: ModelDeploymentData; + info?: ServiceVersionData; }; function BasicInfo({ info }: BasicInfoProps) { @@ -14,42 +15,75 @@ function BasicInfo({ info }: BasicInfoProps) { // 格式化环境变量 const formatEnvText = () => { - if (!info?.env) { + if (!info?.env_variables) { return '--'; } - const env = info.env; + const env = info.env_variables; return Object.entries(env) .map(([key, value]) => `${key}: ${value}`) .join('\n'); }; + const formatCodeConfig = () => { + if (info && info.code_config) { + const url = `${info.code_config.code_path}/tree/${info.code_config.branch}`; + return ( + + {info?.code_config?.show_value} + + ); + } + return undefined; + }; + + const formatResource = () => { + if (info && info.resource) { + return getResourceDescription(info.resource); + } + return undefined; + }; + + const formatModel = () => { + if (info && info.model) { + const model = info.model; + const path = `/dataset/model/info/${model.id}?version=${model.version}&name=${model.name}&owner=${model.owner}&identifier=${model.identifier}`; + return {info?.model?.show_value}; + } + return undefined; + }; + return (
+ + + + + + + + - + - + - + - + @@ -68,19 +102,11 @@ function BasicInfo({ info }: BasicInfoProps) { - + - - - - - diff --git a/react-ui/src/pages/ModelDeployment/components/ModelDeployStatusCell/index.tsx b/react-ui/src/pages/ModelDeployment/components/ModelDeployStatusCell/index.tsx index b8942237..7029c8fd 100644 --- a/react-ui/src/pages/ModelDeployment/components/ModelDeployStatusCell/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/ModelDeployStatusCell/index.tsx @@ -3,42 +3,42 @@ * @Date: 2024-04-18 18:35:41 * @Description: 模型部署状态 */ -import { ModelDeploymentStatus } from '@/enums'; +import { ServiceRunStatus } from '@/enums'; import styles from './index.less'; -export type ModelDeploymentStatusInfo = { +export type ServiceRunStatusInfo = { text: string; classname: string; }; -export const statusInfo: Record = { - [ModelDeploymentStatus.Init]: { +export const statusInfo: Record = { + [ServiceRunStatus.Init]: { text: '启动中', classname: styles['model-deployment-status-cell'], }, - [ModelDeploymentStatus.Running]: { + [ServiceRunStatus.Running]: { classname: styles['model-deployment-status-cell--running'], text: '运行中', }, - [ModelDeploymentStatus.Stopped]: { + [ServiceRunStatus.Stopped]: { classname: styles['model-deployment-status-cell--stopped'], text: '已停止', }, - [ModelDeploymentStatus.Failed]: { + [ServiceRunStatus.Failed]: { classname: styles['model-deployment-status-cell--error'], text: '失败', }, - [ModelDeploymentStatus.Pending]: { + [ServiceRunStatus.Pending]: { classname: styles['model-deployment-status-cell--pending'], text: '挂起中', }, }; -function ModelDeploymentStatusCell(status?: ModelDeploymentStatus | null) { +function ServiceRunStatusCell(status?: ServiceRunStatus | null) { if (status === null || status === undefined || !statusInfo[status]) { return --; } return {statusInfo[status].text}; } -export default ModelDeploymentStatusCell; +export default ServiceRunStatusCell; diff --git a/react-ui/src/pages/ModelDeployment/components/ServerLog/index.tsx b/react-ui/src/pages/ModelDeployment/components/ServerLog/index.tsx index 6f9cfe51..ad74986f 100644 --- a/react-ui/src/pages/ModelDeployment/components/ServerLog/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/ServerLog/index.tsx @@ -1,10 +1,9 @@ -import { ModelDeploymentData } from '@/pages/ModelDeployment/types'; -import { getModelDeploymentLogReq } from '@/services/modelDeployment'; +import { ServiceVersionData } from '@/pages/ModelDeployment/types'; +import { getServiceVersionLogReq } from '@/services/modelDeployment'; import { to } from '@/utils/promise'; import { DoubleRightOutlined } from '@ant-design/icons'; import { Button, DatePicker, type TimeRangePickerProps } from 'antd'; import dayjs from 'dayjs'; -import { pick } from 'lodash'; import { useEffect, useState } from 'react'; import styles from './index.less'; const { RangePicker } = DatePicker; @@ -28,7 +27,7 @@ type LogData = { }; type ServerLogProps = { - info?: ModelDeploymentData; + info?: ServiceVersionData; }; function ServerLog({ info }: ServerLogProps) { @@ -64,9 +63,9 @@ function ServerLog({ info }: ServerLogProps) { const params = { start_time: logTime[0], end_time: logTime[1], - ...pick(info, ['service_id', 'service_ins_id']), + id: info.id, }; - const [res] = await to(getModelDeploymentLogReq(params)); + const [res] = await to(getServiceVersionLogReq(params)); if (res && res.data) { setLogData((prev) => [...prev, res.data]); setHasMore(!!res.data.log_content); diff --git a/react-ui/src/pages/ModelDeployment/components/UserGuide/index.tsx b/react-ui/src/pages/ModelDeployment/components/UserGuide/index.tsx index 995f4e40..c2b73d47 100644 --- a/react-ui/src/pages/ModelDeployment/components/UserGuide/index.tsx +++ b/react-ui/src/pages/ModelDeployment/components/UserGuide/index.tsx @@ -1,12 +1,11 @@ -import { ModelDeploymentData } from '@/pages/ModelDeployment/types'; -import { getModelDeploymentDocsReq } from '@/services/modelDeployment'; +import { ServiceVersionData } from '@/pages/ModelDeployment/types'; +import { getServiceVersionDocsReq } from '@/services/modelDeployment'; import { to } from '@/utils/promise'; -import { pick } from 'lodash'; import { useEffect, useState } from 'react'; import styles from './index.less'; type UserGuideProps = { - info?: ModelDeploymentData; + info?: ServiceVersionData; }; function UserGuide({ info }: UserGuideProps) { @@ -18,8 +17,7 @@ function UserGuide({ info }: UserGuideProps) { // 获取模型部署文档 const getModelDeploymentDocs = async () => { if (info) { - const params = pick(info, ['service_id', 'service_ins_id']); - const [res] = await to(getModelDeploymentDocsReq(params)); + const [res] = await to(getServiceVersionDocsReq(info.id)); if (res && res.data && res.data.docs) { setDocs(JSON.stringify(res.data.docs, null, 2)); } diff --git a/react-ui/src/pages/ModelDeployment/types.ts b/react-ui/src/pages/ModelDeployment/types.ts index 4bdf28c8..d53655b2 100644 --- a/react-ui/src/pages/ModelDeployment/types.ts +++ b/react-ui/src/pages/ModelDeployment/types.ts @@ -1,31 +1,58 @@ -import { ModelDeploymentStatus } from '@/enums'; +import { ServiceRunStatus } from '@/enums'; -// 模型部署列表数据类型 -export type ModelDeploymentData = { - service_id: number; - service_ins_id: number; - service_name: string; - description: string; - status: ModelDeploymentStatus; - update_time: string; - create_time: string; +// 服务列表数据类型 +export type ServiceData = { + id: number; // 服务id + service_name: string; // 服务名称 + service_type: string; // 服务类型 + service_type_name: string; // 服务类型中文 + description: string; // 描述 + version_count: number; // 版本数量 created_by: string; - model_path: string; - url: string; - image: string; - replicas: number; - resource: string; + create_time: string; + update_by: string; + update_time: string; +}; + +// 服务版本数据类型 +export type ServiceVersionData = { + id: number; // 版本id + service_id: number; // 服务id + service_name: string; // 服务名称 + description: string; // 版本描述 + version: string; // 版本 + run_state: ServiceRunStatus; // 运行状态 + image: string; // 镜像 + replicas: number; // 副本数 + resource: string; // 资源 + mount_path: string; // 挂载路径 model: { + // 模型 id: number; + name: string; version: string; path: string; + identifier: string; + owner: string; show_value: string; }; - env: Record; + code_config: { + // 代码配置 + code_path: string; + branch: string; + show_value: string; + }; + env_variables: Record; // 环境变量 + url: string; // API URL + deployment_name: string; + update_by: string; + update_time: string; + create_time: string; + created_by: string; }; // 操作类型 -export enum ModelDeploymentOperationType { +export enum ServiceOperationType { Create = 'Create', // 创建 Update = 'Update', // 更新 Restart = 'Restart', // 重启 diff --git a/react-ui/src/pages/Pipeline/Info/index.jsx b/react-ui/src/pages/Pipeline/Info/index.jsx index 9af2c422..b538fa50 100644 --- a/react-ui/src/pages/Pipeline/Info/index.jsx +++ b/react-ui/src/pages/Pipeline/Info/index.jsx @@ -433,7 +433,7 @@ const EditPipeline = () => { fitView: true, minZoom: 0.5, maxZoom: 5, - fitViewPadding: 300, + fitViewPadding: 200, modes: { default: [ // config the shouldBegin for drag-node to avoid node moving while dragging on the anchor-point circles diff --git a/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx b/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx index 523ca7bc..6a42535c 100644 --- a/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx +++ b/react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx @@ -15,6 +15,8 @@ import { useEffect, useState } from 'react'; import CodeConfigItem from '../CodeConfigItem'; import styles from './index.less'; +export { type CodeConfigData }; + export interface CodeSelectorModalProps extends Omit { onOk?: (params: CodeConfigData | undefined) => void; } diff --git a/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx b/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx index 1cea7dca..bea129dd 100644 --- a/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx +++ b/react-ui/src/pages/Pipeline/components/PipelineNodeDrawer/index.tsx @@ -136,7 +136,6 @@ const PipelineNodeParameter = forwardRef(({ onFormChange }: PipelineNodeParamete const { close } = openAntdModal(CodeSelectorModal, { onOk: (res) => { if (res) { - console.log('res', res); const value = JSON.stringify({ id: res.id, name: res.code_repo_name, diff --git a/react-ui/src/services/modelDeployment/index.ts b/react-ui/src/services/modelDeployment/index.ts index 4492318d..eccf841e 100644 --- a/react-ui/src/services/modelDeployment/index.ts +++ b/react-ui/src/services/modelDeployment/index.ts @@ -5,73 +5,102 @@ */ import { request } from '@umijs/max'; -// 分页查询模型部署列表 -export function getModelDeploymentListReq(data: any) { - return request(`/api/v1/model/get`, { +// 分页查询服务列表 +export function getServiceListReq(data: any) { + return request(`/api/mmp/service`, { + method: 'GET', + params: data, + }); +} + +// 创建推理服务 +export function createServiceReq(data: any) { + return request(`/api/mmp/service`, { method: 'POST', data, }); } -// 查询模型部署详情 -export function getModelDeploymentInfoReq(id: number) { - return request(`/api/mmp/image/${id}`, { +// 编辑推理服务 +export function updateServiceReq(data: any) { + return request(`/api/mmp/service`, { + method: 'PUT', + data, + }); +} + +// 删除推理服务 +export function deleteServiceReq(id: any) { + return request(`/api/mmp/service/${id}`, { + method: 'DELETE', + }); +} + +// 获取服务详情 +export function getServiceInfoReq(id: any) { + return request(`/api/mmp/service/serviceDetail/${id}`, { method: 'GET', }); } -// 创建模型部署 -export function createModelDeploymentReq(data: any) { - return request(`/api/v1/model/create`, { - method: 'POST', - data, +// ------------------------------- 服务版本部分 --------------------------------------------- + +// 获取服务版本列表 +export function getServiceVersionsReq(data: any) { + return request(`/api/mmp/service/serviceVersion`, { + method: 'GET', + params: data, }); } -// 删除模型部署 -export function deleteModelDeploymentReq(data: any) { - return request(`/api/v1/model/delete`, { +// 创建服务版本 +export function createServiceVersionReq(data: any) { + return request(`/api/mmp/service/serviceVersion`, { method: 'POST', data, }); } -// 重启模型部署 -export function restartModelDeploymentReq(data: any) { - return request(`/api/v1/model/restart`, { - method: 'POST', +// 更新服务版本 +export function updateServiceVersionReq(data: any) { + return request(`/api/mmp/service/serviceVersion`, { + method: 'PUT', data, }); } -// 停止模型部署 -export function stopModelDeploymentReq(data: any) { - return request(`/api/v1/model/stop`, { - method: 'POST', - data, +// 删除服务版本 +export function deleteServiceVersionReq(id: any) { + return request(`/api/mmp/service/serviceVersion/${id}`, { + method: 'DELETE', }); } -// 更新模型部署 -export function updateModelDeploymentReq(data: any) { - return request(`/api/v1/model/update`, { - method: 'POST', - data, +// 获取服务版本详情 +export function getServiceVersionInfoReq(id: any) { + return request(`/api/mmp/service/serviceVersionDetail/${id}`, { + method: 'GET', }); } -// 获取模型部署操作指南 -export function getModelDeploymentDocsReq(data: any) { - return request(`/api/v1/model/getDocs`, { - method: 'POST', - data, +// 停止服务版本 +export function stopServiceVersionReq(id: any) { + return request(`/api/mmp/service/stopServiceVersion/${id}`, { + method: 'DELETE', }); } -// 获取模型部署日志 -export function getModelDeploymentLogReq(data: any) { - return request(`/api/v1/model/getAppLog`, { - method: 'POST', - data, +// 获取服务版本操作指南 +export function getServiceVersionDocsReq(id: any) { + return request(`/api/mmp/service/getServiceVersionDocs/${id}`, { + method: 'GET', + }); +} + +// 获取服务版本日志 +export function getServiceVersionLogReq(params: any) { + return request(`/api/mmp/service/getServiceVersionLog`, { + method: 'GET', + params, }); } diff --git a/react-ui/src/utils/sessionStorage.ts b/react-ui/src/utils/sessionStorage.ts index dbb4de4f..c1a1e59e 100644 --- a/react-ui/src/utils/sessionStorage.ts +++ b/react-ui/src/utils/sessionStorage.ts @@ -1,7 +1,9 @@ // 用于新建镜像 export const mirrorNameKey = 'mirror-name'; -// 模型部署 -export const modelDeploymentInfoKey = 'model-deployment-info'; +// 模型部署服务 +export const serviceInfoKey = 'service-info'; +// 模型部署服务版本 +export const serviceVersionInfoKey = 'service-version-info'; // 编辑器 url export const editorUrlKey = 'editor-url'; // 数据集、模型资源