From 89bf402ec3ac4e6b70258c6136fc292ba187c040 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Thu, 10 Oct 2024 09:42:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E9=83=A8=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/routes.ts | 16 +- react-ui/src/assets/img/service-version.png | Bin 0 -> 852 bytes react-ui/src/components/BasicInfo/index.tsx | 2 +- react-ui/src/components/CodeSelect/index.less | 11 + react-ui/src/components/CodeSelect/index.tsx | 71 +++ .../src/components/ParameterInput/index.tsx | 6 + .../src/components/ParameterSelect/index.tsx | 6 + .../src/components/ResourceSelect/index.tsx | 10 +- react-ui/src/enums/index.ts | 33 +- .../Dataset/components/ResourceInfo/index.tsx | 2 +- .../{Create => CreateService}/index.less | 0 .../{CreateServer => CreateService}/index.tsx | 100 ++-- .../index.less | 2 +- .../{Create => CreateVersion}/index.tsx | 250 +++++++--- .../src/pages/ModelDeployment/List/index.tsx | 186 +++----- .../ModelDeployment/ServerInfo/index.less | 38 -- .../ModelDeployment/ServerInfo/index.tsx | 76 ---- .../ModelDeployment/ServiceInfo/index.less | 24 + .../ModelDeployment/ServiceInfo/index.tsx | 430 ++++++++++++++++++ .../{Info => VersionInfo}/index.less | 2 +- .../{Info => VersionInfo}/index.tsx | 49 +- .../components/BasicInfo/index.tsx | 68 ++- .../ModelDeployStatusCell/index.tsx | 20 +- .../components/ServerLog/index.tsx | 11 +- .../components/UserGuide/index.tsx | 10 +- react-ui/src/pages/ModelDeployment/types.ts | 61 ++- .../components/CodeSelectorModal/index.tsx | 2 + .../components/PipelineNodeDrawer/index.tsx | 1 - .../src/services/modelDeployment/index.ts | 105 +++-- react-ui/src/utils/sessionStorage.ts | 6 +- 30 files changed, 1091 insertions(+), 507 deletions(-) create mode 100644 react-ui/src/assets/img/service-version.png create mode 100644 react-ui/src/components/CodeSelect/index.less create mode 100644 react-ui/src/components/CodeSelect/index.tsx rename react-ui/src/pages/ModelDeployment/{Create => CreateService}/index.less (100%) rename react-ui/src/pages/ModelDeployment/{CreateServer => CreateService}/index.tsx (59%) rename react-ui/src/pages/ModelDeployment/{CreateServer => CreateVersion}/index.less (92%) rename react-ui/src/pages/ModelDeployment/{Create => CreateVersion}/index.tsx (57%) delete mode 100644 react-ui/src/pages/ModelDeployment/ServerInfo/index.less delete mode 100644 react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx create mode 100644 react-ui/src/pages/ModelDeployment/ServiceInfo/index.less create mode 100644 react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx rename react-ui/src/pages/ModelDeployment/{Info => VersionInfo}/index.less (96%) rename react-ui/src/pages/ModelDeployment/{Info => VersionInfo}/index.tsx (56%) diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index 88502bdf..66de518b 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -222,23 +222,23 @@ export default [ }, { name: '服务详情', - path: 'serverInfo/:id', - component: './ModelDeployment/Info', + path: 'serviceInfo/:id', + component: './ModelDeployment/ServiceInfo', }, { - name: '模型部署详情', - path: 'info/:id', - component: './ModelDeployment/Info', + name: '服务版本详情', + path: 'versionInfo/:id', + component: './ModelDeployment/VersionInfo', }, { name: '创建推理服务', - path: 'create', - component: './ModelDeployment/CreateServer', + path: 'createService', + component: './ModelDeployment/CreateService', }, { name: '新增服务版本', path: 'addVersion/:id', - component: './ModelDeployment/Create', + 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 0000000000000000000000000000000000000000..08361ac9b70ed731a58c886e938c86de9433f79e GIT binary patch literal 852 zcmV-a1FQUrP);4+V}JYi?9A+rAfv6Wx^*GQ z!%@NCj(KfH=Yf}( z^@te!}VNUqOrDq6XuRs3rX})}b9wI*%9V2tn&k(sgx1 z%SqL?4$Wp!B07kxde*@(61JH@BmC}qlA1-d|JojG}I;$0`An|Fh;2t8TIC-uXEV3sl{zqx!~? zRqYF^>K32GDqLyJ&)V}`*+LzWw~wb4+rCknv(|Ca7c(#_wwu$6t$q=kicuR^lXJ#x eV${Zan&l@Q3)|(|WmX3O0000{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/ModelDeployment/Create/index.less b/react-ui/src/pages/ModelDeployment/CreateService/index.less similarity index 100% rename from react-ui/src/pages/ModelDeployment/Create/index.less rename to react-ui/src/pages/ModelDeployment/CreateService/index.less diff --git a/react-ui/src/pages/ModelDeployment/CreateServer/index.tsx b/react-ui/src/pages/ModelDeployment/CreateService/index.tsx similarity index 59% rename from react-ui/src/pages/ModelDeployment/CreateServer/index.tsx rename to react-ui/src/pages/ModelDeployment/CreateService/index.tsx index 74072f52..a827828f 100644 --- a/react-ui/src/pages/ModelDeployment/CreateServer/index.tsx +++ b/react-ui/src/pages/ModelDeployment/CreateService/index.tsx @@ -1,82 +1,63 @@ /* * @Author: 赵伟 * @Date: 2024-04-16 13:58:08 - * @Description: 创建模型部署 + * @Description: 创建推理服务 */ + import PageTitle from '@/components/PageTitle'; import SubAreaTitle from '@/components/SubAreaTitle'; -import { CommonTabKeys } from '@/enums'; -import { - createModelDeploymentReq, - restartModelDeploymentReq, - updateModelDeploymentReq, -} from '@/services/modelDeployment'; -import { camelCaseToUnderscore, underscoreToCamelCase } from '@/utils'; +import { CommonTabKeys, serviceTypeOptions } from '@/enums'; +import { createServiceReq, updateServiceReq } from '@/services/modelDeployment'; import { to } from '@/utils/promise'; import { getSessionStorageItem, - modelDeploymentInfoKey, removeSessionStorageItem, + serviceInfoKey, } from '@/utils/sessionStorage'; import { useNavigate } from '@umijs/max'; -import { App, Button, Col, Form, Input, Row } from 'antd'; +import { App, Button, Col, Form, Input, Row, Select } from 'antd'; import { pick } from 'lodash'; import { useEffect, useState } from 'react'; -import { ModelDeploymentData, ModelDeploymentOperationType } from '../types'; +import { ServiceData, ServiceOperationType } from '../types'; import styles from './index.less'; // 表单数据 export type FormData = { - serviceName: string; // 服务名称 - serviceVersion: string; // 服务版本 + service_name: string; // 服务名称 + service_type: string; // 服务类型 description: string; // 描述 }; -function ModelDeploymentCreate() { +function CreateService() { const navigate = useNavigate(); const [form] = Form.useForm(); - const [operationType, setOperationType] = useState(ModelDeploymentOperationType.Create); - const [modelDeploymentInfo, setModelDeploymentInfo] = useState( - undefined, - ); + const [operationType, setOperationType] = useState(ServiceOperationType.Create); + const [serviceInfo, setServiceInfo] = useState(undefined); const { message } = App.useApp(); useEffect(() => { - const res = getSessionStorageItem(modelDeploymentInfoKey, true); + const res = getSessionStorageItem(serviceInfoKey, true); if (res) { setOperationType(res.operationType); - setModelDeploymentInfo(res); - const formData = underscoreToCamelCase(res) as FormData; - form.setFieldsValue(formData); + setServiceInfo(res); + form.setFieldsValue(pick(res, ['service_name', 'service_type', 'description'])); } return () => { - removeSessionStorageItem(modelDeploymentInfoKey); + removeSessionStorageItem(serviceInfoKey); }; }, []); - // 创建 - const createModelDeployment = async (formData: FormData) => { - // 根据后台要求,修改表单数据 - const object = camelCaseToUnderscore({ - ...formData, - }); - + // 创建、更新服务 + const createService = async (formData: FormData) => { + const request = + operationType === ServiceOperationType.Create ? createServiceReq : updateServiceReq; const params = - operationType === ModelDeploymentOperationType.Create - ? object + operationType === ServiceOperationType.Create + ? formData : { - ...pick(modelDeploymentInfo, ['service_id', 'service_ins_id']), - update_model: { - ...pick(object, ['description', 'env', 'replicas', 'resource', 'image']), - }, + id: serviceInfo?.id, + ...formData, }; - - let request = createModelDeploymentReq; - if (operationType === ModelDeploymentOperationType.Restart) { - request = restartModelDeploymentReq; - } else if (operationType === ModelDeploymentOperationType.Update) { - request = updateModelDeploymentReq; - } const [res] = await to(request(params)); if (res) { message.success('操作成功'); @@ -86,7 +67,7 @@ function ModelDeploymentCreate() { // 提交 const handleSubmit = (values: FormData) => { - createModelDeployment(values); + createService(values); }; // 取消 @@ -94,17 +75,12 @@ function ModelDeploymentCreate() { navigate(-1); }; - const disabled = operationType !== ModelDeploymentOperationType.Create; - let buttonText = '新建'; - if (operationType === ModelDeploymentOperationType.Update) { - buttonText = '更新'; - } else if (operationType === ModelDeploymentOperationType.Restart) { - buttonText = '重启'; - } + 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.map(({ key, name, ...restField }) => ( @@ -329,9 +430,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: + '变量名只支持字母、数字、下划线、中横线且开头必须是字母或下划线', + }, + ]} > - + = - + ))} + )} @@ -381,4 +499,4 @@ function ModelDeploymentCreate() { ); } -export default ModelDeploymentCreate; +export default CreateServiceVersion; diff --git a/react-ui/src/pages/ModelDeployment/List/index.tsx b/react-ui/src/pages/ModelDeployment/List/index.tsx index b93e3166..f0e4cb70 100644 --- a/react-ui/src/pages/ModelDeployment/List/index.tsx +++ b/react-ui/src/pages/ModelDeployment/List/index.tsx @@ -1,22 +1,18 @@ /* * @Author: 赵伟 * @Date: 2024-04-16 13:58:08 - * @Description: 模型部署列表 + * @Description: 模型部署服务列表 */ import CommonTableCell from '@/components/CommonTableCell'; import DateTableCell from '@/components/DateTableCell'; import KFIcon from '@/components/KFIcon'; import PageTitle from '@/components/PageTitle'; -import { ModelDeploymentStatus, modelDeploymentStatusOptions } from '@/enums'; +import { serviceTypeOptions } from '@/enums'; import { useCacheState } from '@/hooks/pageCacheState'; -import { - deleteModelDeploymentReq, - getModelDeploymentListReq, - stopModelDeploymentReq, -} from '@/services/modelDeployment'; +import { deleteServiceReq, getServiceListReq } from '@/services/modelDeployment'; import themes from '@/styles/theme.less'; import { to } from '@/utils/promise'; -import { modelDeploymentInfoKey, setSessionStorageItem } from '@/utils/sessionStorage'; +import { serviceInfoKey, setSessionStorageItem } from '@/utils/sessionStorage'; import { modalConfirm } from '@/utils/ui'; import { useNavigate } from '@umijs/max'; import { @@ -31,20 +27,20 @@ import { } from 'antd'; import { type SearchProps } from 'antd/es/input'; import classNames from 'classnames'; -import { pick } from 'lodash'; import { useEffect, useState } from 'react'; -import ModelDeploymentStatusCell from '../components/ModelDeployStatusCell'; -import { ModelDeploymentData, ModelDeploymentOperationType } from '../types'; +import { ServiceData, ServiceOperationType } from '../types'; import styles from './index.less'; +const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions]; + function ModelDeployment() { const navigate = useNavigate(); const { message } = App.useApp(); const [cacheState, setCacheState] = useCacheState(); - const [searchStatus, setSearchStatus] = useState(cacheState?.searchStatus ?? ''); + const [serviceType, setServiceType] = useState(cacheState?.serviceType ?? ''); const [searchText, setSearchText] = useState(cacheState?.searchText); const [inputText, setInputText] = useState(cacheState?.searchText); - const [tableData, setTableData] = useState([]); + const [tableData, setTableData] = useState([]); const [total, setTotal] = useState(0); const [pagination, setPagination] = useState( cacheState?.pagination ?? { @@ -54,29 +50,28 @@ function ModelDeployment() { ); useEffect(() => { - getModelDeploymentList(); - }, [pagination, searchText, searchStatus]); + getServiceList(); + }, [pagination, searchText, serviceType]); - // 获取模型部署列表 - const getModelDeploymentList = async () => { + // 获取模型部署服务列表 + const getServiceList = async () => { const params: Record = { - page: pagination.current!, + page: pagination.current! - 1, size: pagination.pageSize, service_name: searchText, - status: searchStatus, + service_type: serviceType, }; - const [res] = await to(getModelDeploymentListReq(params)); + const [res] = await to(getServiceListReq(params)); if (res && res.data) { - const { service_list = [], total = 0 } = res.data; - setTableData(service_list); - setTotal(total); + const { content = [], totalElements = 0 } = res.data; + setTableData(content); + setTotal(totalElements); } }; // 删除模型部署 - const deleteModelDeploy = async (record: ModelDeploymentData) => { - const params = pick(record, ['service_id', 'service_ins_id']); - const [res] = await to(deleteModelDeploymentReq(params)); + const deleteService = async (record: ServiceData) => { + const [res] = await to(deleteServiceReq(record.id)); if (res) { message.success('删除成功'); // 如果是一页的唯一数据,删除时,请求第一页的数据 @@ -88,54 +83,31 @@ function ModelDeployment() { current: 1, })); } else { - getModelDeploymentList(); + getServiceList(); } } }; - // 停止模型部署 - const stopModelDeploy = async (record: ModelDeploymentData) => { - const params = pick(record, ['service_id', 'service_ins_id']); - const [res] = await to(stopModelDeploymentReq(params)); - if (res) { - message.success('操作成功'); - getModelDeploymentList(); - } - }; - // 搜索 const onSearch: SearchProps['onSearch'] = (value) => { setSearchText(value); }; // 处理删除 - const handleModelDeployDelete = (record: ModelDeploymentData) => { + const handleServiceDelete = (record: ServiceData) => { modalConfirm({ - title: '删除后,该模型部署将不可恢复', + title: '删除后,该服务将不可恢复', content: '是否确认删除?', onOk: () => { - deleteModelDeploy(record); + deleteService(record); }, }); }; - // 处理停止 - const handleModelDeployStop = async (record: ModelDeploymentData) => { - modalConfirm({ - content: '是否确认停止?', - onOk: () => { - stopModelDeploy(record); - }, - }); - }; - - // 创建、更新、重启模型部署 - const createModelDeployment = ( - type: ModelDeploymentOperationType, - record?: ModelDeploymentData, - ) => { + // 创建、更新服务 + const createService = (type: ServiceOperationType, record?: ServiceData) => { setSessionStorageItem( - modelDeploymentInfoKey, + serviceInfoKey, { ...record, operationType: type, @@ -146,23 +118,23 @@ function ModelDeployment() { setCacheState({ pagination, searchText, - searchStatus, + serviceType: serviceType, }); - navigate(`/modelDeployment/create`); + navigate(`/modelDeployment/createService`); }; // 查看详情 - const toDetail = (record: ModelDeploymentData) => { - setSessionStorageItem(modelDeploymentInfoKey, record, true); + const toDetail = (record: ServiceData) => { + setSessionStorageItem(serviceInfoKey, record, true); setCacheState({ pagination, searchText, - searchStatus, + serviceType: serviceType, }); - navigate(`/modelDeployment/info/${record.service_id}`); + navigate(`/modelDeployment/serviceInfo/${record.id}`); }; // 分页切换 @@ -173,7 +145,7 @@ function ModelDeployment() { // console.log(pagination, filters, sorter, action); }; - const columns: TableProps['columns'] = [ + const columns: TableProps['columns'] = [ { title: '序号', dataIndex: 'index', @@ -197,23 +169,23 @@ function ModelDeployment() { }, }, { - title: '模型', - dataIndex: ['model', 'show_value'], - key: 'model', + title: '服务类型', + dataIndex: 'service_type_name', + key: 'service_type_name', width: '20%', render: CommonTableCell(), }, { - title: '状态', - dataIndex: 'status', - key: 'status', + title: '版本数量', + dataIndex: 'version_count', + key: 'version_count', width: '20%', - render: ModelDeploymentStatusCell, + render: CommonTableCell(), }, { - title: '创建人', - dataIndex: 'created_by', - key: 'created_by', + title: '服务描述', + dataIndex: 'description', + key: 'description', render: CommonTableCell(), width: '20%', }, @@ -227,44 +199,28 @@ function ModelDeployment() { { title: '操作', dataIndex: 'operation', - width: 250, + width: 300, key: 'operation', - render: (_: any, record: ModelDeploymentData) => ( + render: (_: any, record: ServiceData) => (
+ - {(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/ServerInfo/index.less b/react-ui/src/pages/ModelDeployment/ServerInfo/index.less deleted file mode 100644 index 4dcf90d9..00000000 --- a/react-ui/src/pages/ModelDeployment/ServerInfo/index.less +++ /dev/null @@ -1,38 +0,0 @@ -.model-deployment-info { - height: 100%; - - &__content { - display: flex; - flex-direction: column; - height: calc(100% - 60px); - margin-top: 10px; - padding: 30px 30px 0; - background-color: white; - border-radius: 10px; - - &__tabs { - flex: 1; - min-height: 0; - margin-top: 20px; - padding-bottom: 10px; - - :global { - .ant-tabs { - height: 100%; - - .ant-tabs-nav { - margin-bottom: 10px; - } - - .ant-tabs-content { - height: 100%; - - .ant-tabs-tabpane { - height: 100%; - } - } - } - } - } - } -} diff --git a/react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx b/react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx deleted file mode 100644 index 4f73f46f..00000000 --- a/react-ui/src/pages/ModelDeployment/ServerInfo/index.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/* - * @Author: 赵伟 - * @Date: 2024-04-16 13:58:08 - * @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 { Tabs, type TabsProps } from 'antd'; -import { useState } from 'react'; -import BasicInfo from '../components/BasicInfo'; -import ServerLog from '../components/ServerLog'; -import UserGuide from '../components/UserGuide'; -import { ModelDeploymentData } from '../types'; -import styles from './index.less'; - -export enum ModelDeploymentTabKey { - Predict = 'Predict', // 预测 - Guide = 'Guide', // 调用指南 - Log = 'Log', // 服务日志 -} - -function ModelDeploymentInfo() { - const [activeTab, setActiveTab] = useState(ModelDeploymentTabKey.Predict); - const [modelDeployementInfo] = useSessionStorage( - modelDeploymentInfoKey, - true, - undefined, - ); - - const tabItems = [ - { - key: ModelDeploymentTabKey.Predict, - label: '预测', - icon: , - }, - { - key: ModelDeploymentTabKey.Guide, - label: '调用指南', - icon: , - children: , - }, - { - key: ModelDeploymentTabKey.Log, - label: '服务日志', - icon: , - children: , - }, - ]; - - // 切换 Tab,重置数据 - const hanleTabChange: TabsProps['onChange'] = (value) => { - setActiveTab(value); - }; - - return ( -
- -
- - -
- -
-
-
- ); -} - -export default ModelDeploymentInfo; 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..a27cf50f --- /dev/null +++ b/react-ui/src/pages/ModelDeployment/ServiceInfo/index.tsx @@ -0,0 +1,430 @@ +/* + * @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({ + 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/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'; // 数据集、模型资源