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