synapse-sdk 1.0.0a11__py3-none-any.whl → 2026.1.1b2__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 synapse-sdk might be problematic. Click here for more details.
- synapse_sdk/__init__.py +24 -0
- synapse_sdk/cli/__init__.py +9 -8
- synapse_sdk/cli/agent/__init__.py +25 -0
- synapse_sdk/cli/agent/config.py +104 -0
- synapse_sdk/cli/agent/select.py +197 -0
- synapse_sdk/cli/auth.py +104 -0
- synapse_sdk/cli/main.py +1025 -0
- synapse_sdk/cli/plugin/__init__.py +58 -0
- synapse_sdk/cli/plugin/create.py +566 -0
- synapse_sdk/cli/plugin/job.py +196 -0
- synapse_sdk/cli/plugin/publish.py +322 -0
- synapse_sdk/cli/plugin/run.py +131 -0
- synapse_sdk/cli/plugin/test.py +200 -0
- synapse_sdk/clients/README.md +239 -0
- synapse_sdk/clients/__init__.py +5 -0
- synapse_sdk/clients/_template.py +266 -0
- synapse_sdk/clients/agent/__init__.py +84 -29
- synapse_sdk/clients/agent/async_ray.py +289 -0
- synapse_sdk/clients/agent/container.py +83 -0
- synapse_sdk/clients/agent/plugin.py +101 -0
- synapse_sdk/clients/agent/ray.py +296 -39
- synapse_sdk/clients/backend/__init__.py +152 -12
- synapse_sdk/clients/backend/annotation.py +164 -22
- synapse_sdk/clients/backend/core.py +101 -0
- synapse_sdk/clients/backend/data_collection.py +292 -0
- synapse_sdk/clients/backend/hitl.py +87 -0
- synapse_sdk/clients/backend/integration.py +374 -46
- synapse_sdk/clients/backend/ml.py +134 -22
- synapse_sdk/clients/backend/models.py +247 -0
- synapse_sdk/clients/base.py +538 -59
- synapse_sdk/clients/exceptions.py +35 -7
- synapse_sdk/clients/pipeline/__init__.py +5 -0
- synapse_sdk/clients/pipeline/client.py +636 -0
- synapse_sdk/clients/protocols.py +178 -0
- synapse_sdk/clients/utils.py +86 -8
- synapse_sdk/clients/validation.py +58 -0
- synapse_sdk/enums.py +76 -0
- synapse_sdk/exceptions.py +168 -0
- synapse_sdk/integrations/__init__.py +74 -0
- synapse_sdk/integrations/_base.py +119 -0
- synapse_sdk/integrations/_context.py +53 -0
- synapse_sdk/integrations/ultralytics/__init__.py +78 -0
- synapse_sdk/integrations/ultralytics/_callbacks.py +126 -0
- synapse_sdk/integrations/ultralytics/_patches.py +124 -0
- synapse_sdk/loggers.py +476 -95
- synapse_sdk/mcp/MCP.md +69 -0
- synapse_sdk/mcp/__init__.py +48 -0
- synapse_sdk/mcp/__main__.py +6 -0
- synapse_sdk/mcp/config.py +349 -0
- synapse_sdk/mcp/prompts/__init__.py +4 -0
- synapse_sdk/mcp/resources/__init__.py +4 -0
- synapse_sdk/mcp/server.py +1352 -0
- synapse_sdk/mcp/tools/__init__.py +6 -0
- synapse_sdk/plugins/__init__.py +133 -9
- synapse_sdk/plugins/action.py +229 -0
- synapse_sdk/plugins/actions/__init__.py +82 -0
- synapse_sdk/plugins/actions/dataset/__init__.py +37 -0
- synapse_sdk/plugins/actions/dataset/action.py +471 -0
- synapse_sdk/plugins/actions/export/__init__.py +55 -0
- synapse_sdk/plugins/actions/export/action.py +183 -0
- synapse_sdk/plugins/actions/export/context.py +59 -0
- synapse_sdk/plugins/actions/inference/__init__.py +84 -0
- synapse_sdk/plugins/actions/inference/action.py +285 -0
- synapse_sdk/plugins/actions/inference/context.py +81 -0
- synapse_sdk/plugins/actions/inference/deployment.py +322 -0
- synapse_sdk/plugins/actions/inference/serve.py +252 -0
- synapse_sdk/plugins/actions/train/__init__.py +54 -0
- synapse_sdk/plugins/actions/train/action.py +326 -0
- synapse_sdk/plugins/actions/train/context.py +57 -0
- synapse_sdk/plugins/actions/upload/__init__.py +49 -0
- synapse_sdk/plugins/actions/upload/action.py +165 -0
- synapse_sdk/plugins/actions/upload/context.py +61 -0
- synapse_sdk/plugins/config.py +98 -0
- synapse_sdk/plugins/context/__init__.py +109 -0
- synapse_sdk/plugins/context/env.py +113 -0
- synapse_sdk/plugins/datasets/__init__.py +113 -0
- synapse_sdk/plugins/datasets/converters/__init__.py +76 -0
- synapse_sdk/plugins/datasets/converters/base.py +347 -0
- synapse_sdk/plugins/datasets/converters/yolo/__init__.py +9 -0
- synapse_sdk/plugins/datasets/converters/yolo/from_dm.py +468 -0
- synapse_sdk/plugins/datasets/converters/yolo/to_dm.py +381 -0
- synapse_sdk/plugins/datasets/formats/__init__.py +82 -0
- synapse_sdk/plugins/datasets/formats/dm.py +351 -0
- synapse_sdk/plugins/datasets/formats/yolo.py +240 -0
- synapse_sdk/plugins/decorators.py +83 -0
- synapse_sdk/plugins/discovery.py +790 -0
- synapse_sdk/plugins/docs/ACTION_DEV_GUIDE.md +933 -0
- synapse_sdk/plugins/docs/ARCHITECTURE.md +1225 -0
- synapse_sdk/plugins/docs/LOGGING_SYSTEM.md +683 -0
- synapse_sdk/plugins/docs/OVERVIEW.md +531 -0
- synapse_sdk/plugins/docs/PIPELINE_GUIDE.md +145 -0
- synapse_sdk/plugins/docs/README.md +513 -0
- synapse_sdk/plugins/docs/STEP.md +656 -0
- synapse_sdk/plugins/enums.py +70 -10
- synapse_sdk/plugins/errors.py +92 -0
- synapse_sdk/plugins/executors/__init__.py +43 -0
- synapse_sdk/plugins/executors/local.py +99 -0
- synapse_sdk/plugins/executors/ray/__init__.py +18 -0
- synapse_sdk/plugins/executors/ray/base.py +282 -0
- synapse_sdk/plugins/executors/ray/job.py +298 -0
- synapse_sdk/plugins/executors/ray/jobs_api.py +511 -0
- synapse_sdk/plugins/executors/ray/packaging.py +137 -0
- synapse_sdk/plugins/executors/ray/pipeline.py +792 -0
- synapse_sdk/plugins/executors/ray/task.py +257 -0
- synapse_sdk/plugins/models/__init__.py +26 -0
- synapse_sdk/plugins/models/logger.py +173 -0
- synapse_sdk/plugins/models/pipeline.py +25 -0
- synapse_sdk/plugins/pipelines/__init__.py +81 -0
- synapse_sdk/plugins/pipelines/action_pipeline.py +417 -0
- synapse_sdk/plugins/pipelines/context.py +107 -0
- synapse_sdk/plugins/pipelines/display.py +311 -0
- synapse_sdk/plugins/runner.py +114 -0
- synapse_sdk/plugins/schemas/__init__.py +19 -0
- synapse_sdk/plugins/schemas/results.py +152 -0
- synapse_sdk/plugins/steps/__init__.py +63 -0
- synapse_sdk/plugins/steps/base.py +128 -0
- synapse_sdk/plugins/steps/context.py +90 -0
- synapse_sdk/plugins/steps/orchestrator.py +128 -0
- synapse_sdk/plugins/steps/registry.py +103 -0
- synapse_sdk/plugins/steps/utils/__init__.py +20 -0
- synapse_sdk/plugins/steps/utils/logging.py +85 -0
- synapse_sdk/plugins/steps/utils/timing.py +71 -0
- synapse_sdk/plugins/steps/utils/validation.py +68 -0
- synapse_sdk/plugins/templates/__init__.py +50 -0
- synapse_sdk/plugins/templates/base/.gitignore.j2 +26 -0
- synapse_sdk/plugins/templates/base/.synapseignore.j2 +11 -0
- synapse_sdk/plugins/templates/base/README.md.j2 +26 -0
- synapse_sdk/plugins/templates/base/plugin/__init__.py.j2 +1 -0
- synapse_sdk/plugins/templates/base/pyproject.toml.j2 +14 -0
- synapse_sdk/plugins/templates/base/requirements.txt.j2 +1 -0
- synapse_sdk/plugins/templates/custom/plugin/main.py.j2 +18 -0
- synapse_sdk/plugins/templates/data_validation/plugin/validate.py.j2 +32 -0
- synapse_sdk/plugins/templates/export/plugin/export.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/inference.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/train.py.j2 +33 -0
- synapse_sdk/plugins/templates/post_annotation/plugin/post_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/pre_annotation/plugin/pre_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/smart_tool/plugin/auto_label.py.j2 +44 -0
- synapse_sdk/plugins/templates/upload/plugin/upload.py.j2 +35 -0
- synapse_sdk/plugins/testing/__init__.py +25 -0
- synapse_sdk/plugins/testing/sample_actions.py +98 -0
- synapse_sdk/plugins/types.py +206 -0
- synapse_sdk/plugins/upload.py +595 -64
- synapse_sdk/plugins/utils.py +325 -37
- synapse_sdk/shared/__init__.py +25 -0
- synapse_sdk/utils/__init__.py +1 -0
- synapse_sdk/utils/auth.py +74 -0
- synapse_sdk/utils/file/__init__.py +58 -0
- synapse_sdk/utils/file/archive.py +449 -0
- synapse_sdk/utils/file/checksum.py +167 -0
- synapse_sdk/utils/file/download.py +286 -0
- synapse_sdk/utils/file/io.py +129 -0
- synapse_sdk/utils/file/requirements.py +36 -0
- synapse_sdk/utils/network.py +168 -0
- synapse_sdk/utils/storage/__init__.py +238 -0
- synapse_sdk/utils/storage/config.py +188 -0
- synapse_sdk/utils/storage/errors.py +52 -0
- synapse_sdk/utils/storage/providers/__init__.py +13 -0
- synapse_sdk/utils/storage/providers/base.py +76 -0
- synapse_sdk/utils/storage/providers/gcs.py +168 -0
- synapse_sdk/utils/storage/providers/http.py +250 -0
- synapse_sdk/utils/storage/providers/local.py +126 -0
- synapse_sdk/utils/storage/providers/s3.py +177 -0
- synapse_sdk/utils/storage/providers/sftp.py +208 -0
- synapse_sdk/utils/storage/registry.py +125 -0
- synapse_sdk/utils/websocket.py +99 -0
- synapse_sdk-2026.1.1b2.dist-info/METADATA +715 -0
- synapse_sdk-2026.1.1b2.dist-info/RECORD +172 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/WHEEL +1 -1
- synapse_sdk-2026.1.1b2.dist-info/licenses/LICENSE +201 -0
- locale/en/LC_MESSAGES/messages.mo +0 -0
- locale/en/LC_MESSAGES/messages.po +0 -39
- locale/ko/LC_MESSAGES/messages.mo +0 -0
- locale/ko/LC_MESSAGES/messages.po +0 -34
- synapse_sdk/cli/create_plugin.py +0 -10
- synapse_sdk/clients/agent/core.py +0 -7
- synapse_sdk/clients/agent/service.py +0 -15
- synapse_sdk/clients/backend/dataset.py +0 -51
- synapse_sdk/clients/ray/__init__.py +0 -6
- synapse_sdk/clients/ray/core.py +0 -22
- synapse_sdk/clients/ray/serve.py +0 -20
- synapse_sdk/i18n.py +0 -35
- synapse_sdk/plugins/categories/__init__.py +0 -0
- synapse_sdk/plugins/categories/base.py +0 -235
- synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -10
- synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -5
- synapse_sdk/plugins/categories/decorators.py +0 -13
- synapse_sdk/plugins/categories/export/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/export.py +0 -10
- synapse_sdk/plugins/categories/import/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -45
- synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -18
- synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -10
- synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -143
- synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -12
- synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -4
- synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -2
- synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -14
- synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -10
- synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -3
- synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -10
- synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -3
- synapse_sdk/plugins/categories/registry.py +0 -16
- synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -37
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -7
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -11
- synapse_sdk/plugins/categories/templates.py +0 -32
- synapse_sdk/plugins/cli/__init__.py +0 -21
- synapse_sdk/plugins/cli/publish.py +0 -37
- synapse_sdk/plugins/cli/run.py +0 -67
- synapse_sdk/plugins/exceptions.py +0 -22
- synapse_sdk/plugins/models.py +0 -121
- synapse_sdk/plugins/templates/cookiecutter.json +0 -11
- synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -3
- synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -21
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -27
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -7
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -5
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -6
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -13
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -1
- synapse_sdk/shared/enums.py +0 -8
- synapse_sdk/utils/debug.py +0 -5
- synapse_sdk/utils/file.py +0 -87
- synapse_sdk/utils/module_loading.py +0 -29
- synapse_sdk/utils/pydantic/__init__.py +0 -0
- synapse_sdk/utils/pydantic/config.py +0 -4
- synapse_sdk/utils/pydantic/errors.py +0 -33
- synapse_sdk/utils/pydantic/validators.py +0 -7
- synapse_sdk/utils/storage.py +0 -91
- synapse_sdk/utils/string.py +0 -11
- synapse_sdk-1.0.0a11.dist-info/LICENSE +0 -21
- synapse_sdk-1.0.0a11.dist-info/METADATA +0 -43
- synapse_sdk-1.0.0a11.dist-info/RECORD +0 -111
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"""Export action base class with optional step support."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from synapse_sdk.plugins.action import BaseAction
|
|
10
|
+
from synapse_sdk.plugins.actions.export.context import ExportContext
|
|
11
|
+
from synapse_sdk.plugins.enums import PluginCategory
|
|
12
|
+
from synapse_sdk.plugins.steps import Orchestrator, StepRegistry
|
|
13
|
+
|
|
14
|
+
P = TypeVar('P', bound=BaseModel)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ExportProgressCategories:
|
|
21
|
+
"""Standard progress category names for export workflows.
|
|
22
|
+
|
|
23
|
+
Use these constants with set_progress() to track export phases:
|
|
24
|
+
- DATASET_CONVERSION: Data conversion and file generation
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
>>> self.set_progress(50, 100, self.progress.DATASET_CONVERSION)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
DATASET_CONVERSION: str = 'dataset_conversion'
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class BaseExportAction(BaseAction[P]):
|
|
34
|
+
"""Base class for export actions.
|
|
35
|
+
|
|
36
|
+
Provides helper methods for export workflows.
|
|
37
|
+
Override get_filtered_results() for your specific target type.
|
|
38
|
+
|
|
39
|
+
Supports two execution modes:
|
|
40
|
+
1. Simple execute: Override execute() directly for simple workflows
|
|
41
|
+
2. Step-based: Override setup_steps() to register workflow steps
|
|
42
|
+
|
|
43
|
+
If setup_steps() registers any steps, the step-based workflow
|
|
44
|
+
takes precedence and execute() is not called directly.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
category: Plugin category (defaults to EXPORT).
|
|
48
|
+
progress: Standard progress category names.
|
|
49
|
+
|
|
50
|
+
Example (simple execute):
|
|
51
|
+
>>> class MyExportAction(BaseExportAction[MyParams]):
|
|
52
|
+
... action_name = 'export'
|
|
53
|
+
... params_model = MyParams
|
|
54
|
+
...
|
|
55
|
+
... def get_filtered_results(self, filters: dict) -> tuple[Any, int]:
|
|
56
|
+
... return self.client.get_assignments(filters)
|
|
57
|
+
...
|
|
58
|
+
... def execute(self) -> dict[str, Any]:
|
|
59
|
+
... results, count = self.get_filtered_results(self.params.filter)
|
|
60
|
+
... self.set_progress(0, count, self.progress.DATASET_CONVERSION)
|
|
61
|
+
... for i, item in enumerate(results, 1):
|
|
62
|
+
... # Process and export item
|
|
63
|
+
... self.set_progress(i, count, self.progress.DATASET_CONVERSION)
|
|
64
|
+
... return {'exported': count}
|
|
65
|
+
|
|
66
|
+
Example (step-based):
|
|
67
|
+
>>> class MyExportAction(BaseExportAction[MyParams]):
|
|
68
|
+
... def setup_steps(self, registry: StepRegistry[ExportContext]) -> None:
|
|
69
|
+
... registry.register(FetchResultsStep())
|
|
70
|
+
... registry.register(ProcessStep())
|
|
71
|
+
... registry.register(FinalizeStep())
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
category = PluginCategory.EXPORT
|
|
75
|
+
progress = ExportProgressCategories()
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def client(self) -> BackendClient:
|
|
79
|
+
"""Backend client from context.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
BackendClient instance.
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
RuntimeError: If no client in context.
|
|
86
|
+
"""
|
|
87
|
+
if self.ctx.client is None:
|
|
88
|
+
raise RuntimeError(
|
|
89
|
+
'No client in context. Either provide a client via RuntimeContext or override get_filtered_results().'
|
|
90
|
+
)
|
|
91
|
+
return self.ctx.client
|
|
92
|
+
|
|
93
|
+
def setup_steps(self, registry: StepRegistry[ExportContext]) -> None:
|
|
94
|
+
"""Register workflow steps for step-based execution.
|
|
95
|
+
|
|
96
|
+
Override this method to register custom steps for your export workflow.
|
|
97
|
+
If steps are registered, step-based execution takes precedence.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
registry: StepRegistry to register steps with.
|
|
101
|
+
|
|
102
|
+
Example:
|
|
103
|
+
>>> def setup_steps(self, registry: StepRegistry[ExportContext]) -> None:
|
|
104
|
+
... registry.register(FetchResultsStep())
|
|
105
|
+
... registry.register(ProcessStep())
|
|
106
|
+
... registry.register(FinalizeStep())
|
|
107
|
+
"""
|
|
108
|
+
pass # Default: no steps, uses simple execute()
|
|
109
|
+
|
|
110
|
+
def create_context(self) -> ExportContext:
|
|
111
|
+
"""Create export context for step-based workflow.
|
|
112
|
+
|
|
113
|
+
Override to customize context creation or add additional state.
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
ExportContext instance with params and runtime context.
|
|
117
|
+
"""
|
|
118
|
+
params_dict = self.params.model_dump() if hasattr(self.params, 'model_dump') else dict(self.params)
|
|
119
|
+
return ExportContext(
|
|
120
|
+
runtime_ctx=self.ctx,
|
|
121
|
+
params=params_dict,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def run(self) -> Any:
|
|
125
|
+
"""Run the action, using steps if registered.
|
|
126
|
+
|
|
127
|
+
This method is called by executors. It checks if steps are
|
|
128
|
+
registered and uses step-based execution if so.
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Action result (dict or any return type).
|
|
132
|
+
"""
|
|
133
|
+
# Check if steps are registered
|
|
134
|
+
registry: StepRegistry[ExportContext] = StepRegistry()
|
|
135
|
+
self.setup_steps(registry)
|
|
136
|
+
|
|
137
|
+
if registry:
|
|
138
|
+
# Step-based execution
|
|
139
|
+
context = self.create_context()
|
|
140
|
+
orchestrator: Orchestrator[ExportContext] = Orchestrator(
|
|
141
|
+
registry=registry,
|
|
142
|
+
context=context,
|
|
143
|
+
progress_callback=lambda curr, total: self.set_progress(curr, total),
|
|
144
|
+
)
|
|
145
|
+
result = orchestrator.execute()
|
|
146
|
+
|
|
147
|
+
# Add context data to result
|
|
148
|
+
result['exported_count'] = context.exported_count
|
|
149
|
+
if context.output_path:
|
|
150
|
+
result['output_path'] = context.output_path
|
|
151
|
+
|
|
152
|
+
return result
|
|
153
|
+
|
|
154
|
+
# Simple execute mode
|
|
155
|
+
return self.execute()
|
|
156
|
+
|
|
157
|
+
def get_filtered_results(self, filters: dict[str, Any]) -> tuple[Any, int]:
|
|
158
|
+
"""Fetch filtered results for export.
|
|
159
|
+
|
|
160
|
+
Override this method for your specific target type
|
|
161
|
+
(assignments, ground_truth, tasks, or custom).
|
|
162
|
+
|
|
163
|
+
Args:
|
|
164
|
+
filters: Filter criteria dict.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Tuple of (results_iterator, total_count).
|
|
168
|
+
|
|
169
|
+
Raises:
|
|
170
|
+
NotImplementedError: Must be overridden by subclass.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
>>> # Override for assignments:
|
|
174
|
+
>>> def get_filtered_results(self, filters: dict) -> tuple[Any, int]:
|
|
175
|
+
... return self.client.get_assignments(filters)
|
|
176
|
+
>>>
|
|
177
|
+
>>> # Override for ground truth:
|
|
178
|
+
>>> def get_filtered_results(self, filters: dict) -> tuple[Any, int]:
|
|
179
|
+
... return self.client.get_ground_truth(filters)
|
|
180
|
+
"""
|
|
181
|
+
raise NotImplementedError(
|
|
182
|
+
'Override get_filtered_results() for your target type. Example: return self.client.get_assignments(filters)'
|
|
183
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Export context for sharing state between workflow steps."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from synapse_sdk.plugins.steps import BaseStepContext
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class ExportContext(BaseStepContext):
|
|
16
|
+
"""Shared context passed between export workflow steps.
|
|
17
|
+
|
|
18
|
+
Extends BaseStepContext with export-specific state fields.
|
|
19
|
+
Carries parameters and accumulated state as the workflow
|
|
20
|
+
progresses through steps.
|
|
21
|
+
|
|
22
|
+
Attributes:
|
|
23
|
+
params: Export parameters (from action params).
|
|
24
|
+
results: Fetched results to export (populated by fetch step).
|
|
25
|
+
total_count: Total number of items to export.
|
|
26
|
+
exported_count: Number of items successfully exported.
|
|
27
|
+
output_path: Path to export output file/directory.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
>>> context = ExportContext(
|
|
31
|
+
... runtime_ctx=runtime_ctx,
|
|
32
|
+
... params={'format': 'coco', 'filter': {}},
|
|
33
|
+
... )
|
|
34
|
+
>>> # Steps populate state as they execute
|
|
35
|
+
>>> context.results = fetched_data
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# Export parameters
|
|
39
|
+
params: dict[str, Any] = field(default_factory=dict)
|
|
40
|
+
|
|
41
|
+
# Processing state (populated by steps)
|
|
42
|
+
results: Any | None = None
|
|
43
|
+
total_count: int = 0
|
|
44
|
+
exported_count: int = 0
|
|
45
|
+
output_path: str | None = None
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def client(self) -> BackendClient:
|
|
49
|
+
"""Backend client from runtime context.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
BackendClient instance.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
RuntimeError: If no client in runtime context.
|
|
56
|
+
"""
|
|
57
|
+
if self.runtime_ctx.client is None:
|
|
58
|
+
raise RuntimeError('No client in runtime context')
|
|
59
|
+
return self.runtime_ctx.client
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Inference action module with Ray Serve integration.
|
|
2
|
+
|
|
3
|
+
This module provides base classes for inference and deployment actions:
|
|
4
|
+
|
|
5
|
+
- **BaseInferenceAction**: For batch inference or REST API inference
|
|
6
|
+
- **BaseDeploymentAction**: For deploying models to Ray Serve
|
|
7
|
+
- **BaseServeDeployment**: Ray Serve deployment class for model serving
|
|
8
|
+
- **InferenceContext**: Step-based workflow context for inference
|
|
9
|
+
- **DeploymentContext**: Step-based workflow context for deployment
|
|
10
|
+
|
|
11
|
+
Example (Simple Inference):
|
|
12
|
+
>>> from synapse_sdk.plugins.actions.inference import BaseInferenceAction
|
|
13
|
+
>>>
|
|
14
|
+
>>> class MyInferenceAction(BaseInferenceAction[MyParams]):
|
|
15
|
+
... action_name = 'inference'
|
|
16
|
+
... category = 'neural_net'
|
|
17
|
+
... params_model = MyParams
|
|
18
|
+
...
|
|
19
|
+
... def execute(self) -> dict:
|
|
20
|
+
... model_info = self.load_model(self.params.model_id)
|
|
21
|
+
... results = self.infer(model_info, self.params.inputs)
|
|
22
|
+
... return {'results': results}
|
|
23
|
+
|
|
24
|
+
Example (Ray Serve Deployment):
|
|
25
|
+
>>> from synapse_sdk.plugins.actions.inference import (
|
|
26
|
+
... BaseDeploymentAction,
|
|
27
|
+
... BaseServeDeployment,
|
|
28
|
+
... )
|
|
29
|
+
>>>
|
|
30
|
+
>>> class MyServeDeployment(BaseServeDeployment):
|
|
31
|
+
... async def _get_model(self, model_info: dict) -> Any:
|
|
32
|
+
... import torch
|
|
33
|
+
... return torch.load(model_info['path'] / 'model.pt')
|
|
34
|
+
...
|
|
35
|
+
... async def infer(self, inputs: list[dict]) -> list[dict]:
|
|
36
|
+
... model = await self.get_model()
|
|
37
|
+
... return [{'pred': model(inp)} for inp in inputs]
|
|
38
|
+
>>>
|
|
39
|
+
>>> class MyDeploymentAction(BaseDeploymentAction[MyParams]):
|
|
40
|
+
... action_name = 'deployment'
|
|
41
|
+
... category = 'neural_net'
|
|
42
|
+
... params_model = MyParams
|
|
43
|
+
... entrypoint = MyServeDeployment
|
|
44
|
+
...
|
|
45
|
+
... def execute(self) -> dict:
|
|
46
|
+
... self.ray_init()
|
|
47
|
+
... self.deploy()
|
|
48
|
+
... app_id = self.register_serve_application()
|
|
49
|
+
... return {'serve_application': app_id}
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from __future__ import annotations
|
|
53
|
+
|
|
54
|
+
from synapse_sdk.plugins.actions.inference.action import (
|
|
55
|
+
BaseInferenceAction,
|
|
56
|
+
InferenceProgressCategories,
|
|
57
|
+
)
|
|
58
|
+
from synapse_sdk.plugins.actions.inference.context import (
|
|
59
|
+
DeploymentContext,
|
|
60
|
+
InferenceContext,
|
|
61
|
+
)
|
|
62
|
+
from synapse_sdk.plugins.actions.inference.deployment import (
|
|
63
|
+
BaseDeploymentAction,
|
|
64
|
+
DeploymentProgressCategories,
|
|
65
|
+
)
|
|
66
|
+
from synapse_sdk.plugins.actions.inference.serve import (
|
|
67
|
+
BaseServeDeployment,
|
|
68
|
+
create_serve_multiplexed_model_id,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
__all__ = [
|
|
72
|
+
# Actions
|
|
73
|
+
'BaseInferenceAction',
|
|
74
|
+
'BaseDeploymentAction',
|
|
75
|
+
# Serve
|
|
76
|
+
'BaseServeDeployment',
|
|
77
|
+
'create_serve_multiplexed_model_id',
|
|
78
|
+
# Contexts
|
|
79
|
+
'InferenceContext',
|
|
80
|
+
'DeploymentContext',
|
|
81
|
+
# Progress Categories
|
|
82
|
+
'InferenceProgressCategories',
|
|
83
|
+
'DeploymentProgressCategories',
|
|
84
|
+
]
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""Inference action base class with optional step support."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import tempfile
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Any, TypeVar
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
|
|
11
|
+
from synapse_sdk.plugins.action import BaseAction
|
|
12
|
+
from synapse_sdk.plugins.actions.inference.context import InferenceContext
|
|
13
|
+
from synapse_sdk.plugins.enums import PluginCategory
|
|
14
|
+
from synapse_sdk.plugins.steps import Orchestrator, StepRegistry
|
|
15
|
+
from synapse_sdk.utils.file.archive import extract_archive
|
|
16
|
+
|
|
17
|
+
P = TypeVar('P', bound=BaseModel)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from synapse_sdk.clients.backend import BackendClient
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class InferenceProgressCategories:
|
|
24
|
+
"""Standard progress category names for inference workflows.
|
|
25
|
+
|
|
26
|
+
Use these constants with set_progress() to track inference phases:
|
|
27
|
+
- MODEL_LOAD: Model loading and initialization
|
|
28
|
+
- INFERENCE: Running inference on inputs
|
|
29
|
+
- POSTPROCESS: Post-processing results
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
>>> self.set_progress(1, 3, self.progress.MODEL_LOAD)
|
|
33
|
+
>>> self.set_progress(2, 3, self.progress.INFERENCE)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
MODEL_LOAD: str = 'model_load'
|
|
37
|
+
INFERENCE: str = 'inference'
|
|
38
|
+
POSTPROCESS: str = 'postprocess'
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class BaseInferenceAction(BaseAction[P]):
|
|
42
|
+
"""Base class for inference actions.
|
|
43
|
+
|
|
44
|
+
Provides helper methods for model loading and inference workflows.
|
|
45
|
+
Supports both REST API-based inference (via Ray Serve) and batch
|
|
46
|
+
inference with step-based workflows.
|
|
47
|
+
|
|
48
|
+
Supports two execution modes:
|
|
49
|
+
1. Simple execute: Override execute() directly for simple workflows
|
|
50
|
+
2. Step-based: Override setup_steps() to register workflow steps
|
|
51
|
+
|
|
52
|
+
If setup_steps() registers any steps, the step-based workflow
|
|
53
|
+
takes precedence and execute() is not called directly.
|
|
54
|
+
|
|
55
|
+
Attributes:
|
|
56
|
+
category: Plugin category (defaults to NEURAL_NET).
|
|
57
|
+
progress: Standard progress category names.
|
|
58
|
+
|
|
59
|
+
Example (simple execute):
|
|
60
|
+
>>> class MyInferenceAction(BaseInferenceAction[MyParams]):
|
|
61
|
+
... action_name = 'inference'
|
|
62
|
+
... params_model = MyParams
|
|
63
|
+
...
|
|
64
|
+
... def execute(self) -> dict[str, Any]:
|
|
65
|
+
... model = self.load_model(self.params.model_id)
|
|
66
|
+
... self.set_progress(1, 3, self.progress.MODEL_LOAD)
|
|
67
|
+
... results = self.infer(model, self.params.inputs)
|
|
68
|
+
... self.set_progress(2, 3, self.progress.INFERENCE)
|
|
69
|
+
... return {'results': results}
|
|
70
|
+
|
|
71
|
+
Example (step-based):
|
|
72
|
+
>>> class MyInferenceAction(BaseInferenceAction[MyParams]):
|
|
73
|
+
... def setup_steps(self, registry: StepRegistry[InferenceContext]) -> None:
|
|
74
|
+
... registry.register(LoadModelStep())
|
|
75
|
+
... registry.register(InferenceStep())
|
|
76
|
+
... registry.register(PostProcessStep())
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
category = PluginCategory.NEURAL_NET
|
|
80
|
+
progress = InferenceProgressCategories()
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def client(self) -> BackendClient:
|
|
84
|
+
"""Backend client from context.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
BackendClient instance.
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
RuntimeError: If no client in context.
|
|
91
|
+
"""
|
|
92
|
+
if self.ctx.client is None:
|
|
93
|
+
raise RuntimeError(
|
|
94
|
+
'No client in context. Either provide a client via RuntimeContext '
|
|
95
|
+
'or override the helper methods (load_model, get_model).'
|
|
96
|
+
)
|
|
97
|
+
return self.ctx.client
|
|
98
|
+
|
|
99
|
+
def setup_steps(self, registry: StepRegistry[InferenceContext]) -> None:
|
|
100
|
+
"""Register workflow steps for step-based execution.
|
|
101
|
+
|
|
102
|
+
Override this method to register custom steps for your inference workflow.
|
|
103
|
+
If steps are registered, step-based execution takes precedence.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
registry: StepRegistry to register steps with.
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
>>> def setup_steps(self, registry: StepRegistry[InferenceContext]) -> None:
|
|
110
|
+
... registry.register(LoadModelStep())
|
|
111
|
+
... registry.register(InferenceStep())
|
|
112
|
+
... registry.register(PostProcessStep())
|
|
113
|
+
"""
|
|
114
|
+
pass # Default: no steps, uses simple execute()
|
|
115
|
+
|
|
116
|
+
def create_context(self) -> InferenceContext:
|
|
117
|
+
"""Create inference context for step-based workflow.
|
|
118
|
+
|
|
119
|
+
Override to customize context creation or add additional state.
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
InferenceContext instance with params and runtime context.
|
|
123
|
+
"""
|
|
124
|
+
params_dict = self.params.model_dump() if hasattr(self.params, 'model_dump') else dict(self.params)
|
|
125
|
+
return InferenceContext(
|
|
126
|
+
runtime_ctx=self.ctx,
|
|
127
|
+
params=params_dict,
|
|
128
|
+
model_id=params_dict.get('model_id'),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def run(self) -> Any:
|
|
132
|
+
"""Run the action, using steps if registered.
|
|
133
|
+
|
|
134
|
+
This method is called by executors. It checks if steps are
|
|
135
|
+
registered and uses step-based execution if so.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Action result (dict or any return type).
|
|
139
|
+
"""
|
|
140
|
+
# Check if steps are registered
|
|
141
|
+
registry: StepRegistry[InferenceContext] = StepRegistry()
|
|
142
|
+
self.setup_steps(registry)
|
|
143
|
+
|
|
144
|
+
if registry:
|
|
145
|
+
# Step-based execution
|
|
146
|
+
context = self.create_context()
|
|
147
|
+
orchestrator: Orchestrator[InferenceContext] = Orchestrator(
|
|
148
|
+
registry=registry,
|
|
149
|
+
context=context,
|
|
150
|
+
progress_callback=lambda curr, total: self.set_progress(curr, total),
|
|
151
|
+
)
|
|
152
|
+
result = orchestrator.execute()
|
|
153
|
+
|
|
154
|
+
# Add context data to result
|
|
155
|
+
result['processed_count'] = context.processed_count
|
|
156
|
+
if context.results:
|
|
157
|
+
result['results'] = context.results
|
|
158
|
+
|
|
159
|
+
return result
|
|
160
|
+
|
|
161
|
+
# Simple execute mode
|
|
162
|
+
return self.execute()
|
|
163
|
+
|
|
164
|
+
def get_model(self, model_id: int) -> dict[str, Any]:
|
|
165
|
+
"""Retrieve model metadata by ID.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
model_id: Model identifier.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Model metadata dictionary including file URL.
|
|
172
|
+
|
|
173
|
+
Raises:
|
|
174
|
+
RuntimeError: If no client in context.
|
|
175
|
+
|
|
176
|
+
Example:
|
|
177
|
+
>>> model = self.get_model(123)
|
|
178
|
+
>>> print(model['name'], model['file'])
|
|
179
|
+
"""
|
|
180
|
+
return self.client.get_model(model_id)
|
|
181
|
+
|
|
182
|
+
def download_model(
|
|
183
|
+
self,
|
|
184
|
+
model_id: int,
|
|
185
|
+
output_dir: str | Path | None = None,
|
|
186
|
+
) -> Path:
|
|
187
|
+
"""Download and extract model artifacts.
|
|
188
|
+
|
|
189
|
+
Fetches model metadata, downloads the model archive, and extracts
|
|
190
|
+
it to the specified directory (or a temp directory if not specified).
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
model_id: Model identifier.
|
|
194
|
+
output_dir: Directory to extract model to. If None, uses tempdir.
|
|
195
|
+
|
|
196
|
+
Returns:
|
|
197
|
+
Path to extracted model directory.
|
|
198
|
+
|
|
199
|
+
Raises:
|
|
200
|
+
RuntimeError: If no client in context.
|
|
201
|
+
ValueError: If model has no file URL.
|
|
202
|
+
|
|
203
|
+
Example:
|
|
204
|
+
>>> model_path = self.download_model(123)
|
|
205
|
+
>>> # Load model from model_path
|
|
206
|
+
"""
|
|
207
|
+
model = self.get_model(model_id)
|
|
208
|
+
|
|
209
|
+
if not model.get('file'):
|
|
210
|
+
raise ValueError(f'Model {model_id} has no file URL')
|
|
211
|
+
|
|
212
|
+
# Determine output directory
|
|
213
|
+
if output_dir is None:
|
|
214
|
+
output_dir = Path(tempfile.mkdtemp(prefix='synapse_model_'))
|
|
215
|
+
else:
|
|
216
|
+
output_dir = Path(output_dir)
|
|
217
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
218
|
+
|
|
219
|
+
# Download and extract
|
|
220
|
+
from synapse_sdk.utils.file.download import download_file
|
|
221
|
+
|
|
222
|
+
archive_path = output_dir / 'model.zip'
|
|
223
|
+
download_file(model['file'], archive_path)
|
|
224
|
+
extract_archive(archive_path, output_dir)
|
|
225
|
+
|
|
226
|
+
# Remove archive after extraction
|
|
227
|
+
archive_path.unlink(missing_ok=True)
|
|
228
|
+
|
|
229
|
+
return output_dir
|
|
230
|
+
|
|
231
|
+
def load_model(self, model_id: int) -> dict[str, Any]:
|
|
232
|
+
"""Load model for inference.
|
|
233
|
+
|
|
234
|
+
Downloads model artifacts and returns model info with local path.
|
|
235
|
+
Override this method for custom model loading (e.g., loading into
|
|
236
|
+
specific framework like PyTorch, TensorFlow).
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
model_id: Model identifier.
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Model metadata dict with 'path' key for local artifacts.
|
|
243
|
+
|
|
244
|
+
Example:
|
|
245
|
+
>>> model_info = self.load_model(123)
|
|
246
|
+
>>> model_path = model_info['path']
|
|
247
|
+
>>> # Load your model framework here:
|
|
248
|
+
>>> # model = torch.load(model_path / 'model.pt')
|
|
249
|
+
"""
|
|
250
|
+
model = self.get_model(model_id)
|
|
251
|
+
model_path = self.download_model(model_id)
|
|
252
|
+
model['path'] = str(model_path)
|
|
253
|
+
return model
|
|
254
|
+
|
|
255
|
+
def infer(
|
|
256
|
+
self,
|
|
257
|
+
model: Any,
|
|
258
|
+
inputs: list[dict[str, Any]],
|
|
259
|
+
) -> list[dict[str, Any]]:
|
|
260
|
+
"""Run inference on inputs.
|
|
261
|
+
|
|
262
|
+
Override this method to implement your inference logic.
|
|
263
|
+
This is called by execute() in simple mode.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
model: Loaded model (framework-specific).
|
|
267
|
+
inputs: List of input dictionaries.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
List of result dictionaries.
|
|
271
|
+
|
|
272
|
+
Raises:
|
|
273
|
+
NotImplementedError: Must be overridden by subclass.
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
>>> def infer(self, model, inputs):
|
|
277
|
+
... results = []
|
|
278
|
+
... for inp in inputs:
|
|
279
|
+
... prediction = model.predict(inp['image'])
|
|
280
|
+
... results.append({'prediction': prediction})
|
|
281
|
+
... return results
|
|
282
|
+
"""
|
|
283
|
+
raise NotImplementedError(
|
|
284
|
+
'Override infer() to implement inference logic. Example: return model.predict(inputs)'
|
|
285
|
+
)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Inference context for step-based workflows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from synapse_sdk.plugins.steps import BaseStepContext
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class InferenceContext(BaseStepContext):
|
|
13
|
+
"""Context for inference action step-based workflows.
|
|
14
|
+
|
|
15
|
+
Extends BaseStepContext with inference-specific state including
|
|
16
|
+
model information, request/response tracking, and batch processing.
|
|
17
|
+
|
|
18
|
+
Attributes:
|
|
19
|
+
params: Action parameters dict.
|
|
20
|
+
model_id: ID of the model being used for inference.
|
|
21
|
+
model: Loaded model information from backend.
|
|
22
|
+
model_path: Local path to downloaded/extracted model.
|
|
23
|
+
requests: Input requests to process.
|
|
24
|
+
results: Inference results.
|
|
25
|
+
batch_size: Batch size for processing.
|
|
26
|
+
processed_count: Number of processed items.
|
|
27
|
+
|
|
28
|
+
Example:
|
|
29
|
+
>>> context = InferenceContext(
|
|
30
|
+
... runtime_ctx=self.ctx,
|
|
31
|
+
... params={'model_id': 123},
|
|
32
|
+
... model_id=123,
|
|
33
|
+
... )
|
|
34
|
+
>>> context.results.append({'prediction': 0.95})
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
params: dict[str, Any] = field(default_factory=dict)
|
|
38
|
+
model_id: int | None = None
|
|
39
|
+
model: dict[str, Any] | None = None
|
|
40
|
+
model_path: str | None = None
|
|
41
|
+
requests: list[dict[str, Any]] = field(default_factory=list)
|
|
42
|
+
results: list[dict[str, Any]] = field(default_factory=list)
|
|
43
|
+
batch_size: int = 1
|
|
44
|
+
processed_count: int = 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class DeploymentContext(BaseStepContext):
|
|
49
|
+
"""Context for deployment action step-based workflows.
|
|
50
|
+
|
|
51
|
+
Extends BaseStepContext with deployment-specific state including
|
|
52
|
+
model information, serve application configuration, and deployment status.
|
|
53
|
+
|
|
54
|
+
Attributes:
|
|
55
|
+
params: Action parameters dict.
|
|
56
|
+
model_id: ID of the model to deploy.
|
|
57
|
+
model: Model information from backend.
|
|
58
|
+
model_path: Local path to model artifacts.
|
|
59
|
+
serve_app_name: Name of the Ray Serve application.
|
|
60
|
+
serve_app_id: ID of the created serve application.
|
|
61
|
+
route_prefix: URL route prefix for the deployment.
|
|
62
|
+
ray_actor_options: Ray actor configuration options.
|
|
63
|
+
deployed: Whether deployment succeeded.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
>>> context = DeploymentContext(
|
|
67
|
+
... runtime_ctx=self.ctx,
|
|
68
|
+
... params={'model_id': 123},
|
|
69
|
+
... serve_app_name='my-model-v1',
|
|
70
|
+
... )
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
params: dict[str, Any] = field(default_factory=dict)
|
|
74
|
+
model_id: int | None = None
|
|
75
|
+
model: dict[str, Any] | None = None
|
|
76
|
+
model_path: str | None = None
|
|
77
|
+
serve_app_name: str | None = None
|
|
78
|
+
serve_app_id: int | None = None
|
|
79
|
+
route_prefix: str | None = None
|
|
80
|
+
ray_actor_options: dict[str, Any] = field(default_factory=dict)
|
|
81
|
+
deployed: bool = False
|