Browse Source

Merge pull request 'feat: 实验对比' (#86) from dev-zw into dev

pull/87/head
cp3hnu 1 year ago
parent
commit
e96e777ae8
10 changed files with 298 additions and 14 deletions
  1. +5
    -0
      react-ui/config/routes.ts
  2. +1
    -1
      react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
  3. +9
    -1
      react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
  4. +21
    -0
      react-ui/src/pages/Experiment/Comparison/index.less
  5. +212
    -0
      react-ui/src/pages/Experiment/Comparison/index.tsx
  6. +31
    -2
      react-ui/src/pages/Experiment/index.jsx
  7. +1
    -1
      react-ui/src/pages/Experiment/index.less
  8. +1
    -1
      react-ui/src/requestConfig.ts
  9. +14
    -0
      react-ui/src/services/experiment/index.js
  10. +3
    -8
      react-ui/src/services/session.ts

+ 5
- 0
react-ui/config/routes.ts View File

@@ -96,6 +96,11 @@ export default [
path: ':workflowId/:id',
component: './Experiment/training/index',
},
{
name: '实验对比',
path: 'compare',
component: './Experiment/Comparison/index',
},
],
},
],


+ 1
- 1
react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx View File

@@ -58,7 +58,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => {
};
}),
);
if (versionParam) {
if (versionParam && res.data.includes(versionParam)) {
setVersion(versionParam);
versionParam = null;
} else {


+ 9
- 1
react-ui/src/pages/DevelopmentEnvironment/List/index.tsx View File

@@ -38,6 +38,7 @@ export type EditorData = {
computing_resource: string;
update_by: string;
create_time: string;
url: string;
};

function EditorList() {
@@ -140,7 +141,14 @@ function EditorList() {
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
render: (text, record) =>
record.url ? (
<a href={record.url} target="_blank" rel="noreferrer">
{text}
</a>
) : (
<span>{text ?? '--'}</span>
),
},
{
title: '状态',


+ 21
- 0
react-ui/src/pages/Experiment/Comparison/index.less View File

@@ -0,0 +1,21 @@
.experiment-comparison {
height: 100%;
&__header {
display: flex;
align-items: center;
height: 50px;
margin-bottom: 10px;
padding: 0 30px;
background-image: url(@/assets/img/page-title-bg.png);
background-repeat: no-repeat;
background-position: top center;
background-size: 100% 100%;
}

&__table {
height: calc(100% - 60px);
padding: 20px 30px 0;
background-color: white;
border-radius: 10px;
}
}

+ 212
- 0
react-ui/src/pages/Experiment/Comparison/index.tsx View File

@@ -0,0 +1,212 @@
import CommonTableCell from '@/components/CommonTableCell';
import { useCacheState } from '@/hooks/pageCacheState';
import { getExpEvaluateInfosReq, getExpTrainInfosReq } from '@/services/experiment';
import { to } from '@/utils/promise';
import { useSearchParams } from '@umijs/max';
import { Button, Table, TablePaginationConfig, TableProps } from 'antd';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import styles from './index.less';

export enum ComparisonType {
Train = 'train',
Evaluate = 'evaluate',
}

function ExperimentComparison() {
const [searchParams] = useSearchParams();
const comparisonType = searchParams.get('type');
const experimentId = searchParams.get('experimentId');
const [tableData, setTableData] = useState([]);
const [cacheState, setCacheState] = useCacheState();
const [total, setTotal] = useState(0);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [pagination, setPagination] = useState<TablePaginationConfig>(
cacheState?.pagination ?? {
current: 1,
pageSize: 10,
},
);

useEffect(() => {
getComparisonData();
}, [experimentId]);

// 获取对比数据列表
const getComparisonData = async () => {
const request =
comparisonType === ComparisonType.Train ? getExpTrainInfosReq : getExpEvaluateInfosReq;
const [res] = await to(request(experimentId));
if (res && res.data) {
const { content = [], totalElements = 0 } = res.data;
setTableData(content);
setTotal(totalElements);
}
};

// 分页切换
const handleTableChange: TableProps['onChange'] = (pagination, filters, sorter, { action }) => {
if (action === 'paginate') {
setPagination(pagination);
}
// console.log(pagination, filters, sorter, action);
};

const rowSelection: TableProps['rowSelection'] = {
type: 'checkbox',
selectedRowKeys,
onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
setSelectedRowKeys(selectedRowKeys);
},
};

const columns: TableProps['columns'] = [
{
title: '基本信息',
children: [
{
title: '实例ID',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: '运行时间',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: '运行状态',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: '训练数据集',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: '增量训练',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
],
},
{
title: '训练参数',
children: [
{
title: 'batchsize',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'config',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'epoch',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'lr',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'warmup_iters',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
],
},
{
title: '训练指标',
children: [
{
title: 'metrc_name',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'test_1',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'test_2',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'test_3',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
{
title: 'test_4',
dataIndex: 'name',
key: 'name',
width: '30%',
render: CommonTableCell(),
},
],
},
];

return (
<div className={styles['experiment-comparison']}>
<div className={styles['experiment-comparison__header']}>
<Button type="default">可视化对比</Button>
</div>
<div className={classNames('vertical-scroll-table', styles['experiment-comparison__table'])}>
<Table
dataSource={tableData}
columns={columns}
rowSelection={rowSelection}
scroll={{ y: 'calc(100% - 55px)' }}
pagination={{
...pagination,
total: total,
showSizeChanger: true,
showQuickJumper: true,
}}
onChange={handleTableChange}
rowKey="id"
/>
</div>
</div>
);
}

export default ExperimentComparison;

+ 31
- 2
react-ui/src/pages/Experiment/index.jsx View File

@@ -18,11 +18,12 @@ import themes from '@/styles/theme.less';
import { elapsedTime, formatDate } from '@/utils/date';
import { to } from '@/utils/promise';
import { modalConfirm } from '@/utils/ui';
import { App, Button, ConfigProvider, Space, Table, Tooltip } from 'antd';
import { App, Button, ConfigProvider, Dropdown, Space, Table, Tooltip } from 'antd';
import classNames from 'classnames';
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import AddExperimentModal from './components/AddExperimentModal';
import { ComparisonType } from './components/ComparisonModal/config';
import TensorBoardStatus, { TensorBoardStatusEnum } from './components/TensorBoardStatus';
import Styles from './index.less';
import { experimentStatusInfo } from './status';
@@ -270,6 +271,26 @@ function Experiment() {
window.open(experimentIn.tensorboardUrl, '_blank');
}
};

// 实验对比菜单
const getComparisonMenu = (experimentId) => {
return {
items: [
{
label: <span>训练对比</span>,
key: ComparisonType.Train,
},
{
label: <span>评估对比</span>,
key: ComparisonType.Evaluate,
},
],
onClick: ({ key }) => {
navgite(`/pipeline/experiment/compare?type=${key}&id=${experimentId}`);
},
};
};

const columns = [
{
title: '实验名称',
@@ -320,7 +341,7 @@ function Experiment() {
{
title: '操作',
key: 'action',
width: 300,
width: 350,
render: (_, record) => (
<Space size="small">
<Button
@@ -345,6 +366,14 @@ function Experiment() {
>
编辑
</Button>
<Dropdown key="comparison" menu={getComparisonMenu(record.id)}>
<a onClick={(e) => e.preventDefault()}>
<Space style={{ padding: '0 7px' }}>
<KFIcon type="icon-shiyanduibi" />
实验对比
</Space>
</a>
</Dropdown>
<ConfigProvider
theme={{
token: {


+ 1
- 1
react-ui/src/pages/Experiment/index.less View File

@@ -58,7 +58,7 @@
}

.operation {
width: 284px;
width: 334px;
}
}
.tableExpandBoxContent {


+ 1
- 1
react-ui/src/requestConfig.ts View File

@@ -40,7 +40,7 @@ export const requestConfig: RequestConfig = {
[
(response: AxiosResponse) => {
const { status, data } = response || {};
console.log(message, data);
// console.log(message, data);
if (status >= 200 && status < 300) {
if (data && (data instanceof Blob || data.code === 200)) {
return response;


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

@@ -116,3 +116,17 @@ export function getTensorBoardStatusReq(data) {
data,
});
}

// 获取当前实验的模型推理指标信息
export function getExpEvaluateInfosReq(experimentId) {
return request(`/api/mmp/aim/getExpEvaluateInfos/${experimentId}`, {
method: 'GET',
});
}

// 获取当前实验的模型训练指标信息
export function getExpTrainInfosReq(experimentId) {
return request(`/api/mmp//aim/getExpTrainInfos/${experimentId}`, {
method: 'GET',
});
}

+ 3
- 8
react-ui/src/services/session.ts View File

@@ -60,8 +60,8 @@ function patchRouteItems(route: any, menu: any, parentPath: string) {
element: React.createElement(lazy(() => import('@/pages/' + path))),
path: parentPath + menuItem.path,
};
console.log(newRoute);
// console.log(newRoute);
route.children.push(newRoute);
route.routes.push(newRoute);
}
@@ -74,10 +74,7 @@ export function patchRouteWithRemoteMenus(routes: any) {
}
let proLayout = null;
for (const routeItem of routes) {

if (routeItem.id === 'ant-design-pro-layout') {
proLayout = routeItem;
break;
}
@@ -101,7 +98,6 @@ export async function refreshToken() {
}

export function convertCompatRouters(childrens: API.RoutersMenuItem[]): any[] {

return childrens.map((item: API.RoutersMenuItem) => {
return {
path: item.path,
@@ -149,12 +145,11 @@ export function getMatchMenuItem(
const subpath = path.substr(item.path.length + 1);
const subItem: MenuDataItem[] = getMatchMenuItem(subpath, item.routes);
items = items.concat(subItem);

} else {
const paths = path.split('/');
if (paths.length >= 2 && paths[0] === item.path && paths[1] === 'index') {
console.log(item);
items.push(item);
}
}


Loading…
Cancel
Save