|
- /*
- * @Author: 赵伟
- * @Date: 2024-04-16 13:58:08
- * @Description: 创建模型部署
- */
- import KFIcon from '@/components/KFIcon';
- import PageTitle from '@/components/PageTitle';
- import ResourceSelect, {
- requiredValidator,
- type ParameterInputObject,
- } from '@/components/ResourceSelect';
- import SubAreaTitle from '@/components/SubAreaTitle';
- import { CommonTabKeys } from '@/enums';
- import { useComputingResource } from '@/hooks/resource';
- import { ResourceSelectorType } from '@/pages/Pipeline/components/ResourceSelectorModal';
- import {
- createModelDeploymentReq,
- restartModelDeploymentReq,
- updateModelDeploymentReq,
- } from '@/services/modelDeployment';
- import { camelCaseToUnderscore, underscoreToCamelCase } from '@/utils';
- import { to } from '@/utils/promise';
- import {
- getSessionStorageItem,
- modelDeploymentInfoKey,
- removeSessionStorageItem,
- } from '@/utils/sessionStorage';
- import { modalConfirm } from '@/utils/ui';
- import { useNavigate } from '@umijs/max';
- import { App, Button, Col, Flex, Form, Input, Row, Select } from 'antd';
- import { omit, pick } from 'lodash';
- import { useEffect, useState } from 'react';
- import { ModelDeploymentData, ModelDeploymentOperationType } from '../types';
- import styles from './index.less';
-
- // 表单数据
- export type FormData = {
- serviceName: string; // 服务名称
- description: string; // 描述
- model: ParameterInputObject; // 模型
- image: ParameterInputObject; // 镜像
- resource: string; // 资源规格
- replicas: string; // 副本数量
- modelPath: string; // 模型路径
- env: { key: string; value: string }[]; // 环境变量
- };
-
- function ModelDeploymentCreate() {
- const navgite = useNavigate();
- const [form] = Form.useForm();
- const [resourceStandardList, filterResourceStandard] = useComputingResource();
- const [operationType, setOperationType] = useState(ModelDeploymentOperationType.Create);
- const [modelDeploymentInfo, setModelDeploymentInfo] = useState<ModelDeploymentData | undefined>(
- undefined,
- );
- const { message } = App.useApp();
-
- useEffect(() => {
- const res = getSessionStorageItem(modelDeploymentInfoKey, true);
- if (res) {
- setOperationType(res.operationType);
- setModelDeploymentInfo(res);
- const formData = underscoreToCamelCase(res) as FormData;
- form.setFieldsValue(formData);
- }
- return () => {
- removeSessionStorageItem(modelDeploymentInfoKey);
- };
- }, []);
-
- // 创建
- const createModelDeployment = async (formData: FormData) => {
- const envList = formData['env'] ?? [];
- const image = formData['image'];
- const model = formData['model'];
- const env = envList.reduce((acc, cur) => {
- acc[cur.key] = cur.value;
- return acc;
- }, {} as Record<string, string>);
-
- // 根据后台要求,修改表单数据
- const object = camelCaseToUnderscore({
- ...omit(formData, ['replicas', 'env', 'image', 'model']),
- replicas: Number(formData.replicas),
- env,
- image: image.value,
- model: pick(model, ['id', 'version', 'path', 'showValue']),
- });
-
- const params =
- operationType === ModelDeploymentOperationType.Create
- ? object
- : {
- ...pick(modelDeploymentInfo, ['service_id', 'service_ins_id']),
- update_model: {
- ...pick(object, ['description', 'env', 'replicas', 'resource', 'image']),
- },
- };
-
- 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('操作成功');
- navgite(-1);
- }
- };
-
- // 提交
- const handleSubmit = (values: FormData) => {
- createModelDeployment(values);
- };
-
- // 取消
- const cancel = () => {
- navgite(-1);
- };
-
- const disabled = operationType !== ModelDeploymentOperationType.Create;
- let buttonText = '新建';
- if (operationType === ModelDeploymentOperationType.Update) {
- buttonText = '更新';
- } else if (operationType === ModelDeploymentOperationType.Restart) {
- buttonText = '重启';
- }
-
- return (
- <div className={styles['model-deployment-create']}>
- <PageTitle title="创建推理服务"></PageTitle>
- <div className={styles['model-deployment-create__content']}>
- <div>
- <Form
- name="model-deployment-create"
- labelCol={{ flex: '100px' }}
- labelAlign="left"
- form={form}
- initialValues={{ upload_type: CommonTabKeys.Public }}
- onFinish={handleSubmit}
- size="large"
- autoComplete="off"
- >
- <SubAreaTitle
- title="基本信息"
- image={require('@/assets/img/mirror-basic.png')}
- style={{ marginBottom: '26px' }}
- ></SubAreaTitle>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="服务名称"
- name="serviceName"
- rules={[
- {
- required: true,
- message: '请输入服务名称',
- },
- ]}
- >
- <Input
- placeholder="请输入服务名称"
- disabled={disabled}
- maxLength={30}
- showCount
- allowClear
- />
- </Form.Item>
- </Col>
- </Row>
- <Row gutter={8}>
- <Col span={20}>
- <Form.Item
- label="描 述"
- name="description"
- rules={[
- {
- required: true,
- message: '请输入描述',
- },
- ]}
- >
- <Input.TextArea
- autoSize={{ minRows: 2, maxRows: 6 }}
- placeholder="请输入描述,最长128字符"
- maxLength={128}
- showCount
- allowClear
- />
- </Form.Item>
- </Col>
- </Row>
- <SubAreaTitle
- title="部署构建"
- image={require('@/assets/img/model-deployment.png')}
- style={{ marginTop: '20px', marginBottom: '24px' }}
- ></SubAreaTitle>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="选择模型"
- name="model"
- rules={[
- {
- validator: requiredValidator,
- message: '请选择模型',
- },
- ]}
- required
- >
- <ResourceSelect
- type={ResourceSelectorType.Model}
- placeholder="请选择模型"
- disabled={disabled}
- canInput={false}
- size="large"
- />
- </Form.Item>
- </Col>
- </Row>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="选择镜像"
- name="image"
- rules={[
- {
- validator: requiredValidator,
- message: '请选择镜像',
- },
- ]}
- required
- >
- <ResourceSelect
- type={ResourceSelectorType.Mirror}
- placeholder="请选择镜像"
- canInput={false}
- size="large"
- />
- </Form.Item>
- </Col>
- </Row>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="资源规格"
- name="resource"
- rules={[
- {
- required: true,
- message: '请选择资源规格',
- },
- ]}
- >
- <Select
- showSearch
- placeholder="请选择资源规格"
- filterOption={filterResourceStandard}
- options={resourceStandardList}
- fieldNames={{
- label: 'description',
- value: 'standard',
- }}
- />
- </Form.Item>
- </Col>
- </Row>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="副本数量"
- name="replicas"
- rules={[
- {
- required: true,
- message: '请输入副本数量',
- },
- {
- pattern: /^-?\d+(\.\d+)?$/,
- message: '副本数量必须是数字',
- },
- ]}
- >
- <Input placeholder="请输入副本数量" allowClear />
- </Form.Item>
- </Col>
- </Row>
-
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item
- label="挂载路径"
- name="modelPath"
- rules={[
- {
- required: true,
- message: '请输入模型挂载路径',
- },
- ]}
- >
- <Input
- placeholder="请输入模型挂载路径"
- disabled={disabled}
- maxLength={64}
- showCount
- allowClear
- />
- </Form.Item>
- </Col>
- </Row>
-
- <Form.List name="env">
- {(fields, { add, remove }) => (
- <>
- <Row gutter={8}>
- <Col span={10}>
- <Form.Item label="环境变量">
- <Button type="link" style={{ padding: '0' }} onClick={() => add()}>
- 添加环境变量
- </Button>
- </Form.Item>
- </Col>
- </Row>
- {fields.map(({ key, name, ...restField }) => (
- <Flex key={key} align="center" gap="0 8px" style={{ width: '50%' }}>
- <Form.Item
- {...restField}
- name={[name, 'key']}
- style={{ flex: 1 }}
- rules={[{ required: true, message: '请输入变量名' }]}
- >
- <Input placeholder="请输入变量名" />
- </Form.Item>
- <span style={{ marginBottom: '24px' }}>=</span>
- <Form.Item
- {...restField}
- name={[name, 'value']}
- style={{ flex: 1 }}
- rules={[{ required: true, message: '请输入变量值' }]}
- >
- <Input placeholder="请输入变量值" />
- </Form.Item>
- <Button
- type="link"
- style={{ marginBottom: '24px' }}
- icon={<KFIcon type="icon-shanchu" font={16} />}
- onClick={() => {
- modalConfirm({
- content: '是否确认删除?',
- onOk: () => {
- remove(name);
- },
- });
- }}
- ></Button>
- </Flex>
- ))}
- </>
- )}
- </Form.List>
-
- <Form.Item wrapperCol={{ offset: 0, span: 16 }}>
- <Button type="primary" htmlType="submit">
- {buttonText}
- </Button>
- <Button
- type="default"
- htmlType="button"
- onClick={cancel}
- style={{ marginLeft: '20px' }}
- >
- 取消
- </Button>
- </Form.Item>
- </Form>
- </div>
- </div>
- </div>
- );
- }
-
- export default ModelDeploymentCreate;
|