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.
Files changed (47) hide show
  1. seetapsych_lib/__init__.py +5 -0
  2. seetapsych_lib/_version.py +24 -0
  3. seetapsych_lib/_version_resolve.py +121 -0
  4. seetapsych_lib/api/__init__.py +8 -0
  5. seetapsych_lib/api/device.py +41 -0
  6. seetapsych_lib/api/error.py +9 -0
  7. seetapsych_lib/api/instance.py +34 -0
  8. seetapsych_lib/api/model.py +51 -0
  9. seetapsych_lib/api/package.py +19 -0
  10. seetapsych_lib/example/example.py +84 -0
  11. seetapsych_lib/example/example.yml +84 -0
  12. seetapsych_lib/manager/__main__.py +8 -0
  13. seetapsych_lib/manager/cli.py +589 -0
  14. seetapsych_lib/modules/face_selection.yml +29 -0
  15. seetapsych_lib/onnx/session.py +84 -0
  16. seetapsych_lib/runtime/__init__.py +5 -0
  17. seetapsych_lib/runtime/actions.py +368 -0
  18. seetapsych_lib/runtime/export.py +197 -0
  19. seetapsych_lib/runtime/factory.py +153 -0
  20. seetapsych_lib/runtime/model.py +437 -0
  21. seetapsych_lib/runtime/module.py +151 -0
  22. seetapsych_lib/runtime/parallel/executor.py +684 -0
  23. seetapsych_lib/runtime/parallel/future.py +254 -0
  24. seetapsych_lib/runtime/parallel_runner.py +366 -0
  25. seetapsych_lib/runtime/pipeline.py +862 -0
  26. seetapsych_lib/runtime/runner.py +181 -0
  27. seetapsych_lib/schema/__init__.py +3 -0
  28. seetapsych_lib/schema/module.py +254 -0
  29. seetapsych_lib/toolkit/face_selection.py +114 -0
  30. seetapsych_lib/toolkit/packages/face_selection.py +76 -0
  31. seetapsych_lib/utils/__init__.py +1 -0
  32. seetapsych_lib/utils/cuda.py +114 -0
  33. seetapsych_lib/utils/defer.py +32 -0
  34. seetapsych_lib/utils/dirs.py +15 -0
  35. seetapsych_lib/utils/download_file.py +469 -0
  36. seetapsych_lib/utils/loader.py +88 -0
  37. seetapsych_lib/utils/logger.py +75 -0
  38. seetapsych_lib/utils/markdown.py +30 -0
  39. seetapsych_lib/utils/pencilbox.py +8 -0
  40. seetapsych_lib/webui/__main__.py +8 -0
  41. seetapsych_lib/webui/app.py +1351 -0
  42. seetapsych_lib/webui/cli.py +18 -0
  43. seetapsych_lib-0.0.1.dist-info/METADATA +198 -0
  44. seetapsych_lib-0.0.1.dist-info/RECORD +47 -0
  45. seetapsych_lib-0.0.1.dist-info/WHEEL +4 -0
  46. seetapsych_lib-0.0.1.dist-info/entry_points.txt +3 -0
  47. seetapsych_lib-0.0.1.dist-info/licenses/LICENSE +15 -0
@@ -0,0 +1,5 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ._version_resolve import __version__, get_version
4
+
5
+ __all__ = ["__version__", "get_version"]
@@ -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,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .device import Device
4
+ from .instance import Instance
5
+ from .model import Model, UsageModel
6
+ from .package import Package
7
+
8
+ from .error import *
@@ -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,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ class Error(Exception):
5
+ pass
6
+
7
+
8
+ class MissingModelError(Error):
9
+ pass
@@ -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"
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ from .cli import main
5
+
6
+
7
+ if __name__ == '__main__':
8
+ main()