Browse Source

feat: 机器学习添加文本分类

pull/207/head
zhaowei 6 months ago
parent
commit
75ed802a7f
41 changed files with 506 additions and 245 deletions
  1. +4
    -4
      react-ui/.eslintrc.js
  2. +1
    -0
      react-ui/.prettierignore
  3. +3
    -3
      react-ui/.storybook/babel-plugin-auto-css-modules.js
  4. +5
    -5
      react-ui/.storybook/mock/websocket.mock.js
  5. +1
    -1
      react-ui/README.md
  6. +2
    -2
      react-ui/src/components/CopyingText/clipboard.js
  7. +14
    -0
      react-ui/src/enums/index.ts
  8. +16
    -17
      react-ui/src/pages/ActiveLearn/Create/index.tsx
  9. +8
    -9
      react-ui/src/pages/ActiveLearn/Info/index.tsx
  10. +1
    -1
      react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx
  11. +2
    -4
      react-ui/src/pages/ActiveLearn/components/CreateForm/utils.ts
  12. +5
    -6
      react-ui/src/pages/ActiveLearn/types.ts
  13. +32
    -10
      react-ui/src/pages/AutoML/Create/index.tsx
  14. +9
    -1
      react-ui/src/pages/AutoML/Info/index.tsx
  15. +144
    -102
      react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx
  16. +13
    -3
      react-ui/src/pages/AutoML/components/CreateForm/BasicConfig.tsx
  17. +137
    -0
      react-ui/src/pages/AutoML/components/CreateForm/TextExecuteConfig.tsx
  18. +1
    -1
      react-ui/src/pages/AutoML/components/ExperimentHistory/index.tsx
  19. +2
    -2
      react-ui/src/pages/AutoML/components/ExperimentList/config.ts
  20. +16
    -1
      react-ui/src/pages/AutoML/components/ExperimentList/index.tsx
  21. +9
    -2
      react-ui/src/pages/AutoML/types.ts
  22. +1
    -1
      react-ui/src/pages/HyperParameter/components/ExperimentHistory/index.less
  23. +1
    -1
      react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx
  24. +9
    -10
      react-ui/src/pages/HyperParameter/components/TrialFileTree/index.less
  25. +1
    -1
      react-ui/src/pages/Model/components/ModelMetrics/index.tsx
  26. +2
    -6
      react-ui/src/pages/ModelDeployment/List/index.tsx
  27. +1
    -1
      react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx
  28. +1
    -1
      react-ui/src/pages/System/User/edit.tsx
  29. +1
    -3
      react-ui/src/services/activeLearn/index.js
  30. +1
    -1
      react-ui/src/services/auth/index.js
  31. +12
    -14
      react-ui/src/services/autoML/index.js
  32. +2
    -2
      react-ui/src/services/codeConfig/index.js
  33. +5
    -9
      react-ui/src/services/dataset/index.js
  34. +3
    -3
      react-ui/src/services/experiment/index.js
  35. +2
    -3
      react-ui/src/services/file/index.js
  36. +2
    -3
      react-ui/src/services/hyperParameter/index.js
  37. +2
    -2
      react-ui/src/services/pipeline/index.js
  38. +0
    -1
      react-ui/src/utils/IconUtil.ts
  39. +10
    -4
      react-ui/src/utils/downloadfile.ts
  40. +9
    -4
      react-ui/src/utils/format.ts
  41. +16
    -1
      react-ui/src/utils/table.tsx

+ 4
- 4
react-ui/.eslintrc.js View File

