| @@ -6,7 +6,6 @@ | |||||
| background-color: rgba(0, 0, 0, 0.04); | background-color: rgba(0, 0, 0, 0.04); | ||||
| border: 1px solid #d9d9d9; | border: 1px solid #d9d9d9; | ||||
| border-radius: 6px; | border-radius: 6px; | ||||
| cursor: not-allowed; | |||||
| .ant-typography { | .ant-typography { | ||||
| margin: 0 !important; | margin: 0 !important; | ||||
| @@ -9,7 +9,7 @@ import './index.less'; | |||||
| interface KFSpinProps extends SpinProps { | interface KFSpinProps extends SpinProps { | ||||
| /** 加载文本 */ | /** 加载文本 */ | ||||
| label: string; | |||||
| label?: string; | |||||
| } | } | ||||
| /** 自定义 Spin */ | /** 自定义 Spin */ | ||||
| @@ -25,7 +25,6 @@ enum TabKeys { | |||||
| const NodePrefix = 'auto-ml'; | const NodePrefix = 'auto-ml'; | ||||
| function AutoMLInstance() { | function AutoMLInstance() { | ||||
| const [activeTab, setActiveTab] = useState<string>(TabKeys.Params); | |||||
| const [autoMLInfo, setAutoMLInfo] = useState<AutoMLData | undefined>(undefined); | const [autoMLInfo, setAutoMLInfo] = useState<AutoMLData | undefined>(undefined); | ||||
| const [instanceInfo, setInstanceInfo] = useState<AutoMLInstanceData | undefined>(undefined); | const [instanceInfo, setInstanceInfo] = useState<AutoMLInstanceData | undefined>(undefined); | ||||
| const params = useParams(); | const params = useParams(); | ||||
| @@ -83,10 +82,10 @@ function AutoMLInstance() { | |||||
| }; | }; | ||||
| const setupSSE = (name: string, namespace: string) => { | const setupSSE = (name: string, namespace: string) => { | ||||
| let { origin } = location; | |||||
| if (process.env.NODE_ENV === 'development') { | |||||
| origin = 'http://172.20.32.197:31213'; | |||||
| } | |||||
| const { origin } = location; | |||||
| // if (process.env.NODE_ENV === 'development') { | |||||
| // origin = 'http://172.20.32.197:31213'; | |||||
| // } | |||||
| const params = encodeURIComponent(`metadata.namespace=${namespace},metadata.name=${name}`); | const params = encodeURIComponent(`metadata.namespace=${namespace},metadata.name=${name}`); | ||||
| const evtSource = new EventSource( | const evtSource = new EventSource( | ||||
| `${origin}/api/v1/realtimeStatus?listOptions.fieldSelector=${params}`, | `${origin}/api/v1/realtimeStatus?listOptions.fieldSelector=${params}`, | ||||
| @@ -204,12 +203,7 @@ function AutoMLInstance() { | |||||
| return ( | return ( | ||||
| <div className={styles['auto-ml-instance']}> | <div className={styles['auto-ml-instance']}> | ||||
| <Tabs | |||||
| className={styles['auto-ml-instance__tabs']} | |||||
| items={tabItems} | |||||
| activeKey={activeTab} | |||||
| onChange={setActiveTab} | |||||
| /> | |||||
| <Tabs className={styles['auto-ml-instance__tabs']} items={tabItems} /> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -412,11 +412,8 @@ function ExperimentList({ type }: ExperimentListProps) { | |||||
| onLoadMore={() => loadMoreExperimentIns()} | onLoadMore={() => loadMoreExperimentIns()} | ||||
| ></ExperimentInstance> | ></ExperimentInstance> | ||||
| ), | ), | ||||
| onExpand: (e, a) => { | |||||
| handleExpandChange(e, a); | |||||
| }, | |||||
| onExpand: handleExpandChange, | |||||
| expandedRowKeys: expandedRowKeys, | expandedRowKeys: expandedRowKeys, | ||||
| rowExpandable: () => true, | |||||
| }} | }} | ||||
| rowKey="id" | rowKey="id" | ||||
| /> | /> | ||||
| @@ -549,11 +549,8 @@ function Experiment() { | |||||
| onLoadMore={() => loadMoreExperimentIns()} | onLoadMore={() => loadMoreExperimentIns()} | ||||
| ></ExperimentInstance> | ></ExperimentInstance> | ||||
| ), | ), | ||||
| onExpand: (e, a) => { | |||||
| expandChange(e, a); | |||||
| }, | |||||
| onExpand: expandChange, | |||||
| expandedRowKeys: [expandedRowKeys], | expandedRowKeys: [expandedRowKeys], | ||||
| rowExpandable: (record) => true, | |||||
| }} | }} | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| @@ -23,7 +23,6 @@ enum TabKeys { | |||||
| } | } | ||||
| function HyperParameterInstance() { | function HyperParameterInstance() { | ||||
| const [activeTab, setActiveTab] = useState<string>(TabKeys.Params); | |||||
| const [experimentInfo, setExperimentInfo] = useState<HyperParameterData | undefined>(undefined); | const [experimentInfo, setExperimentInfo] = useState<HyperParameterData | undefined>(undefined); | ||||
| const [instanceInfo, setInstanceInfo] = useState<HyperParameterInstanceData | undefined>( | const [instanceInfo, setInstanceInfo] = useState<HyperParameterInstanceData | undefined>( | ||||
| undefined, | undefined, | ||||
| @@ -101,7 +100,7 @@ function HyperParameterInstance() { | |||||
| }; | }; | ||||
| const setupSSE = (name: string, namespace: string) => { | const setupSSE = (name: string, namespace: string) => { | ||||
| let { origin } = location; | |||||
| const { origin } = location; | |||||
| // if (process.env.NODE_ENV === 'development') { | // if (process.env.NODE_ENV === 'development') { | ||||
| // origin = 'http://172.20.32.197:31213'; | // origin = 'http://172.20.32.197:31213'; | ||||
| // } | // } | ||||
| @@ -204,12 +203,7 @@ function HyperParameterInstance() { | |||||
| return ( | return ( | ||||
| <div className={styles['hyper-parameter-instance']}> | <div className={styles['hyper-parameter-instance']}> | ||||
| <Tabs | |||||
| className={styles['hyper-parameter-instance__tabs']} | |||||
| items={tabItems} | |||||
| activeKey={activeTab} | |||||
| onChange={setActiveTab} | |||||
| /> | |||||
| <Tabs className={styles['hyper-parameter-instance__tabs']} items={tabItems} /> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -202,16 +202,16 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="总实验次数" | |||||
| label="总试验次数" | |||||
| name="num_samples" | name="num_samples" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入总实验次数', | |||||
| message: '请输入总试验次数', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <InputNumber placeholder="请输入总实验次数" min={0} precision={0} /> | |||||
| <InputNumber placeholder="请输入总试验次数" min={0} precision={0} /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -297,7 +297,7 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="参数" | |||||
| label="超参数" | |||||
| style={{ marginBottom: 0, marginTop: '-14px' }} | style={{ marginBottom: 0, marginTop: '-14px' }} | ||||
| required | required | ||||
| ></Form.Item> | ></Form.Item> | ||||
| @@ -460,7 +460,7 @@ function ExecuteConfig() { | |||||
| ); | ); | ||||
| if (arr.length > 0 && arr.length < runParameters.length) { | if (arr.length > 0 && arr.length < runParameters.length) { | ||||
| return Promise.reject( | return Promise.reject( | ||||
| new Error(`手动运行参数 ${name} 必须全部填写或者都不填写`), | |||||
| new Error(`手动运行超参数 ${name} 必须全部填写或者都不填写`), | |||||
| ); | ); | ||||
| } | } | ||||
| } | } | ||||
| @@ -475,7 +475,7 @@ function ExecuteConfig() { | |||||
| <Row gutter={8}> | <Row gutter={8}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="手动运行参数" | |||||
| label="手动运行超参数" | |||||
| style={{ marginBottom: 0, marginTop: '-14px' }} | style={{ marginBottom: 0, marginTop: '-14px' }} | ||||
| ></Form.Item> | ></Form.Item> | ||||
| </Col> | </Col> | ||||
| @@ -567,9 +567,9 @@ function ExecuteConfig() { | |||||
| <Row gutter={0}> | <Row gutter={0}> | ||||
| <Col span={24}> | <Col span={24}> | ||||
| <Form.Item | <Form.Item | ||||
| label="优化方向" | |||||
| label="指标优化方向" | |||||
| name="mode" | name="mode" | ||||
| rules={[{ required: true, message: '请选择优化方向' }]} | |||||
| rules={[{ required: true, message: '请选择指标优化方向' }]} | |||||
| > | > | ||||
| <Radio.Group options={hyperParameterOptimizedModeOptions}></Radio.Group> | <Radio.Group options={hyperParameterOptimizedModeOptions}></Radio.Group> | ||||
| </Form.Item> | </Form.Item> | ||||
| @@ -18,9 +18,19 @@ type ExperimentHistoryProps = { | |||||
| }; | }; | ||||
| function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | ||||
| const [expandedRowKeys, setExpandedRowKeys] = useState<string[]>([]); | |||||
| const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); | const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); | ||||
| const { message } = App.useApp(); | const { message } = App.useApp(); | ||||
| const [tableData, setTableData] = useState<HyperParameterTrial[]>([]); | |||||
| const [loading, setLoading] = useState(true); | |||||
| // 防止 Tabs 卡顿 | |||||
| setTimeout(() => { | |||||
| setTableData(trialList); | |||||
| setLoading(false); | |||||
| }, 100); | |||||
| // 计算 column | |||||
| const first: HyperParameterTrial | undefined = trialList[0]; | const first: HyperParameterTrial | undefined = trialList[0]; | ||||
| const config: Record<string, any> = first?.config ?? {}; | const config: Record<string, any> = first?.config ?? {}; | ||||
| const metricAnalysis: Record<string, any> = first?.metric_analysis ?? {}; | const metricAnalysis: Record<string, any> = first?.metric_analysis ?? {}; | ||||
| @@ -32,7 +42,7 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| title: '序号', | title: '序号', | ||||
| dataIndex: 'index', | dataIndex: 'index', | ||||
| key: 'index', | key: 'index', | ||||
| width: 110, | |||||
| width: 100, | |||||
| render: (_text, record, index: number) => { | render: (_text, record, index: number) => { | ||||
| return ( | return ( | ||||
| <div className={styles['cell-index']}> | <div className={styles['cell-index']}> | ||||
| @@ -114,52 +124,8 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| }); | }); | ||||
| } | } | ||||
| const fileColumns: TableProps<HyperParameterFile>['columns'] = [ | |||||
| { | |||||
| title: '文件名称', | |||||
| dataIndex: 'name', | |||||
| key: 'name', | |||||
| render: tableCellRender(false), | |||||
| }, | |||||
| { | |||||
| title: '文件大小', | |||||
| dataIndex: 'size', | |||||
| key: 'size', | |||||
| width: 200, | |||||
| render: tableCellRender(false), | |||||
| }, | |||||
| { | |||||
| title: '操作', | |||||
| dataIndex: 'option', | |||||
| width: 160, | |||||
| key: 'option', | |||||
| render: (_: any, record: HyperParameterFile) => { | |||||
| return ( | |||||
| <Button | |||||
| type="link" | |||||
| size="small" | |||||
| key="download" | |||||
| icon={<KFIcon type="icon-xiazai" />} | |||||
| onClick={() => { | |||||
| if (record.isFile) { | |||||
| downLoadZip(`/api/mmp/minioStorage/downloadFile`, { path: record.url }); | |||||
| } else { | |||||
| downLoadZip(`/api/mmp/minioStorage/download`, { path: record.url }); | |||||
| } | |||||
| }} | |||||
| > | |||||
| 下载 | |||||
| </Button> | |||||
| ); | |||||
| }, | |||||
| }, | |||||
| ]; | |||||
| const expandedRowRender = (record: HyperParameterTrial) => ( | |||||
| <Table columns={fileColumns} dataSource={[record.file]} pagination={false} rowKey="name" /> | |||||
| ); | |||||
| const expandedRowRender2 = (record: HyperParameterTrial) => { | |||||
| // 自定义展开视图 | |||||
| const expandedRowRender = (record: HyperParameterTrial) => { | |||||
| const filesToTreeData = ( | const filesToTreeData = ( | ||||
| files: HyperParameterFile[], | files: HyperParameterFile[], | ||||
| parent?: HyperParameterFile, | parent?: HyperParameterFile, | ||||
| @@ -207,6 +173,15 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| ); | ); | ||||
| }; | }; | ||||
| // 展开实例 | |||||
| const handleExpandChange = (expanded: boolean, record: HyperParameterTrial) => { | |||||
| if (expanded) { | |||||
| setExpandedRowKeys([record.trial_id]); | |||||
| } else { | |||||
| setExpandedRowKeys([]); | |||||
| } | |||||
| }; | |||||
| // 选择行 | // 选择行 | ||||
| const rowSelection: TableProps<HyperParameterTrial>['rowSelection'] = { | const rowSelection: TableProps<HyperParameterTrial>['rowSelection'] = { | ||||
| type: 'checkbox', | type: 'checkbox', | ||||
| @@ -218,6 +193,7 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| }, | }, | ||||
| }; | }; | ||||
| // 对比 | |||||
| const handleComparisonClick = () => { | const handleComparisonClick = () => { | ||||
| if (selectedRowKeys.length < 1) { | if (selectedRowKeys.length < 1) { | ||||
| message.error('请至少选择一项'); | message.error('请至少选择一项'); | ||||
| @@ -248,14 +224,19 @@ function ExperimentHistory({ trialList = [] }: ExperimentHistoryProps) { | |||||
| )} | )} | ||||
| > | > | ||||
| <Table | <Table | ||||
| loading={loading} | |||||
| rowClassName={(record) => (record.is_best ? styles['table-best-row'] : '')} | rowClassName={(record) => (record.is_best ? styles['table-best-row'] : '')} | ||||
| dataSource={trialList} | |||||
| dataSource={tableData} | |||||
| columns={trialColumns} | columns={trialColumns} | ||||
| pagination={false} | pagination={false} | ||||
| bordered={true} | bordered={true} | ||||
| scroll={{ y: 'calc(100% - 110px)', x: '100%' }} | scroll={{ y: 'calc(100% - 110px)', x: '100%' }} | ||||
| rowKey="trial_id" | rowKey="trial_id" | ||||
| expandable={{ expandedRowRender: expandedRowRender2 }} | |||||
| expandable={{ | |||||
| expandedRowRender: expandedRowRender, | |||||
| onExpand: handleExpandChange, | |||||
| expandedRowKeys: expandedRowKeys, | |||||
| }} | |||||
| rowSelection={rowSelection} | rowSelection={rowSelection} | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| @@ -113,7 +113,7 @@ function HyperParameterBasic({ | |||||
| format: formatModel, | format: formatModel, | ||||
| }, | }, | ||||
| { | { | ||||
| label: '总实验次数', | |||||
| label: '总试验次数', | |||||
| value: info.num_samples, | value: info.num_samples, | ||||
| }, | }, | ||||
| { | { | ||||
| @@ -135,7 +135,7 @@ function HyperParameterBasic({ | |||||
| value: info.min_samples_required, | value: info.min_samples_required, | ||||
| }, | }, | ||||
| { | { | ||||
| label: '优化方向', | |||||
| label: '指标优化方向', | |||||
| value: info.mode, | value: info.mode, | ||||
| format: formatOptimizeMode, | format: formatOptimizeMode, | ||||
| }, | }, | ||||
| @@ -88,9 +88,9 @@ function ParameterInfo({ info }: ParameterInfoProps) { | |||||
| return ( | return ( | ||||
| <div className={styles['parameter-info']}> | <div className={styles['parameter-info']}> | ||||
| <div className={styles['parameter-info__title']}>参数</div> | |||||
| <div className={styles['parameter-info__title']}>超参数</div> | |||||
| <Table dataSource={parameters} columns={columns} rowKey="name" bordered pagination={false} /> | <Table dataSource={parameters} columns={columns} rowKey="name" bordered pagination={false} /> | ||||
| <div className={styles['parameter-info__title']}>手动运行参数</div> | |||||
| <div className={styles['parameter-info__title']}>手动运行超参数</div> | |||||
| <Table | <Table | ||||
| dataSource={runParameters} | dataSource={runParameters} | ||||
| columns={runColumns} | columns={runColumns} | ||||
| @@ -21,7 +21,7 @@ export type FormData = { | |||||
| mode: string; // 优化方向 | mode: string; // 优化方向 | ||||
| search_alg?: string; // 搜索算法 | search_alg?: string; // 搜索算法 | ||||
| scheduler?: string; // 调度算法 | scheduler?: string; // 调度算法 | ||||
| num_samples: number; // 总实验次数 | |||||
| num_samples: number; // 总试验次数 | |||||
| max_t: number; // 单次试验最大时间 | max_t: number; // 单次试验最大时间 | ||||
| min_samples_required: number; // 计算中位数的最小试验数 | min_samples_required: number; // 计算中位数的最小试验数 | ||||
| resource: string; // 资源规格 | resource: string; // 资源规格 | ||||
| @@ -64,7 +64,7 @@ export type HyperParameterInstanceData = { | |||||
| }; | }; | ||||
| export type HyperParameterTrial = { | export type HyperParameterTrial = { | ||||
| trial_id?: string; | |||||
| trial_id: string; | |||||
| training_iteration?: number; | training_iteration?: number; | ||||
| time?: number; | time?: number; | ||||
| status?: string; | status?: string; | ||||
| @@ -9,11 +9,11 @@ import SubAreaTitle from '@/components/SubAreaTitle'; | |||||
| import { getServiceVersionInfoReq } from '@/services/modelDeployment'; | import { getServiceVersionInfoReq } from '@/services/modelDeployment'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useParams } from '@umijs/max'; | import { useParams } from '@umijs/max'; | ||||
| import { Tabs, type TabsProps } from 'antd'; | |||||
| import { Tabs } from 'antd'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import VersionBasicInfo from '../components/VersionBasicInfo'; | |||||
| import ServerLog from '../components/ServerLog'; | import ServerLog from '../components/ServerLog'; | ||||
| import UserGuide from '../components/UserGuide'; | import UserGuide from '../components/UserGuide'; | ||||
| import VersionBasicInfo from '../components/VersionBasicInfo'; | |||||
| import { ServiceVersionData } from '../types'; | import { ServiceVersionData } from '../types'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -24,7 +24,6 @@ export enum ModelDeploymentTabKey { | |||||
| } | } | ||||
| function ServiceVersionInfo() { | function ServiceVersionInfo() { | ||||
| const [activeTab, setActiveTab] = useState<string>(ModelDeploymentTabKey.Predict); | |||||
| const [versionInfo, setVersionInfo] = useState<ServiceVersionData | undefined>(undefined); | const [versionInfo, setVersionInfo] = useState<ServiceVersionData | undefined>(undefined); | ||||
| const params = useParams(); | const params = useParams(); | ||||
| const id = params.id; | const id = params.id; | ||||
| @@ -61,11 +60,6 @@ function ServiceVersionInfo() { | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| // 切换 Tab,重置数据 | |||||
| const hanleTabChange: TabsProps['onChange'] = (value) => { | |||||
| setActiveTab(value); | |||||
| }; | |||||
| return ( | return ( | ||||
| <div className={styles['service-version-info']}> | <div className={styles['service-version-info']}> | ||||
| <PageTitle title="服务版本详情"></PageTitle> | <PageTitle title="服务版本详情"></PageTitle> | ||||
| @@ -77,7 +71,7 @@ function ServiceVersionInfo() { | |||||
| ></SubAreaTitle> | ></SubAreaTitle> | ||||
| <VersionBasicInfo info={versionInfo} /> | <VersionBasicInfo info={versionInfo} /> | ||||
| <div className={styles['service-version-info__content__tabs']}> | <div className={styles['service-version-info__content__tabs']}> | ||||
| <Tabs activeKey={activeTab} items={tabItems} onChange={hanleTabChange} /> | |||||
| <Tabs items={tabItems} /> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||