diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts
index 7edf6db2..74390abf 100644
--- a/react-ui/config/routes.ts
+++ b/react-ui/config/routes.ts
@@ -96,6 +96,11 @@ export default [
path: ':workflowId/:id',
component: './Experiment/training/index',
},
+ {
+ name: '实验对比',
+ path: 'compare',
+ component: './Experiment/Comparison/index',
+ },
],
},
],
diff --git a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
index bcbd123f..e8bed08c 100644
--- a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
@@ -58,7 +58,7 @@ const ResourceIntro = ({ resourceType }: ResourceIntroProps) => {
};
}),
);
- if (versionParam) {
+ if (versionParam && res.data.includes(versionParam)) {
setVersion(versionParam);
versionParam = null;
} else {
diff --git a/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx b/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
index 9c4badb6..76f0dcb9 100644
--- a/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
+++ b/react-ui/src/pages/DevelopmentEnvironment/List/index.tsx
@@ -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 ? (
+
+ {text}
+
+ ) : (
+ {text ?? '--'}
+ ),
},
{
title: '状态',
diff --git a/react-ui/src/pages/Experiment/Comparison/index.less b/react-ui/src/pages/Experiment/Comparison/index.less
new file mode 100644
index 00000000..288ce2ed
--- /dev/null
+++ b/react-ui/src/pages/Experiment/Comparison/index.less
@@ -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;
+ }
+}
diff --git a/react-ui/src/pages/Experiment/Comparison/index.tsx b/react-ui/src/pages/Experiment/Comparison/index.tsx
new file mode 100644
index 00000000..5fca638d
--- /dev/null
+++ b/react-ui/src/pages/Experiment/Comparison/index.tsx
@@ -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([]);
+ const [pagination, setPagination] = useState(
+ 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 (
+
+ );
+}
+
+export default ExperimentComparison;
diff --git a/react-ui/src/pages/Experiment/index.jsx b/react-ui/src/pages/Experiment/index.jsx
index 69648b49..7c7e3eaa 100644
--- a/react-ui/src/pages/Experiment/index.jsx
+++ b/react-ui/src/pages/Experiment/index.jsx
@@ -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: 训练对比,
+ key: ComparisonType.Train,
+ },
+ {
+ label: 评估对比,
+ 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) => (
+
+ e.preventDefault()}>
+
+
+ 实验对比
+
+
+
{
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;
diff --git a/react-ui/src/services/experiment/index.js b/react-ui/src/services/experiment/index.js
index 9d388b71..89028b24 100644
--- a/react-ui/src/services/experiment/index.js
+++ b/react-ui/src/services/experiment/index.js
@@ -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',
+ });
+}
diff --git a/react-ui/src/services/session.ts b/react-ui/src/services/session.ts
index 8430b21b..e1f00d75 100644
--- a/react-ui/src/services/session.ts
+++ b/react-ui/src/services/session.ts
@@ -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);
}
}