Browse Source

feat: 机器学习文本分类可视化结果

pull/208/head
zhaowei 9 months ago
parent
commit
ce9f2638a6
8 changed files with 115 additions and 51 deletions
  1. +10
    -3
      react-ui/src/components/IFramePage/index.tsx
  2. +1
    -1
      react-ui/src/pages/ActiveLearn/components/ExperimentHistory/index.tsx
  3. +31
    -13
      react-ui/src/pages/AutoML/Instance/index.tsx
  4. +1
    -1
      react-ui/src/pages/AutoML/components/ExperimentResult/index.less
  5. +27
    -23
      react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx
  6. +42
    -0
      react-ui/src/pages/AutoML/components/TensorBoard/index.tsx
  7. +1
    -10
      react-ui/src/pages/DevelopmentEnvironment/Create/index.tsx
  8. +2
    -0
      react-ui/src/utils/sessionStorage.ts

+ 10
- 3
react-ui/src/components/IFramePage/index.tsx View File

@@ -16,6 +16,7 @@ export enum IframePageType {
GitLink = 'GitLink', // git link
Aim = 'Aim', // 实验对比
Knowledge = 'Knowledge', // 知识图谱
TensorBoard = 'TensorBoard', // 可视化结果
}

const getRequestAPI = (type: IframePageType): (() => Promise<any>) => {
@@ -36,12 +37,18 @@ const getRequestAPI = (type: IframePageType): (() => Promise<any>) => {
return () =>
Promise.resolve({
code: 200,
data: SessionStorage.getItem(SessionStorage.aimUrlKey) || '',
data: SessionStorage.getItem(SessionStorage.aimUrlKey),
});
case IframePageType.Knowledge: {
case IframePageType.Knowledge:
// 知识图谱
return () => Promise.resolve({ code: 200, data: `http://172.168.15.197:32701` });
}
case IframePageType.TensorBoard:
// 知识图谱
return () =>
Promise.resolve({
code: 200,
data: SessionStorage.getItem(SessionStorage.editorUrlKey),
});
}
};



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