@@ -1,8 +1,8 @@
module.exports = {
extends: [
require.resolve('@umijs/lint/dist/config/eslint'),
'plugin:react/recommended',
"plugin:react-hooks/recommended"
require.resolve('@umijs/lint/dist/config/eslint'),
'plugin:react/recommended',
'plugin:react-hooks/recommended',
],
globals: {
page: true,
@@ -11,6 +11,6 @@ module.exports = {
rules: {
'@typescript-eslint/no-use-before-define': 'off',
'react/react-in-jsx-scope': 'off',
'react/display-name': 'off'
'react/display-name': 'off',
},
};

+ 1
- 0
react-ui/.prettierignore View File

@@ -20,3 +20,4 @@ yarn-error.log
CNAME
/build
/public
/src/iconfont/

+ 3
- 3
react-ui/.storybook/babel-plugin-auto-css-modules.js View File

@@ -1,4 +1,4 @@
export default function(babel) {
export default function (babel) {
const { types: t } = babel;
return {
visitor: {
@@ -6,10 +6,10 @@ export default function(babel) {
const source = path.node.source.value;
if (source.endsWith('.less')) {
if (path.node.specifiers.length > 0) {
path.node.source.value += "?modules";
path.node.source.value += '?modules';
}
}
},
},
};
};
}

+ 5
- 5
react-ui/.storybook/mock/websocket.mock.js View File

@@ -6,7 +6,7 @@ export const createWebSocketMock = () => {
this.listeners = {};
this.count = 0;

console.log("Mock WebSocket connected to:", url);
console.log('Mock WebSocket connected to:', url);

// 模拟服务器推送消息
this.intervalId = setInterval(() => {
@@ -21,8 +21,8 @@ export const createWebSocketMock = () => {
}

sendMessage(data) {
if (this.listeners["message"]) {
this.listeners["message"].forEach((callback) => callback({ data }));
if (this.listeners['message']) {
this.listeners['message'].forEach((callback) => callback({ data }));
}
}

@@ -41,7 +41,7 @@ export const createWebSocketMock = () => {

close() {
this.readyState = WebSocket.CLOSED;
console.log("Mock WebSocket closed");
console.log('Mock WebSocket closed');
}
}

@@ -89,4 +89,4 @@ export const logStreamData = {
],
},
],
};
};

+ 1
- 1
react-ui/README.md View File

@@ -1 +1 @@
# Documentation
# Documentation

+ 2
- 2
react-ui/src/components/CopyingText/clipboard.js View File

@@ -1,5 +1,5 @@
import { message } from 'antd';
import ClipboardJS from 'clipboard';
import { message } from "antd";

const clipboard = new ClipboardJS('#copying');

@@ -9,4 +9,4 @@ clipboard.on('success', () => {

clipboard.on('error', () => {
message.error('复制失败');
});
});

+ 14
- 0
react-ui/src/enums/index.ts View File

@@ -86,6 +86,19 @@ export const serviceTypeOptions = [
{ label: '文本', value: ServiceType.Text },
];

// 自动化类型
export enum AutoMLType {
Table = 'auto_ml',
Text = 'text_classification',
Video = 'video_classification',
}

export const autoMLTypeOptions = [
{ label: '表格', value: AutoMLType.Table },
{ label: '文本分类', value: AutoMLType.Text },
{ label: '视频分类', value: AutoMLType.Video },
];

// 自动化任务类型
export enum AutoMLTaskType {
Classification = 'classification',
@@ -148,4 +161,5 @@ export enum AutoMLTrailStatus {
CRASHED = 'CRASHED', // 崩溃
STOP = 'STOP', // 停止
CANCELLED = 'CANCELLED', // 取消
MEMOUT = 'MEMOUT', // 内存溢出
}

+ 16
- 17
react-ui/src/pages/ActiveLearn/Create/index.tsx View File

@@ -30,27 +30,26 @@ function CreateActiveLearn() {
const isCopy = pathname.includes('copy');

useEffect(() => {
// 获取服务详情
const getActiveLearnInfo = async (id: number) => {
const [res] = await to(getActiveLearnInfoReq({ id }));
if (res && res.data) {
const info: ActiveLearnData = res.data;
const { name: name_str, ...rest } = info;
const name = isCopy ? `${name_str}-copy` : name_str;
const formData = {
...rest,
name,
};

form.setFieldsValue(formData);
}
};
// 编辑,复制
if (id && !Number.isNaN(id)) {
getActiveLearnInfo(id);
}
}, [id]);

// 获取服务详情
const getActiveLearnInfo = async (id: number) => {
const [res] = await to(getActiveLearnInfoReq({ id }));
if (res && res.data) {
const info: ActiveLearnData = res.data;
const { name: name_str, ...rest } = info;
const name = isCopy ? `${name_str}-copy` : name_str;
const formData = {
...rest,
name,
};

form.setFieldsValue(formData);
}
};
}, [id, isCopy, form]);

// 创建、更新、复制实验
const createExperiment = async (formData: FormData) => {


+ 8
- 9
react-ui/src/pages/ActiveLearn/Info/index.tsx View File

@@ -19,18 +19,17 @@ function ActiveLearnInfo() {
const [info, setInfo] = useState<ActiveLearnData | undefined>(undefined);

useEffect(() => {
// 获取详情
const getActiveLearnInfo = async () => {
const [res] = await to(getActiveLearnInfoReq({ id: id }));
if (res && res.data) {
setInfo(res.data);
}
};
if (id) {
getActiveLearnInfo();
}
}, []);

// 获取详情
const getActiveLearnInfo = async () => {
const [res] = await to(getActiveLearnInfoReq({ id: id }));
if (res && res.data) {
setInfo(res.data);
}
};
}, [id]);

return (
<div className={styles['auto-ml-info']}>


+ 1
- 1
react-ui/src/pages/ActiveLearn/components/ActiveLearnBasic/index.tsx View File

@@ -245,7 +245,7 @@ function BasicInfo({ info, className, runStatus, isInstance = false }: BasicInfo
ellipsis: true,
},
];
}, [runStatus]);
}, [runStatus, info]);

return (
<div className={classNames(styles['active-learn-basic'], className)}>


+ 2
- 4
react-ui/src/pages/ActiveLearn/components/CreateForm/utils.ts View File

@@ -39,7 +39,7 @@ export const regressorAlgorithms = [
{
label: 'gaussian_process(高斯回归)',
value: 'gaussian_process',
}
},
];

// 框架类型
@@ -65,7 +65,6 @@ export const frameworkTypeOptions = [
},
];


