From acd6c6df4bb6d74722ecde19f127917e7c9f4e0a Mon Sep 17 00:00:00 2001 From: RotPublic <63988781+xiaoyixin-cmd@users.noreply.github.com> Date: Fri, 13 Jan 2023 16:56:26 +0800 Subject: [PATCH] fasdeploy frontend (#1198) * end * end2 * end3 * end4 * end5 * end6 * end7 Co-authored-by: chenjian --- frontend/packages/core/package.json | 14 +- .../core/public/locales/en/Fastdeploy.json | 68 + .../core/public/locales/zh/Fastdeploy.json | 68 + frontend/packages/core/snowpack.config.js | 8 +- frontend/packages/core/src/App.tsx | 18 +- .../core/src/components/BarsChart.tsx | 4 +- .../packages/core/src/components/Check.tsx | 1 + .../src/components/CurvesPage/CurveChart.tsx | 1 - .../core/src/components/DistributedChart.tsx | 3 +- .../components/FastdeployGraph/CPUTables.tsx | 93 + .../src/components/FastdeployGraph/Clinet.tsx | 36 + .../FastdeployGraph/ModelTables.tsx | 122 + .../FastdeployGraph/ServerConfig.tsx | 1329 ++++++++ .../src/components/FastdeployGraph/index.tsx | 2684 +++++++++++++++++ .../components/FastdeployGraph/serverBox.tsx | 299 ++ .../src/components/GraphPage/GraphDynamic.tsx | 1 + .../src/components/GraphPage/GraphStatic.tsx | 1 + .../src/components/GraphPage/GraphStatic2.tsx | 2 + .../src/components/GraphPage/Uploader.tsx | 27 +- .../core/src/components/LineChart.tsx | 2 +- .../packages/core/src/components/Navbar.tsx | 83 +- .../ProfilerPage/MemoryView/MemoryView.tsx | 5 +- .../ProfilerPage/OperatorView/tools.tsx | 4 +- .../overview/PerformanceContent.tsx | 2 +- .../ProfilerPage/overview/overview.tsx | 18 +- .../core/src/components/ScalarChart.tsx | 2 +- .../core/src/components/StackColumnChart.tsx | 1 + .../core/src/components/StackColumnChart2.tsx | 4 +- .../packages/core/src/components/pieChart.tsx | 4 +- .../packages/core/src/pages/Fastdeploy.tsx | 480 +++ .../core/src/pages/FastdeployClient.tsx | 112 + .../packages/core/src/pages/graphDynamic.tsx | 7 +- .../packages/core/src/pages/graphStatic.tsx | 23 +- .../packages/core/src/pages/graphStatic2.tsx | 13 +- frontend/packages/core/src/pages/profiler.tsx | 3 +- frontend/packages/core/src/pages/x2paddle.tsx | 40 +- frontend/packages/core/src/routes/index.ts | 14 +- frontend/packages/core/src/utils/fetch.ts | 1 + frontend/packages/core/types/netron.d.ts | 4 + frontend/packages/mock/data/component_tabs.js | 33 + .../data/fastdeploy/check_server_alive.js | 17 + .../mock/data/fastdeploy/config_update.js | 17 + .../fastdeploy/create_fastdeploy_client.js | 17 + .../fastdeploy/delete_config_for_model.js | 17 + .../delete_resource_for_model.js} | 25 +- .../fastdeploy/download_pretrain_model.js | 32 + .../mock/data/fastdeploy/get_config.js | 303 ++ .../get_config_filenames_for_model.js | 30 + .../data/fastdeploy/get_config_for_model.js | 62 + .../mock/data/fastdeploy/get_directory.js | 20 + .../fastdeploy/get_pretrain_model_list.js | 185 ++ .../mock/data/fastdeploy/get_server_config.js | 287 ++ .../mock/data/fastdeploy/get_server_list.js | 17 + .../mock/data/fastdeploy/get_server_metric.js | 122 + .../mock/data/fastdeploy/get_server_output.js | 135 + .../fastdeploy/rename_resource_for_model.js | 28 + .../set_default_config_for_model.js | 17 + .../mock/data/fastdeploy/start_server.js | 19 + .../mock/data/fastdeploy/stop_server.js | 17 + frontend/packages/mock/data/graph_runs.js | 2 +- frontend/packages/netron2/src/view.js | 1 + frontend/packages/netron3/.browserslistrc | 4 + frontend/packages/netron3/README.md | 9 + frontend/packages/netron3/package.json | 68 + frontend/packages/netron3/postcss.config.js | 19 + frontend/packages/netron3/src/index.html | 15 + frontend/packages/netron3/src/index.js | 85 + frontend/packages/netron3/webpack.config.js | 146 + frontend/yarn.lock | 391 ++- 69 files changed, 7581 insertions(+), 160 deletions(-) create mode 100644 frontend/packages/core/public/locales/en/Fastdeploy.json create mode 100644 frontend/packages/core/public/locales/zh/Fastdeploy.json create mode 100644 frontend/packages/core/src/components/FastdeployGraph/CPUTables.tsx create mode 100644 frontend/packages/core/src/components/FastdeployGraph/Clinet.tsx create mode 100644 frontend/packages/core/src/components/FastdeployGraph/ModelTables.tsx create mode 100644 frontend/packages/core/src/components/FastdeployGraph/ServerConfig.tsx create mode 100644 frontend/packages/core/src/components/FastdeployGraph/index.tsx create mode 100644 frontend/packages/core/src/components/FastdeployGraph/serverBox.tsx create mode 100644 frontend/packages/core/src/pages/Fastdeploy.tsx create mode 100644 frontend/packages/core/src/pages/FastdeployClient.tsx create mode 100644 frontend/packages/mock/data/component_tabs.js create mode 100644 frontend/packages/mock/data/fastdeploy/check_server_alive.js create mode 100644 frontend/packages/mock/data/fastdeploy/config_update.js create mode 100644 frontend/packages/mock/data/fastdeploy/create_fastdeploy_client.js create mode 100644 frontend/packages/mock/data/fastdeploy/delete_config_for_model.js rename frontend/packages/mock/data/{app/component_tabs.js => fastdeploy/delete_resource_for_model.js} (69%) create mode 100644 frontend/packages/mock/data/fastdeploy/download_pretrain_model.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_config.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_config_filenames_for_model.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_config_for_model.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_directory.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_pretrain_model_list.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_server_config.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_server_list.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_server_metric.js create mode 100644 frontend/packages/mock/data/fastdeploy/get_server_output.js create mode 100644 frontend/packages/mock/data/fastdeploy/rename_resource_for_model.js create mode 100644 frontend/packages/mock/data/fastdeploy/set_default_config_for_model.js create mode 100644 frontend/packages/mock/data/fastdeploy/start_server.js create mode 100644 frontend/packages/mock/data/fastdeploy/stop_server.js create mode 100644 frontend/packages/netron3/.browserslistrc create mode 100644 frontend/packages/netron3/README.md create mode 100644 frontend/packages/netron3/package.json create mode 100644 frontend/packages/netron3/postcss.config.js create mode 100644 frontend/packages/netron3/src/index.html create mode 100644 frontend/packages/netron3/src/index.js create mode 100644 frontend/packages/netron3/webpack.config.js diff --git a/frontend/packages/core/package.json b/frontend/packages/core/package.json index 7c267960..2c8b3022 100644 --- a/frontend/packages/core/package.json +++ b/frontend/packages/core/package.json @@ -39,6 +39,18 @@ "dist" ], "dependencies": { + "@antv/layout": "^0.3.7", + "@antv/x6": "^2.0.2", + "@antv/x6-plugin-clipboard": "^2.0.1", + "@antv/x6-plugin-dnd": "^2.0.2", + "@antv/x6-plugin-export": "^2.1.5", + "@antv/x6-plugin-history": "^2.1.1", + "@antv/x6-plugin-keyboard": "^2.1.2", + "@antv/x6-plugin-selection": "^2.1.3", + "@antv/x6-plugin-snapline": "^2.1.2", + "@antv/x6-plugin-stencil": "^2.0.1", + "@antv/x6-plugin-transform": "^2.0.1", + "@antv/x6-react-shape": "^2.0.0", "@material-ui/core": "^4.12.4", "@snowpack/plugin-sass": "^1.4.0", "@tippyjs/react": "4.2.5", @@ -60,7 +72,6 @@ "i18next-browser-languagedetector": "6.1.2", "i18next-fetch-backend": "3.0.0", "jszip": "3.7.1", - "lodash": "4.17.21", "mime-types": "2.1.32", "moment": "2.29.1", "nprogress": "0.2.0", @@ -127,6 +138,7 @@ "dotenv": "10.0.0", "enhanced-resolve": "5.8.2", "html-minifier": "4.0.0", + "lodash": "^4.17.21", "snowpack": "3.8.8", "snowpack-plugin-copy": "1.0.1", "typescript": "4.4.2" diff --git a/frontend/packages/core/public/locales/en/Fastdeploy.json b/frontend/packages/core/public/locales/en/Fastdeploy.json new file mode 100644 index 00000000..ecc98479 --- /dev/null +++ b/frontend/packages/core/public/locales/en/Fastdeploy.json @@ -0,0 +1,68 @@ +{ + "Load-model": "Please select a model repository", + "Current-model": "Current model repository", + "ensemble-pipeline": "ensemble pipeline", + "variable": "variable", + "instance": "instance", + "Pre-trained": "Pre-trained model name", + "The-config": "The config file chosen as startup config will overwrite config.pbtxt, and a backup config.pbtxt will be created first, please check to confirm", + "Confirm": "Confirm to shutdown server", + "Confirm-delete-config": "Confirm to delete config file", + "Confirm-delete-resource": "Confirm to delete resource file", + "load-model-repository": "load model repository", + "ensemble-configuration": "ensemble configuration", + "launch-server": "launch server", + "cancel": "cancel", + "launch": "launch", + "set-as-launch-config": "set as start up config", + "update": "update", + "log": "log", + "metric": "metric", + "ok": "ok", + "model-repository": "model repository", + "open-client": "open client", + "shutdown": "shutdown", + "updates": "update", + "Load-model-repository": "Load model repository", + "Download-pre-trained-model": "Download pre-trained model", + "Model-configuration": "Model configuration", + "Ensemble-configuration": "Ensemble configuration", + "Launch-parameters-configuration": "Launch parameters configuration", + "Delete-config-file": "Delete config file", + "Delete-resource-file": "Delete resource file", + "Rename-resource-file": "Rename resource file", + "Shutdown-server": "Shutdown server", + "Update-configuration-successfully": "update configuration successfully", + "Launch-server-successfully": "Launch server successfully", + "Update-successfully": "Update log and metric for successfully", + "Shutdown-server-successfully": "Shutdown server successfully", + "Download-successfully": "Download pre-trained model successfully", + "Set-successfully": "Set as startup config file successfully", + "Rename-successfully": "Rename resource file successfully", + "Delete-config-successfully": "Delete config file successfully", + "Delete-resource-successfully": "Delete resource file successfully", + "Backup-config": "Backup config file is not permitted to modify, please re-select", + "Model-name": "Model name", + "Execution-metric": "Execution metric", + "inference-request-success": "inference request success", + "inference-request-failure": "inference request failure", + "inference-count": "inference count", + "inference-exec-count": "inference exec count", + "inference-request-duration": "inference request duration", + "inference-queue-duration": "inference queue duration", + "inference-comput-input-duration": "inference comput input duration", + "inference-compute-infer-duration": "inference compute infer duration", + "inference-compute-output-duration": "inference compute output duration", + "Delay-metric": "Delay metric", + "Device-name": "Device name", + "Performance-metric": "Performance metric", + "Memory": "Memory", + "utilization": "utilization", + "power-usage": "power usage", + "power-limit": "power limit", + "energy-consumption": "energy consumption", + "total": "total", + "used": "used", + "Model-metrics": "Model metrics", + "GPU-metrics": "GPU metrics" +} diff --git a/frontend/packages/core/public/locales/zh/Fastdeploy.json b/frontend/packages/core/public/locales/zh/Fastdeploy.json new file mode 100644 index 00000000..ed0256d3 --- /dev/null +++ b/frontend/packages/core/public/locales/zh/Fastdeploy.json @@ -0,0 +1,68 @@ +{ + "Load-model": "请载入模型库", + "Current-model": "当前模型库", + "ensemble-pipeline": "ensemble模型结构", + "variable": "变量", + "instance": "实例", + "Pre-trained": "预训练模型名", + "The-config": "设为启动配置文件即会将当前文件作为config.pbtxt,并覆盖之前的config.pbtxt的内容,被覆盖前的config.pbtxt会自动进行备份,是否继续", + "Confirm": "请确认是否关闭所启动服务", + "Confirm-delete-config": "请确认是否删除配置文件", + "Confirm-delete-resource": "请确认是否删除资源文件", + "load-model-repository": "载入模型库", + "ensemble-configuration": "ensemble配置", + "launch-server": "启动服务", + "cancel": "取消", + "launch": "启动", + "set-as-launch-config": "设为启动配置文件", + "update": "更新", + "log": "日志", + "metric": "性能", + "ok": "确定", + "model-repository": "模型库配置", + "open-client": "打开客户端", + "shutdown": "关闭服务", + "updates": "更新数据", + "Load-model-repository": "载入模型库", + "Download-pre-trained-model": "预训练模型下载", + "Model-configuration": "配置模型", + "Ensemble-configuration": "配置ensemble", + "Launch-parameters-configuration": "配置启动参数", + "Delete-config-file": "删除配置文件", + "Delete-resource-file": "删除资源文件", + "Rename-resource-file": "重命名文件", + "Shutdown-server": "关闭服务", + "Update-configuration-successfully": "更新配置成功", + "Launch-server-successfully": "启动服务成功", + "Update-successfully": "更新日志和性能数据成功", + "Shutdown-server-successfully": "关闭服务成功", + "Download-successfully": "下载预训练模型成功", + "Set-successfully": "设为启动配置成功", + "Rename-successfully": "重命名资源文件成功", + "Delete-config-successfully": "删除配置文件成功", + "Delete-resource-successfully": "删除资源文件成功", + "Backup-config": "该文件为备份配置文件不允许修改,请重新选择", + "Model-name": "模型名称", + "Execution-metric": "执行统计", + "inference-request-success": "请求处理成功数", + "inference-request-failure": "请求处理失败数", + "inference-count": "推理batch数", + "inference-exec-count": "推理样本数", + "inference-request-duration": "请求处理时间", + "inference-queue-duration": "任务队列等待时间", + "inference-comput-input-duration": "输入处理时间", + "inference-compute-infer-duration": "模型推理时间", + "inference-compute-output-duration": "输出处理时间", + "Delay-metric": "延迟统计", + "Device-name": "GPU", + "Performance-metric": "性能指标", + "Memory": "显存", + "utilization": "利用率", + "power-usage": "功率", + "power-limit": "功率限制", + "energy-consumption": "耗电量", + "total": "总量", + "used": "已使用", + "Model-metrics": "模型服务监控", + "GPU-metrics": "GPU监控" +} diff --git a/frontend/packages/core/snowpack.config.js b/frontend/packages/core/snowpack.config.js index 41107135..657650d3 100644 --- a/frontend/packages/core/snowpack.config.js +++ b/frontend/packages/core/snowpack.config.js @@ -37,6 +37,8 @@ function isWorkspace() { const iconsPath = path.dirname(resolve.sync(cwd, '@visualdl/icons')); const netronPath = path.dirname(resolve.sync(cwd, '@visualdl/netron')); const netronPath2 = path.dirname(resolve.sync(cwd, '@visualdl/netron2')); +// const netronPath3 = path.dirname(resolve.sync(cwd, '@visualdl/netron3')); + const TracePath = path.dirname(resolve.sync(cwd, './public/static')); const wasmPath = path.dirname(resolve.sync(cwd, '@visualdl/wasm')); const dest = path.resolve(cwd, './dist/__snowpack__/link/packages'); @@ -102,6 +104,10 @@ export default { source: [path.join(netronPath2, '**/*')], destination: path.join(dest, 'netron2/dist') }, + // { + // source: [path.join(netronPath3, '**/*')], + // destination: path.join(dest, 'netron3/dist') + // }, { source: [path.join(TracePath, '**/*')], destination: path.join(dest, 'trace/dist') @@ -120,7 +126,7 @@ export default { }, packageOptions: { polyfillNode: true, - namedExports: ['gl-vec2', 'dagre'], + namedExports: [], // knownEntrypoints: ['chai', '@testing-library/react', 'fetch-mock/esm/client'] knownEntrypoints: ['chai', '@testing-library/react'] }, diff --git a/frontend/packages/core/src/App.tsx b/frontend/packages/core/src/App.tsx index 79403418..b857e82b 100644 --- a/frontend/packages/core/src/App.tsx +++ b/frontend/packages/core/src/App.tsx @@ -16,11 +16,11 @@ // cSpell:words pageview inited import 'antd/dist/antd.css'; -import React, {FunctionComponent, Suspense, useCallback, useEffect, useMemo, useState} from 'react'; -import {Redirect, Route, BrowserRouter as Router, Switch, useLocation, useHistory} from 'react-router-dom'; +import React, {FunctionComponent, Suspense, useCallback, useEffect, useMemo} from 'react'; +import {Redirect, Route, BrowserRouter as Router, Switch, useLocation} from 'react-router-dom'; import {THEME, matchMedia} from '~/utils/theme'; import {actions, selectors} from '~/store'; -import {headerHeight, position, size, zIndexes, setRem} from '~/utils/style'; +import {headerHeight, position, size, zIndexes} from '~/utils/style'; import {useDispatch, useSelector} from 'react-redux'; import ErrorBoundary from '~/components/ErrorBoundary'; import ErrorPage from '~/pages/error'; @@ -32,12 +32,19 @@ import {ToastContainer} from 'react-toastify'; import {fetcher} from '~/utils/fetch'; import routes from '~/routes'; import styled from 'styled-components'; -import {setDefaults, useTranslation} from 'react-i18next'; +import {useTranslation} from 'react-i18next'; const BASE_URI: string = import.meta.env.SNOWPACK_PUBLIC_BASE_URI; const Main = styled.main` padding-top: ${headerHeight}; + .ant-select-selector { + .ant-select-selection-item { + .select_icon { + display: none; + } + } + } `; const Header = styled.header` @@ -74,10 +81,9 @@ const Telemetry: FunctionComponent = () => { }, [location.pathname]); return null; }; - +const defaultRoute = ''; const App: FunctionComponent = () => { const {t, i18n} = useTranslation('errors'); - const [defaultRoute, setDefaultRoute] = useState(''); const dir = useMemo(() => (i18n.language ? i18n.dir(i18n.language) : ''), [i18n]); const dispatch = useDispatch(); diff --git a/frontend/packages/core/src/components/BarsChart.tsx b/frontend/packages/core/src/components/BarsChart.tsx index 62d5f2dc..49fb362c 100644 --- a/frontend/packages/core/src/components/BarsChart.tsx +++ b/frontend/packages/core/src/components/BarsChart.tsx @@ -14,9 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import * as chart from '~/utils/chart'; - import React, {useEffect, useImperativeHandle} from 'react'; import {primaryColor} from '~/utils/style'; import useECharts, {Options, Wrapper, useChartTheme} from '~/hooks/useECharts'; @@ -219,6 +216,7 @@ const Charts = React.forwardRef( }); echart?.setOption(chartOptions, {notMerge: true}); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [options, data, title, theme, i18n.language, echart, isLegend, units, text]); return ( diff --git a/frontend/packages/core/src/components/Check.tsx b/frontend/packages/core/src/components/Check.tsx index b68cbecb..a90c92d8 100644 --- a/frontend/packages/core/src/components/Check.tsx +++ b/frontend/packages/core/src/components/Check.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * diff --git a/frontend/packages/core/src/components/CurvesPage/CurveChart.tsx b/frontend/packages/core/src/components/CurvesPage/CurveChart.tsx index 6ab2e7b2..4af4200f 100644 --- a/frontend/packages/core/src/components/CurvesPage/CurveChart.tsx +++ b/frontend/packages/core/src/components/CurvesPage/CurveChart.tsx @@ -23,7 +23,6 @@ import {rem, size} from '~/utils/style'; import Chart from '~/components/Chart'; import {Chart as ChartLoader} from '~/components/Loader/ChartPage'; import ChartToolbox from '~/components/ChartToolbox'; -import type {EChartsOption} from 'echarts'; import TooltipTable from '~/components/TooltipTable'; import {cycleFetcher} from '~/utils/fetch'; import {format} from 'd3-format'; diff --git a/frontend/packages/core/src/components/DistributedChart.tsx b/frontend/packages/core/src/components/DistributedChart.tsx index fe5f2e5b..c1bcbf36 100644 --- a/frontend/packages/core/src/components/DistributedChart.tsx +++ b/frontend/packages/core/src/components/DistributedChart.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import * as chart from '~/utils/chart'; +// import * as chart from '~/utils/chart'; import React, {useEffect, useCallback} from 'react'; import {primaryColor} from '~/utils/style'; @@ -59,6 +59,7 @@ export type LineChartRef = { const DistributedChart = React.forwardRef( ({options, data, titles, loading, zoom, className, onInit}, ref) => { + console.log(ref); const {t} = useTranslation(['profiler', 'common']); const {i18n} = useTranslation(); diff --git a/frontend/packages/core/src/components/FastdeployGraph/CPUTables.tsx b/frontend/packages/core/src/components/FastdeployGraph/CPUTables.tsx new file mode 100644 index 00000000..98371a55 --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/CPUTables.tsx @@ -0,0 +1,93 @@ +import {Table} from 'antd'; +import type {ColumnsType} from 'antd/es/table'; +import React, {FunctionComponent, useEffect, useState} from 'react'; +import {useTranslation} from 'react-i18next'; + +interface DataType { + key: string; + name: string; + money: string; + address: string; +} + +type ArgumentProps = { + Datas: any; +}; +const App: FunctionComponent = ({Datas}) => { + const {t} = useTranslation(['Fastdeploy']); + const columns: ColumnsType = [ + { + title: t('Fastdeploy:Device-name'), + dataIndex: 'name', + key: 'name', + width: 100, + fixed: 'left' + }, + { + title: t('Fastdeploy:Performance-metric'), + children: [ + { + title: `${t('Fastdeploy:utilization')}(%)`, + dataIndex: 'nv_gpu_utilization', + key: 'nv_gpu_utilization', + width: 150 + }, + { + title: `${t('Fastdeploy:power-usage')}(W)`, + dataIndex: 'nv_gpu_power_usage', + key: 'nv_gpu_power_usage', + width: 150 + }, + { + title: `${t('Fastdeploy:power-limit')}(W)`, + dataIndex: 'nv_gpu_power_limit', + key: 'nv_gpu_power_limit', + width: 150 + }, + { + title: `${t('Fastdeploy:energy-consumption')}(W)`, + dataIndex: 'nv_energy_consumption', + key: 'nv_energy_consumption', + width: 150 + } + ] + }, + { + title: t('Fastdeploy:Memory'), + children: [ + { + title: `${t('Fastdeploy:total')}(GB)`, + dataIndex: 'nv_gpu_memory_total_bytes', + key: 'nv_gpu_memory_total_bytes', + width: 150 + }, + { + title: `${t('Fastdeploy:total')}(GB)`, + dataIndex: 'nv_gpu_memory_used_bytes', + key: 'nv_gpu_memory_used_bytes', + width: 150 + } + ] + } + ]; + const [tabelData, setTabelData] = useState(); + useEffect(() => { + if (!Datas) { + return; + } + const arrays = Object.keys(Datas); + const data = arrays.map((name: string) => { + const model = Datas[name]; + + return { + ...model, + key: name, + name: name + }; + }); + setTabelData(data); + }, [Datas]); + return ; +}; + +export default App; diff --git a/frontend/packages/core/src/components/FastdeployGraph/Clinet.tsx b/frontend/packages/core/src/components/FastdeployGraph/Clinet.tsx new file mode 100644 index 00000000..c509e1fb --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/Clinet.tsx @@ -0,0 +1,36 @@ +import React, {FunctionComponent} from 'react'; +import {useTranslation} from 'react-i18next'; +const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH; +// type ArgumentProps = { + +// }; +console.log('PUBLIC_PATH', PUBLIC_PATH, PUBLIC_PATH + '/api/fastdeploy/fastdeploy_client'); + +const ServerBox: FunctionComponent = () => { + // const {t} = useTranslation(['Fastdeploy']); + const {i18n} = useTranslation(['Fastdeploy']); + const language: string = i18n.language; + return ( +
+ +
+ ); +}; + +export default ServerBox; diff --git a/frontend/packages/core/src/components/FastdeployGraph/ModelTables.tsx b/frontend/packages/core/src/components/FastdeployGraph/ModelTables.tsx new file mode 100644 index 00000000..c7111d8a --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/ModelTables.tsx @@ -0,0 +1,122 @@ +import {Table} from 'antd'; +import type {ColumnsType} from 'antd/es/table'; +import React, {FunctionComponent, useEffect, useState} from 'react'; +import {useTranslation} from 'react-i18next'; +interface DataType { + key: string; + name: string; + money: string; + address: string; +} + +type ArgumentProps = { + Datas: any; +}; +const App: FunctionComponent = ({Datas}) => { + const [tabelData, setTabelData] = useState(); + const {t} = useTranslation(['Fastdeploy']); + const columns: ColumnsType = [ + { + title: t('Fastdeploy:Model-name'), + dataIndex: 'name', + key: 'name', + width: 100, + fixed: 'left' + }, + { + title: t('Fastdeploy:Execution-metric'), + children: [ + { + title: t('Fastdeploy:inference-request-success'), + dataIndex: 'nv_inference_request_success', + key: 'nv_inference_request_success', + width: 150 + }, + { + title: t('Fastdeploy:inference-request-failure'), + dataIndex: 'nv_inference_request_failure', + key: 'nv_inference_request_failure', + width: 150 + }, + { + title: t('Fastdeploy:inference-count'), + dataIndex: 'nv_inference_count', + key: 'nv_inference_count', + width: 150 + }, + { + title: t('Fastdeploy:inference-exec-count'), + dataIndex: 'nv_inference_exec_count', + key: 'nv_inference_exec_count', + width: 150 + } + ] + }, + { + title: t('Fastdeploy:Delay-metric'), + children: [ + { + title: `${t('Fastdeploy:inference-request-duration')}(ms)`, + dataIndex: 'nv_inference_request_duration_us', + key: 'nv_inference_request_duration_us', + width: 150 + }, + { + title: `${t('Fastdeploy:inference-queue-duration')}(ms)`, + dataIndex: 'nv_inference_queue_duration_us', + key: 'nv_inference_queue_duration_us', + width: 150 + }, + { + title: `${t('Fastdeploy:inference-comput-input-duration')}(ms)`, + dataIndex: 'nv_inference_compute_input_duration_us', + key: 'nv_inference_compute_input_duration_us', + width: 150 + }, + { + title: `${t('Fastdeploy:inference-compute-infer-duration')}(ms)`, + dataIndex: 'nv_inference_compute_infer_duration_us', + key: 'nv_inference_compute_infer_duration_us', + width: 150 + }, + { + title: `${t('Fastdeploy:inference-compute-output-duration')}(ms)`, + dataIndex: 'nv_inference_compute_output_duration_us', + key: 'nv_inference_compute_output_duration_us', + width: 150 + } + ] + } + ]; + useEffect(() => { + if (!Datas) { + return; + } + const arrays = Object.keys(Datas); + const data = arrays.map((name: string) => { + const model = Datas[name]; + + return { + ...model, + key: name, + name: name + }; + }); + setTabelData(data); + // for (let i = 0; i < 100; i++) { + // data.push({ + // key: i, + // name: 'John Brown', + // age: i + 1, + // street: 'Lake Park', + // building: 'C', + // number: 2035, + // companyAddress: 'Lake Street 42', + // companyName: 'SoftLake Co', + // gender: 'M', + // }); + }, [Datas]); + return
; +}; + +export default App; diff --git a/frontend/packages/core/src/components/FastdeployGraph/ServerConfig.tsx b/frontend/packages/core/src/components/FastdeployGraph/ServerConfig.tsx new file mode 100644 index 00000000..72ebda10 --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/ServerConfig.tsx @@ -0,0 +1,1329 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import React, {useState, useEffect, FunctionComponent} from 'react'; +import {MinusCircleOutlined, DownOutlined, VerticalAlignBottomOutlined} from '@ant-design/icons'; +import {Graph, Shape} from '@antv/x6'; +import {Form, Input, Select, Space} from 'antd'; +import type {TreeProps} from 'antd/es/tree'; +import {Tree} from 'antd'; +import styled from 'styled-components'; +import {Modal} from 'antd'; +// import {Child} from '../ProfilerPage/OperatorView/type'; +import {useTranslation} from 'react-i18next'; +const Content = styled.div` + height: 100%; + #container { + height: 100%; + display: flex; + border: 1px solid #dfe3e8; + .custom-html { + width: 100%; + height: 100%; + border-radius: 1em; + perspective: 600px; + text-align: center; + line-height: 40px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.25), 0 0.02125em 0.06125em rgba(0, 0, 0, 0.25); + } + } + #stencil_content { + min-width: 180px; + width: auto; + height: 100%; + position: relative; + border-right: 1px solid #dfe3e8; + display: flex; + justify-content: center; + flex-wrap: wrap; + border-left: 1px solid #dfe3e8; + .stencli_select { + height: 50px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + border-bottom: 1px solid #dfe3e8; + } + #stencil { + height: 80%; + .dnd-rect { + min-width: 100px; + width: auto; + height: 40px; + border: 1px solid #8f8f8f; + padding-left: 10px; + padding-right: 10px; + border-radius: 6px; + text-align: center; + line-height: 40px; + margin: 16px; + cursor: move; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + #buttonContent { + display: flex; + position: absolute; + width: 100%; + bottom: 1%; + display: flex; + justify-content: center; + } + } + .graph-containers { + width: calc(100% - 180px); + height: 100%; + // display: flex; + // align-items: center; + // justify-content: center; + } + .x6-widget-stencil { + background-color: #fff; + } + .x6-widget-stencil-title { + background-color: #fff; + } + .x6-widget-stencil-group-title { + background-color: #fff !important; + } + .x6-widget-transform { + margin: -1px 0 0 -1px; + padding: 0px; + border: 1px solid #239edd; + } + .x6-widget-transform > div { + border: 1px solid #239edd; + } + .x6-widget-transform > div:hover { + background-color: #3dafe4; + } + .x6-widget-transform-active-handle { + background-color: #3dafe4; + } + .x6-widget-transform-resize { + border-radius: 0; + } + .x6-widget-selection-inner { + border: 1px solid #239edd; + } + .x6-widget-selection-box { + opacity: 0; + } +`; +const SelectContent = styled.div` + height: 50px; + width: 100%; + display: flex; + align-items: center; + .ant-select { + .ant-select-selector { + height: 100%; + border: none; + .ant-select-selection-placeholder { + line-height: 50px; + } + .ant-select-selection-item { + line-height: 50px; + } + } + } +`; +const Buttons = styled.div` + height: 2.5714285714285716rem; + line-height: 2.5714285714285716rem; + text-align: center; + font-size: 16px; + margin-left: 2px; + width: 86px; + color: white; + background-color: var(--navbar-background-color); +`; +const formItems = ['name', 'backend', 'version', 'maxBatchSize', 'input', 'output', 'instanceGroup', 'optimization']; +const layout = { + labelCol: {span: 6}, + wrapperCol: {span: 16} +}; +const dataType = [ + 'TYPE_BOOL', + 'TYPE_UINT8', + 'TYPE_UINT16', + 'TYPE_UINT32', + 'TYPE_UINT64', + 'TYPE_INT8', + 'TYPE_INT16', + 'TYPE_INT32', + 'TYPE_INT64', + 'TYPE_FP16', + 'TYPE_FP32', + 'TYPE_FP64', + 'TYPE_STRING', + 'TYPE_BF16' +]; +const kindType = ['KIND_AUTO', 'KIND_GPU', 'KIND_CPU', 'KIND_MODEL']; +const {Option} = Select; +type ArgumentProps = { + modelData: any; + serverId: string; +}; +const ports = { + groups: { + top: { + position: 'top', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } + } + } + }, + bottom: { + position: 'bottom', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } + } + } + } + }, + items: [ + { + id: 'top', + group: 'top' + }, + // { + // id: 'right', + // group: 'right' + // }, + { + id: 'bottom', + group: 'bottom' + } + // { + // id: 'left', + // group: 'left' + // } + ] +}; +const ServerConfig: FunctionComponent = ({modelData, serverId}) => { + const graphContainer = `graph-containers${serverId}`; + // const [ModelDatas, setModelDatas] = useState(modelData); + const [steps, setSteps] = useState(); + const [selectOptions, setSelectOptions] = useState([]); + const [graphModel, setGraphModel] = useState(); + // const [modelName, setModelName] = useState(); + const [nodeClick, setNodeClick] = useState(); + const [showFlag, setShowFlag] = useState(); + const [IsEmsembles, setIsEmsembles] = useState(); + const [showGpus, setShowGpus] = useState({}); + const [isModalOpen, setIsModalOpen] = useState(false); + const [ensemblesName, setEnsemblesName] = useState(); + const [triggerClick, setTriggerClick] = useState(); + const [flag, setFlag] = useState(); + const [graphs, setGraphs] = useState(); + + const [form] = Form.useForm(); + const [treeData, setTreeData] = useState(modelData?.ensembles[0]?.versions); + const {t} = useTranslation(['Fastdeploy']); + const getmodelData = (model: any, name: string) => { + // setModelName(name); + setGraphModel(model); + const treedata = model.versions.map((version: any) => { + return { + ...version + }; + }); + setTreeData(treedata); + if (IsEmsembles) { + setIsEmsembles(false); + } + const flag = !showFlag; + setShowFlag(flag); + }; + const onFill = (models: any) => { + const newcpu = models?.optimization?.cpuExecutionAccelerator?.map((cpu: any) => { + const attr = Object.keys(cpu); + const attr2 = cpu[attr[1]] && Object.keys(cpu[attr[1]]); + const parameters = attr2?.map((key: any) => { + return { + key: key, + value: cpu?.parameters?.[key] + }; + }); + return { + name: cpu.name, + parameters: parameters + }; + }); + + const newgpu = models?.optimization?.gpuExecutionAccelerator?.map((gpu: any) => { + const attr = Object.keys(gpu); + const attr2 = gpu[attr[1]] && Object.keys(gpu[attr[1]]); + const parameters = attr2?.map((key: any) => { + return { + key: key, + value: gpu?.parameters?.[key] + }; + }); + return { + name: gpu.name, + parameters: parameters + }; + }); + + const modelss = { + ...models, + cpuExecutionAccelerator: newcpu, + gpuExecutionAccelerator: newgpu + }; + const newShowGpus = []; + if (modelss?.instanceGroup) { + for (const item of modelss?.instanceGroup) { + if (item.kind !== 'KIND_CPU' && item.kind !== 'KIND_MODEL') { + newShowGpus.push(true); + } else { + newShowGpus.push(false); + } + } + } + setShowGpus(newShowGpus); + // form.setFieldsValue({}); + for (const item of formItems) { + if (!modelss[item]) { + modelss[item] = undefined; + } + } + form.setFieldsValue(modelss); + }; + const changeEmsembles = () => { + setIsEmsembles(true); + setShowFlag(!showFlag); + // setTreeData(modelData.ensembles[0].versions); + const treedata = modelData.ensembles[0].versions.map((version: any) => { + return { + ...version + // checkable: false + // icon: + }; + }); + // const treedatas = getTreeData(modelData.ensembles[0].versions); + // const treedata = treedatas.map((version: any) => { + // return { + // ...version, + // checkable: true + // }; + // }); + setTreeData(treedata); + }; + const getTreeData = (treedata: any) => { + const treedatas = treedata.map((version: any) => { + let Child: any = ''; + if (version.children) { + Child = getTreeData(version.children); + } + if (Child) { + return { + ...version, + children: Child, + checkable: false + }; + } + return { + ...version, + checkable: false + }; + }); + return treedatas; + }; + const handleOk = () => { + // onfinish(); + setIsModalOpen(false); + }; + const handleCancel = () => { + setIsModalOpen(false); + if (nodeClick) { + setNodeClick(undefined); + } + }; + const onSelect: TreeProps['onSelect'] = (selectedKeys: any, info: any) => { + console.log('selected', selectedKeys, info); + }; + const showModal = () => { + setIsModalOpen(true); + }; + const EnsemblesNameChange = (value: string) => { + setEnsemblesName(value); + }; + useEffect(() => { + const graph = new Graph({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + container: document.getElementById(graphContainer)!, + grid: true, + mousewheel: { + enabled: false, + zoomAtMousePosition: true, + minScale: 0.5, + maxScale: 3 + // modifiers: ['ctrl', 'meta'] + }, + panning: false, + // scroller: { + // enabled: true, + // pannable: true, + // pageVisible: true, + // pageBreak: false + // }, + translating: { + restrict: false + }, + interacting: { + edgeMovable: false, + nodeMovable: false + }, + connecting: { + router: { + name: 'manhattan', + args: { + padding: 1 + } + }, + connector: { + name: 'rounded', + args: { + radius: 8 + } + }, + anchor: 'center', + connectionPoint: 'anchor', + allowBlank: false, + snap: { + radius: 20 + }, + createEdge() { + return new Shape.Edge({ + attrs: { + line: { + stroke: '#A2B1C3', + strokeWidth: 2, + targetMarker: { + name: 'block', + width: 12, + height: 8 + } + } + }, + zIndex: 0 + }); + }, + validateConnection({targetMagnet}) { + return !!targetMagnet; + } + }, + highlighting: { + magnetAdsorbed: { + name: 'stroke', + args: { + attrs: { + fill: '#5F95FF', + stroke: '#5F95FF' + } + } + } + } + }); + graph.on('node:dblclick', ({node}) => { + setTriggerClick({ + name: node.id + }); + }); + // debugger; + setGraphs(graph); + setFlag(true); + }, []); + useEffect(() => { + if (!triggerClick) { + return; + } + const name = triggerClick.name; + for (const model of modelData.models) { + if (model.name === name) { + setNodeClick({ + name: model.name, + data: model + }); + return; + } + } + }, [triggerClick]); + useEffect(() => { + if (!nodeClick) { + return; + } + getmodelData(nodeClick.data, nodeClick.name); + }, [nodeClick]); + useEffect(() => { + if (!modelData) { + return; + } + console.log('modelData.ensembles', modelData?.ensembles); + const SelectOptions = modelData?.ensembles?.map((ensembles: any) => { + return { + value: ensembles.name, + label: ensembles.name + }; + }); + setEnsemblesName(modelData.ensembles[0]?.name); + // setModelDatas(modelData); + setSelectOptions(SelectOptions); + }, [modelData]); + useEffect(() => { + if (!ensemblesName || !modelData) { + return; + } + console.log('modelData.ensembles', modelData.ensembles); + const ensembles = modelData.ensembles?.filter((ensembles: any) => { + if (ensembles.name === ensemblesName) { + return ensembles; + } + }); + setSteps(ensembles[0]?.step); + if (ensembles[0]?.versions) { + const treedatas = getTreeData(ensembles[0]?.versions); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true, + icon: + }; + }); + setTreeData(treedata); + } else { + setTreeData([]); + } + }, [ensemblesName]); + useEffect(() => { + if (!flag || !steps) { + return; + } + // debugger; + graphs?.clearCells(); + const edgeMap: any = {}; + + steps?.map((node: any) => { + const inputs = node.inputModels; + for (const input of inputs) { + let tuple = edgeMap[input]; + if (!tuple) { + tuple = {from: [], to: []}; + edgeMap[input] = tuple; + } + tuple.to.push(node.modelName); + } + const outputs = node.outputModels; + for (const output of outputs) { + let tuple = edgeMap[output]; + if (!tuple) { + tuple = {from: [], to: []}; + edgeMap[output] = tuple; + } + tuple.from.push(node.modelName); + } + }); + + console.log('edgeMap', edgeMap); + const edges = []; + const nodes = []; + for (const name of Object.keys(edgeMap)) { + nodes.push({ + id: `${name}`, + width: 60, + height: 40, + label: name + }); + const node = edgeMap[name]; + for (const output of node.to) { + // edges.push([name, output]); + edges.push({ + source: name, + target: output + }); + } + console.log('nodes', nodes); + console.log('edges', edges); + } + + const nodeEdges = []; + for (const edge of edges) { + nodeEdges.push({ + source: { + cell: edge.source, + connectionPoint: { + name: 'boundary', + args: { + sticky: true + } + } + }, + target: {cell: edge.target, connectionPoint: 'boundary'}, // 没有参数时可以简化写法}, + // shape: 'custom-edge', + // tools: ['vertices', 'segments'], + // 基类 + inherit: 'edge', + // 属性样式 + attrs: { + line: { + stroke: '#5755a1' + } + }, + // 默认标签 + defaultLabel: { + markup: [ + { + tagName: 'rect', + selector: 'body' + }, + { + tagName: 'text', + selector: 'label' + } + ], + attrs: { + label: { + fill: 'black', + fontSize: 14, + textAnchor: 'middle', + textVerticalAnchor: 'middle', + pointerEvents: 'none' + }, + body: { + ref: 'label', + fill: 'white', + stroke: '#5755a1', + strokeWidth: 2, + rx: 4, + ry: 4, + refWidth: '140%', + refHeight: '140%', + refX: '-20%', + refY: '-20%' + } + }, + position: { + distance: 100, // 绝对定位 + options: { + absoluteDistance: true + } + } + } + }); + } + + const nodess: any = []; + const postions: any = {}; + let max = 0; + for (const step of steps) { + const name = step.modelName; + if (name.length > max) { + max = name.length; + } + postions[name] = { + x: step['pos_x'], + y: step['pos_y'], + lengths: name.length + }; + } + for (let index = 0; index < nodes.length; index++) { + const node = nodes[index]; + const postion = postions[node?.id]; + Shape.HTML.register({ + shape: node.id, + width: 10 + max * 10, + // width: 10 + postion['lengths'] * 10, + height: 40, + html() { + const div = document.createElement('div'); + const textNode = document.createTextNode(node.id); + div.className = 'custom-html'; + div.appendChild(textNode); + return div; + } + }); + + // debugger; + // const HtmlNode = graphs?.createNode(); + nodess.push({ + id: node.id, + shape: node.id, + size: { + width: 10 + max * 10, + height: 40 + }, + x: 300 + postion.x * 90, + y: 50 + postion.y * 80, + ports: ports + // tools: ['button-remove'] + }); + } + console.log('nodess', nodess, Shape.HTML.shapeMaps); + // debugger; + graphs?.fromJSON({ + nodes: nodess, + edges: nodeEdges + }); + // setFlag(false); + setGraphs(graphs); + }, [steps, flag]); + useEffect(() => { + if (showFlag !== undefined) { + showModal(); + } + }, [showFlag]); + useEffect(() => { + if (isModalOpen && modelData) { + if (!IsEmsembles) { + graphModel && onFill(graphModel); + } else { + // modelData && onFill(modelData.ensembles[0]); + for (const ensembles of modelData.ensembles) { + // debugger; + if (ensembles.name === ensemblesName) { + onFill(ensembles); + return; + } + } + } + } + }, [isModalOpen, graphModel, IsEmsembles]); + + return ( + +
+
+ {/* */} +
+
+
+
+ + + + {!IsEmsembles ? ( + + + + ) : ( + + + + )} + {/* + + */} + + } + defaultExpandedKeys={['0-0-0']} + selectable={true} + onSelect={onSelect} + treeData={treeData} + /> + + + + + + + {fields => ( +
+ {fields?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:variable')}${index + 1}`}
+ {/* remove(field.name)} /> */} +
+
+ + + + + + + + + +
+
+ ))} + + {/* + + */} +
+ )} +
+
+
+ + + {fields2 => ( +
+ {fields2?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:variable')}${index + 1}`}
+ {/* remove(field.name)} /> */} +
+
+ + + + + + + + + +
+
+ ))} + + {/* + + */} +
+ )} +
+
+ + + {(fields3, {}) => ( +
+ {fields3?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:instance')}${index + 1}`}
+ {/* remove(field.name)} /> */} +
+
+ + + + + {/* */} + {/* */} + + + {showGpus[index] && ( + + + + )} +
+
+ ))} + + + {/* */} + +
+ )} +
+
+ +
+ + {(fields4, {}) => ( +
+
+
{`cpuExecutionAccelerator`}
+ {/* add()} /> */} +
+ {fields4?.map(field => ( + +
+
+ + + + remove(field.name)} + /> +
+ + + {(fields5, {}) => ( +
+
+
+ parameters +
+ {/* addTest()} /> */} +
+ {fields5?.map(fields => ( + + + + + + + + removeTest(fields.name)} + /> + + ))} +
+ )} +
+
+
+
+ ))} +
+ )} +
+
+
+ + {(fields6, {}) => ( +
+
+
{`gpuExecutionAccelerator`}
+ {/* add()} /> */} +
+ {fields6?.map(field => ( + +
+
+ + + + remove(field.name)} + /> +
+ + + {(fields7, {}) => ( +
+
+
+ parameters +
+ {/* addTest()} /> */} +
+ {fields7?.map(fields => ( + + + + + + + + removeTest(fields.name)} + /> + + ))} +
+ )} +
+
+
+
+ ))} +
+ )} +
+
+
+ + + + ); +}; + +export default ServerConfig; diff --git a/frontend/packages/core/src/components/FastdeployGraph/index.tsx b/frontend/packages/core/src/components/FastdeployGraph/index.tsx new file mode 100644 index 00000000..dc4faad9 --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/index.tsx @@ -0,0 +1,2684 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable prettier/prettier */ +import styled from 'styled-components'; +import React, {useState, useEffect, useRef, FunctionComponent, useCallback} from 'react'; +// import {rem, primaryColor, size} from '~/utils/style'; +import {Graph, Shape} from '@antv/x6'; +import {Modal, Cascader} from 'antd'; +import {toast} from 'react-toastify'; +// import dagre from 'dagre'; +// import {DagreLayout} from '@antv/layout'; +// import {Stencil} from '@antv/x6-plugin-stencil'; +// import {Transform} from '@antv/x6-plugin-transform'; +// import {Selection} from '@antv/x6-plugin-selection'; +import {Snapline} from '@antv/x6-plugin-snapline'; +import {Keyboard} from '@antv/x6-plugin-keyboard'; +import {Clipboard} from '@antv/x6-plugin-clipboard'; +import {Export} from '@antv/x6-plugin-export'; +import {DownOutlined} from '@ant-design/icons'; +import {Tree} from 'antd'; +import {fetcher} from '~/utils/fetch'; +// import {Dnd} from '@antv/x6-plugin-dnd'; +import {useTranslation} from 'react-i18next'; +import {History} from '@antv/x6-plugin-history'; +import { + MinusCircleOutlined, + PlusOutlined, + PlusCircleOutlined, + VerticalAlignBottomOutlined, + DeleteOutlined +} from '@ant-design/icons'; +import {Button, Form, Input, Select, Space} from 'antd'; +import {isArray} from 'lodash'; +const {TreeNode} = Tree; +import {div} from 'numeric'; +const Content = styled.div` + height: 100%; + .ant-select-selector { + .ant-select-selection-item { + .select_icon { + display: none; + } + } + } + #container { + height: 100%; + display: flex; + border: 1px solid #dfe3e8; + .custom-html { + width: 100%; + height: 100%; + border-radius: 1em; + perspective: 600px; + text-align: center; + line-height: 40px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.25), 0 0.02125em 0.06125em rgba(0, 0, 0, 0.25); + } + } + #stencil_content { + min-width: 180px; + width: auto; + height: 100%; + position: relative; + border-right: 1px solid #dfe3e8; + display: flex; + justify-content: center; + flex-wrap: wrap; + border-left: 1px solid #dfe3e8; + .stencli_select { + height: 50px; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + border-bottom: 1px solid #dfe3e8; + } + #stencil { + height: 80%; + .dnd-rect { + min-width: 100px; + width: auto; + height: 40px; + border: 1px solid #8f8f8f; + padding-left: 10px; + padding-right: 10px; + border-radius: 6px; + text-align: center; + line-height: 40px; + margin: 16px; + cursor: move; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + #buttonContent { + display: flex; + position: absolute; + width: 100%; + bottom: 1%; + display: flex; + justify-content: center; + } + } + #graph-container { + width: calc(100% - 180px); + height: 100%; + } + .x6-widget-stencil { + background-color: #fff; + } + .x6-widget-stencil-title { + background-color: #fff; + } + .x6-widget-stencil-group-title { + background-color: #fff !important; + } + .x6-widget-transform { + margin: -1px 0 0 -1px; + padding: 0px; + border: 1px solid #239edd; + } + .x6-widget-transform > div { + border: 1px solid #239edd; + } + .x6-widget-transform > div:hover { + background-color: #3dafe4; + } + .x6-widget-transform-active-handle { + background-color: #3dafe4; + } + .x6-widget-transform-resize { + border-radius: 0; + } + .x6-widget-selection-inner { + border: 1px solid #239edd; + } + .x6-widget-selection-box { + opacity: 0; + } +`; +const SelectContent = styled.div` + height: 50px; + width: 100%; + display: flex; + align-items: center; + .ant-select { + .ant-select-selector { + height: 100%; + border: none; + .ant-select-selection-placeholder { + line-height: 50px; + } + .ant-select-selection-item { + line-height: 50px; + } + } + } +`; +const Buttons = styled.div` + height: 2.5714285714285716rem; + line-height: 2.5714285714285716rem; + text-align: center; + font-size: 16px; + margin-left: 2px; + padding-left: 5px; + padding-right: 5px; + min-width: 86px; + color: white; + background-color: var(--navbar-background-color); +`; +const Buttons2 = styled(Buttons)` + min-width: 138px; + height: 32px; + padding-left: 5px; + padding-right: 5px; + line-height: 32px; + padding-left: 5px; + padding-right: 5px; + margin-left: 20px; +`; +const {Option} = Select; +const layout = { + labelCol: {span: 6}, + wrapperCol: {span: 16} +}; +interface Option { + value: string | number; + label: string; + children?: Option[]; +} +const dataType = [ + 'TYPE_BOOL', + 'TYPE_UINT8', + 'TYPE_UINT16', + 'TYPE_UINT32', + 'TYPE_UINT64', + 'TYPE_INT8', + 'TYPE_INT16', + 'TYPE_INT32', + 'TYPE_INT64', + 'TYPE_FP16', + 'TYPE_FP32', + 'TYPE_FP64', + 'TYPE_STRING', + 'TYPE_BF16' +]; +const kindType = ['KIND_AUTO', 'KIND_GPU', 'KIND_CPU', 'KIND_MODEL']; +type ArgumentProps = { + // upModels: (dirValues: string) => void; + modelData: any; + dirValue?: any; + ChangeServerId?: any; +}; +const formItems = ['name', 'backend', 'version', 'maxBatchSize', 'input', 'output', 'instanceGroup', 'optimization']; +const Index: FunctionComponent = ({modelData, dirValue, ChangeServerId}) => { + // #region 初始化图形 + const [ModelDatas, setModelDatas] = useState(modelData); + const [flag, setFlag] = useState(); + const [flag2, setFlag2] = useState(); + // const [Dnds, setDnds] = useState(); + const [graphs, setGraphs] = useState(); + // const [edgeMaps, setEdgeMaps] = useState({}); + const [showGpus, setShowGpus] = useState({}); + + const configs = { + 'server-name': null, + 'model-repository': 'yolov5_serving/models', + 'backend-config': 'python,shm-default-byte-size=10485760', + 'http-port': 8000, + 'grpc-port': 8001, + 'metrics-port': 8002, + gpus: null + }; + const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalOpen2, setIsModalOpen2] = useState(false); + const [isModalOpen3, setIsModalOpen3] = useState(false); + const [isModalOpen4, setIsModalOpen4] = useState(false); + const [isModalOpen5, setIsModalOpen5] = useState(false); + const [isModalOpen6, setIsModalOpen6] = useState(false); + const [isModalOpen7, setIsModalOpen7] = useState(false); + + const dndContainerRef = useRef(null); + const [graphModel, setGraphModel] = useState(); + const [filenames, setFilenames] = useState([]); + // const [config_filename, setConfig_filename] = useState(''); + const [modelName, setModelName] = useState(); + + const [IsEmsembles, setIsEmsembles] = useState(); + const [showFlag, setShowFlag] = useState(false); + const [Isopen, setIsopen] = useState(false); + const [selectOptions, setSelectOptions] = useState([]); + // const [ensembles, setEmsembles] = useState(); + const [steps, setSteps] = useState(); + const [nodeClick, setNodeClick] = useState(); + const [triggerClick, setTriggerClick] = useState(); + const [ensemblesName, setEnsemblesName] = useState(); + const [selectKeys, setSelectKeys] = useState(); + const [configsButton, setConfigsButton] = useState(true); + const [version, setVersion] = useState(); + const [CascaderOptions, setCascaderOptions] = useState([]); + + // const iframe = useRef(null); + const [form] = Form.useForm(); + const [form2] = Form.useForm(); + const [form3] = Form.useForm(); + const [form4] = Form.useForm(); + + const [svgs, setSvgs] = useState(); + console.log('form', form.getFieldsValue(true)); + + const [treeData, setTreeData] = useState(modelData?.ensembles?.versions); + const {t, i18n} = useTranslation(['Fastdeploy']); + const language: string = i18n.language; + const ports = { + groups: { + top: { + position: 'top', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } + } + } + }, + bottom: { + position: 'bottom', + attrs: { + circle: { + r: 4, + magnet: true, + stroke: '#5F95FF', + strokeWidth: 1, + fill: '#fff', + style: { + visibility: 'hidden' + } + } + } + } + }, + items: [ + { + id: 'top', + group: 'top' + }, + // { + // id: 'right', + // group: 'right' + // }, + { + id: 'bottom', + group: 'bottom' + } + // { + // id: 'left', + // group: 'left' + // } + ] + }; + useEffect(() => { + const graph = new Graph({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + container: document.getElementById('graph-container')!, + grid: true, + mousewheel: { + enabled: true, + zoomAtMousePosition: true, + minScale: 0.5, + maxScale: 3 + // modifiers: ['ctrl', 'meta'] + }, + panning: true, + // scroller: { + // enabled: true, + // pannable: true, + // pageVisible: true, + // pageBreak: false + // }, + connecting: { + router: { + name: 'manhattan', + args: { + padding: 1 + } + }, + connector: { + name: 'rounded', + args: { + radius: 8 + } + }, + anchor: 'center', + connectionPoint: 'anchor', + allowBlank: false, + snap: { + radius: 20 + }, + createEdge() { + return new Shape.Edge({ + attrs: { + line: { + stroke: '#A2B1C3', + strokeWidth: 2, + targetMarker: { + name: 'block', + width: 12, + height: 8 + } + } + }, + zIndex: 0 + }); + }, + validateConnection({targetMagnet}) { + return !!targetMagnet; + } + }, + highlighting: { + magnetAdsorbed: { + name: 'stroke', + args: { + attrs: { + fill: '#5F95FF', + stroke: '#5F95FF' + } + } + } + } + }); + // Graph.registerEdge( + // 'custom-edge', // 边名称 + + // ); + // const dnd = new Dnd({ + // target: graph, + // scaled: false, + // dndContainer: dndContainerRef.current + // }); + // setDnds(dnd); + graph.on('node:dblclick', ({node}) => { + setTriggerClick({ + name: node.id + }); + }); + setGraphs(graph); + setFlag(true); + }, []); + useEffect(() => { + if (!flag || !graphs) { + return; + } + graphPlug(graphs); + }, [flag]); + useEffect(() => { + if (flag2 && graphs) { + graphRegion(graphs); + } + }, [flag2]); + useEffect(() => { + if (!modelData) { + return; + } + console.log('modelData.ensembles', modelData?.ensembles); + if (modelData?.ensembles.length === 0) { + setEnsemblesName(''); + setSelectOptions([]); + } else { + const SelectOptions = modelData?.ensembles?.map((ensembles: any) => { + return { + value: ensembles.name, + label: ensembles.name + }; + }); + setSelectOptions(SelectOptions); + setEnsemblesName(modelData.ensembles[0]?.name); + } + + setModelDatas(modelData); + }, [modelData]); + useEffect(() => { + if (ensemblesName === undefined || !modelData) { + return; + } + console.log('modelData.ensembles', modelData.ensembles); + const ensembles = modelData.ensembles?.filter((ensembles: any) => { + if (ensembles.name === ensemblesName) { + return ensembles; + } + }); + if (ensembles?.length) { + setSteps(ensembles[0]?.step); + if (ensembles[0]?.versions) { + const treedatas = getTreeData(ensembles[0]?.versions); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true, + icon: + }; + }); + setTreeData(treedata); + } else { + setTreeData([]); + } + } else { + setSteps([]); + setTreeData([]); + } + }, [ensemblesName]); + useEffect(() => { + if (!flag || !steps) { + return; + } + graphs?.clearCells(); + const edgeMap: any = {}; + + steps?.map((node: any) => { + const inputs = node.inputModels; + for (const input of inputs) { + let tuple = edgeMap[input]; + if (!tuple) { + tuple = {from: [], to: []}; + edgeMap[input] = tuple; + } + tuple.to.push(node.modelName); + } + const outputs = node.outputModels; + for (const output of outputs) { + let tuple = edgeMap[output]; + if (!tuple) { + tuple = {from: [], to: []}; + edgeMap[output] = tuple; + } + tuple.from.push(node.modelName); + } + }); + const edges = []; + const nodes = []; + for (const name of Object.keys(edgeMap)) { + // Shape.HTML.register({ + // shape: name, + // width: 60, + // height: 40, + // html() { + // const div = document.createElement('div'); + // const textNode = document.createTextNode(name); + // div.className = 'custom-html'; + // div.appendChild(textNode); + // return div; + // } + // }); + nodes.push({ + id: `${name}`, + width: 60, + height: 40, + label: name + }); + const node = edgeMap[name]; + for (const output of node.to) { + // edges.push([name, output]); + edges.push({ + source: name, + target: output + }); + } + console.log('nodes', nodes); + console.log('edges', edges); + // const dagreLayout = new DagreLayout({ + // type: 'dagre', + // rankdir: 'BT', + // align: 'UR', + // ranksep: 35, + // nodesep: 15, + // controlPoints: true + // }); + // const data = { + // edges: edges, + // nodes: nodes + // }; + // const model = dagreLayout.layout(data); + // console.log('model', model); + } + + const nodeEdges = []; + for (const edge of edges) { + nodeEdges.push({ + source: { + cell: edge.source, + connectionPoint: { + name: 'boundary', + args: { + sticky: true + } + } + }, + target: {cell: edge.target, connectionPoint: 'boundary'}, // 没有参数时可以简化写法}, + // shape: 'custom-edge', + // tools: ['vertices', 'segments'], + // 基类 + inherit: 'edge', + // 属性样式 + attrs: { + line: { + stroke: '#5755a1' + } + }, + // 默认标签 + defaultLabel: { + markup: [ + { + tagName: 'rect', + selector: 'body' + }, + { + tagName: 'text', + selector: 'label' + } + ], + attrs: { + label: { + fill: 'black', + fontSize: 14, + textAnchor: 'middle', + textVerticalAnchor: 'middle', + pointerEvents: 'none' + }, + body: { + ref: 'label', + fill: 'white', + stroke: '#5755a1', + strokeWidth: 2, + rx: 4, + ry: 4, + refWidth: '140%', + refHeight: '140%', + refX: '-20%', + refY: '-20%' + } + }, + position: { + distance: 100, // 绝对定位 + options: { + absoluteDistance: true + } + } + } + }); + } + + const nodess: any = []; + const postions: any = {}; + let max = 0; + for (const step of steps) { + const name = step.modelName; + if (name.length > max) { + max = name.length; + } + postions[name] = { + x: step['pos_x'], + y: step['pos_y'], + lengths: name.length + }; + } + for (let index = 0; index < nodes.length; index++) { + const node = nodes[index]; + // debugger; + // debugger; + // const registers = Object.keys(Shape.HTML.shapeMaps); + // if (!registers.includes(node.id)) { + // Shape.HTML.register({ + // shape: node.id, + // width: 60, + // height: 40, + // html() { + // const div = document.createElement('div'); + // const textNode = document.createTextNode(node.id); + // div.className = 'custom-html'; + // div.appendChild(textNode); + // return div; + // } + // }); + // } + const postion = postions[node?.id]; + Shape.HTML.register({ + shape: node.id, + width: 10 + max * 10, + // width: 10 + postion['lengths'] * 10, + height: 40, + html() { + const div = document.createElement('div'); + const textNode = document.createTextNode(node.id); + div.className = 'custom-html'; + div.appendChild(textNode); + return div; + } + }); + + // debugger; + // const HtmlNode = graphs?.createNode(); + nodess.push({ + id: node.id, + shape: node.id, + size: { + width: 10 + max * 10, + height: 40 + }, + x: 300 + postion.x * 90, + y: 50 + postion.y * 80, + ports: ports + // tools: ['button-remove'] + }); + // debugger; + // debugger; + // graphs?.addEdges(nodeEdges); + // nodess?.push({ + // id: node.id, + // x: 300 + edgeMaps2[node.id] * 120, + // y: 100, + // width: 60, + // height: 40, + // shape: 'html', + // size: { + // width: 60, + // height: 40 + // }, + // html: { + // render(node: Cell) { + // return `
+ // ${node.id} + //
`; + // } + // }, + // shouldComponentUpdate(node: Cell) { + // return node.hasChanged('data'); + // }, + // ports: ports + // }); + // debugger; + } + console.log('nodess', nodess, Shape.HTML.shapeMaps); + // debugger; + // graphs?.addNodes(nodess); + // debugger; + graphs?.fromJSON({ + nodes: nodess, + edges: nodeEdges + }); + // setFlag(false); + setGraphs(graphs); + }, [steps, flag]); + const graphPlug = (graph: any) => { + // graph.use( + // new Transform({ + // resizing: true, + // rotating: true + // }) + // ); + // graph.use( + // new Selection({ + // enabled: true, + // rubberband: true, + // showNodeSelectionBox: true + // }) + // ); + graph.use(new Export()); + graph.use( + new Snapline({ + enabled: true, + sharp: true + }) + ); + graph.use( + new Keyboard({ + enabled: true + }) + ); + graph.use( + new Clipboard({ + enabled: true + }) + ); + graph.use( + new History({ + enabled: true + }) + ); + setFlag2(true); + }; + const getTreeData = (treedata: any) => { + const treedatas = treedata?.map((version: any) => { + let Child: any = ''; + if (version.children) { + Child = getTreeData(version.children); + } + if (Child) { + return { + ...version, + children: Child, + selectable: false + }; + } + return { + ...version, + selectable: false + }; + }); + return treedatas; + }; + const showPorts = (ports: NodeListOf, show: boolean) => { + for (let i = 0, len = ports.length; i < len; i = i + 1) { + ports[i].style.visibility = show ? 'visible' : 'hidden'; + } + }; + const graphRegion = (graph: any) => { + graph.bindKey(['meta+c', 'ctrl+c'], () => { + const cells = graph.getSelectedCells(); + if (cells.length) { + graph.copy(cells); + } + return false; + }); + graph.bindKey(['meta+x', 'ctrl+x'], () => { + const cells = graph.getSelectedCells(); + if (cells.length) { + graph.cut(cells); + } + return false; + }); + graph.bindKey(['meta+v', 'ctrl+v'], () => { + if (!graph.isClipboardEmpty()) { + const cells = graph.paste({offset: 32}); + graph.cleanSelection(); + graph.select(cells); + } + return false; + }); + + //undo redo + graph.bindKey(['meta+z', 'ctrl+z'], () => { + if (graph.canUndo()) { + graph.undo(); + } + return false; + }); + graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => { + if (graph.canRedo()) { + graph.redo(); + } + return false; + }); + + // select all + graph.bindKey(['meta+a', 'ctrl+a'], () => { + const nodes = graph.getNodes(); + if (nodes) { + graph.select(nodes); + } + }); + + //delete + graph.bindKey('backspace', () => { + const cells = graph.getSelectedCells(); + if (cells.length) { + graph.removeCells(cells); + } + }); + + // zoom + graph.bindKey(['ctrl+1', 'meta+1'], () => { + const zoom = graph.zoom(); + if (zoom < 1.5) { + graph.zoom(0.1); + } + }); + graph.bindKey(['ctrl+2', 'meta+2'], () => { + const zoom = graph.zoom(); + if (zoom > 0.5) { + graph.zoom(-0.1); + } + }); + graph.on('node:mouseenter', () => { + const container = document.getElementById('graph-container')!; + const ports = container.querySelectorAll('.x6-port-body') as NodeListOf; + showPorts(ports, true); + }); + graph.on('node:mouseleave', () => { + const container = document.getElementById('graph-container')!; + const ports = container.querySelectorAll('.x6-port-body') as NodeListOf; + showPorts(ports, false); + }); + }; + const upModelData = (name: any, dir: string, config: any) => { + // debugger; + let formBody: any = []; + const details: any = { + name: name, + dir: dir, + config: JSON.stringify(config) + }; + // debugger; + // if (config_filename) { + // details['config_filename'] = config_filename; + // } + details['config_filename'] = form.getFieldValue('config_filenames'); + for (const property in details) { + const encodedKey = encodeURIComponent(property); + const encodedValue = encodeURIComponent(details[property]); + formBody.push(encodedKey + '=' + encodedValue); + } + formBody = formBody.join('&'); + // formData.append('name', name); + // formData.append('dir', dir); + // formData.append('config', JSON.stringify(config)); + fetcher(`/fastdeploy/config_update`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' + }, + body: formBody + }).then( + (res: any) => { + console.log('blobres', res); + // debugger; + // downloadEvt(res.data, fileName); + // setConfig_filename(''); + setModelDatas(config); + setIsModalOpen(false); + const message = + language === 'zh' ? `${name} 更新配置成功` : `Update ${name} configuration successfully`; + toast.success(message, { + autoClose: 2000 + }); + }, + res => { + console.log('blobres', res); + } + ); + }; + // const startDrag = (e: React.MouseEvent) => { + // const target = e.currentTarget; + // const type = target.getAttribute('data-type'); + // console.log('types', target, e); + // showModal(); + // }; + const showModal = () => { + setIsModalOpen(true); + }; + + const handleOk = () => { + // onfinish(); + if (!configsButton) { + toast.error(t('Fastdeploy:Backup-config'), { + autoClose: 2000 + }); + return; + } + form?.validateFields() + .then(async values => { + // debugger; + // setIsModalOpen(false); + const ModelData = ModelDatas; + // debugger; + const newcpuExecutionAccelerator = values.cpuExecutionAccelerator?.map((item: any) => { + // const parameters = + const newObject: any = {}; + // newObject[item.key] = item.value; + if (item.parameters) { + for (const param of item.parameters) { + newObject[param['key']] = param['value']; + } + } + + return { + name: item.name, + parameters: newObject + }; + }); + const newgpuExecutionAccelerator = values.gpuExecutionAccelerator?.map((item: any) => { + const newObject: any = {}; + if (item.parameters) { + for (const param of item.parameters) { + newObject[param['key']] = param['value']; + } + } + return { + name: item.name, + parameters: newObject + }; + }); + const newInput = values.input.map((input: any) => { + const type = isArray(input.dims); + const dimss = type ? input.dims : input.dims.split(','); + return { + ...input, + dims: dimss + }; + }); + + const newOutput = values.output.map((output: any) => { + const type = isArray(output.dims); + const dimss = type ? output.dims : output.dims.split(','); + return { + ...output, + dims: dimss + }; + }); + const newInstanceGroups = values.instanceGroup.map((group: any) => { + if (group.gpus) { + const type = isArray(group.gpus); + const gpuss = type ? group.gpus : group.gpus.split(','); + return { + ...group, + gpus: gpuss + }; + } else { + return { + ...group + }; + } + }); + if (IsEmsembles) { + console.log('values', values); + const emsembless = ModelDatas.ensembles?.map((ensembles: any) => { + if (ensembles.name === ensemblesName) { + const newemsembles = { + ...ensembles, + ...values, + input: newInput, + output: newOutput, + instanceGroup: newInstanceGroups, + optimization: { + cpuExecutionAccelerator: newcpuExecutionAccelerator, + gpuExecutionAccelerator: newgpuExecutionAccelerator + } + }; + + delete newemsembles['cpuExecutionAccelerator']; + delete newemsembles['gpuExecutionAccelerator']; + return newemsembles; + } else { + return ensembles; + } + }); + ModelData.ensembles = emsembless; + // setModelDatas(ModelData); + console.log('ModelDatas', ModelData); + + upModelData(ensemblesName, dirValue, ModelData); + // await getModelData(dirValue); + // setIsModalOpen(false); + } else { + // debuggersss; + const models = ModelData.models?.map((model: any) => { + if (model.name === modelName) { + const newmodel = { + ...model, + ...values, + input: newInput, + output: newOutput, + instanceGroup: newInstanceGroups, + optimization: { + cpuExecutionAccelerator: newcpuExecutionAccelerator, + gpuExecutionAccelerator: newgpuExecutionAccelerator + } + }; + const newInstanceGroup = newmodel.instanceGroup.map((item: any) => { + if (item.kind !== 'KIND_CPU' && item.kind !== 'KIND_MODEL') { + return item; + } else { + return { + count: item.count, + gpus: undefined, + kind: item.kind + }; + } + }); + newmodel.instanceGroup = newInstanceGroup; + delete newmodel['cpuExecutionAccelerator']; + delete newmodel['gpuExecutionAccelerator']; + return newmodel; + } else { + return model; + } + }); + // models.delete('cpuExecutionAccelerator'); + // models.delete('gpuExecutionAccelerator'); + ModelData.models = models; + console.log('ModelDatas', ModelData); + upModelData(modelName, dirValue, ModelData); + // await getModelData(dirValue); + // setModelDatas(ModelData); + } + }) + .catch(errorInfo => { + console.log('errorInfo', errorInfo); + // alert(errorInfo); + }); + }; + const handleOk2 = () => { + // console.log(111); + // setIsModalOpen2(false); + form2 + ?.validateFields() + .then(values => { + const bodys = { + ...values, + default_model_name: ensemblesName + }; + if (svgs) { + bodys['ensemble-img'] = svgs; + } + let formBody: any = []; + const details: any = { + config: JSON.stringify(bodys) + }; + // debugger; + for (const property in details) { + const encodedKey = encodeURIComponent(property); + const encodedValue = encodeURIComponent(details[property]); + formBody.push(encodedKey + '=' + encodedValue); + } + formBody = formBody.join('&'); + console.log('formBody', formBody); + + fetcher(`/fastdeploy/start_server`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' + }, + body: formBody + }).then( + (res: any) => { + console.log('resss', res); + // ChangeServerId(res.id); + ChangeServerId(res); + setIsModalOpen2(false); + toast.success(t('Fastdeploy:Launch-server-successfully'), { + autoClose: 2000 + }); + }, + res => { + console.log(res); + setIsModalOpen2(false); + } + ); + }) + .catch(errorInfo => { + alert(errorInfo); + }); + }; + const handleOk3 = () => { + // console.log(111); + // setIsModalOpen2(false); + form3 + ?.validateFields() + .then(values => { + console.log('valuesssss', values); + + const pretrain_model_name = values.models[values.models.length - 1]; + // const version = selectedKeys[0]; + const name = IsEmsembles ? ensemblesName : modelName; + fetcher( + '/fastdeploy/download_pretrain_model' + + `?dir=${dirValue}` + + `&name=${name}` + + `&version=${version}` + + `&pretrain_model_name=${pretrain_model_name}` + ).then( + (res: any) => { + const ModelData = ModelDatas; + if (IsEmsembles) { + console.log('values', values); + + const emsembless = ModelDatas.ensembles?.map((ensembles: any) => { + if (ensembles.name === ensemblesName) { + const newemsembles = { + ...ensembles, + versions: res + }; + return newemsembles; + } else { + return ensembles; + } + }); + ModelData.ensembles = emsembless; + // await getModelData(dirValue); + // setIsModalOpen(false); + } else { + // debuggersss; + const models = ModelData.models?.map((model: any) => { + if (model.name === modelName) { + const newmodel = { + ...model, + versions: res + }; + return newmodel; + } else { + return model; + } + }); + // models.delete('cpuExecutionAccelerator'); + // models.delete('gpuExecutionAccelerator'); + ModelData.models = models; + + // await getModelData(dirValue); + // setModelDatas(ModelData); + } + const treedatas = getTreeData(res); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true + }; + }); + form.setFields([ + { + name: 'versions', + value: res + } + ]); + setTreeData(treedata); + setModelDatas(ModelData); + setCascaderOptions([]); + setIsModalOpen3(false); + setSelectKeys(null); + toast.success(t('Download-successfully'), { + autoClose: 2000 + }); + }, + res => { + console.log(res); + setIsModalOpen(false); + setSelectKeys(null); + } + ); + }) + .catch(errorInfo => { + alert(errorInfo); + }); + }; + const handleOk4 = () => { + const modelNames = IsEmsembles ? ensemblesName : modelName; + const name = form.getFieldValue('config_filenames'); + fetcher( + '/fastdeploy/set_default_config_for_model' + + `?dir=${dirValue}` + + `&name=${modelNames}` + + `&config_filename=${name}` + ).then( + (res: any) => { + console.log('set_default_config_for_model', res); + setIsModalOpen4(false); + // const name = form.getf + // setConfig_filename(name); + fetcher('/fastdeploy/get_config_filenames_for_model' + `?dir=${dirValue}` + `&name=${modelNames}`).then( + (res: any) => { + // debugger; + setFilenames(res); + toast.success(t('Set-successfully'), { + autoClose: 2000 + }); + if (name !== 'config.pbtxt') { + onGetConfigModel('config.pbtxt'); + } + } + ); + }, + res => { + console.log(res); + } + ); + }; + const handleOk5 = () => { + const modelNames = IsEmsembles ? ensemblesName : modelName; + fetcher( + '/fastdeploy/delete_resource_for_model' + + `?dir=${dirValue}` + + `&name=${modelNames}` + + `&version=${version}` + + `&resource_filename=${selectKeys}` + ).then( + (res: any) => { + const ModelData = ModelDatas; + if (IsEmsembles) { + const emsembless = ModelDatas.ensembles?.map((ensembles: any) => { + if (ensembles.name === ensemblesName) { + const newemsembles = { + ...ensembles, + versions: res + }; + return newemsembles; + } else { + return ensembles; + } + }); + ModelData.ensembles = emsembless; + } else { + // debuggersss; + const models = ModelData.models?.map((model: any) => { + if (model.name === modelName) { + const newmodel = { + ...model, + versions: res + }; + return newmodel; + } else { + return model; + } + }); + ModelData.models = models; + } + const treedatas = getTreeData(res); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + selectable: true + }; + }); + form.setFields([ + { + name: 'versions', + value: res + } + ]); + setTreeData(treedata); + setModelDatas(ModelData); + setIsModalOpen5(false); + toast.success(t('Delete-resource-successfully'), { + autoClose: 2000 + }); + }, + res => { + console.log(res); + } + ); + }; + const handleOk6 = () => { + form4?.validateFields().then(values => { + console.log('valuesssss', values); + const new_filename = values['new_filename']; + const modelNames = IsEmsembles ? ensemblesName : modelName; + fetcher( + '/fastdeploy/rename_resource_for_model' + + `?dir=${dirValue}` + + `&name=${modelNames}` + + `&version=${version}` + + `&new_filename=${new_filename}` + + `&resource_filename=${selectKeys}` + ).then( + (res: any) => { + const ModelData = ModelDatas; + if (IsEmsembles) { + const emsembless = ModelDatas.ensembles?.map((ensembles: any) => { + if (ensembles.name === ensemblesName) { + const newemsembles = { + ...ensembles, + versions: res + }; + return newemsembles; + } else { + return ensembles; + } + }); + ModelData.ensembles = emsembless; + } else { + // debuggersss; + const models = ModelData.models?.map((model: any) => { + if (model.name === modelName) { + const newmodel = { + ...model, + versions: res + }; + return newmodel; + } else { + return model; + } + }); + ModelData.models = models; + } + const treedatas = getTreeData(res); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + selectable: true + }; + }); + form.setFields([ + { + name: 'versions', + value: res + } + ]); + setTreeData(treedata); + setModelDatas(ModelData); + setIsModalOpen6(false); + form4.setFields([ + { + name: 'new_filename', + value: '' + } + ]); + toast.success(t('Rename-successfully'), { + autoClose: 2000 + }); + }, + res => { + console.log(res); + } + ); + }); + }; + const handleOk7 = async () => { + const modelNames = IsEmsembles ? ensemblesName : modelName; + fetcher( + '/fastdeploy/delete_config_for_model' + + `?dir=${dirValue}` + + `&name=${modelNames}` + + `&config_filename=${selectKeys}` + ).then((res: any) => { + console.log('delete_config', res); + setFilenames(res); + onGetConfigModel(res[0]); + setIsModalOpen7(false); + toast.success(t('Delete-config-successfully'), { + autoClose: 2000 + }); + }); + // onGetConfigModel() + }; + const handleCancel = () => { + setIsModalOpen(false); + if (nodeClick) { + setNodeClick(undefined); + } + }; + const handleCancel2 = () => { + setIsModalOpen2(false); + }; + const handleCancel3 = () => { + setSelectKeys(null); + setIsModalOpen3(false); + }; + const handleCancel4 = () => { + setIsModalOpen4(false); + }; + const handleCancel5 = () => { + setIsModalOpen5(false); + }; + const handleCancel6 = () => { + setIsModalOpen6(false); + }; + const handleCancel7 = () => { + setIsModalOpen7(false); + }; + // const onFinish = (values: any) => { + // console.log('Received values of form:', values); + // }; + + // const handleChange = () => { + // form.setFieldsValue({}); + // }; + const onSelect = (selectedKeys: any) => { + // debugger; + console.log('selected', selectedKeys); + setSelectKeys(selectedKeys); + setVersion(selectedKeys); + fetcher('/fastdeploy/get_pretrain_model_list').then((res: any) => { + setCascaderOptions(res); + setIsModalOpen3(true); + }); + }; + const onDelete_config = (selectedKeys: any) => { + setSelectKeys(selectedKeys); + setIsModalOpen7(true); + }; + const onDelete = (selectedKeys: any) => { + console.log('selected', selectedKeys, treeData); + let versions = ''; + for (const trees of treeData) { + if (trees.key === selectedKeys) { + versions = trees.key; + return; + } + if (trees.children) { + for (const trees2 of trees.children) { + if (trees2.key === selectedKeys) { + versions = trees.key; + setSelectKeys(selectedKeys); + setVersion(versions); + setIsModalOpen5(true); + return; + } + } + } + } + }; + const onRename = (selectedKeys: any) => { + // debugger; + console.log('selected', selectedKeys); + let versions = ''; + for (const trees of treeData) { + if (trees.key === selectedKeys) { + versions = trees.key; + return; + } + if (trees.children) { + for (const trees2 of trees.children) { + if (trees2.key === selectedKeys) { + versions = trees.key; + setSelectKeys(selectedKeys); + setVersion(versions); + setIsModalOpen6(true); + return; + } + } + } + } + }; + const onFill = (models: any) => { + const newcpu = models?.optimization?.cpuExecutionAccelerator?.map((cpu: any) => { + const attr = Object.keys(cpu); + const attr2 = cpu[attr[1]] && Object.keys(cpu[attr[1]]); + const parameters = attr2?.map((key: any) => { + return { + key: key, + value: cpu?.parameters?.[key] + }; + }); + return { + name: cpu.name, + parameters: parameters + }; + }); + + const newgpu = models?.optimization?.gpuExecutionAccelerator?.map((gpu: any) => { + const attr = Object.keys(gpu); + const attr2 = gpu[attr[1]] && Object.keys(gpu[attr[1]]); + const parameters = attr2?.map((key: any) => { + return { + key: key, + value: gpu?.parameters?.[key] + }; + }); + return { + name: gpu.name, + parameters: parameters + }; + }); + + const modelss = { + ...models, + cpuExecutionAccelerator: newcpu, + gpuExecutionAccelerator: newgpu + }; + const newShowGpus = []; + if (modelss?.instanceGroup) { + for (const item of modelss?.instanceGroup) { + if (item.kind !== 'KIND_CPU' && item.kind !== 'KIND_MODEL') { + newShowGpus.push(true); + } else { + newShowGpus.push(false); + } + } + } + setShowGpus(newShowGpus); + + // form.setFieldsValue({}); + for (const item of formItems) { + if (!modelss[item]) { + modelss[item] = undefined; + } + } + console.log('modelss', modelss); + + form.setFieldsValue(modelss); + }; + const onFill2 = (config: any) => { + form2.setFieldsValue(config); + }; + const onFill3 = () => { + form3.setFieldsValue({ + models: [] + }); + }; + + const getmodelData = (model: any, name: string) => { + setModelName(name); + setGraphModel(model); + if (model?.versions) { + const treedatas = getTreeData(model?.versions); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true, + icon: + }; + }); + setTreeData(treedata); + } else { + setTreeData([]); + } + + if (IsEmsembles) { + setIsEmsembles(false); + } + const flag = !showFlag; + setShowFlag(flag); + }; + const changeEmsembles = () => { + setIsEmsembles(true); + setShowFlag(!showFlag); + }; + const EnsemblesNameChange = (value: string) => { + setEnsemblesName(value); + }; + const getTreeNode = useCallback( + (data: any) => { + // debugger; + if (data && data.length > 0) { + return data.map((item: any) => { + if (item.children) { + return ( + +
+ {item.title} +
+ { + onSelect(item.key); + }} + /> +
+ } + > + {getTreeNode(item.children)} + + ); + } + return ( + +
{ + onRename(item.key); + }} + > + {item.title} +
+ { + onDelete(item.key); + }} + /> +
+ } + > + ); + }); + } + return []; + }, + [treeData] + ); + useEffect(() => { + if (!flag) { + return; + } + showModal(); + }, [showFlag]); + useEffect(() => { + if (!nodeClick) { + return; + } + getmodelData(nodeClick.data, nodeClick.name); + }, [nodeClick]); + useEffect(() => { + if (isModalOpen && modelData) { + if (!IsEmsembles) { + fetcher('/fastdeploy/get_config_filenames_for_model' + `?dir=${dirValue}` + `&name=${modelName}`).then( + (res: any) => { + // debugger; + setFilenames(res); + graphModel && onFill(graphModel); + } + ); + } else { + for (const ensembles of modelData.ensembles) { + if (ensembles.name === ensemblesName) { + if (ensembles?.versions) { + const treedatas = getTreeData(ensembles?.versions); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true + }; + }); + setTreeData(treedata); + } else { + setTreeData([]); + } + fetcher( + '/fastdeploy/get_config_filenames_for_model' + `?dir=${dirValue}` + `&name=${ensemblesName}` + ).then((res: any) => { + // debugger; + setFilenames(res); + onFill(ensembles); + }); + + return; + } + } + } + } + }, [isModalOpen, graphModel, IsEmsembles]); + useEffect(() => { + if (isModalOpen2 && dirValue) { + onFill2({ + 'server-name': configs['server-name'], + 'backend-config': configs['backend-config'], + 'metrics-port': configs['metrics-port'], + 'http-port': configs['http-port'], + 'grpc-port': configs['grpc-port'], + 'model-repository': dirValue, + gpus: configs['gpus'] + }); + const styles = `.custom-html { + width: 100%; + height: 100%; + border-radius: 1em; + perspective: 600px; + text-align: center; + line-height: 40px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.25), 0 0.02125em 0.06125em rgba(0, 0, 0, 0.25); + }`; + graphs && + graphs.toPNG( + (dataUri: string) => { + console.log('dataUri', dataUri); + setSvgs(dataUri); + // debugger; + }, + + {copyStyles: true, preserveDimensions: true, stylesheet: styles, padding: 50} + ); + } + }, [dirValue, isModalOpen2]); + useEffect(() => { + if (isModalOpen3) { + onFill3(); + } + }, [isModalOpen3]); + useEffect(() => { + if (!triggerClick) { + return; + } + const name = triggerClick.name; + for (const model of modelData.models) { + if (model.name === name) { + setNodeClick({ + name: model.name, + data: model + }); + return; + } + } + }, [triggerClick]); + const onConfig = () => { + setIsModalOpen4(true); + }; + const onGetConfigModel = (value: string) => { + const modelNames = IsEmsembles ? ensemblesName : modelName; + fetcher( + '/fastdeploy/get_config_for_model' + + `?dir=${dirValue}` + + `&name=${modelNames}` + + `&config_filename=${value}` + ).then((res: any) => { + form.setFields([ + { + name: 'versions', + value: res.versions + } + ]); + const treedatas = getTreeData(res?.versions); + const treedata = treedatas?.map((version: any) => { + return { + ...version, + // checkable: false + selectable: true, + icon: + }; + }); + setTreeData(treedata); + setIsopen(false); + // setModelDatas(ModelData) + res && onFill(res); + if (value.includes('vdlbackup')) { + setConfigsButton(false); + } else { + setConfigsButton(true); + } + }); + }; + console.log('graphssss'); + console.log('showFlag', showFlag); + // const createhtml = svg => { + // return {__html: svg}; + // }; + return ( + +
+
+
+
+ + { + onGetConfigModel(value); + }} + onDropdownVisibleChange={() => { + setIsopen(true); + }} + > + {filenames?.map((item: string) => ( + + ))} + + + {t('Fastdeploy:set-as-launch-config')} +
+ + + + + {!IsEmsembles ? ( + + + + ) : ( + + + + )} + {/* + treeData + */} + + } + defaultExpandedKeys={['0-0-0']} + // onSelect={onSelect} + // treeData={treeData} + > + {getTreeNode(treeData)} + + + + + + + + {fields => ( +
+ {fields?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:variable')}${index + 1}`}
+ {/* remove(field.name)} /> */} +
+
+ + + + + + + + + +
+
+ ))} + + {/* + + */} +
+ )} +
+
+
+ + + {fields2 => ( +
+ {fields2?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:variable')}${index + 1}`}
+ {/* remove(field.name)} /> */} +
+
+ + + + + + + + + +
+
+ ))} + + {/* + + */} +
+ )} +
+
+ + + {(fields3, {add, remove}) => ( +
+ {fields3?.map((field: any, index: number) => ( +
+
+
{`${t('Fastdeploy:instance')}${index + 1}`}
+ remove(field.name)} /> +
+
+ + + + + {/* */} + {/* */} + + + {showGpus[index] && ( + + + + )} +
+
+ ))} + + + + +
+ )} +
+
+ +
+ + {(fields4, {add, remove}) => ( +
+
+
{`cpuExecutionAccelerator`}
+ add()} /> +
+ {fields4?.map(field => ( + +
+
+ + + + remove(field.name)} + /> +
+ + + {(fields5, {add: addTest, remove: removeTest}) => ( +
+
+
+ parameters +
+ addTest()} /> +
+ {fields5?.map(fields => ( + + + + + + + + removeTest(fields.name)} + /> + + ))} +
+ )} +
+
+
+
+ ))} +
+ )} +
+
+
+ + {(fields6, {add, remove}) => ( +
+
+
{`gpuExecutionAccelerator`}
+ add()} /> +
+ {fields6?.map(field => ( + +
+
+ + + + remove(field.name)} + /> +
+ + + {(fields7, {add: addTest, remove: removeTest}) => ( +
+
+
+ parameters +
+ addTest()} /> +
+ {fields7?.map(fields => ( + + + + + + + + removeTest(fields.name)} + /> + + ))} +
+ )} +
+
+
+
+ ))} +
+ )} +
+
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + {t('Fastdeploy:The-config')} + + + {`${t('Fastdeploy:Confirm-delete-resource')} ${selectKeys}`} + + +
+ + + + +
+ + {`${t('Fastdeploy:Confirm-delete-config')} ${selectKeys}`} + + + {/* */} + {/*
*/} + {/*
+ +
*/} + + ); +}; +export default Index; diff --git a/frontend/packages/core/src/components/FastdeployGraph/serverBox.tsx b/frontend/packages/core/src/components/FastdeployGraph/serverBox.tsx new file mode 100644 index 00000000..11a5d1ff --- /dev/null +++ b/frontend/packages/core/src/components/FastdeployGraph/serverBox.tsx @@ -0,0 +1,299 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import React, {useEffect, useState, useRef, forwardRef, ForwardRefRenderFunction} from 'react'; +import styled from 'styled-components'; +import ModelTables from './ModelTables'; +import CPUTables from './CPUTables'; +import ServerConfig from './ServerConfig'; +import {fetcher} from '~/utils/fetch'; +import {rem} from '~/utils/style'; +import {toast} from 'react-toastify'; +import {useTranslation} from 'react-i18next'; +// import type {left} from '@antv/x6/lib/registry/port-label-layout/side'; +const TableTitle = styled.div` + margin-bottom: 20px; + margin-top: 20px; + font-size: 18px; + font-weight: 900; +`; +const Buttons = styled.div` + height: ${rem(36)}; + line-height: ${rem(36)}; + text-align: center; + font-size: 16px; + margin-left: 20px; + min-width: 100px; + width: auto; + border: 1px solid; + padding-left: 5px; + padding-right: 5px; +`; +const ButtonContent = styled.div` + display: flex; + justify-content: space-between; + padding-top: 20px; + padding-bottom: 20px; +`; +const ButtonLeft = styled.div` + display: flex; + justify-content: flex-end; + padding-top: 20px; + padding-bottom: 20px; + .backgrounds { + background-color: var(--navbar-background-color); + color: white; + border: none; + } +`; +const ButtonRight = styled.div` + display: flex; + justify-content: flex-end; + padding-top: 20px; + padding-bottom: 20px; +`; +type ArgumentProps = { + server_id: any; + Flag: number; + onEdit: () => any; +}; +const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH; +// type ArgumentProps = { + +// }; +export type serverBoxRef = { + outDatas(type: number): void; +}; + +console.log('PUBLIC_PATH', PUBLIC_PATH, PUBLIC_PATH + '/api/fastdeploy/fastdeploy_client'); +const ServerBox: ForwardRefRenderFunction = ({Flag, server_id, onEdit}) => { + const [flag, setFlag] = useState(0); + const [Datas, setDatas] = useState({ + text: '', + lengths: 0, + metric: null + }); + const [configs, setConfigs] = useState(); + const {i18n, t} = useTranslation(['Fastdeploy']); + // const {i18n} = useTranslation(['Fastdeploy']); + const language: string = i18n.language; + useEffect(() => { + if (Flag === undefined) { + return; + } + isAlive(); + }, [Flag]); + // useEffect(() => { + // const timer = setInterval(() => { + // setCount(count + 1); + // }, 10000); + // console.log('更新了', timer); + // return () => clearInterval(timer); + // }, [count]); + // Datas.metric + const isAlive = () => { + const serverId = server_id; + // const length = Datas.text.length; + fetcher(`/fastdeploy/check_server_alive?server_id=${serverId}`, { + method: 'GET' + }).then( + (res: any) => { + // debugger; + console.log('check_server_alive', res); + outDatas(); + }, + res => { + console.log('error_check_server_alive', res); + } + ); + }; + const outDatas = () => { + const serverId = server_id; + const length = Datas.text.length; + fetcher(`/fastdeploy/get_server_output?server_id=${serverId}` + `&length=${length}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('get_server_output', res); + metricDatas(serverId, res); + getServe(serverId); + }, + res => { + console.log('get_server_output', res); + } + ); + }; + const clickOutDatas = () => { + const serverId = server_id; + const length = Datas.text.length; + fetcher(`/fastdeploy/get_server_output?server_id=${serverId}` + `&length=${length}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('get_server_output', res); + metricDatas(serverId, res); + getServe(serverId); + const message = + language === 'zh' + ? `${serverId} 更新日志和性能数据成功` + : `Update log and metric for ${serverId} successfully`; + toast.success(message, { + autoClose: 2000 + }); + }, + res => { + console.log('get_server_output', res); + } + ); + }; + const metricDatas = async (serverId: number, texts: any) => { + await fetcher(`/fastdeploy/get_server_metric?server_id=${serverId}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('get_server_metric', res); + setDatas({ + ...Datas, + text: Datas.text + texts, + lengths: Datas.text.length + texts.length, + metric: res + }); + }, + res => { + console.log('get_server_output', res); + } + ); + }; + const getServe = async (serverId: number) => { + await fetcher(`/fastdeploy/get_server_config?server_id=${serverId}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('get_server_config', res); + setConfigs(res); + }, + res => { + console.log('get_server_output', res); + } + ); + }; + const cbRef: any = useRef(); + useEffect(() => { + cbRef.current = outDatas; + }); + useEffect(() => { + const callback = () => { + cbRef.current?.(); + }; + const timer = setInterval(() => { + callback(); + }, 10000); + return () => clearInterval(timer); + }, []); + // useImperativeHandle(ref, () => ({ + // outData(serverId: number) { + // outDatas(serverId); + // } + // })); + return ( +
+ {flag === 0 ? ( +
+ {Datas.text} +
+ ) : flag === 1 ? ( +
+
+ {t('Fastdeploy:Model-metrics')} + +
+
+ {t('Fastdeploy:GPU-metrics')} + +
+
+ ) : ( +
+ +
+ )} + + + { + setFlag(0); + }} + > + {t('Fastdeploy:log')} + + { + setFlag(1); + }} + > + {t('Fastdeploy:metric')} + + { + setFlag(2); + }} + > + {t('Fastdeploy:model-repository')} + + + + { + const url = + PUBLIC_PATH + + `/api/fastdeploy/fastdeploy_client?server_id=${server_id}` + + `&lang=${language}`; + window.open(url); + }} + > + {t('Fastdeploy:open-client')} + + + {t('Fastdeploy:shutdown')} + { + clickOutDatas(); + }} + > + {t('Fastdeploy:updates')} + + + +
+ ); +}; + +export default forwardRef(ServerBox); diff --git a/frontend/packages/core/src/components/GraphPage/GraphDynamic.tsx b/frontend/packages/core/src/components/GraphPage/GraphDynamic.tsx index bfb3d64e..de99c0de 100644 --- a/frontend/packages/core/src/components/GraphPage/GraphDynamic.tsx +++ b/frontend/packages/core/src/components/GraphPage/GraphDynamic.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * diff --git a/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx b/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx index bd68c5d6..7f9d88be 100644 --- a/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx +++ b/frontend/packages/core/src/components/GraphPage/GraphStatic.tsx @@ -209,6 +209,7 @@ const Graph = React.forwardRef( }, [handler, dispatch]); useEffect(() => { + console.log('GraphStaticss', files, ready); (ready && dispatch('change-files', files)) || undefined; }, [dispatch, files, ready]); useEffect( diff --git a/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx b/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx index 7a74aea0..8c58cc04 100644 --- a/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx +++ b/frontend/packages/core/src/components/GraphPage/GraphStatic2.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -26,6 +27,7 @@ import styled from 'styled-components'; import {toast} from 'react-toastify'; import useTheme from '~/hooks/useTheme'; import {useTranslation} from 'react-i18next'; +console.log('netron2', netron2); const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH; diff --git a/frontend/packages/core/src/components/GraphPage/Uploader.tsx b/frontend/packages/core/src/components/GraphPage/Uploader.tsx index ad522646..64ab41f9 100644 --- a/frontend/packages/core/src/components/GraphPage/Uploader.tsx +++ b/frontend/packages/core/src/components/GraphPage/Uploader.tsx @@ -120,12 +120,27 @@ const Uploader: FunctionComponent = ({onClickUpload, onDropFiles, {Xpaddlae ? ( -
- - - - - + // + // + // + // + // + // +
+
+ {t('graph:supported-model')} +
+
{t('graph:supported-model-list-xpaddle')}
+
) : ( diff --git a/frontend/packages/core/src/components/LineChart.tsx b/frontend/packages/core/src/components/LineChart.tsx index fd3955c9..78023cf9 100644 --- a/frontend/packages/core/src/components/LineChart.tsx +++ b/frontend/packages/core/src/components/LineChart.tsx @@ -17,7 +17,7 @@ import * as chart from '~/utils/chart'; -import React, {useEffect, useImperativeHandle, useState} from 'react'; +import React, {useEffect, useImperativeHandle} from 'react'; import {WithStyled, primaryColor} from '~/utils/style'; import useECharts, {Options, Wrapper, useChartTheme} from '~/hooks/useECharts'; diff --git a/frontend/packages/core/src/components/Navbar.tsx b/frontend/packages/core/src/components/Navbar.tsx index 85803954..c50c1c17 100644 --- a/frontend/packages/core/src/components/Navbar.tsx +++ b/frontend/packages/core/src/components/Navbar.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -36,7 +37,6 @@ import useClassNames from '~/hooks/useClassNames'; import useComponents from '~/hooks/useComponents'; import {useTranslation} from 'react-i18next'; import {fetcher} from '~/utils/fetch'; -import {Child} from './ProfilerPage/OperatorView/type'; import {isArray} from 'lodash'; const BASE_URI: string = import.meta.env.SNOWPACK_PUBLIC_BASE_URI; @@ -284,6 +284,7 @@ const Navbar: FunctionComponent = () => { image: 'image', audio: 'audio', text: 'text', + fastdeploy_server: 'fastdeploy_server', graphStatic: 'static_graph', graphDynamic: 'dynamic_graph', 'high-dimensional': 'embeddings', @@ -292,14 +293,17 @@ const Navbar: FunctionComponent = () => { profiler: 'profiler', 'hyper-parameter': 'hyper_parameters', x2paddle: 'x2paddle', - fastdeploy_server: 'fastdeploy_server' + fastdeploy_client: 'fastdeploy_client' }; }, []); + console.log('pathname', pathname); + const currentPath = useMemo(() => pathname.replace(BASE_URI, ''), [pathname]); const [components] = useComponents(); const routePush = (route: any, component: any) => { const Components = isArray(component) ? [...component] : [...component.values()]; + console.log('routeEm[route.id]', navList, navList.includes(routeEm[route.id])); if (navList.includes(routeEm[route.id])) { // debugger; @@ -314,13 +318,13 @@ const Navbar: FunctionComponent = () => { }; const newcomponents = useMemo(() => { const Components = new Map(); - const parent: any[] = []; if (navList.length > 0) { for (const item of components) { // const Id: any = item.id; if (navList.includes(routeEm[item.id])) { // Components.push(item); + Components.set(item.id, item); } if (item.children) { @@ -355,6 +359,8 @@ const Navbar: FunctionComponent = () => { () => flatten(newcomponents.slice(MAX_ITEM_COUNT_IN_NAVBAR)), [newcomponents] ); + console.log('currentPath', currentPath); + const componentsInMoreMenu: any = useMemo( () => flattenMoreComponents.map(item => ({ @@ -364,41 +370,76 @@ const Navbar: FunctionComponent = () => { [currentPath, flattenMoreComponents] ); const [navItemsInNavbar, setNavItemsInNavbar] = useState([]); - const routesChange = (route: any, parentPath?: any) => { + const routesChange = (route: any, parentPath: string, path: string) => { // debugger; - if (navList.includes(routeEm[route.id])) { - // debugger; - if (parentPath) { - history.push(`${parentPath}/${route.id}`); - return true; - } else { - history.push(`/${route.id}`); - return true; - } - // setDefaultRoute(route.id); + // if (navList.includes(routeEm[route.id])) { + // debugger; + // // if (parentPath) { + // // history.push(`${parentPath}/${route.id}`); + // // return true; + // // } else { + // // history.push(`/${route.id}`); + // // return true; + // // } + // // // setDefaultRoute(route.id); + // // } + // // if (route.children) { + // // for (const Route of route.children) { + // // routesChange(Route, `/${route.id}`); + // // } + // // } + // // return false; + // }; + let id = ''; + if (parentPath) { + id = parentPath + `/${route.id}`; + } else { + id = `/${route.id}`; + } + // debugger; + if (routeEm[route.id] === path) { + console.log('path', route); + history.push(id); + return; } if (route.children) { for (const Route of route.children) { - routesChange(Route, `/${route.id}`); + routesChange(Route, id, path); } } - // return false; }; + useEffect(() => { // setLoading(true); fetcher('/component_tabs').then((res: any) => { + console.log('component_tabs', res); + setNavlist(res); }); }, []); useEffect(() => { // const defaultRoute = routes; - if (navList.length > 0) { - for (const route of routes) { - const flag = routesChange(route); - if (flag) { - return; + if (navList.length > 0 && pathname) { + console.log('pathname', pathname); + + // routesChange(route, '', path); + // debugger; + // const path = routeEm[pathNames]; + if (pathname === '/index') { + const path = navList[0]; + for (const route of routes) { + routesChange(route, '', path); + } + } else { + const path = pathname; + for (const route of routes) { + routesChange(route, '', path); } } + + // const route = navList[navList.length - 1]; + // debugger; + // routesChange(route); } }, [navList]); useEffect(() => { diff --git a/frontend/packages/core/src/components/ProfilerPage/MemoryView/MemoryView.tsx b/frontend/packages/core/src/components/ProfilerPage/MemoryView/MemoryView.tsx index 653b708d..7a6704b7 100644 --- a/frontend/packages/core/src/components/ProfilerPage/MemoryView/MemoryView.tsx +++ b/frontend/packages/core/src/components/ProfilerPage/MemoryView/MemoryView.tsx @@ -28,8 +28,8 @@ import SearchInput from '~/components/searchInput2'; import GridLoader from 'react-spinners/GridLoader'; import {Wraper, Title, FullWidthSelect, Configure, EchartPie} from '../../components'; import type {devicesType, curveType, memory_events_type, Datum, op_memory_events_type, op_datum} from './type'; -import {number} from 'echarts'; -import NumberInput from '../NumberInput'; +// import {number} from 'echarts'; +// import NumberInput from '../NumberInput'; interface DataType { key: React.Key; MemoryType: string; @@ -178,6 +178,7 @@ const MemoryView: FunctionComponent = ({runs, workers, spans, u const result = res as devicesType[]; const itemsLists = result.map(element => { const regex1 = /\((.+?)\)/g; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const label: string = element.device.match(regex1)![0]; const labels = label.substring(1, label.length - 1); return {label: labels, value: element.device}; diff --git a/frontend/packages/core/src/components/ProfilerPage/OperatorView/tools.tsx b/frontend/packages/core/src/components/ProfilerPage/OperatorView/tools.tsx index 41b046d1..8014849d 100644 --- a/frontend/packages/core/src/components/ProfilerPage/OperatorView/tools.tsx +++ b/frontend/packages/core/src/components/ProfilerPage/OperatorView/tools.tsx @@ -1,5 +1,5 @@ -import type {ColumnsType} from 'antd/lib/table'; -import React from 'react'; +// import type {ColumnsType} from 'antd/lib/table'; +// import React from 'react'; import type {EChartsOption} from 'echarts'; export const options: EChartsOption = { grid: { diff --git a/frontend/packages/core/src/components/ProfilerPage/overview/PerformanceContent.tsx b/frontend/packages/core/src/components/ProfilerPage/overview/PerformanceContent.tsx index b7a17d3f..32180d3f 100644 --- a/frontend/packages/core/src/components/ProfilerPage/overview/PerformanceContent.tsx +++ b/frontend/packages/core/src/components/ProfilerPage/overview/PerformanceContent.tsx @@ -2,7 +2,7 @@ /* eslint-disable sort-imports */ import React, {Fragment, FunctionComponent} from 'react'; import {rem} from '~/utils/style'; -import {useTranslation} from 'react-i18next'; +// import {useTranslation} from 'react-i18next'; import styled from 'styled-components'; import BarsChart from '~/components/BarsChart'; import {Tabs} from 'antd'; diff --git a/frontend/packages/core/src/components/ProfilerPage/overview/overview.tsx b/frontend/packages/core/src/components/ProfilerPage/overview/overview.tsx index 2001cb03..54817271 100644 --- a/frontend/packages/core/src/components/ProfilerPage/overview/overview.tsx +++ b/frontend/packages/core/src/components/ProfilerPage/overview/overview.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, {FunctionComponent, useCallback, useEffect, useMemo, useState} from 'react'; +import React, {FunctionComponent, useCallback, useEffect, useState} from 'react'; import type {ColumnsType} from 'antd/lib/table'; import PieChart from '~/components/pieChart'; import StackColumnChart from '~/components/StackColumnChart'; @@ -129,10 +129,10 @@ interface chartDataType { gpu: cpuData[]; cpu: cpuData[]; } -type SelectListItem = { - value: T; - label: string; -}; +// type SelectListItem = { +// value: T; +// label: string; +// }; const OverView: FunctionComponent = ({runs, views, workers, spans, units, descriptions}) => { const {t} = useTranslation(['profiler', 'common']); @@ -144,10 +144,10 @@ const OverView: FunctionComponent = ({runs, views, workers, spans const [isExpend, setIsExpend] = useState(false); const [tableData, setTableData] = useState(); const [tableLoading, settableLoading] = useState(true); - const [stepsList, setStepsList] = useState[]>([ - {label: 'cpu', value: 'cpu'}, - {label: 'gpu', value: 'gpu'} - ]); + // const [stepsList, setStepsList] = useState[]>([ + // {label: 'cpu', value: 'cpu'}, + // {label: 'gpu', value: 'gpu'} + // ]); const [TrainType, setTrainType] = useState('cpu'); const [PerformanceType, setPerformanceType] = useState('cpu'); const [tableData2, setTableData2] = useState(); diff --git a/frontend/packages/core/src/components/ScalarChart.tsx b/frontend/packages/core/src/components/ScalarChart.tsx index 0a1a5cce..69626304 100644 --- a/frontend/packages/core/src/components/ScalarChart.tsx +++ b/frontend/packages/core/src/components/ScalarChart.tsx @@ -21,7 +21,7 @@ import {rem, size} from '~/utils/style'; import Chart from '~/components/Chart'; import ChartToolbox from '~/components/ChartToolbox'; -import type {EChartsOption, LineSeriesOption} from 'echarts'; +import type {EChartsOption} from 'echarts'; import TooltipTable from '~/components/TooltipTable'; import {format} from 'd3-format'; import {renderToStaticMarkup} from 'react-dom/server'; diff --git a/frontend/packages/core/src/components/StackColumnChart.tsx b/frontend/packages/core/src/components/StackColumnChart.tsx index 8ab439ed..97b6bbfd 100644 --- a/frontend/packages/core/src/components/StackColumnChart.tsx +++ b/frontend/packages/core/src/components/StackColumnChart.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * diff --git a/frontend/packages/core/src/components/StackColumnChart2.tsx b/frontend/packages/core/src/components/StackColumnChart2.tsx index fd611e31..8a6792c1 100644 --- a/frontend/packages/core/src/components/StackColumnChart2.tsx +++ b/frontend/packages/core/src/components/StackColumnChart2.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -52,11 +53,10 @@ export type LineChartRef = { restore(): void; saveAsImage(): void; }; - +const color = ['#2932E1', '#00CC88', '#981EFF', '#FF6D6D', '#25C9FF', '#E71ED5', '#FFAA00', '#00307D']; const StackColumnChart = React.forwardRef( ({options, data, title, loading, zoom, className, onInit, isWorkerName, units}, ref) => { const {i18n} = useTranslation(); - const color = ['#2932E1', '#00CC88', '#981EFF', '#FF6D6D', '#25C9FF', '#E71ED5', '#FFAA00', '#00307D']; const { ref: echartRef, echart, diff --git a/frontend/packages/core/src/components/pieChart.tsx b/frontend/packages/core/src/components/pieChart.tsx index 2ec72c48..540d715e 100644 --- a/frontend/packages/core/src/components/pieChart.tsx +++ b/frontend/packages/core/src/components/pieChart.tsx @@ -20,7 +20,7 @@ import leftIcon from '~/assets/images/leftClick.svg'; import rightIcon from '~/assets/images/rightClick.svg'; const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH; import React, {useEffect, useImperativeHandle} from 'react'; -import {WithStyled, primaryColor} from '~/utils/style'; +import {primaryColor} from '~/utils/style'; import useECharts, {Options, Wrapper, useChartTheme} from '~/hooks/useECharts'; import styled from 'styled-components'; import type {EChartsOption} from 'echarts'; @@ -90,7 +90,7 @@ const Content = styled.div` `; const PieChart = React.forwardRef( ({option, data, title, loading, zoom, className, onInit, isCpu, color, units}, ref) => { - const {i18n} = useTranslation(); + // const {i18n} = useTranslation(); const {t} = useTranslation(['profiler', 'common']); const { ref: echartRef, diff --git a/frontend/packages/core/src/pages/Fastdeploy.tsx b/frontend/packages/core/src/pages/Fastdeploy.tsx new file mode 100644 index 00000000..fa93ad58 --- /dev/null +++ b/frontend/packages/core/src/pages/Fastdeploy.tsx @@ -0,0 +1,480 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import React, {useState, useEffect} from 'react'; +import {rem, primaryColor, size} from '~/utils/style'; +import {Tabs} from 'antd'; +import Content from '~/components/Content'; +import FastdeployGraph from '~/components/FastdeployGraph'; +import ServerBox from '~/components//FastdeployGraph/serverBox'; +import {fetcher} from '~/utils/fetch'; +import HashLoader from 'react-spinners/HashLoader'; +import {Select} from 'antd'; +import styled from 'styled-components'; +import {toast} from 'react-toastify'; +import {useTranslation} from 'react-i18next'; +import {Modal} from 'antd'; + +// type TabPosition = 'left' | 'right' | 'top' | 'bottom'; +const InputContent = styled.div` + display: flex; + height: ${rem(50)}; + justify-content: center; + align-items: center; + padding: 10px; + .inputWrapper { + width: 500px; + border-radius: 0px; + flex: 1; + } + .titleName { + flex: 1; + font-size: 28px; + } +`; +const Contents = styled.div` + height: 100%; + background: white; + display: flex; + flex-direction: column; +`; +const SelectContent = styled.div` + height: 60px; + display: flex; + align-items: center; + .ant-select { + .ant-select-selector { + height: 100%; + .ant-select-selection-placeholder { + line-height: 60px; + } + .ant-select-selection-item { + line-height: 60px; + color: black; + } + } + } +`; +const Buttons = styled.div` + height: ${rem(36)}; + line-height: ${rem(36)}; + text-align: center; + font-size: 16px; + margin-left: 20px; + min-width: 100px; + padding-left: 5px; + padding-right: 5px; + color: white; + background-color: var(--navbar-background-color); +`; + +const Loading = styled.div` + ${size('100%', '100%')} + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + overscroll-behavior: none; + cursor: progress; + font-size: ${rem(16)}; + line-height: ${rem(60)}; +`; +const TabsContent = styled.div` + padding: 20px 10px 0px 10px; + flex: 1; + .ant-tabs-content-left { + height: 100%; + } + .ant-tabs-nav-add { + display: none; + } + .ant-tabs-nav-list { + .ant-tabs-tab:nth-of-type(1) { + .ant-tabs-tab-remove { + display: none; + } + } + } +`; +const mode = 'left'; +function App() { + const [dirValue, setDirValue] = useState('.'); + const [dirs, setDirs] = useState(''); + const [selectOptions, setSelectOptions] = useState([]); + const [loading, setLoading] = useState(false); + const [modelData, setModelData] = useState(); + const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalOpen2, setIsModalOpen2] = useState(false); + const [targetKeys, setTargetKey] = useState(''); + const [serverId, setServerId] = useState(); + const [serverModels, setServerModels] = useState([]); + const [opens2, setOPens2] = useState(false); + const {t} = useTranslation(['Fastdeploy']); + useEffect(() => { + GetServerList(); + }, []); + useEffect(() => { + // const Graphs: any = Graph; + // getModelData(); + getDir(dirValue); + }, [dirValue]); + useEffect(() => { + if (serverId !== undefined) { + const serverModel = serverModels; + let flag = false; + for (const model of serverModels) { + if (model.Id === serverId) { + flag = true; + } + } + if (flag) { + const newServerModel = serverModel.map((model: any) => { + if (model.Id === serverId) { + return { + Id: serverId + '', + flag: !model.flag + }; + } else { + return model; + } + }); + setServerModels(newServerModel); + } else { + GetServerList(); + } + } + }, [serverId]); + const GetServerList = () => { + setLoading(true); + fetcher(`/fastdeploy/get_server_list`, { + method: 'GET' + }).then( + (res: any) => { + const ServerModel = res.map((Id: number) => { + return { + flag: true, + Id: Id + '' + }; + }); + setServerModels(ServerModel); + // ChangeServerId(res[0]); + setLoading(false); + }, + res => { + console.log('get_server_output', res); + // setServerId(undefined); + setLoading(false); + } + ); + }; + const getModelData = (dirValues: string) => { + fetcher(`/fastdeploy/get_config?dir=${dirValues}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('blobres', res); + // downloadEvt(res.data, fileName); + setDirs(dirValues); + setDirValue('.'); + setModelData(res); + setIsModalOpen(false); + setLoading(false); + }, + res => { + console.log('errblobres', res); + setLoading(false); + } + ); + }; + const ChangeServerId = (id: number) => { + setServerId(id); + }; + const SplicingDir = (value: string) => { + if (value === '..') { + const newDir = dirValue?.split('/'); + const newDir2 = newDir.splice(0, newDir.length - 1).join('/'); + setDirValue(newDir2); + } else { + const newDir = dirValue + `/${value}`; + setDirValue(newDir); + } + }; + const getDir = (dir: string) => { + fetcher(`/fastdeploy/get_directory?dir=${dir}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('res', res); + // downloadEvt(res.data, fileName); + // setModelData(res); + if (res?.sub_dir.length > 0) { + const newOptions = res?.sub_dir.map((dir: string) => { + return { + value: dir, + label: dir + }; + }); + setSelectOptions(newOptions); + } + setLoading(false); + }, + res => { + console.log('errblobres', res); + setLoading(false); + } + ); + }; + const ChangeModelClick = () => { + setIsModalOpen(true); + }; + const handleOk = () => { + // onFinish(); + getModelData(dirValue); + }; + const handleOk2 = () => { + // debugger; + stopSever(targetKeys); + }; + + const handleCancel = () => { + setIsModalOpen(false); + }; + const handleCancel2 = () => { + setIsModalOpen2(false); + }; + const stopSever = (targetKey: string) => { + fetcher(`/fastdeploy/stop_server?server_id=${targetKey}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('res', res); + // downloadEvt(res.data, fileName); + // setModelData(res); + // debugger; + remove(targetKey); + setLoading(false); + toast.success(t('Fastdeploy:Shutdown-server-successfully'), { + autoClose: 2000 + }); + }, + res => { + console.log('errblobres', res); + setLoading(false); + } + ); + }; + const remove = (targetKey: string) => { + const serverModel = serverModels; + const newServerModel = serverModel.filter((model: any) => { + const modelId = `${model.Id}`; + console.log('modelId = `${model.Id}`;', modelId, targetKey); + + if (modelId !== targetKey) { + return model; + } + }); + console.log(newServerModel); + setServerModels(newServerModel); + setServerId(undefined); + setIsModalOpen2(false); + }; + + const onEdit: any = (targetKey: string, action: 'add' | 'remove') => { + // debugger; + if (action === 'add') { + console.log(11111); + } else { + // stopSever(targetKey); + setTargetKey(targetKey); + setIsModalOpen2(true); + } + }; + console.log('serverModels', serverModels); + + return ( + + {loading && ( + + + + )} + {/* {modelData ? ( + + +
{`当前模型库:${dirs}`}
+ 更换模型库 +
+ + + {modelData && ( + + + + )} + {serverModels && + serverModels.map((server: any) => { + // debugger; + return ( + + { + outDatas(server.id); + }} + > + + ); + })} + + +
+ ) : ( + +
+ { + setOPens2(true); + }} + onBlur={() => { + setOPens2(false); + }} + open={opens2} + // filterOption={(input, option) => (option?.label ?? '').includes(input)} + value={dirValue} + options={selectOptions} + onChange={value => { + SplicingDir(value); + }} + /> + + + + {t('Fastdeploy:Confirm')} + + {/* {React.lazy(() => import('~/components/Fastdeploy'))} */} + + ); +} +export default App; diff --git a/frontend/packages/core/src/pages/FastdeployClient.tsx b/frontend/packages/core/src/pages/FastdeployClient.tsx new file mode 100644 index 00000000..5242fd23 --- /dev/null +++ b/frontend/packages/core/src/pages/FastdeployClient.tsx @@ -0,0 +1,112 @@ +import React, {useState} from 'react'; +import {rem, primaryColor, size} from '~/utils/style'; +import {Tabs} from 'antd'; +import Content from '~/components/Content'; +import Clinet from '~/components//FastdeployGraph/Clinet'; +import {fetcher} from '~/utils/fetch'; +import HashLoader from 'react-spinners/HashLoader'; +import styled from 'styled-components'; +import {useTranslation} from 'react-i18next'; + +// import {useTranslation} from 'react-i18next'; + +const Contents = styled.div` + height: 100%; + background: white; + display: flex; + flex-direction: column; +`; +const Loading = styled.div` + ${size('100%', '100%')} + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + overscroll-behavior: none; + cursor: progress; + font-size: ${rem(16)}; + line-height: ${rem(60)}; +`; +const TabsContent = styled.div` + padding: 20px 10px 0px 10px; + flex: 1; + .ant-tabs-content-left { + height: 100%; + } +`; +function App() { + const [loading, setLoading] = useState(false); + const [serverModels, setServerModels] = useState([0]); + const {i18n} = useTranslation(['Fastdeploy']); + const language: string = i18n.language; + const getClient = () => { + fetcher(`/fastdeploy/fastdeploy_client?lang=${language}`, { + method: 'GET' + }).then( + (res: any) => { + console.log('res', res); + const serverModel = [...serverModels]; + if (serverModel.length === 0) { + serverModel.push(0); + } else { + const last = serverModel[serverModels.length - 1] + 1; + serverModel.push(last); + } + setServerModels(serverModel); + setLoading(false); + }, + res => { + console.log('errres', res); + setLoading(false); + } + ); + }; + + const onEdit: any = (targetKey: string, action: 'add' | 'remove') => { + if (action === 'add') { + getClient(); + } else { + // stopSever(targetKey); + console.log('targetKey', targetKey); + const newServerModel: any[] = []; + for (const model of serverModels) { + const models = model + ''; + if (models !== targetKey) { + newServerModel.push(model); + } + } + setServerModels(newServerModel); + } + }; + console.log('serverModels', serverModels); + + return ( + + {loading && ( + + + + )} + + + + {serverModels.map((server: any) => { + return ( + + + + ); + })} + + + + + ); +} +export default App; diff --git a/frontend/packages/core/src/pages/graphDynamic.tsx b/frontend/packages/core/src/pages/graphDynamic.tsx index 7274e06b..e2f8adb3 100644 --- a/frontend/packages/core/src/pages/graphDynamic.tsx +++ b/frontend/packages/core/src/pages/graphDynamic.tsx @@ -120,10 +120,14 @@ const Graph: FunctionComponent = () => { }).then( res => { // debugger + console.log('res', res); + const newFilesId = filesId + 1; setFilesId(newFilesId); }, res => { + console.log('errres', res); + // debugger const newFilesId = filesId + 1; setFilesId(newFilesId); @@ -289,7 +293,7 @@ const Graph: FunctionComponent = () => { checked={selectedRuns === run ? true : false} value={run} title={run} - onChange={(value: string) => { + onChange={() => { setSelectedRuns(run); }} > @@ -309,6 +313,7 @@ const Graph: FunctionComponent = () => { )} ); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ t, bottom, diff --git a/frontend/packages/core/src/pages/graphStatic.tsx b/frontend/packages/core/src/pages/graphStatic.tsx index 61a8348b..951e9839 100644 --- a/frontend/packages/core/src/pages/graphStatic.tsx +++ b/frontend/packages/core/src/pages/graphStatic.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -17,21 +18,11 @@ import Aside, {AsideSection} from '~/components/Aside'; import type {Documentation, OpenedResult, Properties, SearchItem, SearchResult} from '~/resource/graph/types'; import GraphComponent, {GraphRef} from '~/components/GraphPage/GraphStatic'; -import React, { - FunctionComponent, - ForwardRefRenderFunction, - useImperativeHandle, - forwardRef, - useCallback, - useEffect, - useMemo, - useRef, - useState -} from 'react'; +import React, {useImperativeHandle, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import Select, {SelectProps} from '~/components/Select'; -import {actions, selectors} from '~/store'; +import {actions} from '~/store'; import {primaryColor, rem, size} from '~/utils/style'; -import {useDispatch, useSelector} from 'react-redux'; +import {useDispatch} from 'react-redux'; import type {BlobResponse} from '~/utils/fetch'; import Button from '~/components/Button'; @@ -108,11 +99,11 @@ const Graph = React.forwardRef(({changeName, changeshowdata const {t} = useTranslation(['graph', 'common']); const storeDispatch = useDispatch(); - const storeModel = useSelector(selectors.graph.model); + // const storeModel = useSelector(selectors.graph.model); const graph = useRef(null); const file = useRef(null); - const [files, setFiles] = useState(storeModel); + const [files, setFiles] = useState(); const setModelFile = useCallback( (f: FileList | File[]) => { storeDispatch(actions.graph.setModel(f)); @@ -138,7 +129,7 @@ const Graph = React.forwardRef(({changeName, changeshowdata }, [setModelFile] ); - const {data, loading} = useRequest(files ? null : '/graph/graph'); + const {loading} = useRequest(files ? null : '/graph/graph'); // useEffect(() => { // if (data?.data?.size) { diff --git a/frontend/packages/core/src/pages/graphStatic2.tsx b/frontend/packages/core/src/pages/graphStatic2.tsx index e4a5c86e..6fecdb95 100644 --- a/frontend/packages/core/src/pages/graphStatic2.tsx +++ b/frontend/packages/core/src/pages/graphStatic2.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -17,11 +18,11 @@ import Aside, {AsideSection} from '~/components/Aside'; import type {Documentation, OpenedResult, Properties, SearchItem, SearchResult} from '~/resource/graph/types'; import GraphComponent, {GraphRef} from '~/components/GraphPage/GraphStatic2'; -import React, {FunctionComponent, useImperativeHandle, useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import React, {useImperativeHandle, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import Select, {SelectProps} from '~/components/Select'; -import {actions, selectors} from '~/store'; +import {actions} from '~/store'; import {primaryColor, rem, size} from '~/utils/style'; -import {useDispatch, useSelector} from 'react-redux'; +import {useDispatch} from 'react-redux'; import type {BlobResponse} from '~/utils/fetch'; import Button from '~/components/Button'; @@ -99,14 +100,14 @@ const Graph = React.forwardRef(({changeRendered, show = tru const {t} = useTranslation(['graph', 'common']); const storeDispatch = useDispatch(); - const storeModel = useSelector(selectors.graph.model); + // const storeModel = useSelector(selectors.graph.model); const graph = useRef(null); const file = useRef(null); - const [files, setFiles] = useState(storeModel); + const [files, setFiles] = useState(); const [modelGraphs, setModelGraphs] = useState([]); const [selectedGraph, setSelectedGraph] = useState>(''); - const {data, loading} = useRequest(files ? null : '/graph/graph'); + const {loading} = useRequest(files ? null : '/graph/graph'); const setModelFile = useCallback( (f: FileList | File[]) => { storeDispatch(actions.graph.setModel(f)); diff --git a/frontend/packages/core/src/pages/profiler.tsx b/frontend/packages/core/src/pages/profiler.tsx index d6d396fd..13765c6a 100644 --- a/frontend/packages/core/src/pages/profiler.tsx +++ b/frontend/packages/core/src/pages/profiler.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks/exhaustive-deps */ /** * Copyright 2020 Baidu Inc. All Rights Reserved. * @@ -110,9 +111,9 @@ type SelectListItem = { value: T; label: string; }; +const isCompared = false; const Profiler: FunctionComponent = () => { const {t, i18n} = useTranslation(['profiler', 'common']); - const [isCompared, setIsCompared] = useState(false); const [runs, setRuns] = useState(''); const [diffRuns1, setDiffRuns1] = useState(''); const [diffRuns2, setDiffRuns2] = useState(''); diff --git a/frontend/packages/core/src/pages/x2paddle.tsx b/frontend/packages/core/src/pages/x2paddle.tsx index b0a5b6ac..1f3ae825 100644 --- a/frontend/packages/core/src/pages/x2paddle.tsx +++ b/frontend/packages/core/src/pages/x2paddle.tsx @@ -24,17 +24,7 @@ const ButtonContent = styled.section` cursor: not-allowed; } `; -type Fn = (data: FcResponse) => unknown; -interface IAnyObj { - [index: string]: unknown; -} - -interface FcResponse { - errno: string; - errmsg: string; - data: T; -} const Article = styled.article` flex: auto; display: flex; @@ -83,11 +73,11 @@ function App() { const Graph = useRef(null); const Graph2 = useRef(null); // 创建 axios 实例 - const blobToFile = function (theBlob: any, fileName: any, type: any) { - theBlob.lastModifiedDate = new Date(); - theBlob.name = fileName; - return new window.File([theBlob], theBlob.name, {type: type}); - }; + // const blobToFile = function (theBlob: any, fileName: any, type: any) { + // theBlob.lastModifiedDate = new Date(); + // theBlob.name = fileName; + // return new window.File([theBlob], theBlob.name, {type: type}); + // }; const base64UrlToFile = (base64Url: any, filename: any) => { // const arr = base64Url.split(','); // const mime = arr[0].match(/:(.*?);/)[1]; @@ -147,6 +137,7 @@ function App() { }, res => { // debugger + console.log('errres', res); setLoading(false); // const newFilesId = filesId + 1; // setFilesId(newFilesId); @@ -204,15 +195,15 @@ function App() { [fileUploader] ); //将base64转换为blob - const dataURLtoBlob = (base64Url: any) => { - const bstr = atob(base64Url); - let n = bstr.length; - const u8arr = new Uint8Array(n); - while (n--) { - u8arr[n] = bstr.charCodeAt(n); - } - return new Blob([u8arr]); - }; + // const dataURLtoBlob = (base64Url: any) => { + // const bstr = atob(base64Url); + // let n = bstr.length; + // const u8arr = new Uint8Array(n); + // while (n--) { + // u8arr[n] = bstr.charCodeAt(n); + // } + // return new Blob([u8arr]); + // }; // * desc: 下载方法 // * @param url :返回数据的blob对象或链接 // * @param fileName :下载后文件名标记 @@ -236,6 +227,7 @@ function App() { setLoading(false); }, res => { + console.log('errres', res); setLoading(false); } ); diff --git a/frontend/packages/core/src/routes/index.ts b/frontend/packages/core/src/routes/index.ts index 7eda071d..8956c8e0 100644 --- a/frontend/packages/core/src/routes/index.ts +++ b/frontend/packages/core/src/routes/index.ts @@ -30,7 +30,9 @@ export enum Pages { PRCurve = 'pr-curve', ROCCurve = 'roc-curve', Profiler = 'profiler', - HyperParameter = 'hyper-parameter' + HyperParameter = 'hyper-parameter', + fastdeploy_server = 'fastdeploy_server', + fastdeploy_client = 'fastdeploy_client' } export interface Route { @@ -125,6 +127,16 @@ const routes: Route[] = [ id: Pages.ROCCurve, path: '/roc-curve', component: React.lazy(() => import('~/pages/curves/roc')) + }, + { + id: Pages.fastdeploy_server, + path: '/fastdeploy_server', + component: React.lazy(() => import('~/pages/Fastdeploy')) + }, + { + id: Pages.fastdeploy_client, + path: '/fastdeploy_client', + component: React.lazy(() => import('~/pages/FastdeployClient')) } ]; diff --git a/frontend/packages/core/src/utils/fetch.ts b/frontend/packages/core/src/utils/fetch.ts index 2d515f58..60508e6f 100644 --- a/frontend/packages/core/src/utils/fetch.ts +++ b/frontend/packages/core/src/utils/fetch.ts @@ -89,6 +89,7 @@ export async function fetcher(url: string, options?: RequestInit): // res = await fetch('http://10.181.196.14:8040/app/api/deploy/convert?format=onnx', addApiToken(options)); res = await fetch(API_URL + url, addApiToken(options)); + console.log('ressponse', res); } catch (e) { const t = await logErrorAndReturnT(e); throw new Error(t('errors:network-error')); diff --git a/frontend/packages/core/types/netron.d.ts b/frontend/packages/core/types/netron.d.ts index aceeccef..f7229ba4 100644 --- a/frontend/packages/core/types/netron.d.ts +++ b/frontend/packages/core/types/netron.d.ts @@ -22,3 +22,7 @@ declare module '@visualdl/netron2' { const ref: string; export default ref; } +// declare module '@visualdl/netron3' { +// const ref: string; +// export default ref; +// } diff --git a/frontend/packages/mock/data/component_tabs.js b/frontend/packages/mock/data/component_tabs.js new file mode 100644 index 00000000..9e461391 --- /dev/null +++ b/frontend/packages/mock/data/component_tabs.js @@ -0,0 +1,33 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// export default [ +// 'scalar', +// 'image', +// 'text', +// 'embeddings', +// 'audio', +// 'histogram', +// 'hyper_parameters', +// 'static_graph', +// 'dynamic_graph', +// 'pr_curve', +// 'roc_curve', +// 'profiler', +// 'x2paddle', +// 'fastdeploy_server' +// ]; +export default ['fastdeploy_client', 'static_graph', 'x2paddle', 'fastdeploy_server']; diff --git a/frontend/packages/mock/data/fastdeploy/check_server_alive.js b/frontend/packages/mock/data/fastdeploy/check_server_alive.js new file mode 100644 index 00000000..c60ce9d5 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/check_server_alive.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default 0; diff --git a/frontend/packages/mock/data/fastdeploy/config_update.js b/frontend/packages/mock/data/fastdeploy/config_update.js new file mode 100644 index 00000000..c60ce9d5 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/config_update.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default 0; diff --git a/frontend/packages/mock/data/fastdeploy/create_fastdeploy_client.js b/frontend/packages/mock/data/fastdeploy/create_fastdeploy_client.js new file mode 100644 index 00000000..c60ce9d5 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/create_fastdeploy_client.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default 0; diff --git a/frontend/packages/mock/data/fastdeploy/delete_config_for_model.js b/frontend/packages/mock/data/fastdeploy/delete_config_for_model.js new file mode 100644 index 00000000..a591e7aa --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/delete_config_for_model.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default ['config.pbtxt', 'config1.pbtxt']; diff --git a/frontend/packages/mock/data/app/component_tabs.js b/frontend/packages/mock/data/fastdeploy/delete_resource_for_model.js similarity index 69% rename from frontend/packages/mock/data/app/component_tabs.js rename to frontend/packages/mock/data/fastdeploy/delete_resource_for_model.js index a2f9d62a..d9e5f7cd 100644 --- a/frontend/packages/mock/data/app/component_tabs.js +++ b/frontend/packages/mock/data/fastdeploy/delete_resource_for_model.js @@ -15,19 +15,14 @@ */ export default [ - 'scalar', - 'image', - 'text', - 'embeddings', - 'audio', - 'histogram', - 'hyper_parameters', - 'static_graph', - 'dynamic_graph', - 'pr_curve', - 'roc_curve', - 'profiler', - 'x2paddle', - 'fastdeploy_server' + { + title: '1', + key: '1', + children: [ + { + title: 'model.py', + key: 'model.py' + } + ] + } ]; -// export default ['histogram']; diff --git a/frontend/packages/mock/data/fastdeploy/download_pretrain_model.js b/frontend/packages/mock/data/fastdeploy/download_pretrain_model.js new file mode 100644 index 00000000..6d3caa7a --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/download_pretrain_model.js @@ -0,0 +1,32 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default [ + { + title: '2', + key: '2', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + } +]; diff --git a/frontend/packages/mock/data/fastdeploy/get_config.js b/frontend/packages/mock/data/fastdeploy/get_config.js new file mode 100644 index 00000000..83bf4908 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_config.js @@ -0,0 +1,303 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + models: [ + { + name: 'postprocess', + config_filenames: 'config.pbtxt', + input: [ + { + name: 'POST_INPUT_0', + dataType: 'TYPE_FP32', + dims: ['-1', '-1', '-1'] + }, + { + name: 'POST_INPUT_1', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + output: [ + { + name: 'POST_OUTPUT', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + instanceGroup: [ + { + count: 1, + kind: 'KIND_CPU' + } + ], + backend: 'python', + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + } + ] + }, + { + name: 'runtime', + config_filenames: 'config.pbtxt', + maxBatchSize: 16, + input: [ + { + name: 'images', + dataType: 'TYPE_FP32', + dims: ['3', '-1', '-1'] + } + ], + output: [ + { + name: 'output', + dataType: 'TYPE_FP32', + dims: ['-1', '-1'] + } + ], + instanceGroup: [ + { + count: 1, + gpus: [0], + kind: 'KIND_GPU' + } + ], + backend: 'fastdeploy', + optimization: { + gpuExecutionAccelerator: [ + { + name: 'onnxruntime', + parameters: { + cpu_threads: '2' + } + } + ] + }, + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: 'model.onnx', + key: 'model.onnx' + }, + { + title: 'README.md', + key: 'README.md' + } + ] + } + ] + }, + { + name: 'preprocess', + config_filenames: 'config.pbtxt', + maxBatchSize: 1, + input: [ + { + name: 'INPUT_0', + dataType: 'TYPE_UINT8', + dims: ['-1', '-1', '3'] + } + ], + output: [ + { + name: 'preprocess_output_0', + dataType: 'TYPE_FP32', + dims: ['3', '-1', '-1'] + }, + { + name: 'preprocess_output_1', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + instanceGroup: [ + { + count: 1, + kind: 'KIND_CPU' + } + ], + backend: 'python', + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + } + ] + } + ], + ensembles: [ + { + name: 'yolov5', + config_filenames: 'config.pbtxt', + platform: 'ensemble', + maxBatchSize: 1, + input: [ + { + name: 'INPUT', + dataType: 'TYPE_UINT8', + dims: ['-1', '-1', '3'] + } + ], + output: [ + { + name: 'detction_result', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: 'README.md', + key: 'README.md' + } + ] + } + ], + step: [ + { + modelName: 'preprocess', + modelVersion: '1', + inputMap: { + INPUT_0: 'INPUT' + }, + outputMap: { + preprocess_output_1: 'postprocess_input_1', + preprocess_output_0: 'infer_input' + }, + modelType: 'normal', + inputModels: ['feed'], + pos_x: 0, + pos_y: 1, + outputModels: ['postprocess', 'runtime'], + inputVars: ['INPUT'], + outputVars: ['postprocess_input_1', 'infer_input'] + }, + { + modelName: 'runtime', + modelVersion: '1', + inputMap: { + images: 'infer_input' + }, + outputMap: { + output: 'infer_output' + }, + modelType: 'normal', + inputModels: ['preprocess'], + outputModels: ['postprocess'], + inputVars: ['infer_input'], + outputVars: ['infer_output'], + pos_x: 0, + pos_y: 2 + }, + { + modelName: 'postprocess', + modelVersion: '1', + inputMap: { + POST_INPUT_0: 'infer_output', + POST_INPUT_1: 'postprocess_input_1' + }, + outputMap: { + POST_OUTPUT: 'detction_result' + }, + modelType: 'normal', + inputModels: ['preprocess', 'runtime'], + outputModels: ['fetch'], + inputVars: ['postprocess_input_1', 'infer_output'], + outputVars: ['detction_result'], + pos_x: 0, + pos_y: 3 + }, + { + modelName: 'feed', + modelType: 'virtual', + inputModels: [], + outputModels: ['preprocess'], + inputVars: [], + outputVars: ['INPUT'], + pos_x: 0, + pos_y: 0 + }, + { + modelName: 'fetch', + modelType: 'virtual', + inputModels: ['postprocess'], + outputModels: [], + inputVars: ['detction_result'], + outputVars: [], + pos_x: 0, + pos_y: 5 + } + ] + } + ] +}; +// export default { +// ensembles: [], +// models: [ +// { +// name: 'uie', +// maxBatchSize: 1, +// input: [ +// {name: 'INPUT_0', dataType: 'TYPE_STRING', dims: ['1']}, +// {name: 'INPUT_1', dataType: 'TYPE_STRING', dims: ['1']} +// ], +// output: [{name: 'OUTPUT_0', dataType: 'TYPE_STRING', dims: ['1']}], +// instanceGroup: [{count: 1, gpus: [0], kind: 'KIND_GPU'}], +// backend: 'python', +// config_filenames: 'config.pbtxt', +// optimization: {gpuExecutionAccelerator: [{name: 'paddle', parameters: {cpu_threads: '12'}}]}, +// versions: [ +// { +// title: '1', +// key: '1', +// children: [ +// {title: '__pycache__', key: '__pycache__'}, +// {title: 'model.py', key: 'model.py'} +// ] +// } +// ] +// } +// ] +// }; diff --git a/frontend/packages/mock/data/fastdeploy/get_config_filenames_for_model.js b/frontend/packages/mock/data/fastdeploy/get_config_filenames_for_model.js new file mode 100644 index 00000000..fd10bb09 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_config_filenames_for_model.js @@ -0,0 +1,30 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default [ + 'config.pbtxt', + 'config_vdlbackup_2023-01-05T11:25:01.694514.pbtxt', + 'config_vdlbackup_2023-01-05T11:05:13.423998.pbtxt', + 'config_vdlbackup_2023-01-05T11:18:19.996202.pbtxt', + 'config_vdlbackup_2023-01-05T11:09:50.646703.pbtxt', + 'config_vdlbackup_2022-12-28T18:21:25.316965.pbtxt', + 'config_vdlbackup_2022-12-28T16:03:43.568570.pbtxt', + 'config_vdlbackup_2023-01-04T17:29:35.897158.pbtxt', + 'config_vdlbackup_2023-01-05T11:06:51.577665.pbtxt', + 'config_vdlbackup_2022-12-28T16:21:35.908249.pbtxt', + 'config_vdlbackup_2022-12-28T16:03:54.162789.pbtxt', + 'config_vdlbackup_2022-12-29T11:29:25.599371.pbtxt' +]; diff --git a/frontend/packages/mock/data/fastdeploy/get_config_for_model.js b/frontend/packages/mock/data/fastdeploy/get_config_for_model.js new file mode 100644 index 00000000..839640cd --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_config_for_model.js @@ -0,0 +1,62 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + name: 'postprocess', + config_filenames: 'config_vdlbackup_2023-01', + input: [ + { + name: 'POST_INPUT_0', + dataType: 'TYPE_FP32', + dims: ['-1', '-1', '-1'] + }, + { + name: 'POST_INPUT_1', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + output: [ + { + name: 'POST_OUTPUT', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + instanceGroup: [ + { + count: 1, + kind: 'KIND_CPU' + } + ], + backend: 'python', + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + } + ] +}; diff --git a/frontend/packages/mock/data/fastdeploy/get_directory.js b/frontend/packages/mock/data/fastdeploy/get_directory.js new file mode 100644 index 00000000..9af16035 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_directory.js @@ -0,0 +1,20 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + parent_dir: 'cur_dir', + sub_dir: ['sub_dir0', 'sub_dir1', 'sub_dir2', 'sub_dir3', 'sub_dir4', 'sub_dir5', 'sub_dir6', 'sub_dir7', '..'] +}; diff --git a/frontend/packages/mock/data/fastdeploy/get_pretrain_model_list.js b/frontend/packages/mock/data/fastdeploy/get_pretrain_model_list.js new file mode 100644 index 00000000..4fc19177 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_pretrain_model_list.js @@ -0,0 +1,185 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default [ + { + value: '\u4eba\u8138\u5173\u952e\u70b9\u68c0\u6d4b', + label: '\u4eba\u8138\u5173\u952e\u70b9\u68c0\u6d4b', + children: [ + {value: 'FaceLandmark1000', label: 'FaceLandmark1000'}, + {value: 'PIPNet19_ResNet101', label: 'PIPNet19_ResNet101'}, + {value: 'PIPNet19_ResNet18', label: 'PIPNet19_ResNet18'}, + {value: 'PIPNet29_ResNet101', label: 'PIPNet29_ResNet101'}, + {value: 'PIPNet29_ResNet18', label: 'PIPNet29_ResNet18'}, + {value: 'PIPNet68_ResNet101', label: 'PIPNet68_ResNet101'}, + {value: 'PIPNet68_ResNet18', label: 'PIPNet68_ResNet18'}, + {value: 'PIPNet98_ResNet101', label: 'PIPNet98_ResNet101'}, + {value: 'PIPNet98_ResNet18', label: 'PIPNet98_ResNet18'} + ] + }, + { + value: '\u4eba\u8138\u68c0\u6d4b', + label: '\u4eba\u8138\u68c0\u6d4b', + children: [ + {value: 'ArcFace-r100', label: 'ArcFace-r100'}, + {value: 'ArcFace-r100_lr0.1', label: 'ArcFace-r100_lr0.1'}, + {value: 'ArcFace-r18', label: 'ArcFace-r18'}, + {value: 'ArcFace-r34', label: 'ArcFace-r34'}, + {value: 'ArcFace-r50', label: 'ArcFace-r50'}, + {value: 'CosFace-r100', label: 'CosFace-r100'}, + {value: 'CosFace-r18', label: 'CosFace-r18'}, + {value: 'CosFace-r34', label: 'CosFace-r34'}, + {value: 'CosFace-r50', label: 'CosFace-r50'}, + {value: 'PartialFC-r34', label: 'PartialFC-r34'}, + {value: 'PartialFC-r50', label: 'PartialFC-r50'}, + {value: 'RetinaFace_mobile0.25-640', label: 'RetinaFace_mobile0.25-640'}, + {value: 'RetinaFace_mobile0.25-720', label: 'RetinaFace_mobile0.25-720'}, + {value: 'RetinaFace_resnet50-640', label: 'RetinaFace_resnet50-640'}, + {value: 'RetinaFace_resnet50-720', label: 'RetinaFace_resnet50-720'}, + {value: 'SCRFD-10G-1280', label: 'SCRFD-10G-1280'}, + {value: 'SCRFD-10G-320', label: 'SCRFD-10G-320'}, + {value: 'SCRFD-10G-640', label: 'SCRFD-10G-640'}, + {value: 'SCRFD-10G-kps-1280', label: 'SCRFD-10G-kps-1280'}, + {value: 'SCRFD-10G-kps-320', label: 'SCRFD-10G-kps-320'}, + {value: 'SCRFD-10G-kps-640', label: 'SCRFD-10G-kps-640'}, + {value: 'SCRFD-1G-160', label: 'SCRFD-1G-160'}, + {value: 'SCRFD-1G-320', label: 'SCRFD-1G-320'}, + {value: 'SCRFD-1G-640', label: 'SCRFD-1G-640'}, + {value: 'SCRFD-2.5G-160', label: 'SCRFD-2.5G-160'}, + {value: 'SCRFD-2.5G-320', label: 'SCRFD-2.5G-320'}, + {value: 'SCRFD-2.5G-640', label: 'SCRFD-2.5G-640'}, + {value: 'SCRFD-2.5G-kps-160', label: 'SCRFD-2.5G-kps-160'}, + {value: 'SCRFD-2.5G-kps-320', label: 'SCRFD-2.5G-kps-320'}, + {value: 'SCRFD-2.5G-kps-640', label: 'SCRFD-2.5G-kps-640'}, + {value: 'SCRFD-500M-160', label: 'SCRFD-500M-160'}, + {value: 'SCRFD-500M-320', label: 'SCRFD-500M-320'}, + {value: 'SCRFD-500M-640', label: 'SCRFD-500M-640'}, + {value: 'SCRFD-500M-kps-160', label: 'SCRFD-500M-kps-160'}, + {value: 'SCRFD-500M-kps-320', label: 'SCRFD-500M-kps-320'}, + {value: 'SCRFD-500M-kps-640', label: 'SCRFD-500M-kps-640'}, + {value: 'YOLOv5l-Face', label: 'YOLOv5l-Face'}, + {value: 'YOLOv5s-Face', label: 'YOLOv5s-Face'}, + {value: 'YOLOv5s-Face-bak', label: 'YOLOv5s-Face-bak'} + ] + }, + { + value: '\u4fe1\u606f\u62bd\u53d6', + label: '\u4fe1\u606f\u62bd\u53d6', + children: [ + {value: 'uie-base', label: 'uie-base'}, + {value: 'uie-medium', label: 'uie-medium'}, + {value: 'uie-micro', label: 'uie-micro'}, + {value: 'uie-mini', label: 'uie-mini'}, + {value: 'uie-nano', label: 'uie-nano'} + ] + }, + { + value: '\u56fe\u50cf\u5206\u5272', + label: '\u56fe\u50cf\u5206\u5272', + children: [ + {value: 'Deeplabv3-ResNet101-OS8-cityscapes', label: 'Deeplabv3-ResNet101-OS8-cityscapes'}, + {value: 'FCN-HRNet-W18-cityscapes', label: 'FCN-HRNet-W18-cityscapes'}, + {value: 'PP-HumanSegV1-Lite', label: 'PP-HumanSegV1-Lite'}, + {value: 'PP-HumanSegV1-Server', label: 'PP-HumanSegV1-Server'}, + {value: 'PP-HumanSegV2-Lite', label: 'PP-HumanSegV2-Lite'}, + {value: 'PP-HumanSegV2-Mobile', label: 'PP-HumanSegV2-Mobile'}, + {value: 'PP-LiteSeg-T(STDC1)-cityscapes', label: 'PP-LiteSeg-T(STDC1)-cityscapes'}, + {value: 'Portait-PP-HumanSegV2_Lite', label: 'Portait-PP-HumanSegV2_Lite'}, + {value: 'Unet-cityscapes', label: 'Unet-cityscapes'} + ] + }, + { + value: '\u56fe\u50cf\u5206\u7c7b', + label: '\u56fe\u50cf\u5206\u7c7b', + children: [ + {value: 'EfficientNetB0_small', label: 'EfficientNetB0_small'}, + {value: 'EfficientNetB7', label: 'EfficientNetB7'}, + {value: 'GhostNet_x0_5_ssld', label: 'GhostNet_x0_5_ssld'}, + {value: 'GhostNet_x1_3_ssld', label: 'GhostNet_x1_3_ssld'}, + {value: 'InceptionV3', label: 'InceptionV3'}, + {value: 'MobileNetV1_ssld', label: 'MobileNetV1_ssld'}, + {value: 'MobileNetV1_x0_25', label: 'MobileNetV1_x0_25'}, + {value: 'MobileNetV2_ssld', label: 'MobileNetV2_ssld'}, + {value: 'MobileNetV2_x0_25', label: 'MobileNetV2_x0_25'}, + {value: 'MobileNetV3_large_x1_0_ssld', label: 'MobileNetV3_large_x1_0_ssld'}, + {value: 'MobileNetV3_small_x0_35_ssld', label: 'MobileNetV3_small_x0_35_ssld'}, + {value: 'PPHGNet_base_ssld', label: 'PPHGNet_base_ssld'}, + {value: 'PPHGNet_tiny_ssld', label: 'PPHGNet_tiny_ssld'}, + {value: 'PPLCNetV2_base', label: 'PPLCNetV2_base'}, + {value: 'PPLCNet_x1_0', label: 'PPLCNet_x1_0'}, + {value: 'ResNet101_Torch', label: 'ResNet101_Torch'}, + {value: 'ResNet18_Torch', label: 'ResNet18_Torch'}, + {value: 'ResNet34_Torch', label: 'ResNet34_Torch'}, + {value: 'ResNet50_Torch', label: 'ResNet50_Torch'}, + {value: 'ResNet50_vd', label: 'ResNet50_vd'}, + {value: 'ShuffleNetV2_x0_25', label: 'ShuffleNetV2_x0_25'}, + {value: 'ShuffleNetV2_x2_0', label: 'ShuffleNetV2_x2_0'}, + {value: 'SqueezeNet1_1', label: 'SqueezeNet1_1'} + ] + }, + { + value: '\u56fe\u50cf\u751f\u6210', + label: '\u56fe\u50cf\u751f\u6210', + children: [ + {value: 'animegan_v1_hayao_60', label: 'animegan_v1_hayao_60'}, + {value: 'animegan_v2_hayao_64', label: 'animegan_v2_hayao_64'}, + {value: 'animegan_v2_hayao_99', label: 'animegan_v2_hayao_99'}, + {value: 'animegan_v2_paprika_54', label: 'animegan_v2_paprika_54'}, + {value: 'animegan_v2_paprika_74', label: 'animegan_v2_paprika_74'}, + {value: 'animegan_v2_paprika_97', label: 'animegan_v2_paprika_97'}, + {value: 'animegan_v2_paprika_98', label: 'animegan_v2_paprika_98'}, + {value: 'animegan_v2_shinkai_33', label: 'animegan_v2_shinkai_33'}, + {value: 'animegan_v2_shinkai_53', label: 'animegan_v2_shinkai_53'} + ] + }, + { + value: '\u62a0\u56fe', + label: '\u62a0\u56fe', + children: [ + {value: 'Modnet-HRNet_w18', label: 'Modnet-HRNet_w18'}, + {value: 'Modnet-MobileNetV2', label: 'Modnet-MobileNetV2'}, + {value: 'Modnet-ResNet50_vd', label: 'Modnet-ResNet50_vd'}, + {value: 'PP-HumanMatting', label: 'PP-HumanMatting'}, + {value: 'PP-Matting-1024', label: 'PP-Matting-1024'}, + {value: 'PP-Matting-512', label: 'PP-Matting-512'}, + {value: 'modnet_photographic', label: 'modnet_photographic'}, + {value: 'modnet_photographic_1024', label: 'modnet_photographic_1024'}, + {value: 'modnet_photographic_256', label: 'modnet_photographic_256'}, + {value: 'modnet_photographic_512', label: 'modnet_photographic_512'}, + {value: 'modnet_webcam', label: 'modnet_webcam'}, + {value: 'modnet_webcam_1024', label: 'modnet_webcam_1024'}, + {value: 'modnet_webcam_256', label: 'modnet_webcam_256'}, + {value: 'modnet_webcam_512', label: 'modnet_webcam_512'} + ] + }, + { + value: '\u6587\u5b57\u8bc6\u522b', + label: '\u6587\u5b57\u8bc6\u522b', + children: [ + {value: 'ch_PP-OCRv2_det', label: 'ch_PP-OCRv2_det'}, + {value: 'ch_PP-OCRv2_rec', label: 'ch_PP-OCRv2_rec'}, + {value: 'ch_PP-OCRv3_det', label: 'ch_PP-OCRv3_det'}, + {value: 'ch_PP-OCRv3_rec', label: 'ch_PP-OCRv3_rec'}, + {value: 'ch_ppocr_mobile_v2.0_cls', label: 'ch_ppocr_mobile_v2.0_cls'}, + {value: 'ch_ppocr_mobile_v2.0_det', label: 'ch_ppocr_mobile_v2.0_det'}, + {value: 'ch_ppocr_mobile_v2.0_rec', label: 'ch_ppocr_mobile_v2.0_rec'}, + {value: 'ch_ppocr_server_v2.0_det', label: 'ch_ppocr_server_v2.0_det'}, + {value: 'ch_ppocr_server_v2.0_rec', label: 'ch_ppocr_server_v2.0_rec'}, + {value: 'en_PP-OCRv3_det', label: 'en_PP-OCRv3_det'}, + {value: 'en_PP-OCRv3_rec', label: 'en_PP-OCRv3_rec'} + ] + } +]; diff --git a/frontend/packages/mock/data/fastdeploy/get_server_config.js b/frontend/packages/mock/data/fastdeploy/get_server_config.js new file mode 100644 index 00000000..28fc9a73 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_server_config.js @@ -0,0 +1,287 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + 'ensemble-img': + 'data:image/png;base64,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o44q21vZHnzwQfn000/lX//6V6WCxUrFzp07y5lnnin9+vWr1HvZxcuOAEs3yrR1YNlvYWeUB4EHHnhAXnrpJXnjjTekSZMm5blUiXNbtmwpHTt2lJ49e5bpmlVFHDk5OXLyyScrcTzxxBNlKqNlrhoEjDiqBudtugsPH7Jib5dddtmm8+OdBHF06tRJbrrppjJdt6qIg0KtWbNGatWqpY91W0o/BIw4ylkn7FcydOhQ+eijj7STN2/eXG688Ub9JL388suyYMECOeuss+TJJ5+U77//Xp5//nn573//K999951ccMEFMmrUKPn3v/+tqgJpTscmffLJJ6o4nnnmmUgHysrKkocfflhmz54tO+20k+a95ZZbZM89E+/UhdvzzjvvyJdffikNGjSQRo0ayTnnnKNuAQkbcIsoy/777y9nnHGGqhIebiLFIo5x48bJu+++K926dVOFkAiPr776SkaMGCF9+vSRp59+WubMmSN169aVrl276jXcng9gCGZt2rSRhx56SBYuXLhVTbGeYMyYMfr/RLjEqweHdTmbQeBON+IoR5XzcGCHDh2UDPg88MAD1a1YtGiR0KGOPvpo7Wwvvvii3oWOxZPHF110kbz99tv6f0ZVziXO9NprrwkByM8++0yJYMKECXLXXXfJ/PnzddEN8+etW7dWwqCz42tyDum9996TREHuL774QubOnavyn7LRaZo1ayatWrWS119/Xe644w4tIx2WKTc6+LHHHitjx47VpyKjiYMYzODBg+Waa66Rvn376v4tifD48MMPlVhJ5557rvzP//yP3vunn36SkSNHyumnn66/Ub6rrrpKbrjhBpk0aZL89ttvkZpauXKlTJw4UYkWvJPBJV49cH9LZUfAiKPsmEXOoNHefvvtMnr0aDn11FP1/3Qevh900EE6GroG26NHD+nVq1fkXPd/Oh6jKgnCuPrqq3WEhVyiieO2226TN998U2bNmiX16tXTc+g0p512mo7g1113XVLWRLsq69evl//93/+VY445RlWAG/UJgqI4hg0bJuedd14J4qCTDx8+XG3CNlIyeDjiaNeunRDDIeGWHHfccXLhhReqmoomDq9RkDVENW/ePJk8ebKwBikZXOLVQ1KAWaatEDDiKEejwK2YOnWqfPzxx/rEoEuMxKgJlALEwPcPPvigxMyIa8h0AB4aIvGwITMd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559/XjtessmII1mkEud744035Pbbb5d58+bp2gJLVYdAIIiDZ3B4HqciG5cjjhdeeEFOPPHEpGvMiCNpqBJmdMTx7bffqrtlqeoQSBvi+Pzzz2XUqFEyd+5c2X///eXMM8+Unj176ko1EiNLkyZNZOPGjTJ27FhdIj958mS544475IorrpBPPvlEPvroI82LEujfv7/UqlVL/+a6uCq33nqr/o2b8eKLLwoNb9GiRXLUUUdJ+/bt5eKLL04K+XvuuUfmz58v33//vRx22GFCjOjmm2+WY445Ru8zePBgmTFjhpbxyCOPlF69esnRRx+t145FHDxEdNddd6mtDz/8sHYCYg98nz17tv6NqrnlllsisQjw4N48ZzRx4kRVVNz/zjvvlP32+/tta5Rz2LBh8s0330Rwbdu2rey9995anmhX5f3335f33ntPPvvsM10UeN5550mnTp3UxkTpq6++Uqwp26OPPipz5sxRV65169Zy7bXX6gNSLhHnGTp0qObBvhNOOEHrxwXqkcOvvvqquiJg8I9//ENQju3atdM2cN1118nKlSvll19+kWOPPVavPXLkSHnwwQeVyPntzTfflN9++01x4doHH3yw3p5yjhgxQuvsueeek2nTpmlbu+GGGxLWnyv/lClT1PWlDbRq1UpOP/10adOmje5jQWIfG+yjTdIOmjdvLjfeeKN+kkqzz+FUnrpIVFfl/T0tiIOK69Gjh1Zsx44d5YcffpDXX39dK+SZZ56JNHAawfr167XxoCA4B/+WROe/4IILlEAgocsvv1wbMKlPnz4aCX7llVf070GDBsmYMWP0+qeddppMnz5dOzod86qrrkqI6WuvvSb/+c9/5OWXX9bG0qhRIzn33HM11kEnWbVqlTYSVtjReL/88kttoDT+aOLIycmRyy67TBsX5TvggAN0npzr0KE6d+6sjYx7kujUdGI6vAuydunSRZYsWaKYQSZvvfWWdiQkfIcOHRQbPln1N378eG3ckC7E6iUOcCAeRAelI9ApIVjOdaRbGjgffvih2u2uCxksXLhQnn32WaGMAwcO1NMha3CjrF27dlX7nn76acWAzkKg1tXRNddcI4cccohiOGnSJCWmk046SfN/9913Wm+QCIuSrr76am0btBOeqaB98FwFNmA7dQGpest54IEHKj5NmzZVuxPVH+Vn4Lr//vsFAqZO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', + models: [ + { + name: 'postprocess', + input: [ + { + name: 'POST_INPUT_0', + dataType: 'TYPE_FP32', + dims: ['-1', '-1', '-1'] + }, + { + name: 'POST_INPUT_1', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + output: [ + { + name: 'POST_OUTPUT', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + instanceGroup: [ + { + count: 1, + kind: 'KIND_CPU' + } + ], + backend: 'python', + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + }, + { + title: '2', + key: '2', + children: [ + { + title: '__pycache__', + key: '__pycache__2' + }, + { + title: 'model.py', + key: 'model.py2' + } + ] + } + ] + }, + { + name: 'runtime', + maxBatchSize: 16, + input: [ + { + name: 'images', + dataType: 'TYPE_FP32', + dims: ['3', '-1', '-1'] + } + ], + output: [ + { + name: 'output', + dataType: 'TYPE_FP32', + dims: ['-1', '-1'] + } + ], + instanceGroup: [ + { + count: 1, + gpus: [0], + kind: 'KIND_GPU' + } + ], + backend: 'fastdeploy', + optimization: { + gpuExecutionAccelerator: [ + { + name: 'onnxruntime', + parameters: { + cpu_threads: '2' + } + } + ] + }, + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: 'model.onnx', + key: 'model.onnx' + }, + { + title: 'README.md', + key: 'README.md' + } + ] + } + ] + }, + { + name: 'preprocess', + maxBatchSize: 1, + input: [ + { + name: 'INPUT_0', + dataType: 'TYPE_UINT8', + dims: ['-1', '-1', '3'] + } + ], + output: [ + { + name: 'preprocess_output_0', + dataType: 'TYPE_FP32', + dims: ['3', '-1', '-1'] + }, + { + name: 'preprocess_output_1', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + instanceGroup: [ + { + count: 1, + kind: 'KIND_CPU' + } + ], + backend: 'python', + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: '__pycache__', + key: '__pycache__' + }, + { + title: 'model.py', + key: 'model.py' + } + ] + } + ] + } + ], + ensembles: [ + { + name: 'yolov5', + platform: 'ensemble', + maxBatchSize: 1, + input: [ + { + name: 'INPUT', + dataType: 'TYPE_UINT8', + dims: ['-1', '-1', '3'] + } + ], + output: [ + { + name: 'detction_result', + dataType: 'TYPE_STRING', + dims: ['-1'] + } + ], + versions: [ + { + title: '1', + key: '1', + children: [ + { + title: 'README.md', + key: 'README.md' + } + ] + } + ], + step: [ + { + modelName: 'preprocess', + modelVersion: '1', + inputMap: { + INPUT_0: 'INPUT' + }, + outputMap: { + preprocess_output_1: 'postprocess_input_1', + preprocess_output_0: 'infer_input' + }, + modelType: 'normal', + inputModels: ['feed'], + pos_x: 0, + pos_y: 1, + outputModels: ['postprocess', 'runtime'], + inputVars: ['INPUT'], + outputVars: ['postprocess_input_1', 'infer_input'] + }, + { + modelName: 'runtime', + modelVersion: '1', + inputMap: { + images: 'infer_input' + }, + outputMap: { + output: 'infer_output' + }, + modelType: 'normal', + inputModels: ['preprocess'], + outputModels: ['postprocess'], + inputVars: ['infer_input'], + outputVars: ['infer_output'], + pos_x: 0, + pos_y: 2 + }, + { + modelName: 'postprocess', + modelVersion: '1', + inputMap: { + POST_INPUT_0: 'infer_output', + POST_INPUT_1: 'postprocess_input_1' + }, + outputMap: { + POST_OUTPUT: 'detction_result' + }, + modelType: 'normal', + inputModels: ['preprocess', 'runtime'], + outputModels: ['fetch'], + inputVars: ['postprocess_input_1', 'infer_output'], + outputVars: ['detction_result'], + pos_x: 0, + pos_y: 3 + }, + { + modelName: 'feed', + modelType: 'virtual', + inputModels: [], + outputModels: ['preprocess'], + inputVars: [], + outputVars: ['INPUT'], + pos_x: 0, + pos_y: 0 + }, + { + modelName: 'fetch', + modelType: 'virtual', + inputModels: ['postprocess'], + outputModels: [], + inputVars: ['detction_result'], + outputVars: [], + pos_x: 0, + pos_y: 5 + } + ] + } + ] +}; diff --git a/frontend/packages/mock/data/fastdeploy/get_server_list.js b/frontend/packages/mock/data/fastdeploy/get_server_list.js new file mode 100644 index 00000000..ec4a8e62 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_server_list.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default ['test_yolov5', 23421, '34211']; diff --git a/frontend/packages/mock/data/fastdeploy/get_server_metric.js b/frontend/packages/mock/data/fastdeploy/get_server_metric.js new file mode 100644 index 00000000..2f2bd3cd --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_server_metric.js @@ -0,0 +1,122 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + Model: { + yolov5: { + nv_inference_request_success: '0', + nv_inference_request_failure: '0', + nv_inference_count: '0', + nv_inference_exec_count: '0', + nv_inference_request_duration_us: '0', + nv_inference_queue_duration_us: '0', + nv_inference_compute_input_duration_us: '0', + nv_inference_compute_infer_duration_us: '0', + nv_inference_compute_output_duration_us: '0' + }, + runtime: { + nv_inference_request_success: '0', + nv_inference_request_failure: '0', + nv_inference_count: '0', + nv_inference_exec_count: '0', + nv_inference_request_duration_us: '0', + nv_inference_queue_duration_us: '0', + nv_inference_compute_input_duration_us: '0', + nv_inference_compute_infer_duration_us: '0', + nv_inference_compute_output_duration_us: '0' + }, + preprocess: { + nv_inference_request_success: '0', + nv_inference_request_failure: '0', + nv_inference_count: '0', + nv_inference_exec_count: '0', + nv_inference_request_duration_us: '0', + nv_inference_queue_duration_us: '0', + nv_inference_compute_input_duration_us: '0', + nv_inference_compute_infer_duration_us: '0', + nv_inference_compute_output_duration_us: '0' + }, + postprocess: { + nv_inference_request_success: '0', + nv_inference_request_failure: '0', + nv_inference_count: '0', + nv_inference_exec_count: '0', + nv_inference_request_duration_us: '0', + nv_inference_queue_duration_us: '0', + nv_inference_compute_input_duration_us: '0', + nv_inference_compute_infer_duration_us: '0', + nv_inference_compute_output_duration_us: '0' + } + }, + GPU: { + 'GPU-fe9adac3-25d8-0b4f-fffc-9397a7985a28': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '350224384', + nv_gpu_power_usage: '50', + nv_gpu_power_limit: '250', + nv_energy_consumption: '914' + }, + 'GPU-080f3ff9-2e52-0e73-61ea-5fc301f78321': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '350224384', + nv_gpu_power_usage: '51', + nv_gpu_power_limit: '250', + nv_energy_consumption: '940' + }, + 'GPU-7350ae76-901d-45f2-77ef-0ca26da53abf': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '1668284416', + nv_gpu_power_usage: '52', + nv_gpu_power_limit: '250', + nv_energy_consumption: '956' + }, + 'GPU-85ce09c2-23c9-d346-274d-f1eb6de7083f': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '350224384', + nv_gpu_power_usage: '51', + nv_gpu_power_limit: '250', + nv_energy_consumption: '946' + }, + 'GPU-ac8da5c4-9a6e-eb0b-763f-1c7121b2ab65': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '350224384', + nv_gpu_power_usage: '50', + nv_gpu_power_limit: '250', + nv_energy_consumption: '918' + }, + 'GPU-032ea902-18dd-454c-8fc9-459d909005a5': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '350224384', + nv_gpu_power_usage: '50', + nv_gpu_power_limit: '250', + nv_energy_consumption: '924' + }, + 'GPU-87ba4a86-a7c5-b394-d4b0-2b063e95f8c6': { + nv_gpu_utilization: '0', + nv_gpu_memory_total_bytes: '24159191040', + nv_gpu_memory_used_bytes: '11399069696', + nv_gpu_power_usage: '53', + nv_gpu_power_limit: '250', + nv_energy_consumption: '971' + } + } +}; diff --git a/frontend/packages/mock/data/fastdeploy/get_server_output.js b/frontend/packages/mock/data/fastdeploy/get_server_output.js new file mode 100644 index 00000000..d07dd93c --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/get_server_output.js @@ -0,0 +1,135 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default `I1201 03:40:58.374595 9800 metrics.cc:298] Collecting metrics for GPU 0: Tesla P40 +I1201 03:40:58.374853 9800 metrics.cc:298] Collecting metrics for GPU 1: Tesla P40 +I1201 03:40:58.374873 9800 metrics.cc:298] Collecting metrics for GPU 2: Tesla P40 +I1201 03:40:58.374886 9800 metrics.cc:298] Collecting metrics for GPU 3: Tesla P40 +I1201 03:40:58.374900 9800 metrics.cc:298] Collecting metrics for GPU 4: Tesla P40 +I1201 03:40:58.374918 9800 metrics.cc:298] Collecting metrics for GPU 5: Tesla P40 +I1201 03:40:58.374930 9800 metrics.cc:298] Collecting metrics for GPU 6: Tesla P40 +I1201 03:40:58.609011 9800 pinned_memory_manager.cc:240] Pinned memory pool is created at '0x7f8a30000000' with size 268435456 +I1201 03:40:58.614426 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 0 with size 67108864 +I1201 03:40:58.614439 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 1 with size 67108864 +I1201 03:40:58.614444 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 2 with size 67108864 +I1201 03:40:58.614449 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 3 with size 67108864 +I1201 03:40:58.614455 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 4 with size 67108864 +I1201 03:40:58.614460 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 5 with size 67108864 +I1201 03:40:58.614466 9800 cuda_memory_manager.cc:105] CUDA memory pool is created on device 6 with size 67108864 +I1201 03:40:59.361506 9800 model_repository_manager.cc:1022] loading: postprocess:1 +I1201 03:40:59.461702 9800 model_repository_manager.cc:1022] loading: preprocess:1 +I1201 03:40:59.467941 9800 python.cc:1875] TRITONBACKEND_ModelInstanceInitialize: postprocess_0 (CPU device 0) +I1201 03:40:59.561977 9800 model_repository_manager.cc:1022] loading: runtime:1 +I1201 03:41:00.121725 9800 model_repository_manager.cc:1183] successfully loaded 'postprocess' version 1 +I1201 03:41:00.455908 9800 fastdeploy_runtime.cc:1166] TRITONBACKEND_Initialize: fastdeploy +I1201 03:41:00.455951 9800 fastdeploy_runtime.cc:1175] Triton TRITONBACKEND API version: 1.6 +I1201 03:41:00.455960 9800 fastdeploy_runtime.cc:1180] 'fastdeploy' TRITONBACKEND API version: 1.6 +I1201 03:41:00.455967 9800 fastdeploy_runtime.cc:1209] backend configuration: +{} +I1201 03:41:00.455999 9800 python.cc:1875] TRITONBACKEND_ModelInstanceInitialize: preprocess_0 (CPU device 0) +I1201 03:41:01.095376 9800 fastdeploy_runtime.cc:1239] TRITONBACKEND_ModelInitialize: runtime (version 1) +I1201 03:41:01.095540 9800 model_repository_manager.cc:1183] successfully loaded 'preprocess' version 1 +I1201 03:41:01.097731 9800 fastdeploy_runtime.cc:1278] TRITONBACKEND_ModelInstanceInitialize: runtime_0 (GPU device 0) +[INFO] fastdeploy/runtime.cc(496)::Init Runtime initialized with Backend::ORT in Device::GPU. +I1201 03:41:04.015391 9800 model_repository_manager.cc:1183] successfully loaded 'runtime' version 1 +I1201 03:41:04.015668 9800 model_repository_manager.cc:1022] loading: yolov5:1 +I1201 03:41:04.118517 9800 model_repository_manager.cc:1183] successfully loaded 'yolov5' version 1 +I1201 03:41:04.118649 9800 server.cc:522] ++------------------+------+ +| Repository Agent | Path | ++------------------+------+ ++------------------+------+ + +I1201 03:41:04.118708 9800 server.cc:549] ++------------+---------------------------------------------------------------+--------------------------------------------------+ +| Backend | Path | Config | ++------------+---------------------------------------------------------------+--------------------------------------------------+ +| python | /opt/tritonserver/backends/python/libtriton_python.so | {"cmdline":{"shm-default-byte-size":"10485760"}} | +| fastdeploy | /opt/tritonserver/backends/fastdeploy/libtriton_fastdeploy.so | {} | ++------------+---------------------------------------------------------------+--------------------------------------------------+ + +I1201 03:41:04.118766 9800 server.cc:592] ++-------------+---------+--------+ +| Model | Version | Status | ++-------------+---------+--------+ +| postprocess | 1 | READY | +| preprocess | 1 | READY | +| runtime | 1 | READY | +| yolov5 | 1 | READY | ++-------------+---------+--------+ + +I1201 03:41:04.118918 9800 tritonserver.cc:1920] ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| Option | Value | ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| server_id | triton | +| server_version | 2.15.0 | +| server_extensions | classification sequence model_repository model_repository(unload_dependents) schedule_policy model_configuration system_shared_memory cuda_shared_memory binary_tensor_data statistics | +| model_repository_path[0] | models/ | +| model_control_mode | MODE_NONE | +| strict_model_config | 1 | +| rate_limit | OFF | +| pinned_memory_pool_byte_size | 268435456 | +| cuda_memory_pool_byte_size{0} | 67108864 | +| cuda_memory_pool_byte_size{1} | 67108864 | +| cuda_memory_pool_byte_size{2} | 67108864 | +| cuda_memory_pool_byte_size{3} | 67108864 | +| cuda_memory_pool_byte_size{4} | 67108864 | +| cuda_memory_pool_byte_size{5} | 67108864 | +| cuda_memory_pool_byte_size{6} | 67108864 | +| response_cache_byte_size | 0 | +| min_supported_compute_capability | 6.0 | +| strict_readiness | 1 | +| exit_timeout | 30 | ++----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +I1201 03:41:04.120176 9800 grpc_server.cc:4117] Started GRPCInferenceService at 0.0.0.0:8001 +I1201 03:41:04.120557 9800 http_server.cc:2815] Started HTTPService at 0.0.0.0:8000 +I1201 03:41:04.161549 9800 http_server.cc:167] Started Metrics Service at 0.0.0.0:8002 +Signal (2) received. +I1201 03:41:24.491580 9800 server.cc:252] Waiting for in-flight requests to complete. +I1201 03:41:24.491604 9800 model_repository_manager.cc:1055] unloading: yolov5:1 +I1201 03:41:24.491679 9800 model_repository_manager.cc:1055] unloading: runtime:1 +I1201 03:41:24.491727 9800 model_repository_manager.cc:1055] unloading: preprocess:1 +I1201 03:41:24.491772 9800 model_repository_manager.cc:1055] unloading: postprocess:1 +I1201 03:41:24.491822 9800 server.cc:267] Timeout 30: Found 4 live models and 0 in-flight non-inference requests +I1201 03:41:24.492059 9800 fastdeploy_runtime.cc:1310] TRITONBACKEND_ModelInstanceFinalize: delete instance state +I1201 03:41:24.492085 9800 model_repository_manager.cc:1166] successfully unloaded 'yolov5' version 1 +I1201 03:41:24.501626 9800 fastdeploy_runtime.cc:1259] TRITONBACKEND_ModelFinalize: delete model state +I1201 03:41:24.502970 9800 model_repository_manager.cc:1166] successfully unloaded 'runtime' version 1 +Signal (2) received. +Signal (2) received. +Signal (2) received. +Signal (2) received. +Signal (2) received. +Signal (2) received. +I1201 03:41:25.492385 9800 server.cc:267] Timeout 29: Found 2 live models and 0 in-flight non-inference requests +model_config: {'name': 'preprocess', 'platform': '', 'backend': 'python', 'version_policy': {'latest': {'num_versions': 1}}, 'max_batch_size': 1, 'input': [{'name': 'INPUT_0', 'data_type': 'TYPE_UINT8', 'format': 'FORMAT_NONE', 'dims': [-1, -1, 3], 'is_shape_tensor': False, 'allow_ragged_batch': False}], 'output': [{'name': 'preprocess_output_0', 'data_type': 'TYPE_FP32', 'dims': [3, -1, -1], 'label_filename': '', 'is_shape_tensor': False}, {'name': 'preprocess_output_1', 'data_type': 'TYPE_STRING', 'dims': [-1], 'label_filename': '', 'is_shape_tensor': False}], 'batch_input': [], 'batch_output': [], 'optimization': {'priority': 'PRIORITY_DEFAULT', 'input_pinned_memory': {'enable': True}, 'output_pinned_memory': {'enable': True}, 'gather_kernel_buffer_threshold': 0, 'eager_batching': False}, 'instance_group': [{'name': 'preprocess_0', 'kind': 'KIND_CPU', 'count': 1, 'gpus': [], 'secondary_devices': [], 'profile': [], 'passive': False, 'host_policy': ''}], 'default_model_filename': '', 'cc_model_filenames': {}, 'metric_tags': {}, 'parameters': {}, 'model_warmup': []} +preprocess input names: ['INPUT_0'] +preprocess output names: ['preprocess_output_0', 'preprocess_output_1'] +Cleaning up... +model_config: {'name': 'postprocess', 'platform': '', 'backend': 'python', 'version_policy': {'latest': {'num_versions': 1}}, 'max_batch_size': 0, 'input': [{'name': 'POST_INPUT_0', 'data_type': 'TYPE_FP32', 'format': 'FORMAT_NONE', 'dims': [-1, -1, -1], 'is_shape_tensor': False, 'allow_ragged_batch': False}, {'name': 'POST_INPUT_1', 'data_type': 'TYPE_STRING', 'format': 'FORMAT_NONE', 'dims': [-1], 'is_shape_tensor': False, 'allow_ragged_batch': False}], 'output': [{'name': 'POST_OUTPUT', 'data_type': 'TYPE_STRING', 'dims': [-1], 'label_filename': '', 'is_shape_tensor': False}], 'batch_input': [], 'batch_output': [], 'optimization': {'priority': 'PRIORITY_DEFAULT', 'input_pinned_memory': {'enable': True}, 'output_pinned_memory': {'enable': True}, 'gather_kernel_buffer_threshold': 0, 'eager_batching': False}, 'instance_group': [{'name': 'postprocess_0', 'kind': 'KIND_CPU', 'count': 1, 'gpus': [], 'secondary_devices': [], 'profile': [], 'passive': False, 'host_policy': ''}], 'default_model_filename': '', 'cc_model_filenames': {}, 'metric_tags': {}, 'parameters': {}, 'model_warmup': []} +postprocess input names: ['POST_INPUT_0', 'POST_INPUT_1'] +postprocess output names: ['POST_OUTPUT'] +Cleaning up... +I1201 03:41:25.564997 9800 model_repository_manager.cc:1166] successfully unloaded 'preprocess' version 1 +I1201 03:41:25.566774 9800 model_repository_manager.cc:1166] successfully unloaded 'postprocess' version 1 +I1201 03:41:26.492445 9800 server.cc:267] Timeout 28: Found 0 live models and 0 in-flight non-inference requests +Signal (2) received. +Signal (2) received. +Signal (2) received. +Signal (2) received. +`; diff --git a/frontend/packages/mock/data/fastdeploy/rename_resource_for_model.js b/frontend/packages/mock/data/fastdeploy/rename_resource_for_model.js new file mode 100644 index 00000000..c8438b30 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/rename_resource_for_model.js @@ -0,0 +1,28 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default [ + { + title: '1', + key: '1', + children: [ + { + title: 'model.py1', + key: 'model.py1' + } + ] + } +]; diff --git a/frontend/packages/mock/data/fastdeploy/set_default_config_for_model.js b/frontend/packages/mock/data/fastdeploy/set_default_config_for_model.js new file mode 100644 index 00000000..c60ce9d5 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/set_default_config_for_model.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default 0; diff --git a/frontend/packages/mock/data/fastdeploy/start_server.js b/frontend/packages/mock/data/fastdeploy/start_server.js new file mode 100644 index 00000000..4760cfe0 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/start_server.js @@ -0,0 +1,19 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default { + id: 0 +}; diff --git a/frontend/packages/mock/data/fastdeploy/stop_server.js b/frontend/packages/mock/data/fastdeploy/stop_server.js new file mode 100644 index 00000000..c60ce9d5 --- /dev/null +++ b/frontend/packages/mock/data/fastdeploy/stop_server.js @@ -0,0 +1,17 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export default 0; diff --git a/frontend/packages/mock/data/graph_runs.js b/frontend/packages/mock/data/graph_runs.js index bf24f25c..51e21ca1 100644 --- a/frontend/packages/mock/data/graph_runs.js +++ b/frontend/packages/mock/data/graph_runs.js @@ -14,4 +14,4 @@ * limitations under the License. */ -export default {status: 0, msg: '', data: ['test_add_graph/', 'test_add_graph/test1']}; +export default {status: 0, msg: '', data: ['dynamic_graph', 'x2paddle', 'fastdeploy_server']}; diff --git a/frontend/packages/netron2/src/view.js b/frontend/packages/netron2/src/view.js index a3a74f3d..ab45507d 100644 --- a/frontend/packages/netron2/src/view.js +++ b/frontend/packages/netron2/src/view.js @@ -975,6 +975,7 @@ view.View = class { return this._timeout(200).then(() => { const graphRenderer = new grapher.Renderer(this._host, originElement, this); graphRenderer.render(g); + console.log('graphRenderer.render(g)', g); for (const cluster of document.getElementById('clusters').children) { this._clusters[cluster.getAttribute('id')] = cluster; } diff --git a/frontend/packages/netron3/.browserslistrc b/frontend/packages/netron3/.browserslistrc new file mode 100644 index 00000000..fe715eae --- /dev/null +++ b/frontend/packages/netron3/.browserslistrc @@ -0,0 +1,4 @@ +last 2 Chrome versions +last 2 Firefox versions +last 1 Safari version +last 1 iOS version diff --git a/frontend/packages/netron3/README.md b/frontend/packages/netron3/README.md new file mode 100644 index 00000000..62d9334d --- /dev/null +++ b/frontend/packages/netron3/README.md @@ -0,0 +1,9 @@ +# VisualDL FrontEnd Server + +A fork version of [Netron](https://github.com/lutzroeder/netron). + +## Build + +```bash +yarn build +``` diff --git a/frontend/packages/netron3/package.json b/frontend/packages/netron3/package.json new file mode 100644 index 00000000..681f3aa7 --- /dev/null +++ b/frontend/packages/netron3/package.json @@ -0,0 +1,68 @@ +{ + "name": "@visualdl/netron3", + "version": "2.2.1", + "description": "A platform to visualize the deep learning process and result.", + "keywords": [ + "visualdl", + "paddlepaddle", + "visualization", + "deep learning" + ], + "homepage": "https://github.com/PaddlePaddle/VisualDL", + "bugs": { + "url": "https://github.com/PaddlePaddle/VisualDL/issues" + }, + "license": "Apache-2.0", + "author": "PeterPanZH (https://github.com/PeterPanZH)", + "contributors": [ + "Niandalu (https://github.com/Niandalu)" + ], + "repository": { + "type": "git", + "url": "https://github.com/PaddlePaddle/VisualDL.git", + "directory": "frontend/packages/netron" + }, + "scripts": { + "build": "rimraf dist && webpack", + "test": "echo \"Error: no test specified\" && exit 0" + }, + "files": [ + "dist" + ], + "main": "dist/index.html", + "dependencies": { + "@antv/layout": "^0.3.7", + "@antv/x6": "^2.0.2", + "@antv/x6-plugin-clipboard": "^2.0.1", + "@antv/x6-plugin-dnd": "^2.0.2", + "@antv/x6-plugin-history": "^2.1.1", + "@antv/x6-plugin-keyboard": "^2.1.2", + "@antv/x6-plugin-selection": "^2.1.3", + "@antv/x6-plugin-snapline": "^2.1.2", + "@antv/x6-plugin-stencil": "^2.0.1", + "@antv/x6-plugin-transform": "^2.0.1", + "@antv/x6-react-shape": "^2.0.0" + }, + "devDependencies": { + "autoprefixer": "10.3.4", + "copy-webpack-plugin": "9.0.1", + "css-loader": "6.2.0", + "html-webpack-plugin": "5.3.2", + "mini-css-extract-plugin": "2.2.2", + "postcss": "8.3.6", + "postcss-loader": "6.1.1", + "rimraf": "3.0.2", + "sass": "1.39.0", + "sass-loader": "12.1.0", + "terser": "5.7.2", + "webpack": "5.52.0", + "webpack-cli": "4.8.0" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/frontend/packages/netron3/postcss.config.js b/frontend/packages/netron3/postcss.config.js new file mode 100644 index 00000000..fbb325c0 --- /dev/null +++ b/frontend/packages/netron3/postcss.config.js @@ -0,0 +1,19 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +module.exports = { + plugins: [require('autoprefixer')] +}; diff --git a/frontend/packages/netron3/src/index.html b/frontend/packages/netron3/src/index.html new file mode 100644 index 00000000..c18690ce --- /dev/null +++ b/frontend/packages/netron3/src/index.html @@ -0,0 +1,15 @@ + + + + + + + +
+ +
+ + diff --git a/frontend/packages/netron3/src/index.js b/frontend/packages/netron3/src/index.js new file mode 100644 index 00000000..a619778d --- /dev/null +++ b/frontend/packages/netron3/src/index.js @@ -0,0 +1,85 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// cSpell:words actived nextcode +const host = {}; +// host.BrowserHost = class { +// constructor() { +// window.eval = () => { +// throw new Error('window.eval() not supported.'); +// }; +// this._document = window.document; +// this._meta = {}; +// for (const element of Array.from(this._document.getElementsByTagName('meta'))) { +// if (element.content) { +// this._meta[element.name] = this._meta[element.name] || []; +// this._meta[element.name].push(element.content); +// } +// } +// this._type = this._meta.type ? this._meta.type[0] : 'Browser'; +// this._version = this._meta.version ? this._meta.version[0] : null; +// this._ready = false; +// } + +// get document() { +// return this._document; +// } + +// get version() { +// return this._version; +// } + +// get type() { +// return this._type; +// } + +// initialize(view) { +// this._view = view; +// return Promise.resolve(); +// } +// start() { +// window.addEventListener( +// 'message', +// event => { +// const originalData = event.data; +// if (originalData) { +// const type = originalData.type; +// const data = originalData.data; +// switch (type) { +// // 在此书添加一个this._view的事件传递Graph页面过来的数据 +// case 'change-files': +// return this.status(data); +// return; +// } +// } +// }, +// false +// ); + +// this._ready = true; +// this.status('ready'); +// } + +// message(type, data) { +// if (window.parent) { +// window.parent.postMessage({type: type, data: data}, '*'); +// } +// } + +// status(status) { +// // 反传回去 +// } +// }; diff --git a/frontend/packages/netron3/webpack.config.js b/frontend/packages/netron3/webpack.config.js new file mode 100644 index 00000000..d0586c37 --- /dev/null +++ b/frontend/packages/netron3/webpack.config.js @@ -0,0 +1,146 @@ +/** + * Copyright 2020 Baidu Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable no-console */ +const path = require('path'); +const fs = require('fs'); +const webpack = require('webpack'); +const Terser = require('terser'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); + +const netron = path.dirname(require.resolve('netron/src')); +const output = path.resolve(__dirname, 'dist'); + +const excludes = ['index.js', 'view.js', 'view-sidebar.js', 'view-grapher.js', 'app.js', 'base.js', 'electron.js']; +const src = fs.readdirSync(netron, {encoding: 'utf-8'}).filter(file => fs.statSync(path.join(netron, file)).isFile()); +const commons = src.filter(file => path.extname(file) === '.js' && !excludes.includes(file)); +const metadata = src.filter(file => path.extname(file) === '.json'); + +module.exports = { + mode: 'production', + context: __dirname, + stats: { + assets: false, + builtAt: true, + cached: false, + cachedAssets: false, + children: false, + chunks: false, + chunkGroups: false, + chunkModules: false, + chunkOrigins: false, + colors: true, + entrypoints: false, + errors: true, + errorDetails: true, + hash: true, + modules: false, + moduleTrace: false, + performance: false, + providedExports: false, + publicPath: true, + reasons: false, + source: false, + timings: true, + usedExports: false, + version: true, + warnings: false + }, + entry: { + index: './src/index.js' + // shim: './src/shim.js', + // style: './src/style.scss' + }, + output: { + path: output, + filename: '[name].[contenthash].js', + publicPath: './' + }, + optimization: { + splitChunks: { + cacheGroups: { + defaultVendors: { + name: 'vendors', + test: /[\\/]node_modules[\\/](?!netron)/, + chunks: 'all' + } + } + } + }, + resolve: { + fallback: { + zlib: false + } + }, + module: { + rules: [ + { + test: /\.scss/, + use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] + } + ] + }, + plugins: [ + new webpack.ProvidePlugin({ + pako: 'pako' + }), + new MiniCssExtractPlugin({ + filename: '[name].css' + }), + new HtmlWebpackPlugin({ + filename: 'index.html', + template: './src/index.html', + inject: 'body', + scriptLoading: 'blocking' + }), + new CopyWebpackPlugin({ + patterns: commons.map(file => ({ + from: path.join(netron, file), + to: file, + transform: async content => { + try { + // It is important to keep class names and function names after compressing + // Netron relies on Class.constructor.name and Function.prototype.name to show attribute's value + const result = await Terser.minify(content.toString(), { + keep_classnames: true, + keep_fnames: true + }); + return result.code; + } catch (e) { + console.error(e); + return content; + } + } + })) + }), + new CopyWebpackPlugin({ + patterns: metadata.map(file => ({ + from: path.join(netron, file), + to: file, + transform: content => { + try { + return JSON.stringify(JSON.parse(content.toString())); + } catch (e) { + console.error(e); + return content; + } + } + })) + }) + ] +}; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 0d31834e..94ffb4fe 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -36,6 +36,143 @@ lodash "^4.17.21" resize-observer-polyfill "^1.5.1" +"@antv/g-webgpu-core@^0.5.5", "@antv/g-webgpu-core@^0.5.6": + version "0.5.6" + resolved "https://registry.npmmirror.com/@antv/g-webgpu-core/-/g-webgpu-core-0.5.6.tgz#68cde0b5d0b44b5794371c2523682f4734da3c6c" + integrity sha512-DPiH3GkAUiT0Q+LAKeImpI+IOQ/gP2w6HstYKivpFIpBPIvZ/9equM3icVrn1iDfDkZANVXQ1PppcO3xBv1ZTw== + dependencies: + eventemitter3 "^4.0.0" + gl-matrix "^3.1.0" + inversify "^5.0.1" + inversify-inject-decorators "^3.1.0" + probe.gl "^3.1.1" + reflect-metadata "^0.1.13" + +"@antv/g-webgpu-engine@^0.5.5": + version "0.5.6" + resolved "https://registry.npmmirror.com/@antv/g-webgpu-engine/-/g-webgpu-engine-0.5.6.tgz#be7c1bf8e4b1822d72a302d628034345e0577bbd" + integrity sha512-D311qYUefdEFwLayutIHqucrAY3cAGH3BdnXS37nq+0nsglrHcNP0Ab1YTinn9RihLoY3yXFTLzrYkJHJbZXDg== + dependencies: + "@antv/g-webgpu-core" "^0.5.6" + "@webgpu/glslang" "^0.0.15" + "@webgpu/types" "^0.0.31" + gl-matrix "^3.1.0" + hammerjs "^2.0.8" + inversify "^5.0.1" + inversify-inject-decorators "^3.1.0" + probe.gl "^3.1.1" + reflect-metadata "^0.1.13" + regl "^1.3.11" + +"@antv/g-webgpu@0.5.5": + version "0.5.5" + resolved "https://registry.npmmirror.com/@antv/g-webgpu/-/g-webgpu-0.5.5.tgz#003d411453ed03e7dd916bd6c6db26a2b53d1991" + integrity sha512-TxtBniINFq1jFGEPo46xjJfrbJbUqkFd5wmsRs3tcg/7J7xoldOP1kEadpI3AJG9knMYdE92VpILw1VPd6DgzQ== + dependencies: + "@antv/g-webgpu-core" "^0.5.5" + "@antv/g-webgpu-engine" "^0.5.5" + "@webgpu/types" "^0.0.31" + gl-matrix "^3.1.0" + gl-vec2 "^1.3.0" + hammerjs "^2.0.8" + inversify "^5.0.1" + inversify-inject-decorators "^3.1.0" + polyline-miter-util "^1.0.1" + polyline-normals "^2.0.2" + probe.gl "^3.1.1" + reflect-metadata "^0.1.13" + +"@antv/graphlib@^1.0.0": + version "1.2.0" + resolved "https://registry.npmmirror.com/@antv/graphlib/-/graphlib-1.2.0.tgz#c88f97d4b3456d261480a1207ffc4fbc5d7dcf0d" + integrity sha512-hhJOMThec51nU4Fe5p/viLlNIL71uDEgYFzKPajWjr2715SFG1HAgiP6AVylIeqBcAZ04u3Lw7usjl/TuI5RuQ== + +"@antv/layout@^0.3.7": + version "0.3.7" + resolved "https://registry.npmmirror.com/@antv/layout/-/layout-0.3.7.tgz#dcf13188ffb33ee1ce0112a6f21b8d9e5af59055" + integrity sha512-bw1EVRLsQOXhQusNjNr/bEbu6k3OCi8jrJiGq4GUR0j+0vmSS6O6q8dAQEpCJ41djM4lixcAuKQnQAvOw/fQzw== + dependencies: + "@antv/g-webgpu" "0.5.5" + "@antv/graphlib" "^1.0.0" + d3-force "^2.1.1" + d3-quadtree "^2.0.0" + dagre-compound "^0.0.11" + ml-matrix "^6.5.0" + +"@antv/x6-common@^2.0.x": + version "2.0.0" + resolved "https://registry.npmmirror.com/@antv/x6-common/-/x6-common-2.0.0.tgz#89c62c5f23ad8132dfca6fa530ca2d0d1825ef39" + integrity sha512-NocjUMuW6ssfn7etUQMnPi4iqsP4bzUjFZmmFNC3PxzGlavg1QZi3cluM5hrXPzsio8dWxTgJTC0QOpfZVzRkA== + dependencies: + lodash-es "^4.17.15" + utility-types "^3.10.0" + +"@antv/x6-geometry@^2.0.x": + version "2.0.0" + resolved "https://registry.npmmirror.com/@antv/x6-geometry/-/x6-geometry-2.0.0.tgz#219937f50bd0020927a559ab788c29a4d7a3b6e6" + integrity sha512-ULMOTYaCe98nEgIYlZXF7WtCxV/Ly73igm6wah6WbLhAZP/57ZY+JpntTMBNtB1uwvzH0UlsQvUFI+fwqluhDA== + +"@antv/x6-plugin-clipboard@^2.0.1": + version "2.0.1" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-clipboard/-/x6-plugin-clipboard-2.0.1.tgz#399a7ace64233fb6c82826d582023c1edaa0d110" + integrity sha512-ZH9stqSD2p22ZLlrkW6wjzaJo0yW+9jpPrv8jzrq1izk0tWga7KEOEaH1+Qtq0R7sbIPWSPXE/vSw9IBkSXbqg== + +"@antv/x6-plugin-dnd@^2.0.2": + version "2.0.2" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-dnd/-/x6-plugin-dnd-2.0.2.tgz#2b3f947a75df4f6e761d60e238ad99310c46f083" + integrity sha512-uteqxyuKw6bSQcq+Thk8rSjvacoTZuUWCADTNmcVKv+bUY7Y+XVOpr6Uf04hspL7ETDIhYTuJ+JtSEzcX1q+qQ== + +"@antv/x6-plugin-export@^2.1.5": + version "2.1.5" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-export/-/x6-plugin-export-2.1.5.tgz#2b76e12fa0bd57f7db6d1520157c1102909c42a9" + integrity sha512-VvwpaVnAEnqoOf6ePotDg3CJPO89pmRp/Nm9Q5qkADaJIsiLZPv3DMdh9ndA+f61WISxl8CYAi4c2pCvGAk0qg== + +"@antv/x6-plugin-history@^2.1.1": + version "2.1.1" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-history/-/x6-plugin-history-2.1.1.tgz#b00b939f2b2478345b5319955e528f6299fb0811" + integrity sha512-A2tmw7C8ZW9/zrg4xhoruCQ7otHutR7E/RaLPNin6GcRe3dMRiG89547d035E/H5jf9HiDz0wMTaziJtUU9MtQ== + +"@antv/x6-plugin-keyboard@^2.1.2": + version "2.1.2" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-keyboard/-/x6-plugin-keyboard-2.1.2.tgz#96829a9e4896cf0aba76a0f5423244a674001fd6" + integrity sha512-fbeHeu6ejrMgmBpBC9Vt46AaNYeXq6jHk90yxnELMLOEDbCmCPhz8x7md/5qIAY+uqJWd94ljbmg1lruXIKJUA== + dependencies: + mousetrap "^1.6.5" + +"@antv/x6-plugin-selection@^2.1.3": + version "2.1.3" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-selection/-/x6-plugin-selection-2.1.3.tgz#e25fd598321a356b008cca475faaee033d068107" + integrity sha512-SG+M5ONX0Lt44g0dMHPFmTni42D22MWPj0fBnrYiEzdd8ohQjfuvSmXudGl0HgRRXX+hsb0LknlDrnjjEl/6qQ== + +"@antv/x6-plugin-snapline@^2.1.2": + version "2.1.2" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-snapline/-/x6-plugin-snapline-2.1.2.tgz#9afa1878e1d47e2e3e0f13b8ed319e896e639da7" + integrity sha512-BbzJE/AhM5kfyw9bneXtBMgdh1wY5n2ZDham8DZvK8xrPnNTRY/C0GZDIADfd8+up2+07bf7oXgejYZ90EBw5g== + +"@antv/x6-plugin-stencil@^2.0.1": + version "2.0.1" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-stencil/-/x6-plugin-stencil-2.0.1.tgz#8527503b2c8b4c4d5c04209863819a939c650713" + integrity sha512-01B/KZw/czpr1WGE3pteLAsQn4HV3SEv9xOOpvaB9dy0sA6463sP3m9SM/hKYGb4Todw2WASjyPXGseKf1HIxA== + +"@antv/x6-plugin-transform@^2.0.1": + version "2.0.1" + resolved "https://registry.npmmirror.com/@antv/x6-plugin-transform/-/x6-plugin-transform-2.0.1.tgz#0fde699793fb112c7ecf71ae9ed24bca9dcb739c" + integrity sha512-iQifIIxJFXBRL2r8sbHcApXIGimYpWIk43TJe/jeoS9JO3BwSrSgFPdtVbp2kWVAuiSw+Y1CuE0+XHb/rIZgCA== + +"@antv/x6-react-shape@^2.0.0": + version "2.0.0" + resolved "https://registry.npmmirror.com/@antv/x6-react-shape/-/x6-react-shape-2.0.0.tgz#dc26de8a024c834ce89798e7d323d7e6528363b0" + integrity sha512-JZEHVfJb2ihbC4GCHQQS4EX93/xXJ1uglLFafg210m9mV84Wcg48thefQM8lEEAgFogcUz8tx7jzJrNdPDff8A== + +"@antv/x6@^2.0.2": + version "2.0.2" + resolved "https://registry.npmmirror.com/@antv/x6/-/x6-2.0.2.tgz#92cf0dda334433460c15793f90b5018773eeb231" + integrity sha512-mE4aiMQdbjiXLIb84Wp7mqVn5UlBuH1Blgzbet9HPozCrXXp308rpHFJVF8T9pGSkIiWT0PJ+Aj0yfMslVUHKg== + dependencies: + "@antv/x6-common" "^2.0.x" + "@antv/x6-geometry" "^2.0.x" + utility-types "^3.10.0" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -1832,10 +1969,32 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== +"@probe.gl/env@3.5.2": + version "3.5.2" + resolved "https://registry.npmmirror.com/@probe.gl/env/-/env-3.5.2.tgz#f5639d5686235afb165f353675efea26766f8555" + integrity sha512-JlNvJ2p6+ObWX7es6n3TycGPTv5CfVrCS8vblI1eHhrFCcZ6RxIo727ffRVwldpp0YTzdgjx3/4fB/1dnVYElw== + dependencies: + "@babel/runtime" "^7.0.0" + +"@probe.gl/log@3.5.2": + version "3.5.2" + resolved "https://registry.npmmirror.com/@probe.gl/log/-/log-3.5.2.tgz#e33103f6151c30431c4bfe63f1341bc0d9febe94" + integrity sha512-5yo8Dg8LrSltuPBdGlLh/WOvt4LdU7DDHu75GMeiS0fKM+J4IACRpGV8SOrktCj1MWZ6JVHcNQkJnoyZ6G7p/w== + dependencies: + "@babel/runtime" "^7.0.0" + "@probe.gl/env" "3.5.2" + +"@probe.gl/stats@3.5.2": + version "3.5.2" + resolved "https://registry.npmmirror.com/@probe.gl/stats/-/stats-3.5.2.tgz#8ee41f73199182fddb8e40221da967414eaea619" + integrity sha512-YKaYXiHF//fgy1OkX38JD70Lc8qxg2Viw8Q2CTNMwGPDJe12wda7kEmMKPJNw2oYLyFUfTzv00KJMA5h18z02w== + dependencies: + "@babel/runtime" "^7.0.0" + "@rc-component/portal@^1.0.0-6", "@rc-component/portal@^1.0.0-8", "@rc-component/portal@^1.0.2": - version "1.0.3" - resolved "https://registry.npmmirror.com/@rc-component/portal/-/portal-1.0.3.tgz#3aa2c229a7a20ac2412d864e8977e6377973416e" - integrity sha512-rG9j7OMiI9eLFLF6G0B4OcfLac9W8Z7Vjeizbjt/A6R+zzw7vhHbJ4GIkrDpUqXDvFdEEzdxfICpb8/noLwG+w== + version "1.1.0" + resolved "https://registry.npmmirror.com/@rc-component/portal/-/portal-1.1.0.tgz#6b94450d2c2b00d50b141bd7a0be23bd96503dbe" + integrity sha512-tbXM9SB1r5FOuZjRCljERFByFiEUcMmCWMXLog/NmgCzlAzreXyf23Vei3ZpSMxSMavzPnhCovfZjZdmxS3d1w== dependencies: "@babel/runtime" "^7.18.0" classnames "^2.3.2" @@ -3320,6 +3479,16 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@webgpu/glslang@^0.0.15": + version "0.0.15" + resolved "https://registry.npmmirror.com/@webgpu/glslang/-/glslang-0.0.15.tgz#f5ccaf6015241e6175f4b90906b053f88483d1f2" + integrity sha512-niT+Prh3Aff8Uf1MVBVUsaNjFj9rJAKDXuoHIKiQbB+6IUP/3J3JIhBNyZ7lDhytvXxw6ppgnwKZdDJ08UMj4Q== + +"@webgpu/types@^0.0.31": + version "0.0.31" + resolved "https://registry.npmmirror.com/@webgpu/types/-/types-0.0.31.tgz#c05ec6e60024bf1836f31236ecd7677a969a2a2c" + integrity sha512-cvvCMSZBT4VsRNtt0lI6XQqvOIIWw6+NRUtnPUMDVDgsI4pCZColz3qzF5QcP9wIYOHEc3jssIBse8UWONKhlQ== + "@webpack-cli/configtest@^1.0.4": version "1.0.4" resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.0.4.tgz#f03ce6311c0883a83d04569e2c03c6238316d2aa" @@ -3522,10 +3691,10 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -antd@4.24.3: - version "4.24.3" - resolved "https://registry.npmmirror.com/antd/-/antd-4.24.3.tgz#f712b3490622d9c642dd450a6dc14f4de614bd7f" - integrity sha512-3Jv9ktv3Zy1shiVdwnvCgbwRExyGj9Ha8P+GA2rQXBP/t3G7EvpSijSx7cdIy6eLYjEKjuNTqNv0c2kxQX5obQ== +antd@^4.21.0: + version "4.24.5" + resolved "https://registry.npmmirror.com/antd/-/antd-4.24.5.tgz#e2489fe7929b53044f239f0893f22baf52e43c48" + integrity sha512-1dgDd6OqVP0OGNenNm6bPppYsCO1wkT4SFLcpS/QiiiVZQoDCErQYvEH0ULmPWAEler1Brzal260wwpm0uPeeg== dependencies: "@ant-design/colors" "^6.0.0" "@ant-design/icons" "^4.7.0" @@ -3546,8 +3715,8 @@ antd@4.24.3: rc-image "~5.12.0" rc-input "~0.1.4" rc-input-number "~7.3.9" - rc-mentions "~1.11.0" - rc-menu "~9.7.2" + rc-mentions "~1.13.1" + rc-menu "~9.8.0" rc-motion "^2.6.1" rc-notification "~4.6.0" rc-pagination "~3.2.0" @@ -3561,7 +3730,7 @@ antd@4.24.3: rc-steps "~5.0.0-alpha.2" rc-switch "~3.2.0" rc-table "~7.26.0" - rc-tabs "~12.3.0" + rc-tabs "~12.4.1" rc-textarea "~0.4.5" rc-tooltip "~5.2.0" rc-tree "~5.7.0" @@ -4476,6 +4645,11 @@ classnames@2.x, classnames@^2.2.1, classnames@^2.2.5, classnames@^2.2.6, classna resolved "https://registry.npmmirror.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +claygl@^1.2.1: + version "1.3.0" + resolved "https://registry.npmmirror.com/claygl/-/claygl-1.3.0.tgz#7a6e2903210519ac358848f5d78070ed211685f3" + integrity sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ== + clean-css@^4.2.1, clean-css@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" @@ -5262,6 +5436,11 @@ d3-dispatch@1: resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58" integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA== +"d3-dispatch@1 - 2": + version "2.0.0" + resolved "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-2.0.0.tgz#8a18e16f76dd3fcaef42163c97b926aa9b55e7cf" + integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA== + "d3-dispatch@1 - 3", d3-dispatch@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" @@ -5344,6 +5523,15 @@ d3-force@3: d3-quadtree "1 - 3" d3-timer "1 - 3" +d3-force@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/d3-force/-/d3-force-2.1.1.tgz#f20ccbf1e6c9e80add1926f09b51f686a8bc0937" + integrity sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew== + dependencies: + d3-dispatch "1 - 2" + d3-quadtree "1 - 2" + d3-timer "1 - 2" + d3-format@1: version "1.4.5" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4" @@ -5417,6 +5605,11 @@ d3-quadtree@1: resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.7.tgz#ca8b84df7bb53763fe3c2f24bd435137f4e53135" integrity sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA== +"d3-quadtree@1 - 2", d3-quadtree@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/d3-quadtree/-/d3-quadtree-2.0.0.tgz#edbad045cef88701f6fee3aee8e93fb332d30f9d" + integrity sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw== + "d3-quadtree@1 - 3", d3-quadtree@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" @@ -5526,6 +5719,11 @@ d3-timer@1: resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5" integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw== +"d3-timer@1 - 2": + version "2.0.0" + resolved "https://registry.npmmirror.com/d3-timer/-/d3-timer-2.0.0.tgz#055edb1d170cfe31ab2da8968deee940b56623e6" + integrity sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA== + "d3-timer@1 - 3", d3-timer@3: version "3.0.1" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" @@ -5654,9 +5852,14 @@ d3@7.0.1: d3-transition "3" d3-zoom "3" +dagre-compound@^0.0.11: + version "0.0.11" + resolved "https://registry.npmmirror.com/dagre-compound/-/dagre-compound-0.0.11.tgz#8d3d1004d756f420582d29f28c92045375018987" + integrity sha512-UrSgRP9LtOZCYb9e5doolZXpc7xayyszgyOs7uakTK4n4KsLegLVTRRtq01GpQd/iZjYw5fWMapx9ed+c80MAQ== + dagre@0.8.5: version "0.8.5" - resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" + resolved "https://registry.npmmirror.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== dependencies: graphlib "^2.1.8" @@ -6139,13 +6342,21 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -echarts@5.3.0: - version "5.3.0" - resolved "https://registry.npmmirror.com/echarts/-/echarts-5.3.0.tgz#39342fcf0f763413fecd9d2afd1c415163de694d" - integrity sha512-zENufmwFE6WjM+24tW3xQq4ICqQtI0CGj4bDVDNd3BK3LtaA/5wBp+64ykIyKy3QElz0cieKqSYP4FX9Lv9MwQ== +echarts-gl@^2.0.9: + version "2.0.9" + resolved "https://registry.npmmirror.com/echarts-gl/-/echarts-gl-2.0.9.tgz#ee228a6c7520a6fb7bbb71ea94394f3637ade033" + integrity sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA== + dependencies: + claygl "^1.2.1" + zrender "^5.1.1" + +echarts@^5.3.3: + version "5.4.1" + resolved "https://registry.npmmirror.com/echarts/-/echarts-5.4.1.tgz#d7f65a584d78beff62568d878b16151b3381811c" + integrity sha512-9ltS3M2JB0w2EhcYjCdmtrJ+6haZcW6acBolMGIuf01Hql1yrIV01L1aRj7jsaaIULJslEP9Z3vKlEmnJaWJVQ== dependencies: tslib "2.3.0" - zrender "5.3.0" + zrender "5.4.1" ee-first@1.1.1: version "1.1.1" @@ -7348,6 +7559,16 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" +gl-matrix@^3.1.0: + version "3.4.3" + resolved "https://registry.npmmirror.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9" + integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA== + +gl-vec2@^1.0.0, gl-vec2@^1.3.0: + version "1.3.0" + resolved "https://registry.npmmirror.com/gl-vec2/-/gl-vec2-1.3.0.tgz#83d472ed46034de8e09cbc857123fb6c81c51199" + integrity sha512-YiqaAuNsheWmUV0Sa8k94kBB0D6RWjwZztyO+trEYS8KzJ6OQB/4686gdrf59wld4hHFIvaxynO3nRxpk1Ij/A== + glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -7488,6 +7709,11 @@ gud@^1.0.0: resolved "https://registry.npmmirror.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== +hammerjs@^2.0.8: + version "2.0.8" + resolved "https://registry.npmmirror.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" + integrity sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ== + handlebars@^4.7.6: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" @@ -8084,6 +8310,16 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +inversify-inject-decorators@^3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/inversify-inject-decorators/-/inversify-inject-decorators-3.1.0.tgz#d9941080bad77cec8a65ee29d905e4d5d73e1e95" + integrity sha512-/seBlVp5bXrLQS3DpKEmlgeZL6C7Tf/QITd+IMQrbBBGuCbxb7k3hRAWu9XSreNpFzLgSboz3sClLSEmGwHphw== + +inversify@^5.0.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/inversify/-/inversify-5.1.1.tgz#6fbd668c591337404e005a1946bfe0d802c08730" + integrity sha512-j8grHGDzv1v+8T1sAQ+3boTCntFPfvxLCkNcxB1J8qA0lUN+fAlSyYd+RXKvaPRL4AGyPxViutBEJHNXOyUdFQ== + ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -8118,6 +8354,11 @@ is-any-array@^1.0.0: resolved "https://registry.yarnpkg.com/is-any-array/-/is-any-array-1.0.0.tgz#bcb2c7e2d28aaa2fa02ee8f6b604b0b3a957bba7" integrity sha512-0o0ZsgObnylv72nO39P6M+PL7jPUEx39O6BEfZuX36IKPy/RpdudxluAIaRn/LZi5eVPDMlMBaLABzOK6bwPlw== +is-any-array@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/is-any-array/-/is-any-array-2.0.0.tgz#e71bc13741537c06afac03c07885967ef56d8742" + integrity sha512-WdPV58rT3aOWXvvyuBydnCq4S2BM1Yz8shKxlEpk/6x+GX202XRvXOycEFtNgnHVLoc46hpexPFx8Pz1/sMS0w== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -9166,6 +9407,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.15: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -9221,7 +9467,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -9732,6 +9978,13 @@ ml-array-max@^1.2.3: dependencies: is-any-array "^1.0.0" +ml-array-max@^1.2.4: + version "1.2.4" + resolved "https://registry.npmmirror.com/ml-array-max/-/ml-array-max-1.2.4.tgz#2373e2b7e51c8807e456cc0ef364c5863713623b" + integrity sha512-BlEeg80jI0tW6WaPyGxf5Sa4sqvcyY6lbSn5Vcv44lp1I2GR6AWojfUvLnGTNsIXrZ8uqWmo8VcG1WpkI2ONMQ== + dependencies: + is-any-array "^2.0.0" + ml-array-min@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/ml-array-min/-/ml-array-min-1.2.2.tgz#abd68512a57fe8499513e6f2265533807e2bbe6b" @@ -9739,6 +9992,13 @@ ml-array-min@^1.2.2: dependencies: is-any-array "^1.0.0" +ml-array-min@^1.2.3: + version "1.2.3" + resolved "https://registry.npmmirror.com/ml-array-min/-/ml-array-min-1.2.3.tgz#662f027c400105816b849cc3cd786915d0801495" + integrity sha512-VcZ5f3VZ1iihtrGvgfh/q0XlMobG6GQ8FsNyQXD3T+IlstDv85g8kfV0xUG1QPRO/t21aukaJowDzMTc7j5V6Q== + dependencies: + is-any-array "^2.0.0" + ml-array-rescale@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ml-array-rescale/-/ml-array-rescale-1.3.5.tgz#a41a98535e5b3bcdcde2f1ef532f4453feb11104" @@ -9748,6 +10008,15 @@ ml-array-rescale@^1.3.5: ml-array-max "^1.2.3" ml-array-min "^1.2.2" +ml-array-rescale@^1.3.7: + version "1.3.7" + resolved "https://registry.npmmirror.com/ml-array-rescale/-/ml-array-rescale-1.3.7.tgz#c4d129320d113a732e62dd963dc1695bba9a5340" + integrity sha512-48NGChTouvEo9KBctDfHC3udWnQKNKEWN0ziELvY3KG25GR5cA8K8wNVzracsqSW1QEkAXjTNx+ycgAv06/1mQ== + dependencies: + is-any-array "^2.0.0" + ml-array-max "^1.2.4" + ml-array-min "^1.2.3" + ml-levenberg-marquardt@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ml-levenberg-marquardt/-/ml-levenberg-marquardt-2.1.1.tgz#6a26751657adb340ed5ae4daadf5bfd2f757bdd4" @@ -9763,6 +10032,14 @@ ml-matrix@^6.4.1: dependencies: ml-array-rescale "^1.3.5" +ml-matrix@^6.5.0: + version "6.10.4" + resolved "https://registry.npmmirror.com/ml-matrix/-/ml-matrix-6.10.4.tgz#babee344b20062d9c123aa801c2e5d0d0c7477f6" + integrity sha512-rUyEhfNPzqFsltYwvjNeYQXlYEaVea3KgzcJKJteQUj2WVAGFx9fLNRjtMR9mg2B6bd5buxlmkZmxM4hmO+SKg== + dependencies: + is-any-array "^2.0.0" + ml-array-rescale "^1.3.7" + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -9795,6 +10072,11 @@ moo@^0.5.1: resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== +mousetrap@^1.6.5: + version "1.6.5" + resolved "https://registry.npmmirror.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9" + integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -10999,6 +11281,20 @@ polished@4.1.3: dependencies: "@babel/runtime" "^7.14.0" +polyline-miter-util@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/polyline-miter-util/-/polyline-miter-util-1.0.1.tgz#b693f2389ea0ded36a6bcf5ecd2ece4b6917d957" + integrity sha512-/3u91zz6mBerBZo6qnOJOTjv7EfPhKtsV028jMyj86YpzLRNmCCFfrX7IO9tCEQ2W4x45yc+vKOezjf7u2Nd6Q== + dependencies: + gl-vec2 "^1.0.0" + +polyline-normals@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/polyline-normals/-/polyline-normals-2.0.2.tgz#a1737e75d8c0dccb1a591f9cb27f09eef4b7d135" + integrity sha512-dpHrAi61ymhsB4N0XlNb3YpkKJeTFnXBXDWpeH8Ucstq0TUZrCN3YK4Jlgk8ofMWN25lhGC4wnxLMv+TUK8rig== + dependencies: + polyline-miter-util "^1.0.1" + popper.js@1.16.1-lts: version "1.16.1-lts" resolved "https://registry.npmmirror.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" @@ -11145,6 +11441,16 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" +probe.gl@^3.1.1: + version "3.5.2" + resolved "https://registry.npmmirror.com/probe.gl/-/probe.gl-3.5.2.tgz#d24f84a24678bd7ce005826d4cf2d7221b9c7db8" + integrity sha512-8lFQVmi7pMQZkqfj8+VjX4GU9HTkyxgRm5/h/xxA/4/IvZPv3qtP996L+awPwZsrPRKEw99t12SvqEHqSls/sA== + dependencies: + "@babel/runtime" "^7.0.0" + "@probe.gl/env" "3.5.2" + "@probe.gl/log" "3.5.2" + "@probe.gl/stats" "3.5.2" + proc-log@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-1.0.0.tgz#0d927307401f69ed79341e83a0b2c9a13395eb77" @@ -11508,22 +11814,22 @@ rc-input@~0.1.4: classnames "^2.2.1" rc-util "^5.18.1" -rc-mentions@~1.11.0: - version "1.11.0" - resolved "https://registry.npmmirror.com/rc-mentions/-/rc-mentions-1.11.0.tgz#ffbe046af52a0ec057393073d0b1ca4210c3325e" - integrity sha512-0C78O4wvG8UwsT7DtcwV8j7k4T+urrM0VuRT9gmSGbX187Ftl/JbCXL6WMGHSWBYI+LxInw1x4gw0Zi6qOcaig== +rc-mentions@~1.13.1: + version "1.13.1" + resolved "https://registry.npmmirror.com/rc-mentions/-/rc-mentions-1.13.1.tgz#c884b70e1505a197f1b32a7c6b39090db6992a72" + integrity sha512-FCkaWw6JQygtOz0+Vxz/M/NWqrWHB9LwqlY2RtcuFqWJNFK9njijOOzTSsBGANliGufVUzx/xuPHmZPBV0+Hgw== dependencies: "@babel/runtime" "^7.10.1" classnames "^2.2.6" - rc-menu "~9.7.2" + rc-menu "~9.8.0" rc-textarea "^0.4.0" rc-trigger "^5.0.4" rc-util "^5.22.5" -rc-menu@~9.7.2: - version "9.7.2" - resolved "https://registry.npmmirror.com/rc-menu/-/rc-menu-9.7.2.tgz#0b400e2d81377c8001795559139cb29871143be1" - integrity sha512-zyri6Qwr955SOdjzDn7/ylz7Zj8r89wGyoRw0lV9G8K6a3VBfSrP2XMYEc0JgeC62OTghUcRWad7KFqNXysxaA== +rc-menu@~9.8.0: + version "9.8.1" + resolved "https://registry.npmmirror.com/rc-menu/-/rc-menu-9.8.1.tgz#988cd807f78d2f92eab686f6813f50b165f78405" + integrity sha512-179weouypfjWJSRvvoo/vPy+StojsMzK2XC5jRNhL1ryt/N/8wAFESte8K6jZJkNp9DHDLFTe+dCGmikKpiFuA== dependencies: "@babel/runtime" "^7.10.1" classnames "2.x" @@ -11674,15 +11980,15 @@ rc-table@~7.26.0: rc-util "^5.22.5" shallowequal "^1.1.0" -rc-tabs@~12.3.0: - version "12.3.0" - resolved "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-12.3.0.tgz#a346cafa7eafbe5faeeeb8c07b8ad95197f985dc" - integrity sha512-/mOHuq4h/mNC0QmB3iEOrYeiNMvciosSo/v7SMtvoc+jfk63AzZtQzwsC50t6kkL9ViEqyjDqj4bFfxKdQtozA== +rc-tabs@~12.4.1: + version "12.4.2" + resolved "https://registry.npmmirror.com/rc-tabs/-/rc-tabs-12.4.2.tgz#487a1b3f8d8cf0bfc121224013dab00d4a8e0532" + integrity sha512-FFlGwuTjQUznWzJtyhmHc6KAp5lRQFxKUv9Aj1UtsOYe2e7WGmuzcrd+/LQchuPe0VjhaZPdGkmFGcqGqNO6ow== dependencies: "@babel/runtime" "^7.11.2" classnames "2.x" rc-dropdown "~4.0.0" - rc-menu "~9.7.2" + rc-menu "~9.8.0" rc-motion "^2.6.2" rc-resize-observer "^1.0.0" rc-util "^5.16.0" @@ -12202,6 +12508,11 @@ redux@^4.1.2: dependencies: "@babel/runtime" "^7.9.2" +reflect-metadata@^0.1.13: + version "0.1.13" + resolved "https://registry.npmmirror.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" + integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== + regenerator-runtime@^0.13.10: version "0.13.10" resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" @@ -12256,6 +12567,11 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" +regl@^1.3.11: + version "1.7.0" + resolved "https://registry.npmmirror.com/regl/-/regl-1.7.0.tgz#0d185431044a356bf80e9b775b11b935ef2746d3" + integrity sha512-bEAtp/qrtKucxXSJkD4ebopFZYP0q1+3Vb2WECWv/T8yQEgKxDxJ7ztO285tAMaYZVR6mM1GgI6CCn8FROtL1w== + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" @@ -14169,6 +14485,11 @@ utila@~0.4: resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= +utility-types@^3.10.0: + version "3.10.0" + resolved "https://registry.npmmirror.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" + integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -14657,9 +14978,9 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== -zrender@5.3.0: - version "5.3.0" - resolved "https://registry.npmmirror.com/zrender/-/zrender-5.3.0.tgz#297c05dc2521362816c4ddced10a1e306646bbc8" - integrity sha512-Ln2QB5uqI1ftNYMtCRxd+XDq6MOttLgam2tmhKAVA+j0ko47UT+VNlDvKTkqe4K2sJhBvB0EhYNLebqlCTjatQ== +zrender@5.4.1, zrender@^5.1.1: + version "5.4.1" + resolved "https://registry.npmmirror.com/zrender/-/zrender-5.4.1.tgz#892f864b885c71e1dc25dcb3c7a4ba42678d3f11" + integrity sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA== dependencies: tslib "2.3.0" -- GitLab
{t('graph:supported-model')}{t('graph:supported-model-list-xpaddle')}
{t('graph:supported-model')}{t('graph:supported-model-list-xpaddle')}