@@ -54,7 +54,7 @@ function ExperimentHistory({ trialList, isClassification }: ExperimentHistoryPro
icon={<KFIcon type="icon-xiazai" />}
onClick={() => {
if (query_idx) {
const fileName = query_idx.split('/').slice(-1)[0];
const fileName = query_idx.split('/').pop();
let url = query_idx;
if (process.env.NODE_ENV === 'development') {
url = query_idx.replace('172.168.15.197:31213', 'localhost:8000');


+ 31
- 13
react-ui/src/pages/AutoML/Instance/index.tsx View File

@@ -1,5 +1,5 @@
import KFIcon from '@/components/KFIcon';
import { AutoMLTaskType, ExperimentStatus } from '@/enums';
import { AutoMLTaskType, AutoMLType, ExperimentStatus } from '@/enums';
import { getExperimentInsReq } from '@/services/autoML';
import { NodeStatus } from '@/types';
import { parseJsonText } from '@/utils';
@@ -12,6 +12,7 @@ import AutoMLBasic from '../components/AutoMLBasic';
import ExperimentHistory from '../components/ExperimentHistory';
import ExperimentLog from '../components/ExperimentLog';
import ExperimentResult from '../components/ExperimentResult';
import TensorBoard from '../components/TensorBoard';
import { AutoMLData, AutoMLInstanceData } from '../types';
import styles from './index.less';

@@ -20,6 +21,7 @@ enum TabKeys {
Log = 'log',
Result = 'result',
History = 'history',
Visual = 'Visual',
}

const NodePrefix = 'workflow';
@@ -29,6 +31,7 @@ function AutoMLInstance() {
const [instanceInfo, setInstanceInfo] = useState<AutoMLInstanceData | undefined>(undefined);
const [workflowStatus, setWorkflowStatus] = useState<NodeStatus | undefined>(undefined);
const [nodes, setNodes] = useState<Record<string, NodeStatus> | undefined>(undefined);
const [type, setType] = useState<string | undefined>(undefined);
const params = useParams();
const instanceId = safeInvoke(Number)(params.id);
const evtSourceRef = useRef<EventSource | null>(null);
@@ -49,6 +52,8 @@ function AutoMLInstance() {
if (res && res.data) {
const info = res.data as AutoMLInstanceData;
const { param, node_status, argo_ins_name, argo_ins_ns, status, create_time, type } = info;

setType(type);
// 解析配置参数
const paramJson = parseJsonText(param);
if (paramJson) {
@@ -174,24 +179,37 @@ function AutoMLInstance() {
icon: <KFIcon type="icon-shiyanjieguo1" />,
children: (
<ExperimentResult
type={type}
fileUrl={instanceInfo?.result_path}
imageUrl={instanceInfo?.img_path}
modelPath={instanceInfo?.model_path}
/>
),
},
{
key: TabKeys.History,
label: '试验列表',
icon: <KFIcon type="icon-Trialliebiao" />,
children: (
<ExperimentHistory
calcMetrics={autoMLInfo?.scoring_functions}
fileUrl={instanceInfo?.run_history_path}
isClassification={autoMLInfo?.task_type === AutoMLTaskType.Classification}
/>
),
},
type === AutoMLType.Text
? {
key: TabKeys.Visual,
label: '可视化结果',
icon: <KFIcon type="icon-Trialliebiao" />,
children: (
<TensorBoard
path={instanceInfo?.run_history_path}
namespace={instanceInfo?.argo_ins_ns}
/>
),
}
: {
key: TabKeys.History,
label: '试验列表',
icon: <KFIcon type="icon-Trialliebiao" />,
children: (
<ExperimentHistory
calcMetrics={autoMLInfo?.scoring_functions}
fileUrl={instanceInfo?.run_history_path}
isClassification={autoMLInfo?.task_type === AutoMLTaskType.Classification}
/>
),
},
];

const tabItems =


+ 1
- 1
react-ui/src/pages/AutoML/components/ExperimentResult/index.less View File

@@ -9,7 +9,7 @@
&__download {
padding-top: 16px;
padding-bottom: 16px;
margin-top: 16px;
padding-left: @content-padding;
color: @text-color;
font-size: 13px;


+ 27
- 23
react-ui/src/pages/AutoML/components/ExperimentResult/index.tsx View File

@@ -1,4 +1,5 @@
import InfoGroup from '@/components/InfoGroup';
import { AutoMLType } from '@/enums';
import { getFileReq } from '@/services/file';
import { to } from '@/utils/promise';
import { Button, Image } from 'antd';
@@ -9,9 +10,10 @@ type ExperimentResultProps = {
fileUrl?: string;
imageUrl?: string;
modelPath?: string;
type?: string;
};

function ExperimentResult({ fileUrl, imageUrl, modelPath }: ExperimentResultProps) {
function ExperimentResult({ fileUrl, imageUrl, modelPath, type }: ExperimentResultProps) {
const [result, setResult] = useState<string | undefined>('');

const images = useMemo(() => {
@@ -40,31 +42,33 @@ function ExperimentResult({ fileUrl, imageUrl, modelPath }: ExperimentResultProp
<InfoGroup title="实验结果" height={420} width="100%">
<div className={styles['experiment-result__text']}>{result}</div>
</InfoGroup>
<InfoGroup title="可视化结果" style={{ margin: '16px 0' }}>
<div className={styles['experiment-result__images']}>
<Image.PreviewGroup
preview={{
onChange: (current, prev) =>
console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
{images.map((item) => (
<Image
key={item}
className={styles['experiment-result__images__item']}
src={item}
height={248}
draggable={false}
alt=""
/>
))}
</Image.PreviewGroup>
</div>
</InfoGroup>
{type === AutoMLType.Table && (
<InfoGroup title="可视化结果" style={{ margin: '16px 0' }}>
<div className={styles['experiment-result__images']}>
<Image.PreviewGroup
preview={{
onChange: (current, prev) =>
console.log(`current index: ${current}, prev index: ${prev}`),
}}
>
{images.map((item) => (
<Image
key={item}
className={styles['experiment-result__images__item']}
src={item}
height={248}
draggable={false}
alt=""
/>
))}
</Image.PreviewGroup>
</div>
</InfoGroup>
)}
{modelPath && (
<div className={styles['experiment-result__download']}>
<span style={{ marginRight: '12px', color: '#606b7a' }}>文件名</span>
<span>save_model.joblib</span>
<span>{modelPath.split('/').pop()} </span>
<Button
type="primary"
className={styles['experiment-result__download__btn']}


+ 42
- 0
react-ui/src/pages/AutoML/components/TensorBoard/index.tsx View File

@@ -0,0 +1,42 @@
/*
* @Author: 赵伟
* @Date: 2024-09-02 08:42:57
* @Description: 可视化
*/

import IframePage, { IframePageType } from '@/components/IFramePage';
import { runTensorBoardReq } from '@/services/experiment/index.js';
import { to } from '@/utils/promise';
import SessionStorage from '@/utils/sessionStorage';
import { useEffect, useState } from 'react';

type TensorBoardProps = {
namespace?: string;
path?: string;
};

function TensorBoard({ namespace, path }: TensorBoardProps) {
const [tensorboardUrl, setTensorboardUrl] = useState('');
useEffect(() => {
// 运行 TensorBoard
const runTensorBoard = async () => {
const params = {
namespace: namespace,
path: path,
};
const [res] = await to(runTensorBoardReq(params));
if (res && res.data) {
SessionStorage.setItem(SessionStorage.tensorBoardUrlKey, res.data);
setTensorboardUrl(res.data);
}
};

if (namespace && path) {
runTensorBoard();
}
}, [namespace, path]);

return <>{tensorboardUrl && <IframePage type={IframePageType.TensorBoard}></IframePage>}</>;
}

export default TensorBoard;

+ 1
- 10
react-ui/src/pages/DevelopmentEnvironment/Create/index.tsx View File

@@ -17,7 +17,6 @@ import { createEditorReq } from '@/services/developmentEnvironment';
import { to } from '@/utils/promise';
import { useNavigate } from '@umijs/max';
import { App, Button, Col, Form, Input, Row } from 'antd';
import { omit, pick } from 'lodash';
import styles from './index.less';

type FormData = {
@@ -54,15 +53,7 @@ function EditorCreate() {

// 创建编辑器
const createEditor = async (formData: FormData) => {
// 根据后台要求,修改表单数据
const model = formData['model'];
const dataset = formData['dataset'];
const params = {
...omit(formData, ['model', 'dataset']),
model: model && pick(model, ['id', 'version', 'path', 'showValue']),
dataset: dataset && pick(dataset, ['id', 'version', 'path', 'showValue']),
};
const [res] = await to(createEditorReq(params));
const [res] = await to(createEditorReq(formData));
if (res) {
message.success('创建成功');
navigate(-1);


+ 2
- 0
react-ui/src/utils/sessionStorage.ts View File

@@ -11,6 +11,8 @@ export default class SessionStorage {
static readonly clientInfoKey = 'client-info';
/** aim url */
static readonly aimUrlKey = 'aim-url';
/** tensorBoard url */
static readonly tensorBoardUrlKey = 'tensor-board-url';

/**
* 获取 SessionStorage 值


Loading…
Cancel
Save