// 查询策略
export const queryStrategies = [
{
@@ -87,6 +86,5 @@ export const queryStrategies = [
{
label: 'upper_confidence_bound',
value: 'upper_confidence_bound',
}
},
];


+ 5
- 6
react-ui/src/pages/ActiveLearn/types.ts View File

@@ -1,7 +1,7 @@
import { type ParameterInputObject } from '@/components/ResourceSelect';
import { type NodeStatus } from '@/types';
import { AutoMLTaskType } from '@/enums';
import { HyperParameterFile } from '@/pages/HyperParameter/types';
import { type NodeStatus } from '@/types';

// 操作类型
export enum OperationType {
@@ -39,7 +39,6 @@ export type FormData = {
batch_size: number; // batch_size
epochs: number; // epochs
lr: number; // 学习率
};

// 主动学习
@@ -75,8 +74,8 @@ export type ActiveLearnInstanceData = {
update_time: string;
finish_time: string;
nodeStatus?: NodeStatus;
data: string,
trial_list?: ActiveLearnTrial[]
data: string;
trial_list?: ActiveLearnTrial[];
};

export type ActiveLearnTrial = {
@@ -85,8 +84,8 @@ export type ActiveLearnTrial = {
data_num?: number;
accuracy?: number;
mse?: number;
query_idx?: string
query_idx?: string;
file?: HyperParameterFile;
};

export {type HyperParameterFile}
export { type HyperParameterFile };

+ 32
- 10
react-ui/src/pages/AutoML/Create/index.tsx View File

@@ -4,17 +4,19 @@
* @Description: 创建实验
*/
import PageTitle from '@/components/PageTitle';
import { AutoMLEnsembleClass, AutoMLTaskType } from '@/enums';
import { AutoMLEnsembleClass, AutoMLTaskType, AutoMLType } from '@/enums';
import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML';
import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils';
import { safeInvoke } from '@/utils/functional';
import { to } from '@/utils/promise';
import { useLocation, useNavigate, useParams } from '@umijs/max';
import { App, Button, Form } from 'antd';
import { omit } from 'lodash';
import { useEffect } from 'react';
import BasicConfig from '../components/CreateForm/BasicConfig';
import DatasetConfig from '../components/CreateForm/DatasetConfig';
import ExecuteConfig from '../components/CreateForm/ExecuteConfig';
import TextExecuteConfig from '../components/CreateForm/TextExecuteConfig';
import TrialConfig from '../components/CreateForm/TrialConfig';
import { AutoMLData, FormData } from '../types';
import styles from './index.less';
@@ -27,6 +29,7 @@ function CreateAutoML() {
const id = safeInvoke(Number)(params.id);
const { pathname } = useLocation();
const isCopy = pathname.includes('copy');
const type = Form.useWatch('type', form);

useEffect(() => {
// 获取服务详情
@@ -34,6 +37,8 @@ function CreateAutoML() {
const [res] = await to(getAutoMLInfoReq({ id }));
if (res && res.data) {
const autoMLInfo: AutoMLData = res.data;
const { name: name_str, description, type, param } = autoMLInfo;
const paramObj = parseJsonText(param);
const {
include_classifier: include_classifier_str,
include_feature_preprocessor: include_feature_preprocessor_str,
@@ -42,9 +47,8 @@ function CreateAutoML() {
exclude_feature_preprocessor: exclude_feature_preprocessor_str,
exclude_regressor: exclude_regressor_str,
metrics: metrics_str,
ml_name: ml_name_str,
...rest
} = autoMLInfo;
} = paramObj;
const include_classifier = include_classifier_str?.split(',').filter(Boolean);
const include_feature_preprocessor = include_feature_preprocessor_str
?.split(',')
@@ -60,7 +64,7 @@ function CreateAutoML() {
name: key,
value,
}));
const ml_name = isCopy ? `${ml_name_str}-copy` : ml_name_str;
const name = isCopy ? `${name_str}-copy` : name_str;

const formData = {
...rest,
@@ -71,7 +75,9 @@ function CreateAutoML() {
exclude_feature_preprocessor,
exclude_regressor,
metrics,
ml_name,
name,
description,
type,
};

form.setFieldsValue(formData);
@@ -86,6 +92,7 @@ function CreateAutoML() {

// 创建、更新、复制实验
const createExperiment = async (formData: FormData) => {
const { name, description, type } = formData;
const include_classifier = formData['include_classifier']?.join(',');
const include_feature_preprocessor = formData['include_feature_preprocessor']?.join(',');
const include_regressor = formData['include_regressor']?.join(',');
@@ -104,8 +111,8 @@ function CreateAutoML() {
const target_columns = trimCharacter(formData['target_columns'], ',');

// 根据后台要求,修改表单数据
const object = {
...formData,
const param = {
...omit(formData, ['name', 'description', 'type']),
include_classifier: convertEmptyStringToUndefined(include_classifier),
include_feature_preprocessor: convertEmptyStringToUndefined(include_feature_preprocessor),
include_regressor: convertEmptyStringToUndefined(include_regressor),
@@ -116,6 +123,13 @@ function CreateAutoML() {
target_columns,
};

const object = {
name,
description,
type,
param: JSON.stringify(param),
};

const params =
id && !isCopy
? {
@@ -169,6 +183,7 @@ function CreateAutoML() {
autoComplete="off"
scrollToFirstError
initialValues={{
type: AutoMLType.Table,
task_type: AutoMLTaskType.Classification,
shuffle: false,
ensemble_class: AutoMLEnsembleClass.Default,
@@ -186,9 +201,16 @@ function CreateAutoML() {
}}
>
<BasicConfig />
<ExecuteConfig />
<TrialConfig />
<DatasetConfig />

{type === AutoMLType.Table ? (
<>
<ExecuteConfig />
<TrialConfig />
<DatasetConfig />
</>
) : type === AutoMLType.Text ? (
<TextExecuteConfig />
) : null}

<Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}>
<Button type="primary" htmlType="submit">


+ 9
- 1
react-ui/src/pages/AutoML/Info/index.tsx View File

@@ -5,6 +5,7 @@
*/
import PageTitle from '@/components/PageTitle';
import { getAutoMLInfoReq } from '@/services/autoML';
import { parseJsonText } from '@/utils';
import { safeInvoke } from '@/utils/functional';
import { to } from '@/utils/promise';
import { useParams } from '@umijs/max';
@@ -23,7 +24,14 @@ function AutoMLInfo() {
const getAutoMLInfo = async () => {
const [res] = await to(getAutoMLInfoReq({ id: autoMLId }));
if (res && res.data) {
setAutoMLInfo(res.data);
const info = res.data;
const param = info.param;

setAutoMLInfo({
...info,
param: undefined,
...parseJsonText(param),
});
}
};



+ 144
- 102
react-ui/src/pages/AutoML/components/AutoMLBasic/index.tsx View File

@@ -1,5 +1,11 @@
import ConfigInfo, { type BasicInfoData } from '@/components/ConfigInfo';
import { AutoMLTaskType, autoMLEnsembleClassOptions, autoMLTaskTypeOptions } from '@/enums';
import {
AutoMLTaskType,
AutoMLType,
autoMLEnsembleClassOptions,
autoMLTaskTypeOptions,
} from '@/enums';
import { useComputingResource } from '@/hooks/useComputingResource';
import { AutoMLData } from '@/pages/AutoML/types';
import { experimentStatusInfo } from '@/pages/Experiment/status';
import { type NodeStatus } from '@/types';
@@ -37,6 +43,7 @@ type AutoMLBasicProps = {
};

function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLBasicProps) {
const getResourceDescription = useComputingResource()[1];
const basicDatas: BasicInfoData[] = useMemo(() => {
if (!info) {
return [];
@@ -45,11 +52,11 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB
return [
{
label: '实验名称',
value: info.ml_name,
value: info.name,
},
{
label: '实验描述',
value: info.ml_description,
value: info.description,
},
{
label: '创建人',
@@ -72,103 +79,136 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB
if (!info) {
return [];
}
return [
{
label: '任务类型',
value: info.task_type,
format: formatEnum(autoMLTaskTypeOptions),
},
{
label: '特征预处理算法',
value: info.include_feature_preprocessor,
},
{
label: '排除的特征预处理算法',
value: info.exclude_feature_preprocessor,
},
{
label: info.task_type === AutoMLTaskType.Regression ? '回归算法' : '分类算法',
value:
info.task_type === AutoMLTaskType.Regression
? info.include_regressor
: info.include_classifier,
},
{
label: info.task_type === AutoMLTaskType.Regression ? '排除的回归算法' : '排除的分类算法',
value:
info.task_type === AutoMLTaskType.Regression
? info.exclude_regressor
: info.exclude_classifier,
},
{
label: '集成方式',
value: info.ensemble_class,
format: formatEnum(autoMLEnsembleClassOptions),
},
{
label: '集成模型数量',
value: info.ensemble_size,
},
{
label: '集成最佳模型数量',
value: info.ensemble_nbest,
},
{
label: '最大数量',
value: info.max_models_on_disc,
},
{
label: '内存限制(MB)',
value: info.memory_limit,
},
{
label: '单次时间限制(秒)',
value: info.per_run_time_limit,
},
{
label: '搜索时间限制(秒)',
value: info.time_left_for_this_task,
},
{
label: '重采样策略',
value: info.resampling_strategy,
},
{
label: '交叉验证折数',
value: info.folds,
},
{
label: '是否打乱',
value: info.shuffle,
format: formatBoolean,
},
{
label: '训练集比率',
value: info.train_size,
},
{
label: '测试集比率',
value: info.test_size,
},
{
label: '计算指标',
value: info.scoring_functions,
},
{
label: '随机种子',
value: info.seed,
},
{
label: '数据集',
value: info.dataset,
format: formatDataset,
},
{
label: '预测目标列',
value: info.target_columns,
},
];
}, [info]);
if (info.type === AutoMLType.Table) {
return [
{
label: '任务类型',
value: info.task_type,
format: formatEnum(autoMLTaskTypeOptions),
},
{
label: '特征预处理算法',
value: info.include_feature_preprocessor,
},
{
label: '排除的特征预处理算法',
value: info.exclude_feature_preprocessor,
},
{
label: info.task_type === AutoMLTaskType.Regression ? '回归算法' : '分类算法',
value:
info.task_type === AutoMLTaskType.Regression
? info.include_regressor
: info.include_classifier,
},
{
label: info.task_type === AutoMLTaskType.Regression ? '排除的回归算法' : '排除的分类算法',
value:
info.task_type === AutoMLTaskType.Regression
? info.exclude_regressor
: info.exclude_classifier,
},
{
label: '集成方式',
value: info.ensemble_class,
format: formatEnum(autoMLEnsembleClassOptions),
},
{
label: '集成模型数量',
value: info.ensemble_size,
},
{
label: '集成最佳模型数量',
value: info.ensemble_nbest,
},
{
label: '最大数量',
value: info.max_models_on_disc,
},
{
label: '内存限制(MB)',
value: info.memory_limit,
},
{
label: '单次时间限制(秒)',
value: info.per_run_time_limit,
},
{
label: '搜索时间限制(秒)',
value: info.time_left_for_this_task,
},
{
label: '重采样策略',
value: info.resampling_strategy,
},
{
label: '交叉验证折数',
value: info.folds,
},
{
label: '是否打乱',
value: info.shuffle,
format: formatBoolean,
},
{
label: '训练集比率',
value: info.train_size,
},
{
label: '测试集比率',
value: info.test_size,
},
{
label: '计算指标',
value: info.scoring_functions,
},
{
label: '随机种子',
value: info.seed,
},
{
label: '数据集',
value: info.dataset,
format: formatDataset,
},
{
label: '预测目标列',
value: info.target_columns,
},
];
} else if (info.type === AutoMLType.Text) {
return [
{
label: '模型',
value: info.model_type,
},
{
label: '数据集',
value: info.dataset,
format: formatDataset,
},
{
label: '资源规格',
value: info.computing_resource_id,
format: getResourceDescription,
},
{
label: 'batch_size',
value: info.batch_size,
},
{
label: 'epochs',
value: info.epochs,
},
{
label: '学习率',
value: info.lr,
},
];
} else {
return [];
}
}, [info, getResourceDescription]);

const metricsData = useMemo(() => {
if (!info) {
@@ -229,7 +269,7 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB
),
},
];
}, [runStatus]);
}, [runStatus, info]);

return (
<div className={classNames(styles['auto-ml-basic'], className)}>
@@ -255,7 +295,9 @@ function AutoMLBasic({ info, className, runStatus, isInstance = false }: AutoMLB
labelWidth={150}
style={{ marginBottom: '20px' }}
/>
<ConfigInfo title="优化指标" datas={metricsData} labelWidth={70} />
{info?.type === AutoMLType.Table && (
<ConfigInfo title="优化指标" datas={metricsData} labelWidth={70} />
)}
</div>
);
}


+ 13
- 3
react-ui/src/pages/AutoML/components/CreateForm/BasicConfig.tsx View File

@@ -1,5 +1,7 @@
import SubAreaTitle from '@/components/SubAreaTitle';
import { Col, Form, Input, Row } from 'antd';
import { autoMLTypeOptions } from '@/enums';
import { Col, Form, Input, Radio, Row } from 'antd';

function BasicConfig() {
return (
<>
@@ -12,7 +14,7 @@ function BasicConfig() {
<Col span={10}>
<Form.Item
label="实验名称"
name="ml_name"
name="name"
rules={[
{
required: true,
@@ -32,7 +34,7 @@ function BasicConfig() {
<Col span={20}>
<Form.Item
label="实验描述"
name="ml_description"
name="description"
rules={[
{
required: true,
@@ -50,6 +52,14 @@ function BasicConfig() {
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item label="类型" name="type" rules={[{ required: true, message: '请选择类型' }]}>
<Radio.Group options={autoMLTypeOptions}></Radio.Group>
</Form.Item>
</Col>
</Row>
</>
);
}


+ 137
- 0
react-ui/src/pages/AutoML/components/CreateForm/TextExecuteConfig.tsx View File

@@ -0,0 +1,137 @@
import ParameterSelect from '@/components/ParameterSelect';
import ResourceSelect, {
ResourceSelectorType,
requiredValidator,
} from '@/components/ResourceSelect';
import SubAreaTitle from '@/components/SubAreaTitle';
import { Col, Form, InputNumber, Row, Select } from 'antd';

// 模型
const modelTypeOptions = [
'TextCNN',
'TextRNN',
'FasetText',
'TextRCNN',
'TextRNN_Att',
'DPCNN',
'Transformer',
].map((name) => ({ label: name, value: name }));

function TextExecuteConfig() {
return (
<>
<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_type"
rules={[
{
required: true,
message: '请选择模型',
},
]}
>
<Select allowClear placeholder="请选择模型" options={modelTypeOptions} showSearch />
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item
label="数据集"
name="dataset"
rules={[
{
validator: requiredValidator,
message: '请选择数据集',
},
]}
required
>
<ResourceSelect
type={ResourceSelectorType.Dataset}
placeholder="请选择数据集"
canInput={false}
/>
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item
label="资源规格"
name="computing_resource_id"
rules={[
{
required: true,
message: '请选择资源规格',
},
]}
>
<ParameterSelect dataType="resource" placeholder="请选择资源规格" />
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item
label="batch_size"
name="batch_size"
rules={[
{
required: true,
message: '请输入 batch_size',
},
]}
>
<InputNumber placeholder="请输入 batch_size" min={0} precision={0} />
</Form.Item>
</Col>
</Row>
<Row gutter={8}>
<Col span={10}>
<Form.Item
label="epochs"
name="epochs"
rules={[
{
required: true,
message: '请输入epochs',
},
]}
>
<InputNumber placeholder="请输入epochs" min={0} precision={0} />
</Form.Item>
</Col>
</Row>

<Row gutter={8}>
<Col span={10}>
<Form.Item
label="学习率"
name="lr"
rules={[
{
required: true,
message: '请输入学习率',
},
]}
>
<InputNumber placeholder="请输入学习率" min={0} />
</Form.Item>
</Col>
</Row>
</>
);
}

export default TextExecuteConfig;

+ 1
- 1
react-ui/src/pages/AutoML/components/ExperimentHistory/index.tsx View File

@@ -55,7 +55,7 @@ function ExperimentHistory({ calcMetrics, fileUrl, isClassification }: Experimen
if (fileUrl) {
getHistoryFile();
}
}, [fileUrl, isClassification]);
}, [fileUrl, isClassification, calcMetrics]);

const columns: TableProps<TableData>['columns'] = [
{


+ 2
- 2
react-ui/src/pages/AutoML/components/ExperimentList/config.ts View File

@@ -64,8 +64,8 @@ export const experimentListConfig: Record<ExperimentListType, ExperimentListInfo
stopInsReq: stopExperimentInsReq,
title: '自主机器学习',
pathPrefix: 'automl',
nameProperty: 'ml_name',
descProperty: 'ml_description',
nameProperty: 'name',
descProperty: 'description',
idProperty: 'autoMlId',
},
[ExperimentListType.HyperParameter]: {


+ 16
- 1
react-ui/src/pages/AutoML/components/ExperimentList/index.tsx View File

@@ -6,7 +6,7 @@

import KFIcon from '@/components/KFIcon';
import PageTitle from '@/components/PageTitle';
import { ExperimentStatus } from '@/enums';
import { ExperimentStatus, autoMLTypeOptions } from '@/enums';
import { useCacheState } from '@/hooks/useCacheState';
import { AutoMLData } from '@/pages/AutoML/types';
import { experimentStatusInfo } from '@/pages/Experiment/status';
@@ -244,6 +244,20 @@ function ExperimentList({ type }: ExperimentListProps) {
}
};

const typeColumns = [
{
title: '类型',
dataIndex: 'type',
key: 'type',
width: 120,
render: tableCellRender(false, TableCellValueType.Enum, {
options: autoMLTypeOptions,
}),
},
];

const diffColumns = type === ExperimentListType.AutoML ? typeColumns : [];

const columns: TableProps<AutoMLData>['columns'] = [
{
title: '实验名称',
@@ -260,6 +274,7 @@ function ExperimentList({ type }: ExperimentListProps) {
key: 'description',
render: tableCellRender(true),
},
...diffColumns,
{
title: '创建时间',
dataIndex: 'update_time',


+ 9
- 2
react-ui/src/pages/AutoML/types.ts View File

@@ -9,8 +9,9 @@ export enum OperationType {

// 表单数据
export type FormData = {
ml_name: string; // 实验名称
ml_description: string; // 实验描述
name: string; // 实验名称
description: string; // 实验描述
type: string; // 类型
ensemble_class?: string; // 集成方式
ensemble_nbest?: string; // 集成最佳模型数量
ensemble_size?: number; // 集成模型数量
@@ -37,6 +38,11 @@ export type FormData = {
metrics?: { name: string; value: number }[]; // 指标权重
dataset: ParameterInputObject; // 数据集
target_columns: string; // 预测目标列
model_type?: string; // 文本模型
computing_resource_id?: number; // 资源规格
batch_size?: number;
epochs?: number;
lr?: number;
};

export type AutoMLData = {
@@ -57,6 +63,7 @@ export type AutoMLData = {
update_by?: string;
update_time?: string;
status_list: string; // 最近五次运行状态
param: string; // 参数json字符串
} & Omit<
FormData,
'metrics|dataset|include_classifier|include_feature_preprocessor|include_regressor|exclude_classifier|exclude_feature_preprocessor|exclude_regressor'


+ 1
- 1
react-ui/src/pages/HyperParameter/components/ExperimentHistory/index.less View File

@@ -55,4 +55,4 @@
.table-best-row {
color: @success-color;
font-weight: bold;
}
}

+ 1
- 1
react-ui/src/pages/HyperParameter/components/HyperParameterBasic/index.tsx View File

@@ -182,7 +182,7 @@ function HyperParameterBasic({
ellipsis: true,
},
];
}, [runStatus]);
}, [runStatus, info]);

return (
<div className={classNames(styles['hyper-parameter-basic'], className)}>


+ 9
- 10
react-ui/src/pages/HyperParameter/components/TrialFileTree/index.less View File

@@ -1,15 +1,14 @@
.trail-file-tree {
:global {
.ant-tree-node-selected {
.trail-file-tree__icon {
color: white;
}
}
:global {
.ant-tree-node-selected {
.trail-file-tree__icon {
margin-left: 8px;
color: @primary-color;
color: white;
}
}

.trail-file-tree__icon {
margin-left: 8px;
color: @primary-color;
}
}
}

+ 1
- 1
react-ui/src/pages/Model/components/ModelMetrics/index.tsx View File

@@ -31,7 +31,7 @@ type ModelMetricsProps = {
version: string; // 当前版本
};

function ModelMetrics({ resourceId, identifier, owner, version, refreshTag }: ModelMetricsProps) {
function ModelMetrics({ resourceId, identifier, owner, version }: ModelMetricsProps) {
const [pagination, setPagination] = useState<TablePaginationConfig>({
current: 1,
pageSize: 10,


+ 2
- 6
react-ui/src/pages/ModelDeployment/List/index.tsx View File

@@ -9,6 +9,7 @@ import { serviceTypeOptions } from '@/enums';
import { useCacheState } from '@/hooks/useCacheState';
import { deleteServiceReq, getServiceListReq } from '@/services/modelDeployment';
import themes from '@/styles/theme.less';
import { ServiceCreatedMessage } from '@/utils/constant';
import { to } from '@/utils/promise';
import SessionStorage from '@/utils/sessionStorage';
import tableCellRender, { TableCellValueType } from '@/utils/table';
@@ -27,13 +28,8 @@ import {
import { type SearchProps } from 'antd/es/input';
import classNames from 'classnames';
import { useCallback, useEffect, useState } from 'react';
import {
CreateServiceVersionFrom,
ServiceData,
ServiceOperationType,
} from '../types';
import { CreateServiceVersionFrom, ServiceData, ServiceOperationType } from '../types';
import styles from './index.less';
import { ServiceCreatedMessage } from '@/utils/constant';

const allServiceTypeOptions = [{ label: '全部', value: '' }, ...serviceTypeOptions];



+ 1
- 1
react-ui/src/pages/ModelDeployment/components/VersionCompareModal/index.tsx View File

@@ -79,7 +79,7 @@ function VersionCompareModal({ version1, version2, ...rest }: VersionCompareModa
},
},
{
key: 'resource',
key: 'computing_resource_id',
text: '资源规格',
format: getResourceDescription,
},


+ 1
- 1
react-ui/src/pages/System/User/edit.tsx View File

@@ -32,7 +32,7 @@ export type UserFormProps = {

const UserForm: React.FC<UserFormProps> = (props) => {
const [form] = Form.useForm();
const userId = Form.useWatch('userId', form);
// const userId = Form.useWatch('userId', form);
const { sexOptions, statusOptions } = props;
const { roles, posts, depts } = props;
const formLayout = {


+ 1
- 3
react-ui/src/services/activeLearn/index.js View File

@@ -6,7 +6,6 @@

import { request } from '@umijs/max';


// 分页查询超参数自动寻优
export function getActiveLearnListReq(params) {
return request(`/api/mmp/activeLearn`, {
@@ -87,7 +86,6 @@ export function deleteActiveLearnInsReq(id) {
export function batchDeleteActiveLearnInsReq(data) {
return request(`/api/mmp/activeLearnIns/batchDelete`, {
method: 'DELETE',
data
data,
});
}


+ 1
- 1
react-ui/src/services/auth/index.js View File

@@ -13,4 +13,4 @@ export function getClientInfoReq() {
return request(`/api/auth/oauth2ClientInfo`, {
method: 'GET',
});
}
}

+ 12
- 14
react-ui/src/services/autoML/index.js View File

@@ -6,10 +6,9 @@

import { request } from '@umijs/max';


// 分页查询自动学习
export function getAutoMLListReq(params) {
return request(`/api/mmp/autoML`, {
return request(`/api/mmp/machineLearn`, {
method: 'GET',
params,
});
@@ -17,7 +16,7 @@ export function getAutoMLListReq(params) {

// 查询自动学习详情
export function getAutoMLInfoReq(params) {
return request(`/api/mmp/autoML/getAutoMlDetail`, {
return request(`/api/mmp/machineLearn/getMLDetail`, {
method: 'GET',
params,
});
@@ -25,7 +24,7 @@ export function getAutoMLInfoReq(params) {

// 新增自动学习
export function addAutoMLReq(data) {
return request(`/api/mmp/autoML`, {
return request(`/api/mmp/machineLearn`, {
method: 'POST',
data,
});
@@ -33,7 +32,7 @@ export function addAutoMLReq(data) {

// 编辑自动学习
export function updateAutoMLReq(data) {
return request(`/api/mmp/autoML`, {
return request(`/api/mmp/machineLearn`, {
method: 'PUT',
data,
});
@@ -41,14 +40,14 @@ export function updateAutoMLReq(data) {

// 删除自动学习
export function deleteAutoMLReq(id) {
return request(`/api/mmp/autoML/${id}`, {
return request(`/api/mmp/machineLearn/${id}`, {
method: 'DELETE',
});
}

// 运行自动学习
export function runAutoMLReq(id) {
return request(`/api/mmp/autoML/run/${id}`, {
return request(`/api/mmp/machineLearn/run/${id}`, {
method: 'POST',
});
}
@@ -56,7 +55,7 @@ export function runAutoMLReq(id) {
// ----------------------- 实验实例 -----------------------
// 获取实验实例列表
export function getExperimentInsListReq(params) {
return request(`/api/mmp/autoMLIns`, {
return request(`/api/mmp/machineLearnIns`, {
method: 'GET',
params,
});
@@ -64,30 +63,29 @@ export function getExperimentInsListReq(params) {

// 查询实验实例详情
export function getExperimentInsReq(id) {
return request(`/api/mmp/autoMLIns/${id}`, {
return request(`/api/mmp/machineLearnIns/${id}`, {
method: 'GET',
});
}

// 停止实验实例
export function stopExperimentInsReq(id) {
return request(`/api/mmp/autoMLIns/${id}`, {
return request(`/api/mmp/machineLearnIns/${id}`, {
method: 'PUT',
});
}

// 删除实验实例
export function deleteExperimentInsReq(id) {
return request(`/api/mmp/autoMLIns/${id}`, {
return request(`/api/mmp/machineLearnIns/${id}`, {
method: 'DELETE',
});
}

// 批量删除实验实例
export function batchDeleteExperimentInsReq(data) {
return request(`/api/mmp/autoMLIns/batchDelete`, {
return request(`/api/mmp/machineLearnIns/batchDelete`, {
method: 'DELETE',
data
data,
});
}


+ 2
- 2
react-ui/src/services/codeConfig/index.js View File

@@ -34,6 +34,6 @@ export function deleteCodeConfigReq(id) {
// 查询代码配置详情
export function getCodeConfigDetailReq(id) {
return request(`/api/mmp/codeConfig/${id}`, {
method: 'GET'
method: 'GET',
});
}
}

+ 5
- 9
react-ui/src/services/dataset/index.js View File

@@ -42,7 +42,6 @@ export function deleteDataset(params) {
});
}


// 查询数据集版本列表
export function getDatasetVersionList(params) {
return request(`/api/mmp/newdataset/getVersionList`, {
@@ -63,7 +62,7 @@ export function addDatasetVersion(data) {
export function downloadAllFiles(params) {
return request(`/api/mmp/newdataset/downloadAllFiles`, {
method: 'GET',
params
params,
});
}

@@ -109,7 +108,6 @@ export function deleteModel(params) {
});
}


// 查询模型详情
export function getModelInfo(params) {
return request(`/api/mmp/newmodel/getModelDetail`, {
@@ -134,7 +132,6 @@ export function addModelVersion(data) {
});
}


// 删除模型版本
export function deleteModelVersion(params) {
return request(`/api/mmp/newmodel/deleteVersion`, {
@@ -147,7 +144,7 @@ export function deleteModelVersion(params) {
export function getModelAtlasReq(params) {
return request(`/api/mmp/newmodel/getModelDependencyTree`, {
method: 'GET',
params
params,
});
}

@@ -155,7 +152,7 @@ export function getModelAtlasReq(params) {
export function exportModelReq(data) {
return request(`/api/mmp/models/exportModel`, {
method: 'POST',
data
data,
});
}

@@ -163,7 +160,7 @@ export function exportModelReq(data) {
export function getModelPageVersionsReq(params) {
return request(`/api/mmp/newmodel/queryVersions`, {
method: 'GET',
params
params,
});
}

@@ -171,7 +168,7 @@ export function getModelPageVersionsReq(params) {
export function getModelVersionsMetricsReq(data) {
return request(`/api/mmp/newmodel/queryVersionsMetrics`, {
method: 'POST',
data
data,
});
}

@@ -183,7 +180,6 @@ export function compareModelVersion(data) {
});
}


// 删除上传的文件
export function deleteUploadFileReq(params) {
return request(`/api/mmp/newdataset/deleteFile`, {


+ 3
- 3
react-ui/src/services/experiment/index.js View File

@@ -132,7 +132,7 @@ export function getTensorBoardStatusReq(data) {
export function getExpEvaluateInfosReq(experimentId, params) {
return request(`/api/mmp/aim/getExpEvaluateInfos/${experimentId}`, {
method: 'GET',
params
params,
});
}

@@ -140,7 +140,7 @@ export function getExpEvaluateInfosReq(experimentId, params) {
export function getExpTrainInfosReq(experimentId, params) {
return request(`/api/mmp/aim/getExpTrainInfos/${experimentId}`, {
method: 'GET',
params
params,
});
}

@@ -148,6 +148,6 @@ export function getExpTrainInfosReq(experimentId, params) {
export function getExpMetricsReq(data) {
return request(`/api/mmp/aim/getExpMetrics`, {
method: 'POST',
data
data,
});
}

+ 2
- 3
react-ui/src/services/file/index.js View File

@@ -4,7 +4,6 @@
* @Description: 请求文件,比如 json 文件
*/


import { request } from '@umijs/max';

// 获取文件,不需要token,非结构化数据
@@ -15,6 +14,6 @@ export function getFileReq(url, config) {
isToken: false,
},
skipValidating: true,
...config
...config,
});
}
}

+ 2
- 3
react-ui/src/services/hyperParameter/index.js View File

@@ -6,7 +6,6 @@

import { request } from '@umijs/max';


// 分页查询超参数自动寻优
export function getRayListReq(params) {
return request(`/api/mmp/ray`, {
@@ -87,7 +86,7 @@ export function deleteRayInsReq(id) {
export function batchDeleteRayInsReq(data) {
return request(`/api/mmp/rayIns/batchDelete`, {
method: 'DELETE',
data
data,
});
}

@@ -95,6 +94,6 @@ export function batchDeleteRayInsReq(data) {
export function getExpMetricsReq(data) {
return request(`/api/mmp/rayIns/getExpMetrics`, {
method: 'POST',
data
data,
});
}

+ 2
- 2
react-ui/src/services/pipeline/index.js View File

@@ -1,7 +1,7 @@
/*
* @Author: 赵伟
* @Date: 2024-03-25 13:52:54
* @Description:
* @Description:
*/
import { request } from '@umijs/max';
// 查询流水线列表
@@ -73,6 +73,6 @@ export function getWorkflowById(id) {
export function getComputingResourceReq(params) {
return request(`/api/mmp/computingResource`, {
method: 'GET',
params
params,
});
}

+ 0
- 1
react-ui/src/utils/IconUtil.ts View File

@@ -14,7 +14,6 @@ export function createIcon(icon: string | any): React.ReactNode | string {
}
const ele = allIcons[icon];
if (ele) {
return React.createElement(allIcons[icon]);
}
return '';


+ 10
- 4
react-ui/src/utils/downloadfile.ts View File

@@ -4,15 +4,15 @@ import { request } from '@umijs/max';
export enum MimeType {
XLSX = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
ZIP = 'application/zip',
JSON = 'application/json'
};
JSON = 'application/json',
}

/**
* 解析blob响应内容并下载
* @param res - blob响应内容
* @param mimeType - MIME类型
*/
export function resolveBlob(res: any, mimeType: string, specifiedFileName: string = "file") {
export function resolveBlob(res: any, mimeType: string, specifiedFileName: string = 'file') {
const aLink = document.createElement('a');
const blob = new Blob([res.data], { type: mimeType });
// 从response的headers中获取filename,
@@ -77,7 +77,13 @@ export async function downloadXlsx(
* @param method - 请求方法
* @param options - 请求选项
*/
export function downloadCommonFile(url: string, type: string, fileName: string = "file", method: string = 'GET', options?: Record<string, any>) {
export function downloadCommonFile(
url: string,
type: string,
fileName: string = 'file',
method: string = 'GET',
options?: Record<string, any>,
) {
request(url, {
method: method,
headers: {


+ 9
- 4
react-ui/src/utils/format.ts View File

@@ -172,7 +172,14 @@ export const formatBoolean = (value: boolean): string => {
return value ? '是' : '否';
};

type FormatEnumFunc = (value: string | number) => React.ReactNode;
export type FormatEnumFunc = (value: string | number) => React.ReactNode;

// 枚举选项
export type EnumOptions = {
label?: React.ReactNode;
value?: string | number | null;
[key: string | number]: any;
};

/**
* 格式化枚举
@@ -180,9 +187,7 @@ type FormatEnumFunc = (value: string | number) => React.ReactNode;
* @param options - 枚举选项数组
* @return 一个函数,参数是枚举值,从选项数组中找到对应的项,然后返回该项的 label
*/
export const formatEnum = (
options: { value?: string | number | null; label?: React.ReactNode }[],
): FormatEnumFunc => {
export const formatEnum = (options: EnumOptions[]): FormatEnumFunc => {
return (value: string | number) => {
const option = options.find((item) => item.value === value);
return option && option.label ? option.label : '--';


+ 16
- 1
react-ui/src/utils/table.tsx View File

@@ -8,6 +8,8 @@ import { isEmpty } from '@/utils';
import { formatDate } from '@/utils/date';
import { Tooltip, TooltipProps, Typography } from 'antd';
import dayjs from 'dayjs';
import React from 'react';
import { formatEnum, type EnumOptions } from './format';

export enum TableCellValueType {
/** 序号 */
@@ -20,6 +22,8 @@ export enum TableCellValueType {
Array = 'Array',
/** 链接 */
Link = 'Link',
/** 枚举 */
Enum = 'Enum',
/** 自定义 */
Custom = 'Custom',
}
@@ -35,8 +39,14 @@ export type TableCellValueOptions<T> = {
dateFormat?: string;
/** 链接点击回调,类型为 Link 时有效 */
onClick?: (record: T, e: React.MouseEvent) => void;
/** 枚举选项,类型为 Enum 时有效*/
options?: EnumOptions[];
/** 自定义函数,类型为 Custom 时有效*/
format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null;
format?: (
value: any | undefined | null,
record?: T,
index?: number,
) => React.ReactNode | undefined | null;
/** 省略时是否可以复制 */
copyable?: boolean;
};
@@ -110,6 +120,11 @@ function tableCellRender<T>(
case TableCellValueType.Array:
text = formatArray(options?.property)(value);
break;
case TableCellValueType.Enum:
if (options?.options) {
text = formatEnum(options.options)(value);
}
break;
case TableCellValueType.Custom:
text = options?.format?.(value, record, index);
break;


Loading…
Cancel
Save