synapse-sdk 1.0.0a1__tar.gz → 1.0.0a3__tar.gz
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 synapse-sdk might be problematic. Click here for more details.
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/PKG-INFO +1 -1
- synapse_sdk-1.0.0a3/synapse_sdk/clients/agent/__init__.py +21 -0
- synapse_sdk-1.0.0a3/synapse_sdk/clients/agent/service.py +54 -0
- synapse_sdk-1.0.0a3/synapse_sdk/clients/backend/__init__.py +22 -0
- synapse_sdk-1.0.0a3/synapse_sdk/clients/backend/annotation.py +29 -0
- {synapse_sdk-1.0.0a1/synapse_sdk/client/mixins → synapse_sdk-1.0.0a3/synapse_sdk/clients/backend}/dataset.py +6 -4
- synapse_sdk-1.0.0a3/synapse_sdk/clients/backend/integration.py +47 -0
- synapse_sdk-1.0.0a3/synapse_sdk/clients/backend/ml.py +24 -0
- synapse_sdk-1.0.0a1/synapse_sdk/client/__init__.py → synapse_sdk-1.0.0a3/synapse_sdk/clients/base.py +22 -30
- {synapse_sdk-1.0.0a1/synapse_sdk/client → synapse_sdk-1.0.0a3/synapse_sdk/clients}/exceptions.py +0 -8
- synapse_sdk-1.0.0a3/synapse_sdk/loggers.py +52 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/base.py +58 -35
- synapse_sdk-1.0.0a3/synapse_sdk/plugins/categories/neural_net/actions/train.py +37 -0
- synapse_sdk-1.0.0a3/synapse_sdk/plugins/cli/publish.py +36 -0
- synapse_sdk-1.0.0a3/synapse_sdk/plugins/cli/run.py +64 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/upload.py +11 -1
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/storage.py +1 -2
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk.egg-info/PKG-INFO +1 -1
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk.egg-info/SOURCES.txt +11 -9
- synapse_sdk-1.0.0a1/synapse_sdk/client/mixins/annotation.py +0 -28
- synapse_sdk-1.0.0a1/synapse_sdk/client/mixins/integration.py +0 -29
- synapse_sdk-1.0.0a1/synapse_sdk/client/mixins/ml.py +0 -23
- synapse_sdk-1.0.0a1/synapse_sdk/config.py +0 -8
- synapse_sdk-1.0.0a1/synapse_sdk/loggers.py +0 -48
- synapse_sdk-1.0.0a1/synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -96
- synapse_sdk-1.0.0a1/synapse_sdk/plugins/cli/publish.py +0 -24
- synapse_sdk-1.0.0a1/synapse_sdk/plugins/cli/run.py +0 -18
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/.github/workflows/lint.yml +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/.github/workflows/pypi-publish.yml +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/.gitignore +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/.pre-commit-config.yaml +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/LICENSE +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/README.md +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/pyproject.toml +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/requirements.txt +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/setup.cfg +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/__init__.py +0 -0
- {synapse_sdk-1.0.0a1/synapse_sdk/client/mixins → synapse_sdk-1.0.0a3/synapse_sdk/clients}/__init__.py +0 -0
- {synapse_sdk-1.0.0a1/synapse_sdk/client → synapse_sdk-1.0.0a3/synapse_sdk/clients}/utils.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/decorators.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/export/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/export/actions/export.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/import/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/import/actions/import.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/registry.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/cli/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/enums.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/job.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/utils.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/__init__.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/debug.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/file.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/module_loading.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/utils/string.py +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk.egg-info/dependency_links.txt +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk.egg-info/requires.txt +0 -0
- {synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from synapse_sdk.clients.agent.service import ServiceClientMixin
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AgentClient(ServiceClientMixin):
|
|
5
|
+
name = 'Agent'
|
|
6
|
+
agent_token = None
|
|
7
|
+
user_token = None
|
|
8
|
+
tenant = None
|
|
9
|
+
|
|
10
|
+
def __init__(self, base_url, agent_token, user_token, tenant):
|
|
11
|
+
super().__init__(base_url)
|
|
12
|
+
self.agent_token = agent_token
|
|
13
|
+
self.user_token = user_token
|
|
14
|
+
self.tenant = tenant
|
|
15
|
+
|
|
16
|
+
def _get_headers(self):
|
|
17
|
+
return {
|
|
18
|
+
'Authorization': self.agent_token,
|
|
19
|
+
'SYNAPSE-User': f'Token {self.user_token}',
|
|
20
|
+
'SYNAPSE-Tenant': f'Token {self.tenant}',
|
|
21
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from synapse_sdk.clients.base import BaseClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class ServiceClientMixin(BaseClient):
|
|
5
|
+
def run_plugin_release(self, code, data):
|
|
6
|
+
path = f'plugin_releases/{code}/run/'
|
|
7
|
+
return self._post(path, data=data)
|
|
8
|
+
|
|
9
|
+
def run_debug_plugin_release(self, data):
|
|
10
|
+
path = 'plugin_releases/run_debug/'
|
|
11
|
+
return self._post(path, data=data)
|
|
12
|
+
|
|
13
|
+
def create_plugin_release(self, data):
|
|
14
|
+
path = 'plugin_releases/'
|
|
15
|
+
return self._post(path, data=data)
|
|
16
|
+
|
|
17
|
+
def get_job(self, pk):
|
|
18
|
+
path = f'jobs/{pk}/'
|
|
19
|
+
return self._get(path)
|
|
20
|
+
|
|
21
|
+
def list_jobs(self):
|
|
22
|
+
path = 'jobs/'
|
|
23
|
+
return self._get(path)
|
|
24
|
+
|
|
25
|
+
def list_job_logs(self, pk):
|
|
26
|
+
path = f'jobs/{pk}/logs/'
|
|
27
|
+
return self._get(path)
|
|
28
|
+
|
|
29
|
+
def tail_job_logs(self, pk):
|
|
30
|
+
path = f'jobs/{pk}/tail_logs/'
|
|
31
|
+
|
|
32
|
+
url = self._get_url(path)
|
|
33
|
+
headers = self._get_headers()
|
|
34
|
+
|
|
35
|
+
response = self.requests_session.get(url, headers=headers, stream=True)
|
|
36
|
+
for line in response.iter_lines():
|
|
37
|
+
if line:
|
|
38
|
+
yield line.decode('utf-8')
|
|
39
|
+
|
|
40
|
+
def get_node(self, pk):
|
|
41
|
+
path = f'nodes/{pk}/'
|
|
42
|
+
return self._get(path)
|
|
43
|
+
|
|
44
|
+
def list_nodes(self):
|
|
45
|
+
path = 'nodes/'
|
|
46
|
+
return self._get(path)
|
|
47
|
+
|
|
48
|
+
def get_task(self, pk):
|
|
49
|
+
path = f'tasks/{pk}/'
|
|
50
|
+
return self._get(path)
|
|
51
|
+
|
|
52
|
+
def list_tasks(self):
|
|
53
|
+
path = 'tasks/'
|
|
54
|
+
return self._get(path)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from synapse_sdk.clients.backend.annotation import AnnotationClientMixin
|
|
2
|
+
from synapse_sdk.clients.backend.dataset import DatasetClientMixin
|
|
3
|
+
from synapse_sdk.clients.backend.integration import IntegrationClientMixin
|
|
4
|
+
from synapse_sdk.clients.backend.ml import MLClientMixin
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BackendClient(AnnotationClientMixin, DatasetClientMixin, IntegrationClientMixin, MLClientMixin):
|
|
8
|
+
name = 'Backend'
|
|
9
|
+
token = None
|
|
10
|
+
tenant = None
|
|
11
|
+
|
|
12
|
+
def __init__(self, base_url, token, tenant=None):
|
|
13
|
+
super().__init__(base_url)
|
|
14
|
+
self.token = token
|
|
15
|
+
if tenant:
|
|
16
|
+
self.tenant = tenant
|
|
17
|
+
|
|
18
|
+
def _get_headers(self):
|
|
19
|
+
headers = {'Authorization': f'Token {self.token}'}
|
|
20
|
+
if self.tenant:
|
|
21
|
+
headers['SYNAPSE-Tenant'] = f'Token {self.tenant}'
|
|
22
|
+
return headers
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from synapse_sdk.clients.base import BaseClient
|
|
2
|
+
from synapse_sdk.clients.utils import get_default_url_conversion
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class AnnotationClientMixin(BaseClient):
|
|
6
|
+
def get_project(self, pk):
|
|
7
|
+
path = f'projects/{pk}/'
|
|
8
|
+
return self._get(path)
|
|
9
|
+
|
|
10
|
+
def get_label_tag(self, pk):
|
|
11
|
+
path = f'label_tags/{pk}/'
|
|
12
|
+
return self._get(path)
|
|
13
|
+
|
|
14
|
+
def list_label_tags(self, data):
|
|
15
|
+
path = 'label_tags/'
|
|
16
|
+
return self._list(path, data=data)
|
|
17
|
+
|
|
18
|
+
def list_labels(self, data, url_conversion=None, list_all=False):
|
|
19
|
+
path = 'labels/'
|
|
20
|
+
url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
|
|
21
|
+
return self._list(path, data=data, url_conversion=url_conversion, list_all=list_all)
|
|
22
|
+
|
|
23
|
+
def create_labels(self, data):
|
|
24
|
+
path = 'labels/'
|
|
25
|
+
return self._post(path, data=data)
|
|
26
|
+
|
|
27
|
+
def set_tags_labels(self, data, params=None):
|
|
28
|
+
path = 'labels/set_tags/'
|
|
29
|
+
return self._post(path, data=data, params=params)
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from multiprocessing import Pool
|
|
2
2
|
from tqdm import tqdm
|
|
3
|
-
from ..utils import get_batched_list
|
|
4
3
|
|
|
4
|
+
from synapse_sdk.clients.base import BaseClient
|
|
5
|
+
from synapse_sdk.clients.utils import get_batched_list
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
|
|
8
|
+
class DatasetClientMixin(BaseClient):
|
|
7
9
|
def list_dataset(self):
|
|
8
10
|
path = 'datasets/'
|
|
9
11
|
return self._get(path)
|
|
@@ -14,10 +16,10 @@ class DatasetClientMixin:
|
|
|
14
16
|
|
|
15
17
|
def create_data_units(self, data):
|
|
16
18
|
path = 'data_units/'
|
|
17
|
-
return self._post(path,
|
|
19
|
+
return self._post(path, data=data)
|
|
18
20
|
|
|
19
21
|
def import_dataset(self, dataset_id, dataset, project_id=None, batch_size=1000, process_pool=10):
|
|
20
|
-
# TODO validate
|
|
22
|
+
# TODO validate dataset with schema
|
|
21
23
|
|
|
22
24
|
params = [(data, dataset_id) for data in dataset]
|
|
23
25
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from synapse_sdk.clients.base import BaseClient
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IntegrationClientMixin(BaseClient):
|
|
5
|
+
def get_plugin(self, pk):
|
|
6
|
+
path = f'plugins/{pk}/'
|
|
7
|
+
return self._get(path)
|
|
8
|
+
|
|
9
|
+
def create_plugin(self, data):
|
|
10
|
+
path = 'plugins/'
|
|
11
|
+
return self._post(path, data=data)
|
|
12
|
+
|
|
13
|
+
def update_plugin(self, pk, data):
|
|
14
|
+
path = f'plugins/{pk}/'
|
|
15
|
+
return self._put(path, data=data)
|
|
16
|
+
|
|
17
|
+
def run_plugin(self, pk, data):
|
|
18
|
+
path = f'plugins/{pk}/run/'
|
|
19
|
+
return self._post(path, data=data)
|
|
20
|
+
|
|
21
|
+
def get_plugin_release(self, pk, params=None):
|
|
22
|
+
path = f'plugin_releases/{pk}/'
|
|
23
|
+
return self._get(path, params=params)
|
|
24
|
+
|
|
25
|
+
def create_plugin_release(self, data):
|
|
26
|
+
path = 'plugin_releases/'
|
|
27
|
+
files = {'file': data.pop('file')}
|
|
28
|
+
return self._post(path, data=data, files=files)
|
|
29
|
+
|
|
30
|
+
def list_job_console_logs(self, pk):
|
|
31
|
+
path = f'jobs/{pk}/console_logs/'
|
|
32
|
+
return self._get(path)
|
|
33
|
+
|
|
34
|
+
def tail_job_console_logs(self, pk):
|
|
35
|
+
path = f'jobs/{pk}/tail_console_logs/'
|
|
36
|
+
|
|
37
|
+
url = self._get_url(path)
|
|
38
|
+
headers = self._get_headers()
|
|
39
|
+
|
|
40
|
+
response = self.requests_session.get(url, headers=headers, stream=True)
|
|
41
|
+
for line in response.iter_lines():
|
|
42
|
+
if line:
|
|
43
|
+
yield line.decode('utf-8')
|
|
44
|
+
|
|
45
|
+
def create_logs(self, data):
|
|
46
|
+
path = 'logs/'
|
|
47
|
+
return self._post(path, data=data)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from synapse_sdk.clients.base import BaseClient
|
|
2
|
+
from synapse_sdk.clients.utils import get_default_url_conversion
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class MLClientMixin(BaseClient):
|
|
6
|
+
def get_model(self, pk, params=None, url_conversion=None):
|
|
7
|
+
path = f'models/{pk}/'
|
|
8
|
+
url_conversion = get_default_url_conversion(
|
|
9
|
+
url_conversion, files_fields=['files', 'parent.files'], is_list=False
|
|
10
|
+
)
|
|
11
|
+
return self._get(path, params=params, url_conversion=url_conversion)
|
|
12
|
+
|
|
13
|
+
def create_model(self, data):
|
|
14
|
+
path = 'models/'
|
|
15
|
+
return self._post(path, data=data)
|
|
16
|
+
|
|
17
|
+
def update_model(self, pk, data, files=None):
|
|
18
|
+
path = f'models/{pk}/'
|
|
19
|
+
return self._patch(path, data=data, files=files)
|
|
20
|
+
|
|
21
|
+
def list_train_dataset(self, params=None, url_conversion=None, list_all=False):
|
|
22
|
+
path = 'train_dataset/'
|
|
23
|
+
url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
|
|
24
|
+
return self._list(path, params=params, url_conversion=url_conversion, list_all=list_all)
|
synapse_sdk-1.0.0a1/synapse_sdk/client/__init__.py → synapse_sdk-1.0.0a3/synapse_sdk/clients/base.py
RENAMED
|
@@ -4,24 +4,16 @@ from pathlib import Path
|
|
|
4
4
|
|
|
5
5
|
import requests
|
|
6
6
|
|
|
7
|
-
from .exceptions import ClientError
|
|
8
|
-
from .
|
|
9
|
-
from .mixins.dataset import DatasetClientMixin
|
|
10
|
-
from .mixins.integration import IntegrationClientMixin
|
|
11
|
-
from .mixins.ml import MLClientMixin
|
|
12
|
-
from ..utils.file import files_url_to_path_from_objs
|
|
7
|
+
from synapse_sdk.clients.exceptions import ClientError
|
|
8
|
+
from synapse_sdk.utils.file import files_url_to_path_from_objs
|
|
13
9
|
|
|
14
10
|
|
|
15
|
-
class
|
|
11
|
+
class BaseClient:
|
|
12
|
+
name = None
|
|
16
13
|
base_url = None
|
|
17
|
-
token = None
|
|
18
|
-
tenant = None
|
|
19
14
|
|
|
20
|
-
def __init__(self, base_url
|
|
15
|
+
def __init__(self, base_url):
|
|
21
16
|
self.base_url = base_url
|
|
22
|
-
self.token = token
|
|
23
|
-
if tenant:
|
|
24
|
-
self.tenant = tenant
|
|
25
17
|
requests_session = requests.Session()
|
|
26
18
|
self.requests_session = requests_session
|
|
27
19
|
|
|
@@ -31,10 +23,7 @@ class Client(AnnotationClientMixin, DatasetClientMixin, IntegrationClientMixin,
|
|
|
31
23
|
return path
|
|
32
24
|
|
|
33
25
|
def _get_headers(self):
|
|
34
|
-
|
|
35
|
-
if self.tenant:
|
|
36
|
-
headers['SYNAPSE-Tenant'] = f'Token {self.tenant}'
|
|
37
|
-
return headers
|
|
26
|
+
return {}
|
|
38
27
|
|
|
39
28
|
def _request(self, method, path, **kwargs):
|
|
40
29
|
url = self._get_url(path)
|
|
@@ -56,12 +45,12 @@ class Client(AnnotationClientMixin, DatasetClientMixin, IntegrationClientMixin,
|
|
|
56
45
|
response.status_code, response.json() if response.status_code == 400 else response.reason
|
|
57
46
|
)
|
|
58
47
|
except requests.ConnectionError:
|
|
59
|
-
raise ClientError(408, '
|
|
48
|
+
raise ClientError(408, f'{self.name} is not responding')
|
|
60
49
|
|
|
61
50
|
return response.json()
|
|
62
51
|
|
|
63
|
-
def _get(self, path,
|
|
64
|
-
response = self._request('get', path,
|
|
52
|
+
def _get(self, path, url_conversion=None, **kwargs):
|
|
53
|
+
response = self._request('get', path, **kwargs)
|
|
65
54
|
if url_conversion:
|
|
66
55
|
if url_conversion['is_list']:
|
|
67
56
|
files_url_to_path_from_objs(response['results'], **url_conversion)
|
|
@@ -69,21 +58,24 @@ class Client(AnnotationClientMixin, DatasetClientMixin, IntegrationClientMixin,
|
|
|
69
58
|
files_url_to_path_from_objs(response, **url_conversion)
|
|
70
59
|
return response
|
|
71
60
|
|
|
72
|
-
def _post(self, path,
|
|
73
|
-
return self._request('post', path,
|
|
61
|
+
def _post(self, path, **kwargs):
|
|
62
|
+
return self._request('post', path, **kwargs)
|
|
74
63
|
|
|
75
|
-
def
|
|
76
|
-
return self._request('
|
|
64
|
+
def _put(self, path, **kwargs):
|
|
65
|
+
return self._request('put', path, **kwargs)
|
|
77
66
|
|
|
78
|
-
def
|
|
79
|
-
|
|
67
|
+
def _patch(self, path, **kwargs):
|
|
68
|
+
return self._request('patch', path, **kwargs)
|
|
69
|
+
|
|
70
|
+
def _list(self, path, url_conversion=None, list_all=False, **kwargs):
|
|
71
|
+
response = self._get(path, url_conversion, **kwargs)
|
|
80
72
|
if list_all:
|
|
81
|
-
return self._list_all(path,
|
|
73
|
+
return self._list_all(path, url_conversion, **kwargs), response['count']
|
|
82
74
|
else:
|
|
83
75
|
return response
|
|
84
76
|
|
|
85
|
-
def _list_all(self, path,
|
|
86
|
-
response = self._get(path,
|
|
77
|
+
def _list_all(self, path, url_conversion=None, **kwargs):
|
|
78
|
+
response = self._get(path, url_conversion, **kwargs)
|
|
87
79
|
yield from response['results']
|
|
88
80
|
if response['next']:
|
|
89
|
-
yield from self._list_all(response['next'],
|
|
81
|
+
yield from self._list_all(response['next'], url_conversion, **kwargs)
|
{synapse_sdk-1.0.0a1/synapse_sdk/client → synapse_sdk-1.0.0a3/synapse_sdk/clients}/exceptions.py
RENAMED
|
@@ -6,11 +6,3 @@ class ClientError(Exception):
|
|
|
6
6
|
self.status = status
|
|
7
7
|
self.reason = reason
|
|
8
8
|
super().__init__(status, reason, *args)
|
|
9
|
-
|
|
10
|
-
def as_validation_error(self):
|
|
11
|
-
if self.status == 400:
|
|
12
|
-
error = self.reason
|
|
13
|
-
else:
|
|
14
|
-
error = str(self)
|
|
15
|
-
|
|
16
|
-
return {'backend_errors': error}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
from synapse_sdk.clients.exceptions import ClientError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseLogger:
|
|
7
|
+
progress_records = {}
|
|
8
|
+
|
|
9
|
+
def set_progress(self, current, total, category=''):
|
|
10
|
+
percent = 0
|
|
11
|
+
if total > 0:
|
|
12
|
+
percent = (current / total) * 100
|
|
13
|
+
percent = float(round(percent, 2))
|
|
14
|
+
|
|
15
|
+
self.progress_records[category] = {'current': current, 'total': total, 'percent': percent}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ConsoleLogger(BaseLogger):
|
|
19
|
+
def set_progress(self, current, total, category=''):
|
|
20
|
+
super().set_progress(current, total, category=category)
|
|
21
|
+
print(self.progress_records)
|
|
22
|
+
|
|
23
|
+
def log(self, action, data):
|
|
24
|
+
print(action, data)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class BackendLogger(BaseLogger):
|
|
28
|
+
logs_queue = []
|
|
29
|
+
client = None
|
|
30
|
+
job_id = None
|
|
31
|
+
|
|
32
|
+
def __init__(self, client, job_id):
|
|
33
|
+
self.client = client
|
|
34
|
+
self.job_id = job_id
|
|
35
|
+
|
|
36
|
+
def set_progress(self, current, total, category=''):
|
|
37
|
+
super().set_progress(current, total, category=category)
|
|
38
|
+
# TODO set_progress to the job
|
|
39
|
+
|
|
40
|
+
def log(self, action, data):
|
|
41
|
+
log = {
|
|
42
|
+
'action': action,
|
|
43
|
+
'data': data,
|
|
44
|
+
'datetime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'),
|
|
45
|
+
'job': self.job_id,
|
|
46
|
+
}
|
|
47
|
+
self.logs_queue.append(log)
|
|
48
|
+
try:
|
|
49
|
+
self.client.create_logs(self.logs_queue)
|
|
50
|
+
self.logs_queue.clear()
|
|
51
|
+
except ClientError as e:
|
|
52
|
+
print(e)
|
|
@@ -8,11 +8,13 @@ import ray
|
|
|
8
8
|
import requests
|
|
9
9
|
from ray.dashboard.modules.job.sdk import JobSubmissionClient
|
|
10
10
|
|
|
11
|
-
from synapse_sdk.
|
|
11
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
12
|
+
from synapse_sdk.loggers import ConsoleLogger, BackendLogger
|
|
12
13
|
from synapse_sdk.plugins.enums import RunMethod
|
|
13
|
-
from synapse_sdk.plugins.upload import build_and_upload, archive_and_upload
|
|
14
|
+
from synapse_sdk.plugins.upload import build_and_upload, archive_and_upload, download_and_upload
|
|
14
15
|
from synapse_sdk.plugins.utils import get_plugin_checksum
|
|
15
16
|
from synapse_sdk.utils.module_loading import import_string
|
|
17
|
+
from synapse_sdk.utils.storage import get_storage
|
|
16
18
|
|
|
17
19
|
|
|
18
20
|
class Action:
|
|
@@ -29,11 +31,12 @@ class Action:
|
|
|
29
31
|
default_envs = [
|
|
30
32
|
'RAY_DASHBOARD_URL',
|
|
31
33
|
'RAY_SERVE_ADDRESS',
|
|
32
|
-
'SYNAPSE_PLUGIN_URL',
|
|
33
|
-
'SYNAPSE_PLUGIN_PATH',
|
|
34
|
-
'SYNAPSE_PLUGIN_BASE_URL',
|
|
35
34
|
'SYNAPSE_PLUGIN_STORAGE',
|
|
35
|
+
'SYNAPSE_DEBUG_PLUGIN_PATH',
|
|
36
36
|
'SYNAPSE_DEBUG_MODULES',
|
|
37
|
+
'SYNAPSE_PLUGIN_RUN_HOST',
|
|
38
|
+
'SYNAPSE_PLUGIN_RUN_USER_TOKEN',
|
|
39
|
+
'SYNAPSE_PLUGIN_RUN_TENANT',
|
|
37
40
|
]
|
|
38
41
|
|
|
39
42
|
def __init__(self, params, plugin_config, envs=None, job_id=None, direct=False, debug=False):
|
|
@@ -43,13 +46,8 @@ class Action:
|
|
|
43
46
|
self.job_id = job_id
|
|
44
47
|
self.direct = direct
|
|
45
48
|
self.debug = debug
|
|
46
|
-
if envs
|
|
47
|
-
|
|
48
|
-
else:
|
|
49
|
-
self.envs = self.get_default_envs()
|
|
50
|
-
|
|
51
|
-
# TODO logger 지정 방식 개선
|
|
52
|
-
self.logger = ConsoleLogger()
|
|
49
|
+
self.envs = {**envs, **self.get_default_envs()} if envs else self.get_default_envs()
|
|
50
|
+
self.set_logger()
|
|
53
51
|
|
|
54
52
|
@cached_property
|
|
55
53
|
def plugin_id(self):
|
|
@@ -61,38 +59,55 @@ class Action:
|
|
|
61
59
|
def plugin_checksum(self):
|
|
62
60
|
return get_plugin_checksum(self.plugin_id)
|
|
63
61
|
|
|
64
|
-
@cached_property
|
|
65
|
-
def plugin_url(self):
|
|
66
|
-
if self.debug:
|
|
67
|
-
plugin_url = self.envs.get('SYNAPSE_PLUGIN_URL')
|
|
68
|
-
if not plugin_url:
|
|
69
|
-
plugin_url = archive_and_upload(
|
|
70
|
-
self.envs.get('SYNAPSE_PLUGIN_PATH', '.'),
|
|
71
|
-
self.envs['SYNAPSE_PLUGIN_STORAGE'],
|
|
72
|
-
)
|
|
73
|
-
self.envs['SYNAPSE_PLUGIN_URL'] = plugin_url
|
|
74
|
-
return plugin_url
|
|
75
|
-
base_url = self.envs['SYNAPSE_PLUGIN_BASE_URL']
|
|
76
|
-
return str(os.path.join(base_url, f'{self.plugin_checksum}.zip'))
|
|
77
|
-
|
|
78
62
|
@cached_property
|
|
79
63
|
def entrypoint(self):
|
|
80
64
|
return import_string(self.config['entrypoint'])
|
|
81
65
|
|
|
82
|
-
|
|
83
|
-
|
|
66
|
+
@property
|
|
67
|
+
def plugin_storage_url(self):
|
|
68
|
+
return self.envs['SYNAPSE_PLUGIN_STORAGE']
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def plugin_url(self):
|
|
72
|
+
if self.debug:
|
|
73
|
+
plugin_path = self.envs.get('SYNAPSE_DEBUG_PLUGIN_PATH', '.')
|
|
74
|
+
if plugin_path.startswith('https://'): # TODO ray에서 지원하는 remote uri 형식 (https, s3, gs) 모두 지원
|
|
75
|
+
plugin_url = plugin_path
|
|
76
|
+
elif plugin_path.startswith('http://'):
|
|
77
|
+
plugin_url = download_and_upload(plugin_path, self.plugin_storage_url)
|
|
78
|
+
else:
|
|
79
|
+
plugin_url = archive_and_upload(plugin_path, self.plugin_storage_url)
|
|
80
|
+
self.envs['SYNAPSE_DEBUG_PLUGIN_PATH'] = plugin_url
|
|
81
|
+
return plugin_url
|
|
82
|
+
storage = get_storage(self.plugin_storage_url)
|
|
83
|
+
return storage.get_url(f'{self.plugin_checksum}.zip')
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
@property
|
|
86
|
+
def debug_modules(self):
|
|
86
87
|
debug_modules = []
|
|
87
88
|
for module_path in self.envs.get('SYNAPSE_DEBUG_MODULES', '').split(','):
|
|
88
|
-
if module_path.startswith('
|
|
89
|
+
if module_path.startswith('https://'): # TODO ray에서 지원하는 remote uri 형식 (https, s3, gs) 모두 지원
|
|
89
90
|
module_url = module_path
|
|
90
91
|
else:
|
|
91
|
-
module_url = build_and_upload(module_path, self.
|
|
92
|
+
module_url = build_and_upload(module_path, self.plugin_storage_url)
|
|
92
93
|
debug_modules.append(module_url)
|
|
93
94
|
self.envs['SYNAPSE_DEBUG_MODULES'] = ','.join(debug_modules)
|
|
94
95
|
return debug_modules
|
|
95
96
|
|
|
97
|
+
def set_logger(self):
|
|
98
|
+
if self.job_id:
|
|
99
|
+
client = BackendClient(
|
|
100
|
+
self.envs['SYNAPSE_PLUGIN_RUN_HOST'],
|
|
101
|
+
self.envs['SYNAPSE_PLUGIN_RUN_USER_TOKEN'],
|
|
102
|
+
self.envs['SYNAPSE_PLUGIN_RUN_TENANT'],
|
|
103
|
+
)
|
|
104
|
+
self.logger = BackendLogger(client, self.job_id)
|
|
105
|
+
else:
|
|
106
|
+
self.logger = ConsoleLogger()
|
|
107
|
+
|
|
108
|
+
def get_default_envs(self):
|
|
109
|
+
return {env: os.environ[env] for env in self.default_envs if env in os.environ}
|
|
110
|
+
|
|
96
111
|
def get_runtime_env(self):
|
|
97
112
|
runtime_env = {
|
|
98
113
|
'pip': ['-r ${RAY_RUNTIME_ENV_CREATE_WORKING_DIR}/requirements.txt'],
|
|
@@ -100,7 +115,7 @@ class Action:
|
|
|
100
115
|
}
|
|
101
116
|
|
|
102
117
|
if self.debug:
|
|
103
|
-
runtime_env['pip'] += self.
|
|
118
|
+
runtime_env['pip'] += self.debug_modules
|
|
104
119
|
|
|
105
120
|
# 맨 마지막에 진행되어야 함
|
|
106
121
|
runtime_env['env_vars'] = self.envs
|
|
@@ -145,14 +160,22 @@ class Action:
|
|
|
145
160
|
return ray.get(run_task.remote(self.category.value, self.name, *args, **kwargs))
|
|
146
161
|
|
|
147
162
|
def run_by_job(self):
|
|
148
|
-
|
|
163
|
+
main_options = []
|
|
164
|
+
options = ['run', '--direct']
|
|
165
|
+
arguments = [self.name, f'{json.dumps(json.dumps(self.params))}']
|
|
166
|
+
|
|
149
167
|
if self.debug:
|
|
150
|
-
|
|
168
|
+
main_options.append('--debug')
|
|
169
|
+
|
|
170
|
+
if self.job_id:
|
|
171
|
+
options.append(f'--job-id={self.job_id}')
|
|
172
|
+
|
|
173
|
+
cmd = ' '.join(main_options + options + arguments)
|
|
151
174
|
|
|
152
175
|
client = JobSubmissionClient(address=self.envs.get('RAY_DASHBOARD_URL'))
|
|
153
176
|
return client.submit_job(
|
|
154
177
|
submission_id=self.job_id,
|
|
155
|
-
entrypoint=f'python main.py {
|
|
178
|
+
entrypoint=f'python main.py {cmd}',
|
|
156
179
|
runtime_env=self.get_runtime_env(),
|
|
157
180
|
)
|
|
158
181
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from synapse_sdk.plugins.categories.base import Action
|
|
2
|
+
from synapse_sdk.plugins.categories.decorators import register_action
|
|
3
|
+
from synapse_sdk.plugins.enums import RunMethod, PluginCategory
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@register_action
|
|
7
|
+
class TrainAction(Action):
|
|
8
|
+
name = 'train'
|
|
9
|
+
category = PluginCategory.NEURAL_NET
|
|
10
|
+
method = RunMethod.JOB
|
|
11
|
+
|
|
12
|
+
def get_dataset(self):
|
|
13
|
+
return {}
|
|
14
|
+
|
|
15
|
+
def run(self):
|
|
16
|
+
hyperparameter = self.params['hyperparameter']
|
|
17
|
+
|
|
18
|
+
# download dataset
|
|
19
|
+
self.log_event('Preparing dataset for training.')
|
|
20
|
+
input_dataset = self.get_dataset()
|
|
21
|
+
|
|
22
|
+
# train dataset
|
|
23
|
+
self.log_event('Starting model training.')
|
|
24
|
+
|
|
25
|
+
model_files = self.entrypoint(self, input_dataset, hyperparameter)
|
|
26
|
+
|
|
27
|
+
# upload model_data
|
|
28
|
+
self.log_event('Registering model data.')
|
|
29
|
+
|
|
30
|
+
self.end_log()
|
|
31
|
+
return model_files
|
|
32
|
+
|
|
33
|
+
def log_metric(self, x, i, **kwargs):
|
|
34
|
+
self.log(x, {x: i, **kwargs})
|
|
35
|
+
|
|
36
|
+
def log_model(self, files, status=None):
|
|
37
|
+
pass
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
7
|
+
from synapse_sdk.plugins.upload import archive
|
|
8
|
+
from synapse_sdk.plugins.utils import read_config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.command()
|
|
12
|
+
@click.option('--host', required=True)
|
|
13
|
+
@click.option('--user_token', required=True)
|
|
14
|
+
@click.option('--tenant', required=True)
|
|
15
|
+
@click.option('--debug_modules', default='', envvar='SYNAPSE_DEBUG_MODULES')
|
|
16
|
+
@click.pass_context
|
|
17
|
+
def publish(ctx, host, user_token, tenant, debug_modules):
|
|
18
|
+
debug = ctx.obj['DEBUG']
|
|
19
|
+
|
|
20
|
+
config = read_config()
|
|
21
|
+
|
|
22
|
+
source_path = Path('./')
|
|
23
|
+
archive_path = source_path / 'dist' / 'archive.zip'
|
|
24
|
+
archive(source_path, archive_path)
|
|
25
|
+
|
|
26
|
+
data = {'plugin': config['code'], 'file': str(archive_path), 'debug': debug}
|
|
27
|
+
if debug:
|
|
28
|
+
data['debug_meta'] = json.dumps({'modules': debug_modules.split(',')})
|
|
29
|
+
|
|
30
|
+
client = BackendClient(host, user_token, tenant=tenant)
|
|
31
|
+
client.create_plugin_release(data)
|
|
32
|
+
click.secho(
|
|
33
|
+
f'Successfully published "{config["name"]}" ({config["code"]}@{config["version"]}) to synapse backend!',
|
|
34
|
+
fg='green',
|
|
35
|
+
bold=True,
|
|
36
|
+
)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from synapse_sdk.clients.agent import AgentClient
|
|
6
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
7
|
+
from synapse_sdk.plugins.utils import get_action, read_config
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command()
|
|
11
|
+
@click.argument('action')
|
|
12
|
+
@click.argument('params')
|
|
13
|
+
@click.option('--job-id')
|
|
14
|
+
@click.option('--direct/--no-direct', default=False)
|
|
15
|
+
@click.option('--run-by', type=click.Choice(['script', 'agent', 'backend']), default='script')
|
|
16
|
+
@click.option('--agent-host')
|
|
17
|
+
@click.option('--agent-token')
|
|
18
|
+
@click.option('--host')
|
|
19
|
+
@click.option('--agent')
|
|
20
|
+
@click.option('--user-token')
|
|
21
|
+
@click.option('--tenant')
|
|
22
|
+
@click.pass_context
|
|
23
|
+
def run(ctx, action, params, job_id, direct, run_by, agent_host, agent_token, host, agent, user_token, tenant):
|
|
24
|
+
debug = ctx.obj['DEBUG']
|
|
25
|
+
|
|
26
|
+
if run_by == 'script':
|
|
27
|
+
run_by_script(action, params, job_id, direct, debug)
|
|
28
|
+
elif run_by == 'agent':
|
|
29
|
+
run_by_agent(action, params, job_id, agent_host, agent_token, user_token, tenant, debug)
|
|
30
|
+
elif run_by == 'backend':
|
|
31
|
+
run_by_backend(action, params, agent, host, user_token, tenant)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def run_by_script(action, params, job_id, direct, debug):
|
|
35
|
+
action = get_action(action, params, job_id=job_id, direct=direct, debug=debug)
|
|
36
|
+
result = action.run_action()
|
|
37
|
+
|
|
38
|
+
if debug:
|
|
39
|
+
click.echo(result)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def run_by_agent(action, params, job_id, agent_host, agent_token, user_token, tenant, debug):
|
|
43
|
+
client = AgentClient(agent_host, agent_token, user_token, tenant)
|
|
44
|
+
data = {'action': action, 'params': params, 'job_id': job_id}
|
|
45
|
+
if debug:
|
|
46
|
+
data.update({
|
|
47
|
+
'plugin_path': os.getcwd(),
|
|
48
|
+
'modules': os.getenv('SYNAPSE_DEBUG_MODULES', '').split(','),
|
|
49
|
+
})
|
|
50
|
+
result = client.run_debug_plugin_release(data=data)
|
|
51
|
+
else:
|
|
52
|
+
config = read_config()
|
|
53
|
+
result = client.run_plugin_release(code=f'{config["code"]}@{config["version"]}', data=data)
|
|
54
|
+
|
|
55
|
+
click.echo(result)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def run_by_backend(action, params, agent, host, user_token, tenant):
|
|
59
|
+
client = BackendClient(host, user_token, tenant=tenant)
|
|
60
|
+
config = read_config()
|
|
61
|
+
data = {'agent': agent, 'version': config['version'], 'action': action, 'params': params}
|
|
62
|
+
result = client.run_plugin(config['code'], data=data)
|
|
63
|
+
|
|
64
|
+
click.echo(result)
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import subprocess
|
|
3
|
+
import tempfile
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
5
|
-
from synapse_sdk.utils.file import calculate_checksum
|
|
6
|
+
from synapse_sdk.utils.file import calculate_checksum, download_file
|
|
6
7
|
from synapse_sdk.utils.storage import get_storage
|
|
7
8
|
|
|
8
9
|
|
|
@@ -12,6 +13,15 @@ def archive(source_path, archive_path):
|
|
|
12
13
|
subprocess.run(command, cwd=source_path, shell=True, check=True, stdout=subprocess.DEVNULL)
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
def download_and_upload(source_url, url):
|
|
17
|
+
storage = get_storage(url)
|
|
18
|
+
with tempfile.TemporaryDirectory() as temp_path:
|
|
19
|
+
file_path = str(download_file(source_url, temp_path))
|
|
20
|
+
checksum = calculate_checksum(file_path, prefix='dev')
|
|
21
|
+
# TODO 중복 체크
|
|
22
|
+
return storage.upload(file_path, f'{checksum}.zip')
|
|
23
|
+
|
|
24
|
+
|
|
15
25
|
def archive_and_upload(source_path, url):
|
|
16
26
|
storage = get_storage(url)
|
|
17
27
|
dist_path = Path(source_path, 'dist')
|
|
@@ -78,8 +78,7 @@ class S3Storage(BaseStorage):
|
|
|
78
78
|
return False
|
|
79
79
|
|
|
80
80
|
def get_url(self, target):
|
|
81
|
-
|
|
82
|
-
return f'{self.options["base_url"]}/{self.options["bucket_name"]}/{object_name}'
|
|
81
|
+
return os.path.join(self.options['base_url'], self.options['bucket_name'], self.options['location'], target)
|
|
83
82
|
|
|
84
83
|
|
|
85
84
|
STORAGE_STORAGES = {
|
|
@@ -7,21 +7,23 @@ requirements.txt
|
|
|
7
7
|
.github/workflows/lint.yml
|
|
8
8
|
.github/workflows/pypi-publish.yml
|
|
9
9
|
synapse_sdk/__init__.py
|
|
10
|
-
synapse_sdk/config.py
|
|
11
10
|
synapse_sdk/loggers.py
|
|
12
11
|
synapse_sdk.egg-info/PKG-INFO
|
|
13
12
|
synapse_sdk.egg-info/SOURCES.txt
|
|
14
13
|
synapse_sdk.egg-info/dependency_links.txt
|
|
15
14
|
synapse_sdk.egg-info/requires.txt
|
|
16
15
|
synapse_sdk.egg-info/top_level.txt
|
|
17
|
-
synapse_sdk/
|
|
18
|
-
synapse_sdk/
|
|
19
|
-
synapse_sdk/
|
|
20
|
-
synapse_sdk/
|
|
21
|
-
synapse_sdk/
|
|
22
|
-
synapse_sdk/
|
|
23
|
-
synapse_sdk/
|
|
24
|
-
synapse_sdk/
|
|
16
|
+
synapse_sdk/clients/__init__.py
|
|
17
|
+
synapse_sdk/clients/base.py
|
|
18
|
+
synapse_sdk/clients/exceptions.py
|
|
19
|
+
synapse_sdk/clients/utils.py
|
|
20
|
+
synapse_sdk/clients/agent/__init__.py
|
|
21
|
+
synapse_sdk/clients/agent/service.py
|
|
22
|
+
synapse_sdk/clients/backend/__init__.py
|
|
23
|
+
synapse_sdk/clients/backend/annotation.py
|
|
24
|
+
synapse_sdk/clients/backend/dataset.py
|
|
25
|
+
synapse_sdk/clients/backend/integration.py
|
|
26
|
+
synapse_sdk/clients/backend/ml.py
|
|
25
27
|
synapse_sdk/plugins/__init__.py
|
|
26
28
|
synapse_sdk/plugins/enums.py
|
|
27
29
|
synapse_sdk/plugins/job.py
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
from ..utils import get_default_url_conversion
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class AnnotationClientMixin:
|
|
5
|
-
def get_project(self, pk):
|
|
6
|
-
path = f'projects/{pk}/'
|
|
7
|
-
return self._get(path)
|
|
8
|
-
|
|
9
|
-
def get_label_tag(self, pk):
|
|
10
|
-
path = f'label_tags/{pk}/'
|
|
11
|
-
return self._get(path)
|
|
12
|
-
|
|
13
|
-
def list_label_tags(self, payload=None):
|
|
14
|
-
path = 'label_tags/'
|
|
15
|
-
return self._list(path, payload)
|
|
16
|
-
|
|
17
|
-
def list_labels(self, payload=None, url_conversion=None, list_all=False):
|
|
18
|
-
path = 'labels/'
|
|
19
|
-
url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
|
|
20
|
-
return self._list(path, payload, url_conversion, list_all)
|
|
21
|
-
|
|
22
|
-
def create_labels(self, data):
|
|
23
|
-
path = 'labels/'
|
|
24
|
-
return self._post(path, payload=data)
|
|
25
|
-
|
|
26
|
-
def set_tags_labels(self, data, params=None):
|
|
27
|
-
path = 'labels/set_tags/'
|
|
28
|
-
return self._post(path, payload=data, params=params)
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
class IntegrationClientMixin:
|
|
2
|
-
def get_plugin(self, pk):
|
|
3
|
-
path = f'plugins/{pk}/'
|
|
4
|
-
return self._get(path)
|
|
5
|
-
|
|
6
|
-
def create_plugin(self, data):
|
|
7
|
-
path = 'plugins/'
|
|
8
|
-
return self._post(path, payload=data)
|
|
9
|
-
|
|
10
|
-
def update_plugin(self, pk, data):
|
|
11
|
-
path = f'plugins/{pk}/'
|
|
12
|
-
return self._put(path, payload=data)
|
|
13
|
-
|
|
14
|
-
def get_plugin_release(self, pk, params=None):
|
|
15
|
-
path = f'plugin_releases/{pk}/'
|
|
16
|
-
return self._get(path, payload=params)
|
|
17
|
-
|
|
18
|
-
def create_plugin_release(self, data):
|
|
19
|
-
path = 'plugin_releases/'
|
|
20
|
-
files = {'file': data.pop('file')}
|
|
21
|
-
return self._post(path, payload=data, files=files)
|
|
22
|
-
|
|
23
|
-
def create_logs(self, data):
|
|
24
|
-
path = 'logs/'
|
|
25
|
-
return self._post(path, payload=data)
|
|
26
|
-
|
|
27
|
-
def create_task(self, data):
|
|
28
|
-
path = 'agent_tasks/'
|
|
29
|
-
return self._post(path, payload=data)
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
from ..utils import get_default_url_conversion
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class MLClientMixin:
|
|
5
|
-
def get_model(self, pk, payload=None, url_conversion=None):
|
|
6
|
-
path = f'models/{pk}/'
|
|
7
|
-
url_conversion = get_default_url_conversion(
|
|
8
|
-
url_conversion, files_fields=['files', 'parent.files'], is_list=False
|
|
9
|
-
)
|
|
10
|
-
return self._get(path, payload, url_conversion)
|
|
11
|
-
|
|
12
|
-
def create_model(self, data):
|
|
13
|
-
path = 'models/'
|
|
14
|
-
return self._post(path, payload=data)
|
|
15
|
-
|
|
16
|
-
def update_model(self, pk, data, files=None):
|
|
17
|
-
path = f'models/{pk}/'
|
|
18
|
-
return self._patch(path, payload=data, files=files)
|
|
19
|
-
|
|
20
|
-
def list_train_dataset(self, payload=None, url_conversion=None, list_all=False):
|
|
21
|
-
path = 'train_dataset/'
|
|
22
|
-
url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
|
|
23
|
-
return self._list(path, payload, url_conversion, list_all)
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from synapse_sdk.client import ClientError
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class BaseLogger:
|
|
7
|
-
progress_records = {}
|
|
8
|
-
logs_queue = []
|
|
9
|
-
client = None
|
|
10
|
-
|
|
11
|
-
def __init__(self, client=None, task=None):
|
|
12
|
-
self.client = client
|
|
13
|
-
self.task = task
|
|
14
|
-
|
|
15
|
-
def set_progress(self, current, total, category=''):
|
|
16
|
-
percent = 0
|
|
17
|
-
if total > 0:
|
|
18
|
-
percent = (current / total) * 100
|
|
19
|
-
percent = float(round(percent, 2))
|
|
20
|
-
|
|
21
|
-
self.progress_records[category] = {'current': current, 'total': total, 'percent': percent}
|
|
22
|
-
if self.task:
|
|
23
|
-
self.task.update_state(state='PROGRESS', meta=self.progress_records)
|
|
24
|
-
else:
|
|
25
|
-
print(self.progress_records)
|
|
26
|
-
|
|
27
|
-
def log(self, action, data):
|
|
28
|
-
log = {'action': action, 'data': data, 'datetime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')}
|
|
29
|
-
|
|
30
|
-
if self.client and self.task:
|
|
31
|
-
log['task_id'] = self.task.request.id
|
|
32
|
-
self.logs_queue.append(log)
|
|
33
|
-
try:
|
|
34
|
-
self.client.create_logs(self.logs_queue)
|
|
35
|
-
self.logs_queue.clear()
|
|
36
|
-
except ClientError as e:
|
|
37
|
-
print(e)
|
|
38
|
-
else:
|
|
39
|
-
print(log)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class ConsoleLogger(BaseLogger):
|
|
43
|
-
def log(self, action, data):
|
|
44
|
-
print(action, data)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class SynapseLogger(BaseLogger):
|
|
48
|
-
pass
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
from synapse_sdk.plugins.categories.base import Action
|
|
2
|
-
from synapse_sdk.plugins.categories.decorators import register_action
|
|
3
|
-
from synapse_sdk.plugins.enums import RunMethod, PluginCategory
|
|
4
|
-
from synapse_sdk.utils.file import get_dict_from_file, files_url_to_path_from_objs
|
|
5
|
-
from synapse_sdk.utils.module_loading import import_string
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@register_action
|
|
9
|
-
class TrainAction(Action):
|
|
10
|
-
name = 'train'
|
|
11
|
-
category = PluginCategory.NEURAL_NET
|
|
12
|
-
method = RunMethod.JOB
|
|
13
|
-
|
|
14
|
-
def get_input_dataset_for_training(self, model_id=None):
|
|
15
|
-
"""
|
|
16
|
-
:return:
|
|
17
|
-
{
|
|
18
|
-
"train": [
|
|
19
|
-
{
|
|
20
|
-
"files": {
|
|
21
|
-
"image": {
|
|
22
|
-
"path": "/path/to/image.jpg",
|
|
23
|
-
"meta": {
|
|
24
|
-
"width": 265,
|
|
25
|
-
"height": 190,
|
|
26
|
-
"created": 1651563526.0277045,
|
|
27
|
-
"file_size": 5191,
|
|
28
|
-
"last_modified": 1651563526.0277045
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"ground_truth": {
|
|
33
|
-
...label_data
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
...
|
|
37
|
-
],
|
|
38
|
-
"validation": ...,
|
|
39
|
-
"test": ...
|
|
40
|
-
}
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
client = self.logger.client
|
|
44
|
-
input_dataset = {}
|
|
45
|
-
category_int_to_str = {1: 'train', 2: 'validation', 3: 'test'}
|
|
46
|
-
|
|
47
|
-
if client:
|
|
48
|
-
train_dataset, count_dataset = client.list_train_dataset(
|
|
49
|
-
payload={'fields': ['category', 'files', 'ground_truth'], 'model': model_id}, list_all=True
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
for i, train_data in enumerate(train_dataset, start=1):
|
|
53
|
-
self.set_progress(i, count_dataset, category='dataset_download')
|
|
54
|
-
category = category_int_to_str[train_data.pop('category')]
|
|
55
|
-
try:
|
|
56
|
-
input_dataset[category].append(train_data)
|
|
57
|
-
except KeyError:
|
|
58
|
-
input_dataset[category] = [train_data]
|
|
59
|
-
|
|
60
|
-
else:
|
|
61
|
-
for category in category_int_to_str.values():
|
|
62
|
-
dataset_path = self.task['dataset'].get(category)
|
|
63
|
-
if dataset_path:
|
|
64
|
-
input_dataset[category] = get_dict_from_file(dataset_path)
|
|
65
|
-
files_url_to_path_from_objs(input_dataset[category], ['files'], is_list=True)
|
|
66
|
-
|
|
67
|
-
return input_dataset
|
|
68
|
-
|
|
69
|
-
def run_train(self):
|
|
70
|
-
hyperparameter = self.task['hyperparameter']
|
|
71
|
-
train = import_string(self.plugin['train']['entrypoint'])
|
|
72
|
-
|
|
73
|
-
# download dataset
|
|
74
|
-
self.log_event('Preparing dataset for training.')
|
|
75
|
-
input_dataset = self.get_input_dataset_for_training()
|
|
76
|
-
|
|
77
|
-
# train dataset
|
|
78
|
-
self.log_event('Starting model training.')
|
|
79
|
-
|
|
80
|
-
model_files = train(self, input_dataset, hyperparameter)
|
|
81
|
-
|
|
82
|
-
# upload model_data
|
|
83
|
-
self.log_event('Registering model data.')
|
|
84
|
-
|
|
85
|
-
self.end_log()
|
|
86
|
-
return model_files
|
|
87
|
-
|
|
88
|
-
def start(self):
|
|
89
|
-
action = self.task['action']
|
|
90
|
-
getattr(self, f'run_{action}')()
|
|
91
|
-
|
|
92
|
-
def log_metric(self, x, i, **kwargs):
|
|
93
|
-
self.log(x, {x: i, **kwargs})
|
|
94
|
-
|
|
95
|
-
def log_model(self, files, status=None):
|
|
96
|
-
pass
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
|
|
5
|
-
from synapse_sdk.client import Client
|
|
6
|
-
from synapse_sdk.plugins.utils import read_config
|
|
7
|
-
|
|
8
|
-
from ..upload import archive
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@click.command()
|
|
12
|
-
@click.option('-h', '--host', required=True)
|
|
13
|
-
@click.option('-t', '--token', required=True)
|
|
14
|
-
@click.option('-w', '--workspace', required=True)
|
|
15
|
-
def publish(host, token, workspace):
|
|
16
|
-
client = Client(host, token, tenant=workspace)
|
|
17
|
-
config = read_config()
|
|
18
|
-
|
|
19
|
-
source_path = Path('./')
|
|
20
|
-
archive_path = source_path / 'dist' / 'archive.zip'
|
|
21
|
-
archive(source_path, archive_path)
|
|
22
|
-
|
|
23
|
-
data = {'plugin': config['code'], 'file': str(archive_path)}
|
|
24
|
-
client.create_plugin_release(data)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
|
|
3
|
-
from synapse_sdk.plugins.utils import get_action
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@click.command()
|
|
7
|
-
@click.argument('action')
|
|
8
|
-
@click.argument('params')
|
|
9
|
-
@click.option('--direct/--no-direct', default=False)
|
|
10
|
-
@click.pass_context
|
|
11
|
-
def run(ctx, action, params, direct):
|
|
12
|
-
debug = ctx.obj['DEBUG']
|
|
13
|
-
|
|
14
|
-
action = get_action(action, params, direct=direct, debug=debug)
|
|
15
|
-
result = action.run_action()
|
|
16
|
-
|
|
17
|
-
if debug:
|
|
18
|
-
click.echo(result)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/export/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/export/actions/export.py
RENAMED
|
File without changes
|
{synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/import/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/import/actions/import.py
RENAMED
|
File without changes
|
{synapse_sdk-1.0.0a1 → synapse_sdk-1.0.0a3}/synapse_sdk/plugins/categories/neural_net/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|