"git@developer.sourcefind.cn:zhaoyu6/sglang.git" did not exist on "ce86e201df7f2c60677c975f107e080687c07996"
Commit 593a275c authored by Yuge Zhang's avatar Yuge Zhang
Browse files

Merge branch 'master' of https://github.com/microsoft/nni into dev-retiarii

parents b3cdee85 683c458a
import { AllExperimentList, SortInfo } from '../../static/interface';
import { copyAndSort } from '../../static/function';
function compareDate(date1: Date, date2: Date): boolean {
if (date1 !== undefined && date2 !== undefined) {
if (date1.getFullYear() === date2.getFullYear()) {
if (date1.getMonth() === date2.getMonth()) {
if (date1.getDate() === date2.getDate()) {
return true;
}
}
}
}
return false;
}
const filterByStatusOrPlatform = (val: string, type: string, data: AllExperimentList[]): AllExperimentList[] => {
return data.filter(temp => temp[type] === val);
};
function fillOptions(arr: string[]): any {
const list: Array<object> = [];
arr.map(item => {
list.push({ key: item, text: item });
});
return list;
}
function getSortedSource(source: AllExperimentList[], sortInfo: SortInfo): AllExperimentList[] {
const keepSortedSource = copyAndSort(source, sortInfo.field, sortInfo.isDescend);
return keepSortedSource;
}
export { compareDate, filterByStatusOrPlatform, fillOptions, getSortedSource };
const MAXSCREENCOLUMNWIDHT = 180;
const MINSCREENCOLUMNWIDHT = 139;
export { MAXSCREENCOLUMNWIDHT, MINSCREENCOLUMNWIDHT };
......@@ -58,16 +58,16 @@ class Compare extends React.Component<CompareProps, {}> {
super(props);
}
private _generateTooltipSummary(row: Item, metricKey: string): string {
return renderToString(
private _generateTooltipSummary = (row: Item, value: string): string =>
renderToString(
<div className='tooldetailAccuracy'>
<div>Trial No.: {row.sequenceId}</div>
<div>Trial ID: {row.id}</div>
<div>Default metric: {row.metrics.get(metricKey) || 'N/A'}</div>
<div>Intermediate metric: {value}</div>
</div>
);
}
private _intermediates(items: Item[], metricKey: string): React.ReactNode {
private _intermediates(items: Item[]): React.ReactNode {
// Precondition: make sure `items` is not empty
const xAxisMax = Math.max(...items.map(item => item.intermediates.length));
const xAxis = Array(xAxisMax)
......@@ -84,7 +84,7 @@ class Compare extends React.Component<CompareProps, {}> {
trigger: 'item',
enterable: true,
position: (point: number[], data: TooltipForIntermediate): [number, number] => {
if (data.dataIndex < length / 2) {
if (data.dataIndex < xAxisMax / 2) {
return [point[0], 80];
} else {
return [point[0] - 300, 80];
......@@ -92,7 +92,7 @@ class Compare extends React.Component<CompareProps, {}> {
},
formatter: (data: TooltipForIntermediate): string => {
const item = items.find(k => k.id === data.seriesName) as Item;
return this._generateTooltipSummary(item, metricKey);
return this._generateTooltipSummary(item, data.data);
}
},
grid: {
......@@ -187,9 +187,13 @@ class Compare extends React.Component<CompareProps, {}> {
{parameterKeys.map(k =>
this._renderRow(`space_${k}`, k, 'value', items, item => item.parameters.get(k))
)}
{metricKeys.map(k =>
this._renderRow(`metrics_${k}`, `Metric: ${k}`, 'value', items, item => item.metrics.get(k))
)}
{metricKeys !== undefined
? metricKeys.map(k =>
this._renderRow(`metrics_${k}`, `Metric: ${k}`, 'value', items, item =>
item.metrics.get(k)
)
)
: null}
</tbody>
</table>
);
......@@ -209,8 +213,6 @@ class Compare extends React.Component<CompareProps, {}> {
metrics: flatten(trial.metrics(TRIALS.inferredMetricSpace())),
intermediates: _parseIntermediates(trial)
}));
const metricKeys = this._overlapKeys(items.map(item => item.metrics));
const defaultMetricKey = !metricKeys || metricKeys.includes('default') ? 'default' : metricKeys[0];
return (
<Modal
......@@ -232,7 +234,7 @@ class Compare extends React.Component<CompareProps, {}> {
/>
</div>
<Stack className='compare-modal-intermediate'>
{this._intermediates(items, defaultMetricKey)}
{this._intermediates(items)}
<Stack className='compare-yAxis'># Intermediate result</Stack>
</Stack>
{showDetails && <Stack>{this._columns(items)}</Stack>}
......
......@@ -37,9 +37,9 @@ export const Command1 = (): any => {
<div className='basic' style={rightEidtParam}>
<div>
<p className='command'>Training platform</p>
<div className='nowrap'>{EXPERIMENT.profile.params.trainingServicePlatform}</div>
<div className='ellipsis'>{EXPERIMENT.profile.params.trainingServicePlatform}</div>
<p className='lineMargin'>{title.join('/')}</p>
<div className='nowrap'>{builtinName.join('/')}</div>
<div className='ellipsis'>{builtinName.join('/')}</div>
</div>
</div>
);
......
......@@ -24,10 +24,10 @@ export const Command2 = (): any => {
return (
<div className='basic' style={leftProgress}>
<p className='command'>Log directory</p>
<div className='nowrap'>
<div className='ellipsis'>
<TooltipHost
content={EXPERIMENT.profile.logDir || 'unknown'}
className='nowrap'
className='ellipsis'
directionalHint={DirectionalHint.bottomCenter}
tooltipProps={{
calloutProps: {
......@@ -43,10 +43,10 @@ export const Command2 = (): any => {
</TooltipHost>
</div>
<p className='lineMargin'>Trial command</p>
<div className='nowrap'>
<div className='ellipsis'>
<TooltipHost
content={trialCommand || 'unknown'}
className='nowrap'
className='ellipsis'
directionalHint={DirectionalHint.bottomCenter}
tooltipProps={{
calloutProps: {
......
......@@ -6,10 +6,10 @@ import { formatTimestamp } from '../../../static/function';
import { useId } from '@uifabric/react-hooks';
import { BestMetricContext } from '../../Overview';
import { styles } from './basicInfoStyles';
import '../../../static/style/progress/progress.scss';
import '../../../static/style/progress/probar.scss';
import '../../../static/style/overview/probar.scss';
import '../../../static/style/overview/basic.scss';
export const ReBasicInfo = (): any => {
export const BasicInfo = (): any => {
const labelId: string = useId('callout-label');
const descriptionId: string = useId('callout-description');
const ref = React.createRef<HTMLDivElement>();
......@@ -26,9 +26,9 @@ export const ReBasicInfo = (): any => {
<Stack horizontal horizontalAlign='space-between' className='marginTop'>
<div className='basic'>
<p>Name</p>
<div className='nowrap'>{EXPERIMENT.profile.params.experimentName}</div>
<div className='ellipsis'>{EXPERIMENT.profile.params.experimentName}</div>
<p className='marginTop'>ID</p>
<div className='nowrap'>{EXPERIMENT.profile.id}</div>
<div className='ellipsis'>{EXPERIMENT.profile.id}</div>
</div>
<div className='basic'>
<p>Status</p>
......@@ -86,9 +86,9 @@ export const ReBasicInfo = (): any => {
</div>
<div className='basic'>
<p>Start time</p>
<div className='nowrap'>{formatTimestamp(EXPERIMENT.profile.startTime)}</div>
<div className='ellipsis'>{formatTimestamp(EXPERIMENT.profile.startTime)}</div>
<p className='marginTop'>End time</p>
<div className='nowrap'>{formatTimestamp(EXPERIMENT.profile.endTime)}</div>
<div className='ellipsis'>{formatTimestamp(EXPERIMENT.profile.endTime)}</div>
</div>
</Stack>
{/* learn about click -> default active key is dispatcher. */}
......
......@@ -106,7 +106,7 @@ class SuccessTable extends React.Component<SuccessTableProps, SuccessTableState>
</React.Fragment>
);
private columns = [
private columns: IColumn[] = [
{
key: '_expand',
name: '',
......
......@@ -73,18 +73,24 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
data.data[0] < maxSequenceId ? point[0] : point[0] - 300,
80
],
formatter: (data: TooltipForAccuracy): React.ReactNode =>
'<div class="tooldetailAccuracy">' +
'<div>Trial No.: ' +
data.data[0] +
'</div>' +
'<div>Default metric: ' +
data.data[1] +
'</div>' +
'<div>Parameters: <pre>' +
JSON.stringify(data.data[2], null, 4) +
'</pre></div>' +
'</div>'
formatter: (data: TooltipForAccuracy): React.ReactNode => {
return (
'<div class="tooldetailAccuracy">' +
'<div>Trial No.: ' +
data.data[0] +
'</div>' +
'<div>Trial ID: ' +
data.data[2] +
'</div>' +
'<div>Default metric: ' +
data.data[1] +
'</div>' +
'<div>Parameters: <pre>' +
JSON.stringify(data.data[3], null, 4) +
'</pre></div>' +
'</div>'
);
}
},
dataZoom: [
{
......@@ -110,7 +116,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
}
generateScatterSeries(trials: Trial[]): any {
const data = trials.map(trial => [trial.sequenceId, trial.accuracy, trial.description.parameters]);
const data = trials.map(trial => [trial.sequenceId, trial.accuracy, trial.id, trial.description.parameters]);
return {
symbolSize: 6,
type: 'scatter',
......@@ -120,7 +126,7 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
generateBestCurveSeries(trials: Trial[]): any {
let best = trials[0];
const data = [[best.sequenceId, best.accuracy, best.description.parameters]];
const data = [[best.sequenceId, best.accuracy, best.id, best.description.parameters]];
for (let i = 1; i < trials.length; i++) {
const trial = trials[i];
......@@ -128,10 +134,10 @@ class DefaultPoint extends React.Component<DefaultPointProps, DefaultPointState>
const delta = trial.accuracy! - best.accuracy!;
const better = EXPERIMENT.optimizeMode === 'minimize' ? delta < 0 : delta > 0;
if (better) {
data.push([trial.sequenceId, trial.accuracy, trial.description.parameters]);
data.push([trial.sequenceId, trial.accuracy, best.id, trial.description.parameters]);
best = trial;
} else {
data.push([trial.sequenceId, best.accuracy, trial.description.parameters]);
data.push([trial.sequenceId, best.accuracy, best.id, trial.description.parameters]);
}
}
......
......@@ -61,6 +61,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
const temp = source[item];
trialIntermediate.push({
name: temp.id,
trialNum: temp.sequenceId,
data: temp.description.intermediate,
type: 'line',
hyperPara: temp.description.parameters
......@@ -94,13 +95,18 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
},
formatter: function(data: TooltipForIntermediate): React.ReactNode {
const trialId = data.seriesName;
let obj = {};
let parameters = {};
let trialNum = 0;
const temp = trialIntermediate.find(key => key.name === trialId);
if (temp !== undefined) {
obj = temp.hyperPara;
parameters = temp.hyperPara;
trialNum = temp.trialNum;
}
return (
'<div class="tooldetailAccuracy">' +
'<div>Trial No.: ' +
trialNum +
'</div>' +
'<div>Trial ID: ' +
trialId +
'</div>' +
......@@ -109,7 +115,7 @@ class Intermediate extends React.Component<IntermediateProps, IntermediateState>
'</div>' +
'<div>Parameters: ' +
'<pre>' +
JSON.stringify(obj, null, 4) +
JSON.stringify(parameters, null, 4) +
'</pre>' +
'</div>' +
'</div>'
......
......@@ -4,27 +4,29 @@ import App from './App';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Overview = lazy(() => import('./components/Overview'));
const TrialsDetail = lazy(() => import('./components/TrialsDetail'));
const Experiment = lazy(() => import('./components/managementExp/ExperimentManager'));
import './index.css';
import './static/style/loading.scss';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<Router>
<App>
<Suspense
fallback={
<div className='loading'>
<img src={require('./static/img/loading.gif')} />
</div>
}
>
<Route path='/experiment' component={Experiment} exact />
<Switch>
<Suspense
fallback={
<div className='loading'>
<img src={require('./static/img/loading.gif')} />
</div>
}
>
<App>
<Route path='/' component={Overview} exact />
<Route path='/oview' component={Overview} />
<Route path='/detail' component={TrialsDetail} />
</Suspense>
</App>
</Switch>
</App>
</Suspense>
</Router>,
document.getElementById('root')
......
......@@ -15,6 +15,16 @@ const trialJobStatus = [
'SYS_CANCELED',
'EARLY_STOPPED'
];
const EXPERIMENTSTATUS = [
'INITIALIZED',
'RUNNING',
'ERROR',
'STOPPING',
'STOPPED',
'DONE',
'NO_MORE_TRIAL',
'TUNER_NO_MORE_TRIAL'
];
const CONTROLTYPE = ['MAX_EXEC_DURATION', 'MAX_TRIAL_NUM', 'TRIAL_CONCURRENCY', 'SEARCH_SPACE'];
const MONACO = {
readOnly: true,
......@@ -64,6 +74,7 @@ export {
MANAGER_IP,
DOWNLOAD_IP,
trialJobStatus,
EXPERIMENTSTATUS,
COLUMNPro,
WEBUIDOC,
CONTROLTYPE,
......
......@@ -236,6 +236,14 @@ function formatTimestamp(timestamp?: number, placeholder?: string): string {
return timestamp ? new Date(timestamp).toLocaleString('en-US') : placeholder;
}
function expformatTimestamp(timestamp: number | string): string {
if (typeof timestamp === 'number') {
return new Date(timestamp).toLocaleString('en-US');
} else {
return 'N/A';
}
}
function metricAccuracy(metric: MetricDataRecord): number {
const data = parseMetrics(metric.data);
// return typeof data === 'number' ? data : NaN;
......@@ -262,6 +270,10 @@ function formatComplexTypeValue(value: any): string | number {
}
}
function isManagerExperimentPage(): boolean {
return location.pathname.indexOf('experiment') === -1 ? false : true;
}
function caclMonacoEditorHeight(height): number {
// [Search space 56px] + [marginBottom 18px] +
// button[height: 32px, marginTop: 45px, marginBottom: 7px]
......@@ -306,12 +318,14 @@ export {
filterDuration,
formatAccuracy,
formatTimestamp,
expformatTimestamp,
metricAccuracy,
parseMetrics,
isArrayType,
requestAxios,
isNaNorInfinity,
formatComplexTypeValue,
isManagerExperimentPage,
caclMonacoEditorHeight,
copyAndSort
};
......@@ -120,6 +120,7 @@ interface Intermedia {
type: string;
data: Array<number | object>; // intermediate data
hyperPara: object; // each trial hyperpara value
trialNum: number;
}
interface MetricDataRecord {
......@@ -218,6 +219,19 @@ interface SortInfo {
isDescend?: boolean;
}
interface AllExperimentList {
id: string;
experimentName: string;
port: number;
status: string;
platform: string;
startTime: number;
endTime: number;
tag: string[];
pid: number;
webuiUrl: string[];
logDir: string[];
}
export {
TableObj,
TableRecord,
......@@ -240,5 +254,6 @@ export {
EventMap,
SingleAxis,
MultipleAxes,
SortInfo
SortInfo,
AllExperimentList
};
import { MANAGER_IP } from '../const';
import { AllExperimentList } from '../interface';
import { requestAxios } from '../function';
class ExperimentsManager {
private experimentList: AllExperimentList[] = [];
private platform: string[] = [];
private errorMessage: string = '';
public getExperimentList(): AllExperimentList[] {
return this.experimentList;
}
public getPlatformList(): string[] {
return this.platform;
}
public getExpErrorMessage(): string {
return this.errorMessage;
}
public async init(): Promise<void> {
await requestAxios(`${MANAGER_IP}/experiments-info`)
.then(data => {
const platforms: Set<string> = new Set();
for (const item of data) {
if (item.port !== undefined) {
if (typeof item.port === 'string') {
item.port = JSON.parse(item.port);
}
}
platforms.add(item.platform);
}
this.experimentList = data;
this.platform = Array.from(platforms);
})
.catch(error => {
this.errorMessage = error.message;
});
}
}
export { ExperimentsManager };
.cursor{
&:hover, & i:hover{
cursor: pointer;
}
}
\ No newline at end of file
.ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.link {
outline: none;
color: #333 !important;
text-decoration: none;
&:hover {
color: #0071bc !important;
text-decoration: underline;
}
&:active,
&:visited {
color: #0071bc;
}
}
.cursor {
&:hover,
& i:hover {
cursor: pointer;
}
}
.expBackground {
background: #f2f2f2;
height: 100%;
.content {
background: #fff;
}
}
.experimentList {
padding: 42px;
.box {
.search {
width: 90%;
&-input {
width: 330px;
}
}
.filter {
width: 10%;
text-align: right;
&-button-open {
background: #f3f2f1;
}
}
}
.filter-condition {
margin-top: 26px;
.reset {
width: 80px;
position: relative;
top: 29px;
}
&-status {
width: 194px;
}
&-platform {
width: 150px;
}
}
.hidden {
display: none;
}
.margin {
margin-left: 10px;
}
.tagContainer {
width: 100%;
.tag {
font-weight: 500;
background: #f2f2f2;
margin: 0 4px;
padding: 0 6px;
}
}
}
$barHeight: 56px;
.navOptions {
.ms-Button-icon {
color: #fff;
&:hover {
color: #fff;
}
}
.ms-Button--commandBar {
background-color: #0071bc;
user-select: none;
&:hover,
&:active {
color: #fff;
.ms-Button-icon {
color: #fff;
}
}
.ms-Button-textContainer {
color: #fff;
}
.ms-Button-menuIcon {
color: #fff;
background-color: transparent;
}
}
.ms-Button-icon {
color: #fff;
&:hover {
color: #fff;
}
}
.ms-Button--commandBar {
background-color: #0071bc;
user-select: none;
&:hover,
&:active {
color: #fff;
.ms-Button-icon {
color: #fff;
}
}
.ms-Button-textContainer {
color: #fff;
}
.ms-Button-menuIcon {
color: #fff;
background-color: transparent;
}
}
.experiment {
position: relative;
top: 3px;
text-decoration: none;
}
}
.nav {
height: $barHeight;
line-height: $barHeight;
/* desktop mode useful */
.desktop-logo {
position: relative;
top: 6px;
}
&-refresh {
position: relative;
display: flex;
}
&-refresh-num {
position: absolute;
top: -13px;
left: 17px;
color: #fff;
font-size: 12px;
}
width: 100%;
min-width: 1200px;
height: $barHeight;
line-height: $barHeight;
/* desktop mode useful */
.desktop-logo {
position: relative;
top: 6px;
}
.logoTitle {
font-size: 18px;
color: #fff;
}
&-refresh {
position: relative;
display: flex;
}
&-refresh-num {
position: absolute;
top: -13px;
left: 17px;
color: #fff;
font-size: 12px;
}
}
/* overview and detail tabs common style */
a.common-tabs {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
color: #b8c7ce;
text-decoration: none;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
color: #b8c7ce;
text-decoration: none;
}
.common-tabs:visited,
.selected:hover {
color: #fff;
text-decoration: none;
color: #fff;
text-decoration: none;
}
.common-tabs:hover,
.selected {
color: #fff;
border-bottom: 1px solid #fff;
color: #fff;
border-bottom: 1px solid #fff;
}
.left-right-margin {
margin-left: 20px;
margin-right: 20px;
margin-left: 20px;
margin-right: 20px;
}
.expNavTitle {
span {
color: #fff;
text-decoration: none;
position: relative;
top: -4px;
}
i {
color: #fff;
font-size: 12px;
position: relative;
top: -3px;
padding-left: 4px;
}
}
.status {
color: #0573bc;
font-size: 20px;
font-weight: 600;
.status-text {
display: inline-block;
}
.color {
color: #333;
}
}
.inputBox {
height: 32px;
margin-top: 5px;
}
/* office-fabric-ui progressIndicator */
.ms-ProgressIndicator-itemProgress {
padding: 0;
}
......@@ -58,6 +58,7 @@ $margin: 24px;
.concurrency {
.editparam {
margin-top: 5px;
position: relative;
}
}
.editparam {
......@@ -124,5 +125,6 @@ $margin: 24px;
.info {
position: absolute;
z-index: 999;
left: 0;
left: -50%;
width: 270%;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment