learning-loop-node 0.10.13__py3-none-any.whl → 0.10.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of learning-loop-node might be problematic. Click here for more details.
- learning_loop_node/annotation/annotator_node.py +11 -10
- learning_loop_node/data_classes/detections.py +34 -26
- learning_loop_node/data_classes/general.py +27 -17
- learning_loop_node/data_exchanger.py +6 -5
- learning_loop_node/detector/detector_logic.py +3 -3
- learning_loop_node/detector/detector_node.py +21 -15
- learning_loop_node/detector/rest/about.py +34 -10
- learning_loop_node/detector/rest/backdoor_controls.py +9 -26
- learning_loop_node/detector/rest/detect.py +17 -16
- learning_loop_node/detector/rest/model_version_control.py +30 -13
- learning_loop_node/detector/rest/operation_mode.py +11 -5
- learning_loop_node/detector/rest/outbox_mode.py +7 -1
- learning_loop_node/node.py +93 -48
- learning_loop_node/rest.py +25 -2
- learning_loop_node/tests/detector/conftest.py +4 -4
- learning_loop_node/tests/detector/test_client_communication.py +21 -19
- learning_loop_node/tests/detector/test_detector_node.py +3 -3
- learning_loop_node/tests/trainer/conftest.py +4 -4
- learning_loop_node/tests/trainer/states/test_state_detecting.py +8 -9
- learning_loop_node/tests/trainer/states/test_state_download_train_model.py +8 -8
- learning_loop_node/tests/trainer/states/test_state_prepare.py +6 -7
- learning_loop_node/tests/trainer/states/test_state_sync_confusion_matrix.py +21 -18
- learning_loop_node/tests/trainer/states/test_state_train.py +6 -8
- learning_loop_node/tests/trainer/states/test_state_upload_detections.py +7 -9
- learning_loop_node/tests/trainer/states/test_state_upload_model.py +7 -8
- learning_loop_node/tests/trainer/test_errors.py +2 -2
- learning_loop_node/trainer/rest/backdoor_controls.py +19 -40
- learning_loop_node/trainer/trainer_logic_generic.py +7 -4
- learning_loop_node/trainer/trainer_node.py +4 -3
- {learning_loop_node-0.10.13.dist-info → learning_loop_node-0.10.14.dist-info}/METADATA +1 -1
- {learning_loop_node-0.10.13.dist-info → learning_loop_node-0.10.14.dist-info}/RECORD +32 -32
- {learning_loop_node-0.10.13.dist-info → learning_loop_node-0.10.14.dist-info}/WHEEL +0 -0
|
@@ -11,11 +11,9 @@ from ..testing_trainer_logic import TestingTrainerLogic
|
|
|
11
11
|
|
|
12
12
|
# pylint: disable=protected-access
|
|
13
13
|
|
|
14
|
-
error_key = 'sync_confusion_matrix'
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return trainer.errors.has_error_for(error_key)
|
|
15
|
+
def trainer_has_sync_confusion_matrix_error(trainer: TrainerLogic):
|
|
16
|
+
return trainer.errors.has_error_for('sync_confusion_matrix')
|
|
19
17
|
|
|
20
18
|
|
|
21
19
|
async def test_nothing_to_sync(test_initialized_trainer: TestingTrainerLogic):
|
|
@@ -26,10 +24,10 @@ async def test_nothing_to_sync(test_initialized_trainer: TestingTrainerLogic):
|
|
|
26
24
|
create_active_training_file(trainer, training_state=TrainerState.TrainingFinished)
|
|
27
25
|
trainer._init_from_last_training()
|
|
28
26
|
|
|
29
|
-
|
|
27
|
+
trainer._begin_training_task()
|
|
30
28
|
|
|
31
29
|
await assert_training_state(trainer.training, TrainerState.ConfusionMatrixSynced, timeout=1, interval=0.001)
|
|
32
|
-
assert
|
|
30
|
+
assert trainer_has_sync_confusion_matrix_error(trainer) is False
|
|
33
31
|
assert trainer.training.training_state == TrainerState.ConfusionMatrixSynced
|
|
34
32
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
35
33
|
|
|
@@ -38,16 +36,16 @@ async def test_unsynced_model_available__sync_successful(test_initialized_traine
|
|
|
38
36
|
trainer = test_initialized_trainer_node.trainer_logic
|
|
39
37
|
assert isinstance(trainer, TestingTrainerLogic)
|
|
40
38
|
|
|
41
|
-
await mock_socket_io_call(mocker, test_initialized_trainer_node, {'success': True})
|
|
39
|
+
await mock_socket_io_call(mocker, test_initialized_trainer_node, return_value={'success': True})
|
|
42
40
|
create_active_training_file(trainer, training_state=TrainerState.TrainingFinished)
|
|
43
41
|
|
|
44
42
|
trainer._init_from_last_training()
|
|
45
43
|
trainer.has_new_model = True
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
trainer._begin_training_task()
|
|
48
46
|
await assert_training_state(trainer.training, TrainerState.ConfusionMatrixSynced, timeout=1, interval=0.001)
|
|
49
47
|
|
|
50
|
-
assert
|
|
48
|
+
assert trainer_has_sync_confusion_matrix_error(trainer) is False
|
|
51
49
|
# assert trainer.training.training_state == TrainerState.ConfusionMatrixSynced
|
|
52
50
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
53
51
|
|
|
@@ -56,17 +54,19 @@ async def test_unsynced_model_available__sio_not_connected(test_initialized_trai
|
|
|
56
54
|
trainer = test_initialized_trainer_node.trainer_logic
|
|
57
55
|
assert isinstance(trainer, TestingTrainerLogic)
|
|
58
56
|
|
|
57
|
+
await test_initialized_trainer_node.sio_client.disconnect()
|
|
58
|
+
test_initialized_trainer_node.set_skip_repeat_loop(True)
|
|
59
59
|
create_active_training_file(trainer, training_state=TrainerState.TrainingFinished)
|
|
60
60
|
|
|
61
61
|
assert test_initialized_trainer_node.sio_client.connected is False
|
|
62
62
|
trainer.has_new_model = True
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
trainer._begin_training_task()
|
|
65
65
|
|
|
66
|
-
await assert_training_state(trainer.training,
|
|
67
|
-
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=
|
|
66
|
+
await assert_training_state(trainer.training, TrainerState.ConfusionMatrixSyncing, timeout=1, interval=0.001)
|
|
67
|
+
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=10, interval=0.001)
|
|
68
68
|
|
|
69
|
-
assert
|
|
69
|
+
assert trainer_has_sync_confusion_matrix_error(trainer) # Due to sio not being connected, the request will fail
|
|
70
70
|
assert trainer.training.training_state == TrainerState.TrainingFinished
|
|
71
71
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
72
72
|
|
|
@@ -75,17 +75,17 @@ async def test_unsynced_model_available__request_is_not_successful(test_initiali
|
|
|
75
75
|
trainer = test_initialized_trainer_node.trainer_logic
|
|
76
76
|
assert isinstance(trainer, TestingTrainerLogic)
|
|
77
77
|
|
|
78
|
-
await mock_socket_io_call(mocker, test_initialized_trainer_node, {'success': False})
|
|
78
|
+
await mock_socket_io_call(mocker, test_initialized_trainer_node, return_value={'success': False})
|
|
79
79
|
|
|
80
80
|
create_active_training_file(trainer, training_state=TrainerState.TrainingFinished)
|
|
81
81
|
|
|
82
82
|
trainer.has_new_model = True
|
|
83
|
-
|
|
83
|
+
trainer._begin_training_task()
|
|
84
84
|
|
|
85
|
-
await assert_training_state(trainer.training,
|
|
86
|
-
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=
|
|
85
|
+
await assert_training_state(trainer.training, TrainerState.ConfusionMatrixSyncing, timeout=1, interval=0.001)
|
|
86
|
+
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=10, interval=0.001)
|
|
87
87
|
|
|
88
|
-
assert
|
|
88
|
+
assert trainer_has_sync_confusion_matrix_error(trainer) # Due to sio call failure, the error will be set
|
|
89
89
|
assert trainer.training.training_state == TrainerState.TrainingFinished
|
|
90
90
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
91
91
|
|
|
@@ -100,6 +100,9 @@ async def test_basic_mock(test_initialized_trainer_node: TrainerNode, mocker: Mo
|
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
async def mock_socket_io_call(mocker, trainer_node: TrainerNode, return_value):
|
|
103
|
+
'''
|
|
104
|
+
Patch the socketio call function to always return the given return_value
|
|
105
|
+
'''
|
|
103
106
|
for _ in range(10):
|
|
104
107
|
if trainer_node.sio_client is None:
|
|
105
108
|
await asyncio.sleep(0.1)
|
|
@@ -14,10 +14,10 @@ async def test_successful_training(test_initialized_trainer: TestingTrainerLogic
|
|
|
14
14
|
create_active_training_file(trainer, training_state=TrainerState.TrainModelDownloaded)
|
|
15
15
|
trainer._init_from_last_training()
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
trainer._begin_training_task()
|
|
18
18
|
|
|
19
19
|
await condition(lambda: trainer._executor and trainer._executor.is_running(), timeout=1, interval=0.01)
|
|
20
|
-
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=
|
|
20
|
+
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=10, interval=0.01)
|
|
21
21
|
assert trainer.start_training_task is not None
|
|
22
22
|
|
|
23
23
|
assert trainer._executor is not None
|
|
@@ -34,16 +34,15 @@ async def test_stop_running_training(test_initialized_trainer: TestingTrainerLog
|
|
|
34
34
|
create_active_training_file(trainer, training_state=TrainerState.TrainModelDownloaded)
|
|
35
35
|
trainer._init_from_last_training()
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
trainer._begin_training_task()
|
|
38
38
|
|
|
39
39
|
await condition(lambda: trainer._executor and trainer._executor.is_running(), timeout=1, interval=0.01)
|
|
40
|
-
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=
|
|
40
|
+
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=10, interval=0.01)
|
|
41
41
|
assert trainer.start_training_task is not None
|
|
42
42
|
|
|
43
43
|
await trainer.stop()
|
|
44
44
|
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=2, interval=0.01)
|
|
45
45
|
|
|
46
|
-
assert trainer.training.training_state == TrainerState.TrainingFinished
|
|
47
46
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
48
47
|
|
|
49
48
|
|
|
@@ -55,15 +54,14 @@ async def test_training_can_maybe_resumed(test_initialized_trainer: TestingTrain
|
|
|
55
54
|
trainer._init_from_last_training()
|
|
56
55
|
trainer._can_resume_flag = True
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
trainer._begin_training_task()
|
|
59
58
|
|
|
60
59
|
await condition(lambda: trainer._executor and trainer._executor.is_running(), timeout=1, interval=0.01)
|
|
61
|
-
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=
|
|
60
|
+
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=10, interval=0.001)
|
|
62
61
|
assert trainer.start_training_task is not None
|
|
63
62
|
|
|
64
63
|
assert trainer._executor is not None
|
|
65
64
|
await trainer._executor.stop_and_wait() # NOTE normally a training terminates itself e.g
|
|
66
65
|
await assert_training_state(trainer.training, TrainerState.TrainingFinished, timeout=1, interval=0.001)
|
|
67
66
|
|
|
68
|
-
assert trainer.training.training_state == TrainerState.TrainingFinished
|
|
69
67
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
@@ -11,11 +11,10 @@ from ..state_helper import assert_training_state, create_active_training_file
|
|
|
11
11
|
from ..testing_trainer_logic import TestingTrainerLogic
|
|
12
12
|
|
|
13
13
|
# pylint: disable=protected-access
|
|
14
|
-
error_key = 'upload_detections'
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
def
|
|
18
|
-
return trainer.errors.has_error_for(
|
|
16
|
+
def trainer_has_upload_detections_error(trainer: TrainerLogic):
|
|
17
|
+
return trainer.errors.has_error_for('upload_detections')
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
async def create_valid_detection_file(trainer: TrainerLogic, number_of_entries: int = 1, file_index: int = 0):
|
|
@@ -125,12 +124,11 @@ async def test_bad_status_from_LearningLoop(test_initialized_trainer: TestingTra
|
|
|
125
124
|
trainer._init_from_last_training()
|
|
126
125
|
trainer.active_training_io.save_detections([get_dummy_detections()])
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
trainer._begin_training_task()
|
|
129
128
|
await assert_training_state(trainer.training, TrainerState.DetectionUploading, timeout=1, interval=0.001)
|
|
130
|
-
await assert_training_state(trainer.training, TrainerState.Detected, timeout=
|
|
129
|
+
await assert_training_state(trainer.training, TrainerState.Detected, timeout=10, interval=0.001)
|
|
131
130
|
|
|
132
|
-
assert
|
|
133
|
-
assert trainer.training.training_state == TrainerState.Detected
|
|
131
|
+
assert trainer_has_upload_detections_error(trainer)
|
|
134
132
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
135
133
|
|
|
136
134
|
|
|
@@ -143,7 +141,7 @@ async def test_go_to_cleanup_if_no_detections_exist(test_initialized_trainer: Te
|
|
|
143
141
|
create_active_training_file(trainer, training_state=TrainerState.Detected)
|
|
144
142
|
trainer._init_from_last_training()
|
|
145
143
|
|
|
146
|
-
|
|
144
|
+
trainer._begin_training_task()
|
|
147
145
|
await assert_training_state(trainer.training, TrainerState.ReadyForCleanup, timeout=1, interval=0.001)
|
|
148
146
|
|
|
149
147
|
|
|
@@ -154,7 +152,7 @@ async def test_abort_uploading(test_initialized_trainer: TestingTrainerLogic):
|
|
|
154
152
|
trainer._init_from_last_training()
|
|
155
153
|
await create_valid_detection_file(trainer)
|
|
156
154
|
|
|
157
|
-
|
|
155
|
+
trainer._begin_training_task()
|
|
158
156
|
|
|
159
157
|
await assert_training_state(trainer.training, TrainerState.DetectionUploading, timeout=1, interval=0.001)
|
|
160
158
|
|
|
@@ -8,11 +8,10 @@ from ..state_helper import assert_training_state, create_active_training_file
|
|
|
8
8
|
from ..testing_trainer_logic import TestingTrainerLogic
|
|
9
9
|
|
|
10
10
|
# pylint: disable=protected-access
|
|
11
|
-
error_key = 'upload_model'
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
def
|
|
15
|
-
return trainer.errors.has_error_for(
|
|
13
|
+
def trainer_has_upload_model_error(trainer: TrainerLogic):
|
|
14
|
+
return trainer.errors.has_error_for('upload_model')
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
async def test_successful_upload(mocker: MockerFixture, test_initialized_trainer: TestingTrainerLogic):
|
|
@@ -28,7 +27,7 @@ async def test_successful_upload(mocker: MockerFixture, test_initialized_trainer
|
|
|
28
27
|
await assert_training_state(trainer.training, TrainerState.TrainModelUploading, timeout=1, interval=0.001)
|
|
29
28
|
await train_task
|
|
30
29
|
|
|
31
|
-
assert
|
|
30
|
+
assert trainer_has_upload_model_error(trainer) is False
|
|
32
31
|
assert trainer.training.training_state == TrainerState.TrainModelUploaded
|
|
33
32
|
assert trainer.training.model_uuid_for_detecting is not None
|
|
34
33
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
@@ -40,7 +39,7 @@ async def test_abort_upload_model(test_initialized_trainer: TestingTrainerLogic)
|
|
|
40
39
|
create_active_training_file(trainer, training_state=TrainerState.ConfusionMatrixSynced)
|
|
41
40
|
trainer._init_from_last_training()
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
trainer._begin_training_task()
|
|
44
43
|
|
|
45
44
|
await assert_training_state(trainer.training, TrainerState.TrainModelUploading, timeout=1, interval=0.001)
|
|
46
45
|
|
|
@@ -60,13 +59,13 @@ async def test_bad_server_response_content(test_initialized_trainer: TestingTrai
|
|
|
60
59
|
create_active_training_file(trainer, training_state=TrainerState.ConfusionMatrixSynced)
|
|
61
60
|
trainer._init_from_last_training()
|
|
62
61
|
|
|
63
|
-
|
|
62
|
+
trainer._begin_training_task()
|
|
64
63
|
|
|
65
64
|
await assert_training_state(trainer.training, TrainerState.TrainModelUploading, timeout=1, interval=0.001)
|
|
66
65
|
# TODO goes to finished because of the error
|
|
67
|
-
await assert_training_state(trainer.training, TrainerState.ReadyForCleanup, timeout=
|
|
66
|
+
await assert_training_state(trainer.training, TrainerState.ReadyForCleanup, timeout=10, interval=0.001)
|
|
68
67
|
|
|
69
|
-
assert
|
|
68
|
+
assert trainer_has_upload_model_error(trainer)
|
|
70
69
|
assert trainer.training.training_state == TrainerState.ReadyForCleanup
|
|
71
70
|
assert trainer.training.model_uuid_for_detecting is None
|
|
72
71
|
assert trainer.node.last_training_io.load() == trainer.training
|
|
@@ -14,7 +14,7 @@ async def test_training_process_is_stopped_when_trainer_reports_error(test_initi
|
|
|
14
14
|
trainer = test_initialized_trainer
|
|
15
15
|
create_active_training_file(trainer, training_state=TrainerState.TrainModelDownloaded)
|
|
16
16
|
trainer._init_from_last_training()
|
|
17
|
-
|
|
17
|
+
trainer._begin_training_task()
|
|
18
18
|
|
|
19
19
|
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=1, interval=0.001)
|
|
20
20
|
trainer.error_msg = 'some_error'
|
|
@@ -26,7 +26,7 @@ async def test_log_can_provide_only_data_for_current_run(test_initialized_traine
|
|
|
26
26
|
trainer = test_initialized_trainer
|
|
27
27
|
create_active_training_file(trainer, training_state=TrainerState.TrainModelDownloaded)
|
|
28
28
|
trainer._init_from_last_training()
|
|
29
|
-
|
|
29
|
+
trainer._begin_training_task()
|
|
30
30
|
|
|
31
31
|
await assert_training_state(trainer.training, TrainerState.TrainingRunning, timeout=1, interval=0.001)
|
|
32
32
|
await asyncio.sleep(0.1) # give tests a bit time to to check for the state
|
|
@@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Dict
|
|
|
7
7
|
|
|
8
8
|
from fastapi import APIRouter, HTTPException, Request
|
|
9
9
|
|
|
10
|
-
from ...data_classes import ErrorConfiguration
|
|
10
|
+
from ...data_classes import ErrorConfiguration
|
|
11
11
|
from ..trainer_logic import TrainerLogic
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
@@ -16,32 +16,10 @@ if TYPE_CHECKING:
|
|
|
16
16
|
router = APIRouter()
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
@router.put("/socketio")
|
|
20
|
-
async def switch_socketio(request: Request):
|
|
21
|
-
'''
|
|
22
|
-
Example Usage
|
|
23
|
-
|
|
24
|
-
curl -X PUT -d "on" http://localhost:8001/socketio
|
|
25
|
-
'''
|
|
26
|
-
state = str(await request.body(), 'utf-8')
|
|
27
|
-
await _switch_socketio(state, request.app)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
async def _switch_socketio(state: str, trainer_node: TrainerNode):
|
|
31
|
-
if state == 'off':
|
|
32
|
-
if trainer_node.status.state != NodeState.Offline:
|
|
33
|
-
logging.debug('turning socketio off')
|
|
34
|
-
await trainer_node.sio_client.disconnect() # pylint: disable=protected-access
|
|
35
|
-
if state == 'on':
|
|
36
|
-
if trainer_node.status.state == NodeState.Offline:
|
|
37
|
-
logging.debug('turning socketio on')
|
|
38
|
-
await trainer_node.connect_sio()
|
|
39
|
-
|
|
40
|
-
|
|
41
19
|
@router.put("/provide_new_model")
|
|
42
20
|
async def provide_new_model(request: Request):
|
|
43
21
|
value = str(await request.body(), 'utf-8')
|
|
44
|
-
trainer_node =
|
|
22
|
+
trainer_node = request.app
|
|
45
23
|
# trainer_logic is MockTrainerLogic which has a property provide_new_model
|
|
46
24
|
assert hasattr(trainer_node.trainer_logic,
|
|
47
25
|
'provide_new_model'), 'trainer_logic does not have property provide_new_model'
|
|
@@ -56,17 +34,22 @@ async def provide_new_model(request: Request):
|
|
|
56
34
|
|
|
57
35
|
@router.post("/reset")
|
|
58
36
|
async def reset(request: Request):
|
|
59
|
-
|
|
60
|
-
|
|
37
|
+
logging.info('BC: reset')
|
|
38
|
+
trainer_node: 'TrainerNode' = request.app
|
|
39
|
+
async with trainer_node.repeat_loop_lock:
|
|
61
40
|
|
|
62
|
-
|
|
63
|
-
|
|
41
|
+
await trainer_node.trainer_logic.stop() # NOTE first stop may only kill running training process
|
|
42
|
+
await trainer_node.trainer_logic.stop()
|
|
43
|
+
trainer_node.last_training_io.delete()
|
|
44
|
+
trainer_node.status.reset_all_errors()
|
|
64
45
|
|
|
65
|
-
|
|
46
|
+
try:
|
|
47
|
+
await trainer_node.reconnect_to_loop()
|
|
48
|
+
except Exception:
|
|
49
|
+
logging.exception('Could not reset sio connection to loop')
|
|
66
50
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
await trainer_node.send_status()
|
|
51
|
+
logging.info('training should be killed, sending new state to LearningLoop')
|
|
52
|
+
await trainer_node.send_status()
|
|
70
53
|
|
|
71
54
|
|
|
72
55
|
@router.put("/error_configuration")
|
|
@@ -82,7 +65,7 @@ def set_error_configuration(msg: Dict, request: Request):
|
|
|
82
65
|
save_model=msg.get('save_model', None), )
|
|
83
66
|
|
|
84
67
|
logging.info(f'setting error configuration to: {asdict(error_configuration)}')
|
|
85
|
-
trainer_logic =
|
|
68
|
+
trainer_logic = request.app.trainer_logic
|
|
86
69
|
|
|
87
70
|
# NOTE: trainer_logic is MockTrainerLogic which has a property error_configuration
|
|
88
71
|
assert hasattr(trainer_logic, 'error_configuration'), 'trainer_logic does not have property error_configuration'
|
|
@@ -92,7 +75,7 @@ def set_error_configuration(msg: Dict, request: Request):
|
|
|
92
75
|
@router.post("/steps")
|
|
93
76
|
async def add_steps(request: Request):
|
|
94
77
|
logging.warning('Steps was called')
|
|
95
|
-
trainer_node =
|
|
78
|
+
trainer_node = request.app
|
|
96
79
|
trainer_logic = trainer_node.trainer_logic # NOTE: is MockTrainerLogic which has 'provide_new_model' and 'current_iteration'
|
|
97
80
|
|
|
98
81
|
assert isinstance(trainer_logic, TrainerLogic), 'trainer_logic is not TrainerLogic'
|
|
@@ -123,7 +106,7 @@ async def add_steps(request: Request):
|
|
|
123
106
|
async def kill_process(request: Request):
|
|
124
107
|
|
|
125
108
|
# pylint: disable=protected-access
|
|
126
|
-
trainer_node =
|
|
109
|
+
trainer_node = request.app
|
|
127
110
|
trainer_logic = trainer_node.trainer_logic
|
|
128
111
|
assert isinstance(trainer_logic, TrainerLogic), 'trainer_logic is not TrainerLogic'
|
|
129
112
|
if not trainer_logic._executor or not trainer_logic._executor.is_running():
|
|
@@ -133,9 +116,5 @@ async def kill_process(request: Request):
|
|
|
133
116
|
|
|
134
117
|
@router.post("/force_status_update")
|
|
135
118
|
async def force_status_update(request: Request):
|
|
136
|
-
trainer_node =
|
|
119
|
+
trainer_node = request.app
|
|
137
120
|
await trainer_node.send_status()
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def trainer_node_from_request(request: Request) -> TrainerNode:
|
|
141
|
-
return request.app
|
|
@@ -179,7 +179,7 @@ class TrainerLogicGeneric(ABC):
|
|
|
179
179
|
if not self.training_active and self.last_training_io.exists():
|
|
180
180
|
self._init_from_last_training()
|
|
181
181
|
logger.info('found incomplete training, continuing now.')
|
|
182
|
-
|
|
182
|
+
self._begin_training_task()
|
|
183
183
|
return True
|
|
184
184
|
return False
|
|
185
185
|
|
|
@@ -195,7 +195,11 @@ class TrainerLogicGeneric(ABC):
|
|
|
195
195
|
"""Called on `begin_training` event from the Learning Loop.
|
|
196
196
|
"""
|
|
197
197
|
self._init_new_training(Context(organization=organization, project=project), details)
|
|
198
|
-
|
|
198
|
+
self._begin_training_task()
|
|
199
|
+
|
|
200
|
+
def _begin_training_task(self) -> None:
|
|
201
|
+
# NOTE: Task object is used to potentially cancel the task
|
|
202
|
+
self.training_task = asyncio.get_event_loop().create_task(self._run())
|
|
199
203
|
|
|
200
204
|
def _init_new_training(self, context: Context, details: Dict) -> None:
|
|
201
205
|
"""Called on `begin_training` event from the Learning Loop.
|
|
@@ -218,8 +222,7 @@ class TrainerLogicGeneric(ABC):
|
|
|
218
222
|
"""
|
|
219
223
|
self.errors.reset_all()
|
|
220
224
|
try:
|
|
221
|
-
|
|
222
|
-
await self.training_task # NOTE: Task object is used to potentially cancel the task
|
|
225
|
+
await self._training_loop()
|
|
223
226
|
except asyncio.CancelledError:
|
|
224
227
|
if not self.shutdown_event.is_set():
|
|
225
228
|
logger.info('CancelledError in _run - training task was cancelled but not by shutdown event')
|
|
@@ -77,7 +77,7 @@ class TrainerNode(Node):
|
|
|
77
77
|
|
|
78
78
|
async def send_status(self):
|
|
79
79
|
if not self.sio_client.connected:
|
|
80
|
-
self.log.
|
|
80
|
+
self.log.debug('cannot send status - not connected to the Learning Loop')
|
|
81
81
|
return
|
|
82
82
|
|
|
83
83
|
status = TrainingStatus(id=self.uuid,
|
|
@@ -98,10 +98,11 @@ class TrainerNode(Node):
|
|
|
98
98
|
status.errors = self.trainer_logic.errors.errors
|
|
99
99
|
status.context = self.trainer_logic.training_context
|
|
100
100
|
|
|
101
|
-
self.log.
|
|
101
|
+
self.log.debug('sending status: %s', status.short_str())
|
|
102
102
|
result = await self.sio_client.call('update_trainer', jsonable_encoder(asdict(status)), timeout=30)
|
|
103
103
|
if isinstance(result, Dict) and not result['success']:
|
|
104
|
-
self.
|
|
104
|
+
self.socket_connection_broken = True
|
|
105
|
+
self.log.error('Error when sending status update: Response from loop was:\n %s', result)
|
|
105
106
|
|
|
106
107
|
def check_idle_timeout(self):
|
|
107
108
|
if not self.idle_timeout:
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
learning_loop_node/__init__.py,sha256=onN5s8-x_xBsCM6NLmJO0Ym1sJHeCFaGw8qb0oQZmz8,364
|
|
2
2
|
learning_loop_node/annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
learning_loop_node/annotation/annotator_logic.py,sha256=BTaopkJZkIf1CI5lfsVKsxbxoUIbDJrevavuQUT5e_c,1000
|
|
4
|
-
learning_loop_node/annotation/annotator_node.py,sha256=
|
|
4
|
+
learning_loop_node/annotation/annotator_node.py,sha256=UrJ8MpZ44UhsjmVuSHr2BhHyLC-kIMDi3IuBBMKzN1g,4117
|
|
5
5
|
learning_loop_node/data_classes/__init__.py,sha256=wCX88lDgbb8V-gtVCVe9i-NvvZuMe5FX7eD_UJgYYXw,1305
|
|
6
6
|
learning_loop_node/data_classes/annotations.py,sha256=iInU0Nuy_oYT_sj4k_n-W0UShCBI2cHQYrt8imymbtM,1211
|
|
7
|
-
learning_loop_node/data_classes/detections.py,sha256=
|
|
8
|
-
learning_loop_node/data_classes/general.py,sha256=
|
|
7
|
+
learning_loop_node/data_classes/detections.py,sha256=hifsGz2LbmeKLZdHxG7cnlOYNEqDmtJd2gxhyU-Xjjs,5811
|
|
8
|
+
learning_loop_node/data_classes/general.py,sha256=usXokcTOVqTuaKJtBf0ffFWfzZhMrQtF7puKfwi6A5k,6195
|
|
9
9
|
learning_loop_node/data_classes/socket_response.py,sha256=tIdt-oYf6ULoJIDYQCecNM9OtWR6_wJ9tL0Ksu83Vko,655
|
|
10
10
|
learning_loop_node/data_classes/training.py,sha256=hnMHZMk-WNRERyo7U97qL09v1tIdhnzPfTH-JgifLwU,6164
|
|
11
|
-
learning_loop_node/data_exchanger.py,sha256=
|
|
11
|
+
learning_loop_node/data_exchanger.py,sha256=mwZvJf8L1-r6Wi2ZvDfFf4kFjkqxsThXj7AGLUANGlU,8979
|
|
12
12
|
learning_loop_node/detector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
-
learning_loop_node/detector/detector_logic.py,sha256=
|
|
14
|
-
learning_loop_node/detector/detector_node.py,sha256=
|
|
13
|
+
learning_loop_node/detector/detector_logic.py,sha256=IG1s9RF_cCBcNQ8WW1rAS37QKdGzlVoVkuO_CrLGvYs,2084
|
|
14
|
+
learning_loop_node/detector/detector_node.py,sha256=TeChzkpVVmEiZbnfWmtkjuUXNwCZvIWfingmcuAz2cs,19567
|
|
15
15
|
learning_loop_node/detector/inbox_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
learning_loop_node/detector/inbox_filter/cam_observation_history.py,sha256=TD346I9ymtIP0_CJXCIKMRuiXbfVVanXNu_iHAwDd7Q,3318
|
|
17
17
|
learning_loop_node/detector/inbox_filter/relevance_filter.py,sha256=7_-x8D8Zf6KJeJXmiC2VrRHU8Ig_R98uhdXVwwX0N4M,1240
|
|
18
18
|
learning_loop_node/detector/outbox.py,sha256=HrYeS6XJLC-1kqq2hDufxXLRmOYGiBlz-m9B6HG5Ie8,8227
|
|
19
19
|
learning_loop_node/detector/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
learning_loop_node/detector/rest/about.py,sha256=
|
|
21
|
-
learning_loop_node/detector/rest/backdoor_controls.py,sha256=
|
|
22
|
-
learning_loop_node/detector/rest/detect.py,sha256=
|
|
23
|
-
learning_loop_node/detector/rest/model_version_control.py,sha256=
|
|
24
|
-
learning_loop_node/detector/rest/operation_mode.py,sha256=
|
|
25
|
-
learning_loop_node/detector/rest/outbox_mode.py,sha256=
|
|
20
|
+
learning_loop_node/detector/rest/about.py,sha256=COYgmYO1tXGSIwjF__P79mVZUfSDZoHsW0GUarQ2rv0,1686
|
|
21
|
+
learning_loop_node/detector/rest/backdoor_controls.py,sha256=ZNaFOvC0OLWNtcLiG-NIqS_y1kkLP4csgk3CHhp8Gis,885
|
|
22
|
+
learning_loop_node/detector/rest/detect.py,sha256=KSYUOuTxuc2q3RgV37cBBuCvCJf11BFL7QtnPAM4XbU,2343
|
|
23
|
+
learning_loop_node/detector/rest/model_version_control.py,sha256=jLp3rvCYq8T_QC3KK7uLDYpbDjydwazWkQCUXvkxl-c,4654
|
|
24
|
+
learning_loop_node/detector/rest/operation_mode.py,sha256=RAzVLtGzy4n9-LSIq_XSwMfXDehU4XmorgWAWbQ6BW8,1804
|
|
25
|
+
learning_loop_node/detector/rest/outbox_mode.py,sha256=H8coDNbgLGEfXmKQrhtXWeUHBAHpnrdZktuHXQz0xis,1148
|
|
26
26
|
learning_loop_node/detector/rest/upload.py,sha256=IPzxJPayD7_Gx5uYC1lVJwWxdnQgM8MYGa5NugXVosY,544
|
|
27
27
|
learning_loop_node/examples/novelty_score_updater.py,sha256=1DRgM9lxjFV-q2JvGDDsNLz_ic_rhEZ9wc6ZdjcxwPE,2038
|
|
28
28
|
learning_loop_node/globals.py,sha256=tgw_8RYOipPV9aYlyUhYtXfUxvJKRvfUk6u-qVAtZmY,174
|
|
@@ -32,24 +32,24 @@ learning_loop_node/helpers/gdrive_downloader.py,sha256=zeYJciTAJVRpu_eFjwgYLCpIa
|
|
|
32
32
|
learning_loop_node/helpers/log_conf.py,sha256=z_0PHh7U7DkJbSbKoSPyUfS7NhBHtRxXHdNcj67Hpbc,951
|
|
33
33
|
learning_loop_node/helpers/misc.py,sha256=j4is8Rv0ttnCqF-R-wP3xwEi67OI6IBJav5Woo5lyDk,7701
|
|
34
34
|
learning_loop_node/loop_communication.py,sha256=rG5MdavSTaREZ6OWfAUIT_qkkYPw3is2_FujLmHQeIc,6576
|
|
35
|
-
learning_loop_node/node.py,sha256=
|
|
35
|
+
learning_loop_node/node.py,sha256=7Xc6VM_Rk1yDKDjKoUjoY4gSsC1zokjt5YQJu0PP5ao,9931
|
|
36
36
|
learning_loop_node/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
learning_loop_node/rest.py,sha256=
|
|
37
|
+
learning_loop_node/rest.py,sha256=o1dl4Mtznd5duyEQtCYSGlK04l1Y-p_YRjG40Q4l31c,1491
|
|
38
38
|
learning_loop_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
39
|
learning_loop_node/tests/annotator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
40
|
learning_loop_node/tests/annotator/conftest.py,sha256=G4ZvdZUdvPp9bYCzg3eEVkGCeXn9INZ3AcN7d5CyLkU,1931
|
|
41
41
|
learning_loop_node/tests/annotator/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
|
|
42
42
|
learning_loop_node/tests/annotator/test_annotator_node.py,sha256=TPNPPrQAxQ_zEecQcH7hlczgD3ABtTCNtUvWD1_oApk,1985
|
|
43
43
|
learning_loop_node/tests/detector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
-
learning_loop_node/tests/detector/conftest.py,sha256=
|
|
44
|
+
learning_loop_node/tests/detector/conftest.py,sha256=Q14KHTSuSCsASVIxY9CttdVJm5FC7_JH-W5Q4CdDqoM,5414
|
|
45
45
|
learning_loop_node/tests/detector/inbox_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
46
46
|
learning_loop_node/tests/detector/inbox_filter/test_observation.py,sha256=k4WYdvnuV7d_r7zI4M2aA8WuBjm0aycQ0vj1rGE2q4w,1370
|
|
47
47
|
learning_loop_node/tests/detector/inbox_filter/test_relevance_group.py,sha256=XjiMsS0LgvM0OkPf5-s2rjFbG7C42LTmz_rDVMGHKoY,7603
|
|
48
48
|
learning_loop_node/tests/detector/inbox_filter/test_unexpected_observations_count.py,sha256=MWC7PbaCy14jjRw0_oilkXj6gymAsUZXHJdzNW5m2D4,1639
|
|
49
49
|
learning_loop_node/tests/detector/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
|
|
50
50
|
learning_loop_node/tests/detector/test.jpg,sha256=msA-vHPmvPiro_D102Qmn1fn4vNfooqYYEXPxZUmYpk,161390
|
|
51
|
-
learning_loop_node/tests/detector/test_client_communication.py,sha256=
|
|
52
|
-
learning_loop_node/tests/detector/test_detector_node.py,sha256=
|
|
51
|
+
learning_loop_node/tests/detector/test_client_communication.py,sha256=NAOUrHWxoI4yG6oy3BGxWWXX794IOODEj9QBKF3CyrY,9375
|
|
52
|
+
learning_loop_node/tests/detector/test_detector_node.py,sha256=KX2RcFpdIbpPEmcyYM0YMs-6wwTpbOOZONoiwIWryUI,2922
|
|
53
53
|
learning_loop_node/tests/detector/test_outbox.py,sha256=5RMKQfuu1-rvpVCpEtt_D70bYgma-sIrTHWxHdTdU9Y,3001
|
|
54
54
|
learning_loop_node/tests/detector/test_relevance_filter.py,sha256=3VLhHKaxPzLYmiNZagvgg9ZHkPhWk4_-qpmkJw36wBU,2046
|
|
55
55
|
learning_loop_node/tests/detector/testing_detector.py,sha256=FeQroV85IvsT8dmalQBqf1FLNt_buCtZK3-lgtmbrBI,542
|
|
@@ -64,19 +64,19 @@ learning_loop_node/tests/general/test_downloader.py,sha256=C6b_wG3TfQX53lmuanpH1
|
|
|
64
64
|
learning_loop_node/tests/general/test_learning_loop_node.py,sha256=SZd-VChpWnnsPN46pr4E_LL3ZevYx6psU-AWdVeOFpQ,770
|
|
65
65
|
learning_loop_node/tests/test_helper.py,sha256=nTynYtuUaK2hKh87pk7t7AIJaOiD3wJ5d6nCPqnwRMk,3012
|
|
66
66
|
learning_loop_node/tests/trainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
|
-
learning_loop_node/tests/trainer/conftest.py,sha256=
|
|
67
|
+
learning_loop_node/tests/trainer/conftest.py,sha256=E3SQL_CGFJ_sNjEfVJbxbvH0g6hjI5753ndAFUbnkQk,3366
|
|
68
68
|
learning_loop_node/tests/trainer/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
|
|
69
69
|
learning_loop_node/tests/trainer/state_helper.py,sha256=MDe9opeKruip74FoRFff8MSWGiQNFqDpPtIEIbgPnFc,919
|
|
70
70
|
learning_loop_node/tests/trainer/states/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
71
|
learning_loop_node/tests/trainer/states/test_state_cleanup.py,sha256=gZNxSSwnj9f0esExNnQzqadM6-sE3IsF5sNbD0bZNu8,1250
|
|
72
|
-
learning_loop_node/tests/trainer/states/test_state_detecting.py,sha256=
|
|
73
|
-
learning_loop_node/tests/trainer/states/test_state_download_train_model.py,sha256=
|
|
74
|
-
learning_loop_node/tests/trainer/states/test_state_prepare.py,sha256=
|
|
75
|
-
learning_loop_node/tests/trainer/states/test_state_sync_confusion_matrix.py,sha256=
|
|
76
|
-
learning_loop_node/tests/trainer/states/test_state_train.py,sha256=
|
|
77
|
-
learning_loop_node/tests/trainer/states/test_state_upload_detections.py,sha256=
|
|
78
|
-
learning_loop_node/tests/trainer/states/test_state_upload_model.py,sha256=
|
|
79
|
-
learning_loop_node/tests/trainer/test_errors.py,sha256=
|
|
72
|
+
learning_loop_node/tests/trainer/states/test_state_detecting.py,sha256=KGXTR69J_1pJoT8S0ceC3vSyHLw52mIpjbawH4c-8JA,3696
|
|
73
|
+
learning_loop_node/tests/trainer/states/test_state_download_train_model.py,sha256=AuTY63sgrlKT0awS6o38fF3mTkDguAFJtcX7J7WhjgQ,2855
|
|
74
|
+
learning_loop_node/tests/trainer/states/test_state_prepare.py,sha256=3hzRo9ycM802QUZO2Zs_rJRZ23hxTi3XjRCwL9M9m9o,2315
|
|
75
|
+
learning_loop_node/tests/trainer/states/test_state_sync_confusion_matrix.py,sha256=6s4A2d5ahD9UJJiHGK1VtmOrhumzuqTlOwyc_8Oc1vk,5073
|
|
76
|
+
learning_loop_node/tests/trainer/states/test_state_train.py,sha256=HYe1O6zcdtD4dnmfX3cyM1_iF7eGig7dQI4M4Xat7YU,2916
|
|
77
|
+
learning_loop_node/tests/trainer/states/test_state_upload_detections.py,sha256=0Qkavl4i2tZmCOxKkNsQUqa1JWhAgcOsbrW3_eYHfxo,7417
|
|
78
|
+
learning_loop_node/tests/trainer/states/test_state_upload_model.py,sha256=y2o4WBo7kBG_JWSWmt4icjrwya5hQ30zCWC-YMVEwEk,3621
|
|
79
|
+
learning_loop_node/tests/trainer/test_errors.py,sha256=khWCTzi-JW4nSz9QnsRh9wDPmiuE_zdxXukh59qixuY,2109
|
|
80
80
|
learning_loop_node/tests/trainer/test_trainer_states.py,sha256=djYCs5ieajQHRjk8QcUVBUkQEG8UGYFoNGwSX0z2oGk,1067
|
|
81
81
|
learning_loop_node/tests/trainer/testing_trainer_logic.py,sha256=KslqDJDntkgH4Yd_z-guiVPvzi5Q-l-Bqc3fUjT5N7U,3883
|
|
82
82
|
learning_loop_node/trainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -85,11 +85,11 @@ learning_loop_node/trainer/exceptions.py,sha256=hLLDGncC6PLZjKg4lZBpu-QA8itQIxiu
|
|
|
85
85
|
learning_loop_node/trainer/executor.py,sha256=-0BxDqmAI1NCiISi7Rw8McJQfgxxVy1gSa1epYuL3U0,3942
|
|
86
86
|
learning_loop_node/trainer/io_helpers.py,sha256=hGEtNAQBSBbVB56U1ndwfP8qK5K4YIwMQrjCDcaMy9I,7218
|
|
87
87
|
learning_loop_node/trainer/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
|
-
learning_loop_node/trainer/rest/backdoor_controls.py,sha256
|
|
88
|
+
learning_loop_node/trainer/rest/backdoor_controls.py,sha256=-pU4iHheBWf0SW2QzBVBsLiCMZBRz9CDdVZv6414Ts8,5134
|
|
89
89
|
learning_loop_node/trainer/test_executor.py,sha256=6BVGDN_6f5GEMMEvDLSG1yzMybSvgXaP5uYpSfsVPP0,2224
|
|
90
90
|
learning_loop_node/trainer/trainer_logic.py,sha256=PlYExIskU9pWJO0e9m_0KJnUdOI10GtW0oDOevYmg1o,8461
|
|
91
|
-
learning_loop_node/trainer/trainer_logic_generic.py,sha256=
|
|
92
|
-
learning_loop_node/trainer/trainer_node.py,sha256=
|
|
93
|
-
learning_loop_node-0.10.
|
|
94
|
-
learning_loop_node-0.10.
|
|
95
|
-
learning_loop_node-0.10.
|
|
91
|
+
learning_loop_node/trainer/trainer_logic_generic.py,sha256=dVsvl1LC1w3svl4O8HCW49R7vSpVpC9Ermu4C20sFoA,25821
|
|
92
|
+
learning_loop_node/trainer/trainer_node.py,sha256=8ANS9iy-swdTLvt9wEFixE6YlmqvqBl17A-R4tVYD-I,5384
|
|
93
|
+
learning_loop_node-0.10.14.dist-info/METADATA,sha256=RHHVhHfTIPjxY5lO3UsR6L7BbHzwXs9wch4WJzePXJQ,11907
|
|
94
|
+
learning_loop_node-0.10.14.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
|
|
95
|
+
learning_loop_node-0.10.14.dist-info/RECORD,,
|
|
File without changes
|