Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
nni
Commits
430bfea5
"vscode:/vscode.git/clone" did not exist on "568b73fdf86dcc12a88b526633c7bef4bf8cf58f"
Unverified
Commit
430bfea5
authored
Nov 21, 2019
by
liuzhe-lz
Committed by
GitHub
Nov 21, 2019
Browse files
Implement feature: customized trials
parent
b3847186
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
486 additions
and
67 deletions
+486
-67
src/nni_manager/common/manager.ts
src/nni_manager/common/manager.ts
+1
-1
src/nni_manager/common/trainingService.ts
src/nni_manager/common/trainingService.ts
+0
-5
src/nni_manager/core/nnimanager.ts
src/nni_manager/core/nnimanager.ts
+35
-36
src/nni_manager/core/test/nnimanager.test.ts
src/nni_manager/core/test/nnimanager.test.ts
+2
-2
src/nni_manager/rest_server/restHandler.ts
src/nni_manager/rest_server/restHandler.ts
+2
-2
src/nni_manager/rest_server/test/mockedNNIManager.ts
src/nni_manager/rest_server/test/mockedNNIManager.ts
+2
-2
src/sdk/pynni/nni/msg_dispatcher.py
src/sdk/pynni/nni/msg_dispatcher.py
+3
-4
src/sdk/pynni/tests/test_builtin_tuners.py
src/sdk/pynni/tests/test_builtin_tuners.py
+1
-1
src/sdk/pynni/tests/test_msg_dispatcher.py
src/sdk/pynni/tests/test_msg_dispatcher.py
+1
-10
src/webui/src/components/Modal/CustomizedTrial.tsx
src/webui/src/components/Modal/CustomizedTrial.tsx
+317
-0
src/webui/src/components/Modal/customized.scss
src/webui/src/components/Modal/customized.scss
+71
-0
src/webui/src/components/trial-detail/TableList.tsx
src/webui/src/components/trial-detail/TableList.tsx
+51
-4
No files found.
src/nni_manager/common/manager.ts
View file @
430bfea5
...
@@ -105,7 +105,7 @@ abstract class Manager {
...
@@ -105,7 +105,7 @@ abstract class Manager {
public
abstract
importData
(
data
:
string
):
Promise
<
void
>
;
public
abstract
importData
(
data
:
string
):
Promise
<
void
>
;
public
abstract
exportData
():
Promise
<
string
>
;
public
abstract
exportData
():
Promise
<
string
>
;
public
abstract
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
void
>
;
public
abstract
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
number
>
;
public
abstract
cancelTrialJobByUser
(
trialJobId
:
string
):
Promise
<
void
>
;
public
abstract
cancelTrialJobByUser
(
trialJobId
:
string
):
Promise
<
void
>
;
public
abstract
listTrialJobs
(
status
?:
TrialJobStatus
):
Promise
<
TrialJobInfo
[]
>
;
public
abstract
listTrialJobs
(
status
?:
TrialJobStatus
):
Promise
<
TrialJobInfo
[]
>
;
...
...
src/nni_manager/common/trainingService.ts
View file @
430bfea5
...
@@ -58,11 +58,6 @@ interface TrialJobDetail {
...
@@ -58,11 +58,6 @@ interface TrialJobDetail {
isEarlyStopped
?:
boolean
;
isEarlyStopped
?:
boolean
;
}
}
interface
HostJobDetail
{
readonly
id
:
string
;
readonly
status
:
string
;
}
/**
/**
* define TrialJobMetric
* define TrialJobMetric
*/
*/
...
...
src/nni_manager/core/nnimanager.ts
View file @
430bfea5
...
@@ -50,13 +50,12 @@ class NNIManager implements Manager {
...
@@ -50,13 +50,12 @@ class NNIManager implements Manager {
private
dispatcher
:
IpcInterface
|
undefined
;
private
dispatcher
:
IpcInterface
|
undefined
;
private
currSubmittedTrialNum
:
number
;
// need to be recovered
private
currSubmittedTrialNum
:
number
;
// need to be recovered
private
trialConcurrencyChange
:
number
;
// >0: increase, <0: decrease
private
trialConcurrencyChange
:
number
;
// >0: increase, <0: decrease
private
customizedTrials
:
string
[];
// need to be recovered
private
log
:
Logger
;
private
log
:
Logger
;
private
dataStore
:
DataStore
;
private
dataStore
:
DataStore
;
private
experimentProfile
:
ExperimentProfile
;
private
experimentProfile
:
ExperimentProfile
;
private
dispatcherPid
:
number
;
private
dispatcherPid
:
number
;
private
status
:
NNIManagerStatus
;
private
status
:
NNIManagerStatus
;
private
waitingTrials
:
string
[];
private
waitingTrials
:
TrialJobApplicationForm
[];
private
trialJobs
:
Map
<
string
,
TrialJobDetail
>
;
private
trialJobs
:
Map
<
string
,
TrialJobDetail
>
;
private
trialDataForTuner
:
string
;
private
trialDataForTuner
:
string
;
private
readonly
:
boolean
;
private
readonly
:
boolean
;
...
@@ -66,7 +65,6 @@ class NNIManager implements Manager {
...
@@ -66,7 +65,6 @@ class NNIManager implements Manager {
constructor
()
{
constructor
()
{
this
.
currSubmittedTrialNum
=
0
;
this
.
currSubmittedTrialNum
=
0
;
this
.
trialConcurrencyChange
=
0
;
this
.
trialConcurrencyChange
=
0
;
this
.
customizedTrials
=
[];
this
.
trainingService
=
component
.
get
(
TrainingService
);
this
.
trainingService
=
component
.
get
(
TrainingService
);
assert
(
this
.
trainingService
);
assert
(
this
.
trainingService
);
this
.
dispatcherPid
=
0
;
this
.
dispatcherPid
=
0
;
...
@@ -131,19 +129,34 @@ class NNIManager implements Manager {
...
@@ -131,19 +129,34 @@ class NNIManager implements Manager {
return
this
.
dataStore
.
exportTrialHpConfigs
();
return
this
.
dataStore
.
exportTrialHpConfigs
();
}
}
public
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
void
>
{
public
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
number
>
{
if
(
this
.
readonly
)
{
if
(
this
.
readonly
)
{
return
Promise
.
reject
(
new
Error
(
'
Error: can not add customized trial job in readonly mode!
'
));
return
Promise
.
reject
(
new
Error
(
'
Error: can not add customized trial job in readonly mode!
'
));
}
}
if
(
this
.
currSubmittedTrialNum
>=
this
.
experimentProfile
.
params
.
maxTrialNum
)
{
if
(
this
.
currSubmittedTrialNum
>=
this
.
experimentProfile
.
params
.
maxTrialNum
)
{
return
Promise
.
reject
(
return
Promise
.
reject
(
new
Error
(
'
reach maxTrialNum
'
));
new
Error
(
'
reach maxTrialNum
'
)
);
}
}
this
.
customizedTrials
.
push
(
hyperParams
);
// TODO: NNI manager should not peek tuner's internal protocol, let's refactor this later
const
packedParameter
=
{
parameter_id
:
null
,
parameter_source
:
'
customized
'
,
parameters
:
JSON
.
parse
(
hyperParams
)
}
const
form
:
TrialJobApplicationForm
=
{
sequenceId
:
this
.
experimentProfile
.
nextSequenceId
++
,
hyperParameters
:
{
value
:
JSON
.
stringify
(
packedParameter
),
index
:
0
}
};
this
.
waitingTrials
.
push
(
form
);
// trial id has not been generated yet, thus use '' instead
// trial id has not been generated yet, thus use '' instead
return
this
.
dataStore
.
storeTrialJobEvent
(
'
ADD_CUSTOMIZED
'
,
''
,
hyperParams
);
this
.
dataStore
.
storeTrialJobEvent
(
'
ADD_CUSTOMIZED
'
,
''
,
hyperParams
);
return
Promise
.
resolve
(
form
.
sequenceId
);
}
}
public
async
cancelTrialJobByUser
(
trialJobId
:
string
):
Promise
<
void
>
{
public
async
cancelTrialJobByUser
(
trialJobId
:
string
):
Promise
<
void
>
{
...
@@ -560,18 +573,7 @@ class NNIManager implements Manager {
...
@@ -560,18 +573,7 @@ class NNIManager implements Manager {
this
.
trialConcurrencyChange
=
requestTrialNum
;
this
.
trialConcurrencyChange
=
requestTrialNum
;
}
}
const
requestCustomTrialNum
:
number
=
Math
.
min
(
requestTrialNum
,
this
.
customizedTrials
.
length
);
this
.
requestTrialJobs
(
requestTrialNum
);
for
(
let
i
:
number
=
0
;
i
<
requestCustomTrialNum
;
i
++
)
{
// ask tuner for more trials
if
(
this
.
customizedTrials
.
length
>
0
)
{
const
hyperParams
:
string
|
undefined
=
this
.
customizedTrials
.
shift
();
this
.
dispatcher
.
sendCommand
(
ADD_CUSTOMIZED_TRIAL_JOB
,
hyperParams
);
}
}
if
(
requestTrialNum
-
requestCustomTrialNum
>
0
)
{
this
.
requestTrialJobs
(
requestTrialNum
-
requestCustomTrialNum
);
}
// check maxtrialnum and maxduration here
// check maxtrialnum and maxduration here
// NO_MORE_TRIAL is more like a subset of RUNNING, because during RUNNING tuner
// NO_MORE_TRIAL is more like a subset of RUNNING, because during RUNNING tuner
...
@@ -609,26 +611,16 @@ class NNIManager implements Manager {
...
@@ -609,26 +611,16 @@ class NNIManager implements Manager {
this
.
currSubmittedTrialNum
>=
this
.
experimentProfile
.
params
.
maxTrialNum
)
{
this
.
currSubmittedTrialNum
>=
this
.
experimentProfile
.
params
.
maxTrialNum
)
{
break
;
break
;
}
}
const
hyperParams
:
string
|
undefined
=
this
.
waitingTrials
.
shift
();
const
form
=
this
.
waitingTrials
.
shift
()
as
TrialJobApplicationForm
;
if
(
hyperParams
===
undefined
)
{
throw
new
Error
(
`Error: invalid hyper-parameters for job submission:
${
hyperParams
}
`
);
}
this
.
currSubmittedTrialNum
++
;
this
.
currSubmittedTrialNum
++
;
const
trialJobAppForm
:
TrialJobApplicationForm
=
{
this
.
log
.
info
(
`submitTrialJob: form:
${
JSON
.
stringify
(
form
)}
`
);
sequenceId
:
this
.
experimentProfile
.
nextSequenceId
++
,
const
trialJobDetail
:
TrialJobDetail
=
await
this
.
trainingService
.
submitTrialJob
(
form
);
hyperParameters
:
{
value
:
hyperParams
,
index
:
0
}
};
this
.
log
.
info
(
`submitTrialJob: form:
${
JSON
.
stringify
(
trialJobAppForm
)}
`
);
const
trialJobDetail
:
TrialJobDetail
=
await
this
.
trainingService
.
submitTrialJob
(
trialJobAppForm
);
await
this
.
storeExperimentProfile
();
await
this
.
storeExperimentProfile
();
this
.
trialJobs
.
set
(
trialJobDetail
.
id
,
Object
.
assign
({},
trialJobDetail
));
this
.
trialJobs
.
set
(
trialJobDetail
.
id
,
Object
.
assign
({},
trialJobDetail
));
const
trialJobDetailSnapshot
:
TrialJobDetail
|
undefined
=
this
.
trialJobs
.
get
(
trialJobDetail
.
id
);
const
trialJobDetailSnapshot
:
TrialJobDetail
|
undefined
=
this
.
trialJobs
.
get
(
trialJobDetail
.
id
);
if
(
trialJobDetailSnapshot
!=
undefined
)
{
if
(
trialJobDetailSnapshot
!=
undefined
)
{
await
this
.
dataStore
.
storeTrialJobEvent
(
await
this
.
dataStore
.
storeTrialJobEvent
(
trialJobDetailSnapshot
.
status
,
trialJobDetailSnapshot
.
id
,
hyperParam
s
,
trialJobDetailSnapshot
);
trialJobDetailSnapshot
.
status
,
trialJobDetailSnapshot
.
id
,
form
.
hyperParam
eters
.
value
,
trialJobDetailSnapshot
);
}
else
{
}
else
{
assert
(
false
,
`undefined trialJobDetail in trialJobs:
${
trialJobDetail
.
id
}
`
);
assert
(
false
,
`undefined trialJobDetail in trialJobs:
${
trialJobDetail
.
id
}
`
);
}
}
...
@@ -734,7 +726,14 @@ class NNIManager implements Manager {
...
@@ -734,7 +726,14 @@ class NNIManager implements Manager {
this
.
log
.
warning
(
'
It is not supposed to receive more trials after NO_MORE_TRIAL is set
'
);
this
.
log
.
warning
(
'
It is not supposed to receive more trials after NO_MORE_TRIAL is set
'
);
this
.
setStatus
(
'
RUNNING
'
);
this
.
setStatus
(
'
RUNNING
'
);
}
}
this
.
waitingTrials
.
push
(
content
);
const
form
:
TrialJobApplicationForm
=
{
sequenceId
:
this
.
experimentProfile
.
nextSequenceId
++
,
hyperParameters
:
{
value
:
content
,
index
:
0
}
};
this
.
waitingTrials
.
push
(
form
);
break
;
break
;
case
SEND_TRIAL_JOB_PARAMETER
:
case
SEND_TRIAL_JOB_PARAMETER
:
const
tunerCommand
:
any
=
JSON
.
parse
(
content
);
const
tunerCommand
:
any
=
JSON
.
parse
(
content
);
...
...
src/nni_manager/core/test/nnimanager.test.ts
View file @
430bfea5
...
@@ -121,7 +121,7 @@ describe('Unit test for nnimanager', function () {
...
@@ -121,7 +121,7 @@ describe('Unit test for nnimanager', function () {
it
(
'
test addCustomizedTrialJob
'
,
()
=>
{
it
(
'
test addCustomizedTrialJob
'
,
()
=>
{
return
nniManager
.
addCustomizedTrialJob
(
'
hyperParams
'
).
then
(()
=>
{
return
nniManager
.
addCustomizedTrialJob
(
'
"
hyperParams
"
'
).
then
(()
=>
{
}).
catch
((
error
)
=>
{
}).
catch
((
error
)
=>
{
assert
.
fail
(
error
);
assert
.
fail
(
error
);
...
@@ -273,7 +273,7 @@ describe('Unit test for nnimanager', function () {
...
@@ -273,7 +273,7 @@ describe('Unit test for nnimanager', function () {
it
(
'
test addCustomizedTrialJob reach maxTrialNum
'
,
()
=>
{
it
(
'
test addCustomizedTrialJob reach maxTrialNum
'
,
()
=>
{
// test currSubmittedTrialNum reach maxTrialNum
// test currSubmittedTrialNum reach maxTrialNum
return
nniManager
.
addCustomizedTrialJob
(
'
hyperParam
'
).
then
(()
=>
{
return
nniManager
.
addCustomizedTrialJob
(
'
"
hyperParam
"
'
).
then
(()
=>
{
nniManager
.
getTrialJobStatistics
().
then
(
function
(
trialJobStatistics
)
{
nniManager
.
getTrialJobStatistics
().
then
(
function
(
trialJobStatistics
)
{
if
(
trialJobStatistics
[
0
].
trialJobStatus
===
'
WAITING
'
)
if
(
trialJobStatistics
[
0
].
trialJobStatus
===
'
WAITING
'
)
expect
(
trialJobStatistics
[
0
].
trialJobNumber
).
to
.
be
.
equal
(
2
);
expect
(
trialJobStatistics
[
0
].
trialJobNumber
).
to
.
be
.
equal
(
2
);
...
...
src/nni_manager/rest_server/restHandler.ts
View file @
430bfea5
...
@@ -236,8 +236,8 @@ class NNIRestHandler {
...
@@ -236,8 +236,8 @@ class NNIRestHandler {
private
addTrialJob
(
router
:
Router
):
void
{
private
addTrialJob
(
router
:
Router
):
void
{
router
.
post
(
'
/trial-jobs
'
,
async
(
req
:
Request
,
res
:
Response
)
=>
{
router
.
post
(
'
/trial-jobs
'
,
async
(
req
:
Request
,
res
:
Response
)
=>
{
this
.
nniManager
.
addCustomizedTrialJob
(
JSON
.
stringify
(
req
.
body
)).
then
(()
=>
{
this
.
nniManager
.
addCustomizedTrialJob
(
JSON
.
stringify
(
req
.
body
)).
then
((
sequenceId
:
number
)
=>
{
res
.
send
();
res
.
send
(
{
sequenceId
}
);
}).
catch
((
err
:
Error
)
=>
{
}).
catch
((
err
:
Error
)
=>
{
this
.
handle_error
(
err
,
res
);
this
.
handle_error
(
err
,
res
);
});
});
...
...
src/nni_manager/rest_server/test/mockedNNIManager.ts
View file @
430bfea5
...
@@ -65,8 +65,8 @@ export class MockedNNIManager extends Manager {
...
@@ -65,8 +65,8 @@ export class MockedNNIManager extends Manager {
return
deferred
.
promise
;
return
deferred
.
promise
;
}
}
public
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
void
>
{
public
addCustomizedTrialJob
(
hyperParams
:
string
):
Promise
<
number
>
{
return
Promise
.
resolve
();
return
Promise
.
resolve
(
99
);
}
}
public
resumeExperiment
():
Promise
<
void
>
{
public
resumeExperiment
():
Promise
<
void
>
{
...
...
src/sdk/pynni/nni/msg_dispatcher.py
View file @
430bfea5
...
@@ -136,7 +136,6 @@ class MsgDispatcher(MsgDispatcherBase):
...
@@ -136,7 +136,6 @@ class MsgDispatcher(MsgDispatcherBase):
# data: parameters
# data: parameters
id_
=
_create_parameter_id
()
id_
=
_create_parameter_id
()
_customized_parameter_ids
.
add
(
id_
)
_customized_parameter_ids
.
add
(
id_
)
send
(
CommandType
.
NewTrialJob
,
_pack_parameter
(
id_
,
data
,
customized
=
True
))
def
handle_report_metric_data
(
self
,
data
):
def
handle_report_metric_data
(
self
,
data
):
"""
"""
...
@@ -185,7 +184,7 @@ class MsgDispatcher(MsgDispatcherBase):
...
@@ -185,7 +184,7 @@ class MsgDispatcher(MsgDispatcherBase):
"""
"""
id_
=
data
[
'parameter_id'
]
id_
=
data
[
'parameter_id'
]
value
=
data
[
'value'
]
value
=
data
[
'value'
]
if
id_
in
_customized_parameter_ids
:
if
not
id_
or
id_
in
_customized_parameter_ids
:
if
not
hasattr
(
self
.
tuner
,
'_accept_customized'
):
if
not
hasattr
(
self
.
tuner
,
'_accept_customized'
):
self
.
tuner
.
_accept_customized
=
False
self
.
tuner
.
_accept_customized
=
False
if
not
self
.
tuner
.
_accept_customized
:
if
not
self
.
tuner
.
_accept_customized
:
...
@@ -194,8 +193,8 @@ class MsgDispatcher(MsgDispatcherBase):
...
@@ -194,8 +193,8 @@ class MsgDispatcher(MsgDispatcherBase):
customized
=
True
customized
=
True
else
:
else
:
customized
=
False
customized
=
False
self
.
tuner
.
receive_trial_result
(
id_
,
_trial_params
[
id_
],
value
,
customized
=
customized
,
self
.
tuner
.
receive_trial_result
(
id_
,
_trial_params
[
id_
],
value
,
customized
=
customized
,
trial_job_id
=
data
.
get
(
'trial_job_id'
))
trial_job_id
=
data
.
get
(
'trial_job_id'
))
def
_handle_intermediate_metric_data
(
self
,
data
):
def
_handle_intermediate_metric_data
(
self
,
data
):
"""Call assessor to process intermediate results
"""Call assessor to process intermediate results
...
...
src/sdk/pynni/tests/test_tuner.py
→
src/sdk/pynni/tests/test_
builtin_
tuner
s
.py
View file @
430bfea5
...
@@ -41,7 +41,7 @@ logging.basicConfig(level=logging.INFO)
...
@@ -41,7 +41,7 @@ logging.basicConfig(level=logging.INFO)
logger
=
logging
.
getLogger
(
'test_tuner'
)
logger
=
logging
.
getLogger
(
'test_tuner'
)
class
TunerTestCase
(
TestCase
):
class
Builtin
Tuner
s
TestCase
(
TestCase
):
"""
"""
Targeted at testing functions of built-in tuners, including
Targeted at testing functions of built-in tuners, including
- [ ] load_checkpoint
- [ ] load_checkpoint
...
...
src/sdk/pynni/tests/test_msg_dispatcher.py
View file @
430bfea5
...
@@ -80,8 +80,6 @@ class MsgDispatcherTestCase(TestCase):
...
@@ -80,8 +80,6 @@ class MsgDispatcherTestCase(TestCase):
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":0,"type":"PERIODICAL","value":10}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":0,"type":"PERIODICAL","value":10}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":1,"type":"FINAL","value":11}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":1,"type":"FINAL","value":11}'
)
send
(
CommandType
.
UpdateSearchSpace
,
'{"name":"SS0"}'
)
send
(
CommandType
.
UpdateSearchSpace
,
'{"name":"SS0"}'
)
send
(
CommandType
.
AddCustomizedTrialJob
,
'{"param":-1}'
)
send
(
CommandType
.
ReportMetricData
,
'{"parameter_id":2,"type":"FINAL","value":22}'
)
send
(
CommandType
.
RequestTrialJobs
,
'1'
)
send
(
CommandType
.
RequestTrialJobs
,
'1'
)
send
(
CommandType
.
KillTrialJob
,
'null'
)
send
(
CommandType
.
KillTrialJob
,
'null'
)
_restore_io
()
_restore_io
()
...
@@ -99,14 +97,7 @@ class MsgDispatcherTestCase(TestCase):
...
@@ -99,14 +97,7 @@ class MsgDispatcherTestCase(TestCase):
self
.
_assert_params
(
0
,
2
,
[],
None
)
self
.
_assert_params
(
0
,
2
,
[],
None
)
self
.
_assert_params
(
1
,
4
,
[],
None
)
self
.
_assert_params
(
1
,
4
,
[],
None
)
command
,
data
=
receive
()
# this one is customized
self
.
_assert_params
(
2
,
6
,
[[
1
,
4
,
11
,
False
]],
{
'name'
:
'SS0'
})
data
=
json
.
loads
(
data
)
self
.
assertIs
(
command
,
CommandType
.
NewTrialJob
)
self
.
assertEqual
(
data
[
'parameter_id'
],
2
)
self
.
assertEqual
(
data
[
'parameter_source'
],
'customized'
)
self
.
assertEqual
(
data
[
'parameters'
],
{
'param'
:
-
1
})
self
.
_assert_params
(
3
,
6
,
[[
1
,
4
,
11
,
False
],
[
2
,
-
1
,
22
,
True
]],
{
'name'
:
'SS0'
})
self
.
assertEqual
(
len
(
_out_buf
.
read
()),
0
)
# no more commands
self
.
assertEqual
(
len
(
_out_buf
.
read
()),
0
)
# no more commands
...
...
src/webui/src/components/Modal/CustomizedTrial.tsx
0 → 100644
View file @
430bfea5
import
*
as
React
from
'
react
'
;
import
axios
from
'
axios
'
;
import
{
Row
,
Col
,
Input
,
Modal
,
Form
,
Button
,
Icon
}
from
'
antd
'
;
import
{
MANAGER_IP
}
from
'
../../static/const
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
FormComponentProps
}
from
'
antd/lib/form
'
;
const
FormItem
=
Form
.
Item
;
import
'
./customized.scss
'
;
interface
CustomizeProps
extends
FormComponentProps
{
visible
:
boolean
;
copyTrialId
:
string
;
closeCustomizeModal
:
()
=>
void
;
}
interface
CustomizeState
{
isShowSubmitSucceed
:
boolean
;
isShowSubmitFailed
:
boolean
;
isShowWarning
:
boolean
;
searchSpace
:
object
;
copyTrialParameter
:
object
;
// user click the trial's parameters
customParameters
:
object
;
// customized trial, maybe user change trial's parameters
customID
:
number
;
// submit customized trial succeed, return the new customized trial id
}
class
Customize
extends
React
.
Component
<
CustomizeProps
,
CustomizeState
>
{
constructor
(
props
:
CustomizeProps
)
{
super
(
props
);
this
.
state
=
{
isShowSubmitSucceed
:
false
,
isShowSubmitFailed
:
false
,
isShowWarning
:
false
,
searchSpace
:
EXPERIMENT
.
searchSpace
,
copyTrialParameter
:
{},
customParameters
:
{},
customID
:
NaN
};
}
// [submit click] user add a new trial [submit a trial]
addNewTrial
=
()
=>
{
const
{
searchSpace
,
copyTrialParameter
}
=
this
.
state
;
// get user edited hyperParameter, ps: will change data type if you modify the input val
const
customized
=
this
.
props
.
form
.
getFieldsValue
();
// true: parameters are wrong
let
flag
=
false
;
Object
.
keys
(
customized
).
map
(
item
=>
{
if
(
item
!==
'
tag
'
)
{
// unified data type
if
(
typeof
copyTrialParameter
[
item
]
===
'
number
'
&&
typeof
customized
[
item
]
===
'
string
'
)
{
customized
[
item
]
=
JSON
.
parse
(
customized
[
item
]);
}
if
(
searchSpace
[
item
].
_type
===
'
choice
'
)
{
if
(
searchSpace
[
item
].
_value
.
find
((
val
:
string
|
number
)
=>
val
===
customized
[
item
])
===
undefined
)
{
flag
=
true
;
return
;
}
}
else
{
if
(
customized
[
item
]
<
searchSpace
[
item
].
_value
[
0
]
||
customized
[
item
]
>
searchSpace
[
item
].
_value
[
1
])
{
flag
=
true
;
return
;
}
}
}
});
if
(
flag
!==
false
)
{
// open the warning modal
this
.
setState
(()
=>
({
isShowWarning
:
true
,
customParameters
:
customized
}));
}
else
{
// submit a customized job
this
.
submitCustomize
(
customized
);
}
}
warningConfirm
=
()
=>
{
this
.
setState
(()
=>
({
isShowWarning
:
false
}));
const
{
customParameters
}
=
this
.
state
;
this
.
submitCustomize
(
customParameters
);
}
warningCancel
=
()
=>
{
this
.
setState
(()
=>
({
isShowWarning
:
false
}));
}
submitCustomize
=
(
customized
:
Object
)
=>
{
// delete `tag` key
for
(
let
i
in
customized
)
{
if
(
i
===
'
tag
'
)
{
delete
customized
[
i
];
}
}
axios
(
`
${
MANAGER_IP
}
/trial-jobs`
,
{
method
:
'
POST
'
,
headers
:
{
'
Content-Type
'
:
'
application/json
'
},
data
:
customized
})
.
then
(
res
=>
{
if
(
res
.
status
===
200
)
{
this
.
setState
(()
=>
({
isShowSubmitSucceed
:
true
,
customID
:
res
.
data
.
sequenceId
}));
this
.
props
.
closeCustomizeModal
();
}
else
{
this
.
setState
(()
=>
({
isShowSubmitFailed
:
true
}));
}
})
.
catch
(
error
=>
{
this
.
setState
(()
=>
({
isShowSubmitFailed
:
true
}));
});
}
closeSucceedHint
=
()
=>
{
// also close customized trial modal
this
.
setState
(()
=>
({
isShowSubmitSucceed
:
false
}));
this
.
props
.
closeCustomizeModal
();
}
closeFailedHint
=
()
=>
{
// also close customized trial modal
this
.
setState
(()
=>
({
isShowSubmitFailed
:
false
}));
this
.
props
.
closeCustomizeModal
();
}
componentDidMount
()
{
const
{
copyTrialId
}
=
this
.
props
;
if
(
copyTrialId
!==
undefined
&&
TRIALS
.
getTrial
(
copyTrialId
)
!==
undefined
)
{
const
originCopyTrialPara
=
TRIALS
.
getTrial
(
copyTrialId
).
description
.
parameters
;
this
.
setState
(()
=>
({
copyTrialParameter
:
originCopyTrialPara
}));
}
}
componentWillReceiveProps
(
nextProps
:
CustomizeProps
)
{
const
{
copyTrialId
}
=
nextProps
;
if
(
copyTrialId
!==
undefined
&&
TRIALS
.
getTrial
(
copyTrialId
)
!==
undefined
)
{
const
originCopyTrialPara
=
TRIALS
.
getTrial
(
copyTrialId
).
description
.
parameters
;
this
.
setState
(()
=>
({
copyTrialParameter
:
originCopyTrialPara
}));
}
}
render
()
{
const
{
closeCustomizeModal
,
visible
}
=
this
.
props
;
const
{
isShowSubmitSucceed
,
isShowSubmitFailed
,
isShowWarning
,
customID
,
copyTrialParameter
}
=
this
.
state
;
const
{
form
:
{
getFieldDecorator
},
// form: { getFieldDecorator, getFieldValue },
}
=
this
.
props
;
const
warning
=
'
The parameters you set are not in our search space, this may cause the tuner to crash, Are
'
+
'
you sure you want to continue submitting?
'
;
return
(
<
Row
>
{
/* form: search space */
}
<
Modal
title
=
"Customized trial setting"
visible
=
{
visible
}
onCancel
=
{
closeCustomizeModal
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
centered
=
{
true
}
>
{
/* search space form */
}
<
Row
className
=
"hyper-box"
>
<
Form
>
{
Object
.
keys
(
copyTrialParameter
).
map
(
item
=>
(
<
Row
key
=
{
item
}
className
=
"hyper-form"
>
<
Col
span
=
{
9
}
className
=
"title"
>
{
item
}
</
Col
>
<
Col
span
=
{
15
}
className
=
"inputs"
>
<
FormItem
key
=
{
item
}
style
=
{
{
marginBottom
:
0
}
}
>
{
getFieldDecorator
(
item
,
{
initialValue
:
copyTrialParameter
[
item
],
})(
<
Input
/>
)
}
</
FormItem
>
</
Col
>
</
Row
>
)
)
}
<
Row
key
=
"tag"
className
=
"hyper-form tag-input"
>
<
Col
span
=
{
9
}
className
=
"title"
>
Tag
</
Col
>
<
Col
span
=
{
15
}
className
=
"inputs"
>
<
FormItem
key
=
"tag"
style
=
{
{
marginBottom
:
0
}
}
>
{
getFieldDecorator
(
'
tag
'
,
{
initialValue
:
'
Customized
'
,
})(
<
Input
/>
)
}
</
FormItem
>
</
Col
>
</
Row
>
</
Form
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
type
=
"primary"
className
=
"tableButton distance"
onClick
=
{
this
.
addNewTrial
}
>
Submit
</
Button
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
props
.
closeCustomizeModal
}
>
Cancel
</
Button
>
</
Row
>
{
/* control button */
}
</
Modal
>
{
/* clone: prompt succeed or failed */
}
<
Modal
visible
=
{
isShowSubmitSucceed
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
type
=
"check-circle"
className
=
"color-succ"
/>
<
b
>
Submit successfully
</
b
>
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
You can find your customized trial by Trial No.
{
customID
}
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
closeSucceedHint
}
>
OK
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
<
Modal
visible
=
{
isShowSubmitFailed
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
type
=
"check-circle"
className
=
"color-error"
/>
Submit Failed
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
Unknown error.
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button"
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
closeFailedHint
}
>
OK
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
{
/* hyperParameter not match search space, warning modal */
}
<
Modal
visible
=
{
isShowWarning
}
footer
=
{
null
}
destroyOnClose
=
{
true
}
maskClosable
=
{
false
}
closable
=
{
false
}
centered
=
{
true
}
>
<
Row
className
=
"resubmit"
>
<
Row
>
<
h2
className
=
"title"
>
<
span
>
<
Icon
className
=
"color-warn"
type
=
"warning"
/>
Warning
</
span
>
</
h2
>
<
div
className
=
"hint"
>
<
span
>
{
warning
}
</
span
>
</
div
>
</
Row
>
<
Row
className
=
"modal-button center"
>
<
Button
className
=
"tableButton cancelSty distance"
onClick
=
{
this
.
warningConfirm
}
>
Confirm
</
Button
>
<
Button
className
=
"tableButton cancelSty"
onClick
=
{
this
.
warningCancel
}
>
Cancel
</
Button
>
</
Row
>
</
Row
>
</
Modal
>
</
Row
>
);
}
}
export
default
Form
.
create
<
FormComponentProps
>
()(
Customize
);
\ No newline at end of file
src/webui/src/components/Modal/customized.scss
0 → 100644
View file @
430bfea5
.ant-modal-body
{
border-radius
:
none
;
}
.ant-modal-title
{
font-size
:
18px
;
}
/* resubmit confirm modal style */
.resubmit
{
.title
{
font-size
:
16px
;
color
:
#000
;
.color-warn
,
.color-error
{
color
:
red
;
}
i
{
margin-right
:
10px
;
}
}
.hint
{
padding
:
15px
0
;
color
:
#333
;
margin-left
:
30px
;
}
.color-succ
{
color
:
green
;
}
}
.hyper-box
{
padding
:
16px
18px
16px
16px
;
}
.hyper-form
{
height
:
32px
;
margin-bottom
:
8px
;
.title
{
font-size
:
14px
;
font-family
:
'Segoe UI'
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
line-height
:
32px
;
}
.inputs
{
height
:
32px
;
}
input
{
height
:
32px
;
}
}
.tag-input
{
margin-top
:
25px
;
}
/* submit & cancel buttons style*/
.modal-button
{
text-align
:
right
;
height
:
28px
;
/* cancel button style*/
.cancelSty
{
width
:
80px
;
background-color
:
#dadada
;
border
:
none
;
color
:
#333
;
}
.cancelSty
:hover
,
.cancelSty
:active
,
.cancelSty
:focus
{
background-color
:
#dadada
;
}
.distance
{
margin-right
:
8px
;
}
}
.center
{
text-align
:
center
;
}
src/webui/src/components/trial-detail/TableList.tsx
View file @
430bfea5
...
@@ -7,10 +7,11 @@ const Option = Select.Option;
...
@@ -7,10 +7,11 @@ const Option = Select.Option;
const
CheckboxGroup
=
Checkbox
.
Group
;
const
CheckboxGroup
=
Checkbox
.
Group
;
import
{
MANAGER_IP
,
trialJobStatus
,
COLUMN_INDEX
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
MANAGER_IP
,
trialJobStatus
,
COLUMN_INDEX
,
COLUMNPro
}
from
'
../../static/const
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
killJob
}
from
'
../../static/function
'
;
import
{
convertDuration
,
formatTimestamp
,
intermediateGraphOption
,
killJob
}
from
'
../../static/function
'
;
import
{
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
EXPERIMENT
,
TRIALS
}
from
'
../../static/datamodel
'
;
import
{
TableRecord
}
from
'
../../static/interface
'
;
import
{
TableRecord
}
from
'
../../static/interface
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
OpenRow
from
'
../public-child/OpenRow
'
;
import
Compare
from
'
../Modal/Compare
'
;
import
Compare
from
'
../Modal/Compare
'
;
import
Customize
from
'
../Modal/CustomizedTrial
'
;
import
'
../../static/style/search.scss
'
;
import
'
../../static/style/search.scss
'
;
require
(
'
../../static/style/tableStatus.css
'
);
require
(
'
../../static/style/tableStatus.css
'
);
require
(
'
../../static/style/logPath.scss
'
);
require
(
'
../../static/style/logPath.scss
'
);
...
@@ -45,6 +46,8 @@ interface TableListState {
...
@@ -45,6 +46,8 @@ interface TableListState {
intermediateData
:
Array
<
object
>
;
// a trial's intermediate results (include dict)
intermediateData
:
Array
<
object
>
;
// a trial's intermediate results (include dict)
intermediateId
:
string
;
intermediateId
:
string
;
intermediateOtherKeys
:
Array
<
string
>
;
intermediateOtherKeys
:
Array
<
string
>
;
isShowCustomizedModal
:
boolean
;
copyTrialId
:
string
;
// user copy trial to submit a new customized trial
}
}
interface
ColumnIndex
{
interface
ColumnIndex
{
...
@@ -71,7 +74,9 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -71,7 +74,9 @@ class TableList extends React.Component<TableListProps, TableListState> {
selectedRowKeys
:
[],
// close selected trial message after modal closed
selectedRowKeys
:
[],
// close selected trial message after modal closed
intermediateData
:
[],
intermediateData
:
[],
intermediateId
:
''
,
intermediateId
:
''
,
intermediateOtherKeys
:
[]
intermediateOtherKeys
:
[],
isShowCustomizedModal
:
false
,
copyTrialId
:
''
};
};
}
}
...
@@ -236,17 +241,36 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -236,17 +241,36 @@ class TableList extends React.Component<TableListProps, TableListState> {
this
.
setState
({
isShowCompareModal
:
false
,
selectedRowKeys
:
[],
selectRows
:
[]
});
this
.
setState
({
isShowCompareModal
:
false
,
selectedRowKeys
:
[],
selectRows
:
[]
});
}
}
// open customized trial modal
setCustomizedTrial
=
(
trialId
:
string
)
=>
{
this
.
setState
({
isShowCustomizedModal
:
true
,
copyTrialId
:
trialId
});
}
closeCustomizedTrial
=
()
=>
{
this
.
setState
({
isShowCustomizedModal
:
false
,
copyTrialId
:
''
});
}
render
()
{
render
()
{
const
{
pageSize
,
columnList
}
=
this
.
props
;
const
{
pageSize
,
columnList
}
=
this
.
props
;
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
props
.
tableSource
));
const
tableSource
:
Array
<
TableRecord
>
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
props
.
tableSource
));
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
const
{
intermediateOption
,
modalVisible
,
isShowColumn
,
selectRows
,
isShowCompareModal
,
selectedRowKeys
,
intermediateOtherKeys
}
=
this
.
state
;
selectRows
,
isShowCompareModal
,
selectedRowKeys
,
intermediateOtherKeys
,
isShowCustomizedModal
,
copyTrialId
}
=
this
.
state
;
const
rowSelection
=
{
const
rowSelection
=
{
selectedRowKeys
:
selectedRowKeys
,
selectedRowKeys
:
selectedRowKeys
,
onChange
:
(
selected
:
string
[]
|
number
[],
selectedRows
:
Array
<
TableRecord
>
)
=>
{
onChange
:
(
selected
:
string
[]
|
number
[],
selectedRows
:
Array
<
TableRecord
>
)
=>
{
this
.
fillSelectedRowsTostate
(
selected
,
selectedRows
);
this
.
fillSelectedRowsTostate
(
selected
,
selectedRows
);
}
}
};
};
// [supportCustomizedTrial: true]
const
supportCustomizedTrial
=
(
EXPERIMENT
.
multiPhase
===
true
)
?
false
:
true
;
const
disabledAddCustomizedTrial
=
[
'
DONE
'
,
'
ERROR
'
,
'
STOPPED
'
].
includes
(
EXPERIMENT
.
status
);
let
showTitle
=
COLUMNPro
;
let
showTitle
=
COLUMNPro
;
const
showColumn
:
Array
<
object
>
=
[];
const
showColumn
:
Array
<
object
>
=
[];
...
@@ -361,6 +385,22 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -361,6 +385,22 @@ class TableList extends React.Component<TableListProps, TableListState> {
</
Button
>
</
Button
>
</
Popconfirm
>
</
Popconfirm
>
}
}
{
/* Add a new trial-customized trial */
}
{
supportCustomizedTrial
?
<
Button
type
=
"primary"
className
=
"common-style"
disabled
=
{
disabledAddCustomizedTrial
}
onClick
=
{
this
.
setCustomizedTrial
.
bind
(
this
,
record
.
id
)
}
title
=
"Customized trial"
>
<
Icon
type
=
"copy"
/>
</
Button
>
:
null
}
</
Row
>
</
Row
>
);
);
},
},
...
@@ -398,7 +438,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -398,7 +438,7 @@ class TableList extends React.Component<TableListProps, TableListState> {
expandedRowRender
=
{
this
.
openRow
}
expandedRowRender
=
{
this
.
openRow
}
dataSource
=
{
tableSource
}
dataSource
=
{
tableSource
}
className
=
"commonTableStyle"
className
=
"commonTableStyle"
scroll
=
{
{
x
:
'
max-content
'
}
}
scroll
=
{
{
x
:
'
max-content
'
}
}
pagination
=
{
pageSize
>
0
?
{
pageSize
}
:
false
}
pagination
=
{
pageSize
>
0
?
{
pageSize
}
:
false
}
/>
/>
{
/* Intermediate Result Modal */
}
{
/* Intermediate Result Modal */
}
...
@@ -458,7 +498,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
...
@@ -458,7 +498,14 @@ class TableList extends React.Component<TableListProps, TableListState> {
className
=
"titleColumn"
className
=
"titleColumn"
/>
/>
</
Modal
>
</
Modal
>
{
/* compare trials based message */
}
<
Compare
compareRows
=
{
selectRows
}
visible
=
{
isShowCompareModal
}
cancelFunc
=
{
this
.
hideCompareModal
}
/>
<
Compare
compareRows
=
{
selectRows
}
visible
=
{
isShowCompareModal
}
cancelFunc
=
{
this
.
hideCompareModal
}
/>
{
/* clone trial parameters and could submit a customized trial */
}
<
Customize
visible
=
{
isShowCustomizedModal
}
copyTrialId
=
{
copyTrialId
}
closeCustomizeModal
=
{
this
.
closeCustomizedTrial
}
/>
</
Row
>
</
Row
>
);
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment