seetapsych-lib 0.0.1__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.
- seetapsych_lib/__init__.py +5 -0
- seetapsych_lib/_version.py +24 -0
- seetapsych_lib/_version_resolve.py +121 -0
- seetapsych_lib/api/__init__.py +8 -0
- seetapsych_lib/api/device.py +41 -0
- seetapsych_lib/api/error.py +9 -0
- seetapsych_lib/api/instance.py +34 -0
- seetapsych_lib/api/model.py +51 -0
- seetapsych_lib/api/package.py +19 -0
- seetapsych_lib/example/example.py +84 -0
- seetapsych_lib/example/example.yml +84 -0
- seetapsych_lib/manager/__main__.py +8 -0
- seetapsych_lib/manager/cli.py +589 -0
- seetapsych_lib/modules/face_selection.yml +29 -0
- seetapsych_lib/onnx/session.py +84 -0
- seetapsych_lib/runtime/__init__.py +5 -0
- seetapsych_lib/runtime/actions.py +368 -0
- seetapsych_lib/runtime/export.py +197 -0
- seetapsych_lib/runtime/factory.py +153 -0
- seetapsych_lib/runtime/model.py +437 -0
- seetapsych_lib/runtime/module.py +151 -0
- seetapsych_lib/runtime/parallel/executor.py +684 -0
- seetapsych_lib/runtime/parallel/future.py +254 -0
- seetapsych_lib/runtime/parallel_runner.py +366 -0
- seetapsych_lib/runtime/pipeline.py +862 -0
- seetapsych_lib/runtime/runner.py +181 -0
- seetapsych_lib/schema/__init__.py +3 -0
- seetapsych_lib/schema/module.py +254 -0
- seetapsych_lib/toolkit/face_selection.py +114 -0
- seetapsych_lib/toolkit/packages/face_selection.py +76 -0
- seetapsych_lib/utils/__init__.py +1 -0
- seetapsych_lib/utils/cuda.py +114 -0
- seetapsych_lib/utils/defer.py +32 -0
- seetapsych_lib/utils/dirs.py +15 -0
- seetapsych_lib/utils/download_file.py +469 -0
- seetapsych_lib/utils/loader.py +88 -0
- seetapsych_lib/utils/logger.py +75 -0
- seetapsych_lib/utils/markdown.py +30 -0
- seetapsych_lib/utils/pencilbox.py +8 -0
- seetapsych_lib/webui/__main__.py +8 -0
- seetapsych_lib/webui/app.py +1351 -0
- seetapsych_lib/webui/cli.py +18 -0
- seetapsych_lib-0.0.1.dist-info/METADATA +198 -0
- seetapsych_lib-0.0.1.dist-info/RECORD +47 -0
- seetapsych_lib-0.0.1.dist-info/WHEEL +4 -0
- seetapsych_lib-0.0.1.dist-info/entry_points.txt +3 -0
- seetapsych_lib-0.0.1.dist-info/licenses/LICENSE +15 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '0.0.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 0, 1)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Release tags follow the pattern ``r<PEP 440 version>`` where the
|
|
4
|
+
version body **must not contain a dash** (``-``) so it stays distinct
|
|
5
|
+
from the ``-N-gSHA`` suffix produced by ``git describe``.
|
|
6
|
+
|
|
7
|
+
Good tags:
|
|
8
|
+
|
|
9
|
+
* ``r1.0.0`` release
|
|
10
|
+
* ``r1.2.3b1`` beta
|
|
11
|
+
* ``r1.2.3rc2`` release candidate
|
|
12
|
+
* ``r2.0.0a5`` alpha
|
|
13
|
+
* ``r0.9.0.post1`` post release
|
|
14
|
+
|
|
15
|
+
Bad tags (ignored by the hatchling VCS version source):
|
|
16
|
+
|
|
17
|
+
* ``r1.0.0-beta.1`` dash inside the version body
|
|
18
|
+
* ``1.0.0`` missing ``r`` prefix
|
|
19
|
+
* ``r1.0.0-wip`` dash inside trailing segment
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import re
|
|
25
|
+
import subprocess
|
|
26
|
+
from pathlib import Path
|
|
27
|
+
from typing import Optional
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"__version__",
|
|
32
|
+
"get_version",
|
|
33
|
+
"FALLBACK_VERSION",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
FALLBACK_VERSION: str = "0.0.0.dev0"
|
|
38
|
+
|
|
39
|
+
# Keep in sync with ``[tool.hatch.version] tag-pattern`` in pyproject.toml.
|
|
40
|
+
TAG_PATTERN = re.compile(r"^r(?P<version>[^-]+)$")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _version_from_build_file() -> Optional[str]:
|
|
44
|
+
try:
|
|
45
|
+
from ._version import __version__ # type: ignore[import-not-found]
|
|
46
|
+
|
|
47
|
+
return __version__.strip() or None
|
|
48
|
+
except Exception:
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _package_root() -> Path:
|
|
53
|
+
return Path(__file__).resolve().parent
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _run_git(*args: str) -> Optional[str]:
|
|
57
|
+
try:
|
|
58
|
+
completed = subprocess.run(
|
|
59
|
+
["git", "-C", str(_package_root()), *args],
|
|
60
|
+
capture_output=True,
|
|
61
|
+
text=True,
|
|
62
|
+
check=False,
|
|
63
|
+
)
|
|
64
|
+
except (OSError, ValueError):
|
|
65
|
+
return None
|
|
66
|
+
if completed.returncode != 0 or not completed.stdout:
|
|
67
|
+
return None
|
|
68
|
+
return completed.stdout.strip()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _strip_tag_prefix(raw: str) -> str:
|
|
72
|
+
m = TAG_PATTERN.match(raw)
|
|
73
|
+
return m.group("version") if m else raw
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _parse_git_describe(raw: str) -> str:
|
|
77
|
+
# Input shapes (``git describe --long --always``):
|
|
78
|
+
# r1.2.3-5-gabc1234 -> 1.2.3.post5.dev0+gabc1234
|
|
79
|
+
# r1.2.3b1-0-gdeadbea -> 1.2.3b1
|
|
80
|
+
# abc1234 -> 0.0.0.dev0+gabc1234 (no matching tag)
|
|
81
|
+
m = re.match(r"^(?P<tag>.+)-(?P<count>\d+)-g(?P<sha>[^-]+)$", raw)
|
|
82
|
+
if m:
|
|
83
|
+
version = _strip_tag_prefix(m.group("tag"))
|
|
84
|
+
try:
|
|
85
|
+
n = int(m.group("count"))
|
|
86
|
+
except ValueError:
|
|
87
|
+
n = 0
|
|
88
|
+
if n == 0:
|
|
89
|
+
return version
|
|
90
|
+
return f"{version}.post{n}.dev0+g{m.group('sha')}"
|
|
91
|
+
|
|
92
|
+
rev = _run_git("rev-parse", "--short", "HEAD") or raw
|
|
93
|
+
return f"{FALLBACK_VERSION}+g{rev.lstrip('g')}"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _inside_git_worktree() -> bool:
|
|
97
|
+
cur = _package_root()
|
|
98
|
+
while True:
|
|
99
|
+
if (cur / ".git").exists():
|
|
100
|
+
return True
|
|
101
|
+
parent = cur.parent
|
|
102
|
+
if parent == cur:
|
|
103
|
+
return False
|
|
104
|
+
cur = parent
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_version() -> str:
|
|
108
|
+
"""Return the full-precision version. No caching. Intended for debug use."""
|
|
109
|
+
built = _version_from_build_file()
|
|
110
|
+
if built is not None:
|
|
111
|
+
return built
|
|
112
|
+
if _inside_git_worktree():
|
|
113
|
+
raw = _run_git(
|
|
114
|
+
"describe", "--tags", "--long", "--always", "--match=r[0-9]*",
|
|
115
|
+
)
|
|
116
|
+
if raw:
|
|
117
|
+
return _parse_git_describe(raw)
|
|
118
|
+
return FALLBACK_VERSION
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
__version__: str = _version_from_build_file() or FALLBACK_VERSION
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
device_map = {
|
|
4
|
+
'gpu': 'cuda',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
single_devices = {'cpu'}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Device(object):
|
|
11
|
+
def __init__(self, device_type: str = 'cpu', device_index: int = None):
|
|
12
|
+
device_type = device_type.strip().lower()
|
|
13
|
+
|
|
14
|
+
colon_index = device_type.find(':')
|
|
15
|
+
if colon_index >= 0:
|
|
16
|
+
first, second = device_type[:colon_index], device_type[colon_index + 1:]
|
|
17
|
+
device_type = first
|
|
18
|
+
if device_index is None:
|
|
19
|
+
device_index = int(second)
|
|
20
|
+
|
|
21
|
+
if not device_type:
|
|
22
|
+
device_type = 'cpu'
|
|
23
|
+
if device_type in device_map:
|
|
24
|
+
device_type = device_map[device_type]
|
|
25
|
+
|
|
26
|
+
self.type = device_type
|
|
27
|
+
self.index = device_index
|
|
28
|
+
|
|
29
|
+
def __str__(self):
|
|
30
|
+
if self.index is None or self.type in single_devices:
|
|
31
|
+
return self.type
|
|
32
|
+
else:
|
|
33
|
+
return f'{self.type}:{self.index}'
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
dumps = {
|
|
37
|
+
'type': self.type,
|
|
38
|
+
'index': self.index,
|
|
39
|
+
}
|
|
40
|
+
fields = ', '.join([f'{k}={repr(v)}' for k, v in dumps.items() if v is not None])
|
|
41
|
+
return f'Device({fields})'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'Instance',
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Instance(ABC):
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def inference(self, *, data: dict[str, Any], report: dict[str, Any], **kwargs) -> dict[str, Any]:
|
|
14
|
+
"""
|
|
15
|
+
Call a frame of data.
|
|
16
|
+
:param data: dict[str, numpy.ndarray]
|
|
17
|
+
:param report: dict[str, Any]
|
|
18
|
+
:return:
|
|
19
|
+
The report has some predefined system parameters, such as "time" which represents a Unix timestamp.
|
|
20
|
+
"""
|
|
21
|
+
...
|
|
22
|
+
|
|
23
|
+
def reset(self):
|
|
24
|
+
"""
|
|
25
|
+
Reset the status after completing a segment of data processing,
|
|
26
|
+
to proceed with the next segment of data processing.
|
|
27
|
+
"""
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def dispose(self):
|
|
31
|
+
"""
|
|
32
|
+
It will be called when the instance is confirmed to be no longer in use, for timely resource release.
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
'Model',
|
|
8
|
+
'UsageModel',
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Model(ABC):
|
|
13
|
+
@property
|
|
14
|
+
def metadata(self) -> dict[str, Any]:
|
|
15
|
+
"""
|
|
16
|
+
Get model's metadata.
|
|
17
|
+
:return:
|
|
18
|
+
"""
|
|
19
|
+
return {}
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def exists(self) -> bool:
|
|
23
|
+
"""
|
|
24
|
+
Check whether the model already exists.
|
|
25
|
+
:return:
|
|
26
|
+
"""
|
|
27
|
+
...
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def cache(self) -> str:
|
|
31
|
+
"""
|
|
32
|
+
Cache model from host or use directly local file path.
|
|
33
|
+
If `self.exists` returns true, the cached path should be directly returned without extra download.
|
|
34
|
+
The consistency of cache state detection should be ensured by the implementation.
|
|
35
|
+
:return:
|
|
36
|
+
"""
|
|
37
|
+
...
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class UsageModel(Model, ABC):
|
|
41
|
+
@property
|
|
42
|
+
def usage(self) -> str:
|
|
43
|
+
"""
|
|
44
|
+
This model usage. Must be provided while using multi models instance.
|
|
45
|
+
:return: Model usage. Should be same with module config file.
|
|
46
|
+
"""
|
|
47
|
+
return ''
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
if __name__ == '__main__':
|
|
51
|
+
pass
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .device import Device
|
|
7
|
+
from .instance import Instance
|
|
8
|
+
from .model import UsageModel
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
'Package',
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Package(ABC):
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def create(self, *, models: list[UsageModel], parameters: dict[str, Any], device: Device | None,
|
|
18
|
+
**kwargs) -> Instance:
|
|
19
|
+
...
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import time
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import numpy
|
|
8
|
+
|
|
9
|
+
from seetapsych_lib import api
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ExampleInstance(api.Instance):
|
|
13
|
+
def __init__(self, model_path: str, device: api.Device):
|
|
14
|
+
time.sleep(1)
|
|
15
|
+
|
|
16
|
+
self.__model_path = model_path
|
|
17
|
+
self.__device = device
|
|
18
|
+
|
|
19
|
+
def inference(self, *, data: dict[str, Any], report: dict[str, Any], **kwargs) -> dict[str, Any]:
|
|
20
|
+
# print(f'Data: {data}')
|
|
21
|
+
|
|
22
|
+
time.sleep(0.01)
|
|
23
|
+
|
|
24
|
+
default_input = data['default']
|
|
25
|
+
image = numpy.ascontiguousarray(default_input)
|
|
26
|
+
|
|
27
|
+
print(f'Input default: {type(image)} {image.shape}')
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
'example_output': {
|
|
31
|
+
'values': [None, 12, 12.4, 'fff', False],
|
|
32
|
+
'shape': list(image.shape),
|
|
33
|
+
'output': [1, 2, 3],
|
|
34
|
+
'model': self.__model_path,
|
|
35
|
+
'device': None if self.__device is None else str(self.__device),
|
|
36
|
+
},
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class Package(api.Package):
|
|
41
|
+
def create(self, *, models: list[api.Model], parameters: dict[str, Any], device: api.Device | None,
|
|
42
|
+
**kwargs) -> api.Instance:
|
|
43
|
+
assert len(models) >= 1, api.MissingModelError('At least one model required')
|
|
44
|
+
|
|
45
|
+
if device is None:
|
|
46
|
+
device = api.Device('cpu')
|
|
47
|
+
|
|
48
|
+
json_parameters = json.dumps(parameters, indent=2, ensure_ascii=False)
|
|
49
|
+
print(f'Parameters: {json_parameters}')
|
|
50
|
+
|
|
51
|
+
model_path = models[0].cache()
|
|
52
|
+
return ExampleInstance(model_path, device)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def load_package() -> api.Package:
|
|
56
|
+
return Package()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
example_model_cached = False
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class ExampleModel(api.Model):
|
|
63
|
+
def __init__(self, path: str):
|
|
64
|
+
self.__path = path
|
|
65
|
+
|
|
66
|
+
def exists(self) -> bool:
|
|
67
|
+
global example_model_cached
|
|
68
|
+
|
|
69
|
+
return example_model_cached
|
|
70
|
+
|
|
71
|
+
def cache(self) -> str:
|
|
72
|
+
global example_model_cached
|
|
73
|
+
|
|
74
|
+
if self.exists():
|
|
75
|
+
return self.__path
|
|
76
|
+
|
|
77
|
+
time.sleep(1)
|
|
78
|
+
|
|
79
|
+
example_model_cached = True
|
|
80
|
+
return self.__path
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def load_model() -> api.Model:
|
|
84
|
+
return ExampleModel('non-exists-model.bin')
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
version: "1.0"
|
|
2
|
+
|
|
3
|
+
module:
|
|
4
|
+
name: "Example Module"
|
|
5
|
+
version: "0.0.1"
|
|
6
|
+
description: "This is an example module"
|
|
7
|
+
keywords:
|
|
8
|
+
- "Example"
|
|
9
|
+
- "Module"
|
|
10
|
+
requirements:
|
|
11
|
+
- "cowsay"
|
|
12
|
+
|
|
13
|
+
packages:
|
|
14
|
+
- name: "Example Package"
|
|
15
|
+
version: "0.0.1"
|
|
16
|
+
description: "This is an example package. Use to build pipeline to run."
|
|
17
|
+
keywords:
|
|
18
|
+
- "Example"
|
|
19
|
+
- "Package"
|
|
20
|
+
usage_models: []
|
|
21
|
+
inputs: []
|
|
22
|
+
provides:
|
|
23
|
+
- "example/output"
|
|
24
|
+
requires: []
|
|
25
|
+
entry:
|
|
26
|
+
method: "seetapsych_lib.example.example.load_package"
|
|
27
|
+
parameters:
|
|
28
|
+
- name: "min_face"
|
|
29
|
+
type: "integer"
|
|
30
|
+
value: 80
|
|
31
|
+
description: "Min face to detect"
|
|
32
|
+
- name: "threshold"
|
|
33
|
+
type: "number"
|
|
34
|
+
value: 0.8
|
|
35
|
+
description: "Threshold of face"
|
|
36
|
+
- name: "object_name"
|
|
37
|
+
type: "string"
|
|
38
|
+
value: "face"
|
|
39
|
+
description: "Detection target name"
|
|
40
|
+
- name: "scale"
|
|
41
|
+
type: "selection"
|
|
42
|
+
value: "big"
|
|
43
|
+
selection:
|
|
44
|
+
- "big"
|
|
45
|
+
- "small"
|
|
46
|
+
description: "Large?"
|
|
47
|
+
- name: "integer[]"
|
|
48
|
+
type: "integer[]"
|
|
49
|
+
value:
|
|
50
|
+
- 80
|
|
51
|
+
description: "Select multi integer"
|
|
52
|
+
- name: "number[]"
|
|
53
|
+
type: "number[]"
|
|
54
|
+
value:
|
|
55
|
+
- 0.8
|
|
56
|
+
description: "Select multi number"
|
|
57
|
+
- name: "string[]"
|
|
58
|
+
type: "string[]"
|
|
59
|
+
value:
|
|
60
|
+
- "face"
|
|
61
|
+
description: "Select multi string"
|
|
62
|
+
- name: "selection[]"
|
|
63
|
+
type: "selection[]"
|
|
64
|
+
value:
|
|
65
|
+
- "big"
|
|
66
|
+
selection:
|
|
67
|
+
- "big"
|
|
68
|
+
- "small"
|
|
69
|
+
description: "Select multi selection"
|
|
70
|
+
- name: "object"
|
|
71
|
+
type: "object"
|
|
72
|
+
value: {}
|
|
73
|
+
description: "Edit object"
|
|
74
|
+
models:
|
|
75
|
+
- name: "Example Model"
|
|
76
|
+
version: "0.0.1"
|
|
77
|
+
description: "This is an example model. Unable to download and cannot be persistent cached."
|
|
78
|
+
keywords:
|
|
79
|
+
- "Example"
|
|
80
|
+
- "Model"
|
|
81
|
+
usage: ""
|
|
82
|
+
recommended: true
|
|
83
|
+
entry:
|
|
84
|
+
method: "seetapsych_lib.example.example.load_model"
|