synapse-sdk 1.0.0b17__py3-none-any.whl → 1.0.0b19__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.

Files changed (25) hide show
  1. synapse_sdk/clients/backend/data_collection.py +2 -2
  2. synapse_sdk/devtools/docs/docs/contributing.md +1 -1
  3. synapse_sdk/devtools/docs/docs/features/index.md +4 -4
  4. synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +786 -0
  5. synapse_sdk/devtools/docs/docs/{features/plugins/index.md → plugins/plugins.md} +352 -21
  6. synapse_sdk/devtools/docs/docusaurus.config.ts +8 -0
  7. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +788 -0
  8. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md +71 -0
  9. synapse_sdk/devtools/docs/package-lock.json +1366 -37
  10. synapse_sdk/devtools/docs/package.json +2 -1
  11. synapse_sdk/devtools/docs/sidebars.ts +8 -1
  12. synapse_sdk/plugins/categories/export/actions/export.py +2 -1
  13. synapse_sdk/plugins/categories/export/templates/config.yaml +1 -1
  14. synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +376 -0
  15. synapse_sdk/plugins/categories/export/templates/plugin/export.py +56 -190
  16. synapse_sdk/plugins/categories/upload/actions/upload.py +181 -22
  17. synapse_sdk/plugins/categories/upload/templates/config.yaml +24 -2
  18. synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +9 -2
  19. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/METADATA +1 -1
  20. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/RECORD +24 -22
  21. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/plugins/index.md +0 -30
  22. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/WHEEL +0 -0
  23. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/entry_points.txt +0 -0
  24. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/licenses/LICENSE +0 -0
  25. {synapse_sdk-1.0.0b17.dist-info → synapse_sdk-1.0.0b19.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import json
2
3
  import os
3
4
  import shutil
@@ -5,7 +6,7 @@ from datetime import datetime
5
6
  from enum import Enum
6
7
  from io import BytesIO
7
8
  from pathlib import Path
8
- from typing import Annotated, Any, Dict, List, Optional
9
+ from typing import Annotated, Any, Awaitable, Dict, List, Optional, TypeVar
9
10
 
10
11
  from openpyxl import load_workbook
11
12
  from openpyxl.utils.exceptions import InvalidFileException
@@ -25,6 +26,9 @@ from synapse_sdk.shared.enums import Context
25
26
  from synapse_sdk.utils.pydantic.validators import non_blank
26
27
  from synapse_sdk.utils.storage import get_pathlib
27
28
 
29
+ # Type variable for generic async return type
30
+ T = TypeVar('T')
31
+
28
32
 
29
33
  class PathAwareJSONEncoder(json.JSONEncoder):
30
34
  """Custom JSON encoder that handles Path-like objects."""
@@ -178,7 +182,7 @@ class UploadRun(Run):
178
182
  },
179
183
  # Debug information - only for EventLog
180
184
  'EXCEL_FILE_VALIDATION_STARTED': {
181
- 'message': 'Excel file validation started: {}',
185
+ 'message': 'Excel file validation started',
182
186
  'level': Context.INFO,
183
187
  },
184
188
  'EXCEL_WORKBOOK_LOADED': {
@@ -186,7 +190,7 @@ class UploadRun(Run):
186
190
  'level': Context.INFO,
187
191
  },
188
192
  'FILE_ORGANIZATION_STARTED': {
189
- 'message': 'File organization started for directory: {}',
193
+ 'message': 'File organization started',
190
194
  'level': Context.INFO,
191
195
  },
192
196
  'BATCH_PROCESSING_STARTED': {
@@ -202,7 +206,7 @@ class UploadRun(Run):
202
206
  'level': Context.INFO,
203
207
  },
204
208
  'EXCEL_FILE_NOT_FOUND_PATH': {
205
- 'message': 'Excel metadata file not found: {}',
209
+ 'message': 'Excel metadata file not found',
206
210
  'level': Context.WARNING,
207
211
  },
208
212
  'EXCEL_SECURITY_VALIDATION_FAILED': {
@@ -394,6 +398,9 @@ class ExcelMetadataUtils:
394
398
  class UploadParams(BaseModel):
395
399
  """Upload action parameters.
396
400
 
401
+ This class defines all configuration parameters for the upload action, including
402
+ advanced asynchronous upload capabilities for improved performance.
403
+
397
404
  Args:
398
405
  name (str): The name of the action.
399
406
  description (str | None): The description of the action.
@@ -405,6 +412,17 @@ class UploadParams(BaseModel):
405
412
  excel_metadata_path (str | None): Path to excel file containing metadata.
406
413
  Defaults to 'meta.xlsx' or 'meta.xls' in the path directory.
407
414
  is_recursive (bool): Enable recursive file discovery in subdirectories. Defaults to False.
415
+ use_async_upload (bool): Enable asynchronous upload data file processing for improved performance.
416
+ Defaults to True.
417
+ max_file_size_mb (int): The maximum file size not using chunked_upload in MB. Defaults to 50MB.
418
+ creating_data_unit_batch_size (int): The batch size for creating data units. Defaults to 100.
419
+ extra_params (dict | None): Extra parameters for the action.
420
+ Example: {"include_metadata": True, "compression": "gzip"}
421
+
422
+ Note:
423
+ Async upload requires plugin developers to implement handle_upload_files_async()
424
+ method for maximum benefit. Default implementation provides compatibility
425
+ but limited performance improvement.
408
426
  """
409
427
 
410
428
  name: Annotated[str, AfterValidator(non_blank)]
@@ -416,7 +434,9 @@ class UploadParams(BaseModel):
416
434
  excel_metadata_path: str | None = None
417
435
  is_recursive: bool = False
418
436
  max_file_size_mb: int = 50
419
- creating_data_unit_batch_size: int = 100
437
+ creating_data_unit_batch_size: int = 1
438
+ use_async_upload: bool = True
439
+ extra_params: dict | None = None
420
440
 
421
441
  @field_validator('storage', mode='before')
422
442
  @classmethod
@@ -540,8 +560,6 @@ class UploadAction(Action):
540
560
  analyze_collection: The progress category for the analyze collection process.
541
561
  data_file_upload: The progress category for the upload process.
542
562
  generate_data_units: The progress category for the generate data units process.
543
- generate_tasks: The progress category for the generate tasks process.
544
- generate_ground_truths: The progress category for the generate ground truths process.
545
563
 
546
564
  Metrics Categories:
547
565
  data_file: The metrics category for the data file.
@@ -581,9 +599,11 @@ class UploadAction(Action):
581
599
  self.excel_config = ExcelSecurityConfig()
582
600
  self.excel_utils = ExcelMetadataUtils(self.excel_config)
583
601
 
584
- def get_uploader(self, path, file_specification, organized_files):
602
+ def get_uploader(self, path, file_specification, organized_files, params: Dict = None):
585
603
  """Get uploader from entrypoint."""
586
- return self.entrypoint(self.run, path, file_specification, organized_files)
604
+ return self.entrypoint(
605
+ self.run, path, file_specification, organized_files, extra_params=params.get('extra_params')
606
+ )
587
607
 
588
608
  def _discover_files_recursive(self, dir_path: Path) -> List[Path]:
589
609
  """Discover files recursively in a directory."""
@@ -797,10 +817,11 @@ class UploadAction(Action):
797
817
  excel_path = None
798
818
 
799
819
  # Check if user provided a specific excel_metadata_path
800
- if self.params.get('excel_metadata_path'):
801
- excel_path = pathlib_cwd / self.params['excel_metadata_path']
820
+ excel_metadata_path = self.params.get('excel_metadata_path')
821
+ if excel_metadata_path:
822
+ excel_path = pathlib_cwd / excel_metadata_path
802
823
  if not excel_path.exists():
803
- self.run.log_message_with_code('EXCEL_FILE_NOT_FOUND_PATH', str(excel_path))
824
+ self.run.log_message_with_code('EXCEL_FILE_NOT_FOUND_PATH')
804
825
  return {}
805
826
  else:
806
827
  # Look for default meta.xlsx or meta.xls
@@ -810,7 +831,7 @@ class UploadAction(Action):
810
831
  return {}
811
832
 
812
833
  try:
813
- self.run.log_message_with_code('EXCEL_FILE_VALIDATION_STARTED', str(excel_path))
834
+ self.run.log_message_with_code('EXCEL_FILE_VALIDATION_STARTED')
814
835
 
815
836
  # Prepare Excel file with security validation
816
837
  excel_stream = self._prepare_excel_file(excel_path)
@@ -852,8 +873,15 @@ class UploadAction(Action):
852
873
  result: Dict[str, Any] = {}
853
874
 
854
875
  # Setup path object with path and storage.
855
- storage = self.client.get_storage(self.params['storage'])
856
- pathlib_cwd = get_pathlib(storage, self.params['path'])
876
+ storage_id = self.params.get('storage')
877
+ if storage_id is None:
878
+ raise ActionError('Storage parameter is required')
879
+ storage = self.client.get_storage(storage_id)
880
+
881
+ path = self.params.get('path')
882
+ if path is None:
883
+ raise ActionError('Path parameter is required')
884
+ pathlib_cwd = get_pathlib(storage, path)
857
885
 
858
886
  # Read excel metadata if configured or default file exists
859
887
  excel_metadata: Dict[str, Dict[str, Any]] = {}
@@ -881,7 +909,7 @@ class UploadAction(Action):
881
909
  organized_files = self._organize_files(pathlib_cwd, file_specification_template, excel_metadata)
882
910
 
883
911
  # Initialize uploader.
884
- uploader = self.get_uploader(pathlib_cwd, file_specification_template, organized_files)
912
+ uploader = self.get_uploader(pathlib_cwd, file_specification_template, organized_files, self.params)
885
913
 
886
914
  # Get organized files from the uploader (plugin developer's custom implementation)
887
915
  # or use the default organization method if uploader doesn't provide valid files
@@ -896,7 +924,11 @@ class UploadAction(Action):
896
924
  if not organized_files:
897
925
  self.run.log_message_with_code('NO_FILES_FOUND')
898
926
  raise ActionError('Upload is aborted due to missing files.')
899
- uploaded_files = self._upload_files(organized_files)
927
+ # Choose upload method based on async parameter
928
+ if self.params.get('use_async_upload', True):
929
+ uploaded_files = self.run_async(self._upload_files_async(organized_files, 10))
930
+ else:
931
+ uploaded_files = self._upload_files(organized_files)
900
932
  result['uploaded_files_count'] = len(uploaded_files)
901
933
 
902
934
  # Generate data units for the uploaded data.
@@ -904,7 +936,7 @@ class UploadAction(Action):
904
936
  self.run.log_message_with_code('NO_FILES_UPLOADED')
905
937
  raise ActionError('Upload is aborted due to no uploaded files.')
906
938
  generated_data_units = self._generate_data_units(
907
- uploaded_files, self.params.get('creating_data_unit_batch_size')
939
+ uploaded_files, self.params.get('creating_data_unit_batch_size', 1)
908
940
  )
909
941
  result['generated_data_units_count'] = len(generated_data_units)
910
942
 
@@ -929,7 +961,9 @@ class UploadAction(Action):
929
961
  # Initialize progress
930
962
  self.run.set_progress(0, 2, category='analyze_collection')
931
963
 
932
- collection_id = self.params['data_collection']
964
+ collection_id = self.params.get('data_collection')
965
+ if collection_id is None:
966
+ raise ActionError('Data collection parameter is required')
933
967
  self.run.set_progress(1, 2, category='analyze_collection')
934
968
 
935
969
  collection = self.run.client.get_data_collection(collection_id)
@@ -949,7 +983,9 @@ class UploadAction(Action):
949
983
  self.run.log_message_with_code('UPLOADING_DATA_FILES')
950
984
 
951
985
  client = self.run.client
952
- collection_id = self.params['data_collection']
986
+ collection_id = self.params.get('data_collection')
987
+ if collection_id is None:
988
+ raise ActionError('Data collection parameter is required')
953
989
  upload_result = []
954
990
  current_progress = 0
955
991
  success_count = 0
@@ -980,6 +1016,129 @@ class UploadAction(Action):
980
1016
 
981
1017
  return upload_result
982
1018
 
1019
+ def run_async(self, coro: Awaitable[T]) -> T:
1020
+ """Run async coroutine safely using asyncio.run().
1021
+
1022
+ This method properly manages event loop lifecycle and prevents
1023
+ resource exhaustion from repeated event loop creation.
1024
+
1025
+ Args:
1026
+ coro: The coroutine to execute
1027
+
1028
+ Returns:
1029
+ The result of the coroutine execution
1030
+
1031
+ Raises:
1032
+ RuntimeError: If called from within an existing event loop
1033
+ """
1034
+ import concurrent.futures
1035
+
1036
+ def _run_in_thread():
1037
+ """Run the coroutine in a separate thread to avoid event loop conflicts."""
1038
+ return asyncio.run(coro)
1039
+
1040
+ # Check if we're already in an event loop
1041
+ try:
1042
+ # If this doesn't raise, we're in an event loop
1043
+ asyncio.get_running_loop()
1044
+ # Run in thread pool to avoid "RuntimeError: cannot be called from a running event loop"
1045
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
1046
+ future = executor.submit(_run_in_thread)
1047
+ return future.result()
1048
+ except RuntimeError:
1049
+ # No event loop running, safe to use asyncio.run directly
1050
+ return asyncio.run(coro)
1051
+
1052
+ async def _upload_files_async(
1053
+ self, organized_files: List[Dict[str, Any]], max_concurrent: int = 10
1054
+ ) -> List[Dict[str, Any]]:
1055
+ """Upload files to synapse-backend asynchronously with concurrency control."""
1056
+ # Initialize progress
1057
+ organized_files_count = len(organized_files)
1058
+ self.run.set_progress(0, organized_files_count, category='upload_data_files')
1059
+ self.run.log_message_with_code('UPLOADING_DATA_FILES')
1060
+
1061
+ client = self.run.client
1062
+ collection_id = self.params.get('data_collection')
1063
+ if collection_id is None:
1064
+ raise ActionError('Data collection parameter is required')
1065
+ upload_result = []
1066
+ success_count = 0
1067
+ failed_count = 0
1068
+
1069
+ # Initialize metrics
1070
+ self._update_metrics(organized_files_count, success_count, failed_count, 'data_files')
1071
+
1072
+ # Control concurrency with semaphore
1073
+ semaphore = asyncio.Semaphore(max_concurrent)
1074
+
1075
+ async def upload_single_file(organized_file):
1076
+ async with semaphore:
1077
+ loop = asyncio.get_event_loop()
1078
+ try:
1079
+ # Determine if chunked upload should be used based on file size
1080
+ use_chunked_upload = self._requires_chunked_upload(organized_file)
1081
+ # Run sync upload_data_file in thread pool
1082
+ uploaded_data_file = await loop.run_in_executor(
1083
+ None, lambda: client.upload_data_file(organized_file, collection_id, use_chunked_upload)
1084
+ )
1085
+ self.run.log_data_file(organized_file, UploadStatus.SUCCESS)
1086
+ return {'status': 'success', 'result': uploaded_data_file}
1087
+ except ClientError as e:
1088
+ # Handle API client errors (network, authentication, server errors)
1089
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1090
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'Client error: {str(e)}')
1091
+ return {'status': 'failed', 'error': str(e), 'error_type': 'client_error', 'retryable': True}
1092
+ except (OSError, IOError) as e:
1093
+ # Handle file system errors (file not found, permissions, disk full)
1094
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1095
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'File system error: {str(e)}')
1096
+ return {'status': 'failed', 'error': str(e), 'error_type': 'file_error', 'retryable': False}
1097
+ except MemoryError as e:
1098
+ # Handle out of memory errors (large files)
1099
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1100
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'Memory error (file too large): {str(e)}')
1101
+ return {'status': 'failed', 'error': str(e), 'error_type': 'memory_error', 'retryable': False}
1102
+ except asyncio.TimeoutError as e:
1103
+ # Handle timeout errors (slow network, large files)
1104
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1105
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'Upload timeout: {str(e)}')
1106
+ return {'status': 'failed', 'error': str(e), 'error_type': 'timeout_error', 'retryable': True}
1107
+ except ValueError as e:
1108
+ # Handle data validation errors (invalid file format, metadata issues)
1109
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1110
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'Data validation error: {str(e)}')
1111
+ return {'status': 'failed', 'error': str(e), 'error_type': 'validation_error', 'retryable': False}
1112
+ except Exception as e:
1113
+ # Handle any remaining unexpected errors
1114
+ self.run.log_data_file(organized_file, UploadStatus.FAILED)
1115
+ self.run.log_message_with_code('FILE_UPLOAD_FAILED', f'Unexpected error: {str(e)}')
1116
+ return {'status': 'failed', 'error': str(e), 'error_type': 'unknown_error', 'retryable': False}
1117
+
1118
+ # Create tasks for all files
1119
+ tasks = [upload_single_file(organized_file) for organized_file in organized_files]
1120
+
1121
+ # Process files with progress updates
1122
+ current_progress = 0
1123
+ for completed_task in asyncio.as_completed(tasks):
1124
+ result = await completed_task
1125
+ current_progress += 1
1126
+
1127
+ if result['status'] == 'success':
1128
+ success_count += 1
1129
+ upload_result.append(result['result'])
1130
+ else:
1131
+ failed_count += 1
1132
+
1133
+ # Update metrics and progress
1134
+ self._update_metrics(organized_files_count, success_count, failed_count, 'data_files')
1135
+ self.run.set_progress(current_progress, organized_files_count, category='upload_data_files')
1136
+
1137
+ # Finish progress
1138
+ self.run.set_progress(organized_files_count, organized_files_count, category='upload_data_files')
1139
+
1140
+ return upload_result
1141
+
983
1142
  def _generate_data_units(self, uploaded_files: List[Dict[str, Any]], batch_size: int) -> List[Dict[str, Any]]:
984
1143
  """Generate data units for the uploaded data.
985
1144
 
@@ -1073,14 +1232,14 @@ class UploadAction(Action):
1073
1232
  return organized_files
1074
1233
 
1075
1234
  self.run.log_message_with_code('TYPE_STRUCTURE_DETECTED')
1076
- self.run.log_message_with_code('FILE_ORGANIZATION_STARTED', str(directory))
1235
+ self.run.log_message_with_code('FILE_ORGANIZATION_STARTED')
1077
1236
 
1078
1237
  # Collect and process files in a single pass
1079
1238
  dataset_files = {}
1080
1239
  required_specs = [spec['name'] for spec in file_specification if spec.get('is_required', False)]
1081
1240
 
1082
1241
  # Get recursive setting from params
1083
- is_recursive = self.params.get('is_recursive', False)
1242
+ is_recursive = self.params.get('is_recursive', True)
1084
1243
 
1085
1244
  # Process all files from all type directories
1086
1245
  for spec_name, dir_path in type_dirs.items():
@@ -3,5 +3,27 @@ actions:
3
3
  entrypoint: plugin.upload.Uploader
4
4
  options:
5
5
  supported_data_type: image # A primary data type of synapse backend collection. (e.g. 'image', 'text', 'video', 'pcd', 'audio')
6
- ui_schema: |
7
- Dumped FormKit Schema for upload plugin custom options
6
+ ui_schema: # UI schema for the input of extra params
7
+ - $formkit: "radio"
8
+ name: "file_format"
9
+ label: "File Format"
10
+ help: "Select the file format for upload processing"
11
+ required: false
12
+ value: "original"
13
+ options:
14
+ - label: "Keep Original"
15
+ value: "original"
16
+ - label: "Convert to JPEG"
17
+ value: "jpeg"
18
+ - label: "Convert to PNG"
19
+ value: "png"
20
+ - $formkit: "checkbox"
21
+ name: "include_metadata"
22
+ label: "Include Metadata"
23
+ help: "Include file metadata during upload"
24
+ value: true
25
+ - $formkit: "text"
26
+ name: "custom_tag"
27
+ label: "Custom Tag"
28
+ help: "Add a custom tag to uploaded files"
29
+ placeholder: "Enter custom tag"
@@ -1,5 +1,6 @@
1
+ import asyncio
1
2
  from pathlib import Path
2
- from typing import List
3
+ from typing import Dict, List
3
4
 
4
5
 
5
6
  class Uploader:
@@ -9,7 +10,9 @@ class Uploader:
9
10
  their own file organization logic.
10
11
  """
11
12
 
12
- def __init__(self, run, path: Path, file_specification: List = None, organized_files: List = None):
13
+ def __init__(
14
+ self, run, path: Path, file_specification: List = None, organized_files: List = None, extra_params: Dict = None
15
+ ):
13
16
  """Initialize the plugin upload action class.
14
17
 
15
18
  Args:
@@ -17,11 +20,15 @@ class Uploader:
17
20
  path: Path object pointing to the upload target directory.
18
21
  file_specification: List of specifications that define the structure of files to be uploaded.
19
22
  Each specification contains details like file name, type, and requirements.
23
+ organized_files: List of pre-organized files based on the default logic.
24
+ Each item is a dictionary with 'files' and 'meta' keys.
25
+ extra_params: Additional parameters for customization.
20
26
  """
21
27
  self.run = run
22
28
  self.path = path
23
29
  self.file_specification = file_specification
24
30
  self.organized_files = organized_files
31
+ self.extra_params = extra_params
25
32
 
26
33
  def handle_upload_files(self) -> List:
27
34
  """Customize the organization of files for upload.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synapse-sdk
3
- Version: 1.0.0b17
3
+ Version: 1.0.0b19
4
4
  Summary: synapse sdk
5
5
  Author-email: datamaker <developer@datamaker.io>
6
6
  License: MIT
@@ -34,7 +34,7 @@ synapse_sdk/clients/agent/service.py,sha256=s7KuPK_DB1nr2VHrigttV1WyFonaGHNrPvU8
34
34
  synapse_sdk/clients/backend/__init__.py,sha256=9FzjQn0ljRhtdaoG3n38Mdgte7GFwIh4OtEmoqVg2_E,2098
35
35
  synapse_sdk/clients/backend/annotation.py,sha256=t9KnSdCJ7NvDRkAOKn4lm5hgoawbLCwIHMeo45QiIlQ,1249
36
36
  synapse_sdk/clients/backend/core.py,sha256=oXAQwIz2QFuheaG79vXcYQFSlDDU1hxn2oRc6F5jyOc,2197
37
- synapse_sdk/clients/backend/data_collection.py,sha256=C3_vWWkzdX0nfHmeTL1KDAejPkIffL9_Yz0JN7Xz1IM,7740
37
+ synapse_sdk/clients/backend/data_collection.py,sha256=L0TmV-4jXPgKwWu9baKHz_WFRTqMe5nZH-qW-5PlUYM,7742
38
38
  synapse_sdk/clients/backend/hitl.py,sha256=1rKczQBKOeEVS0Ynu--mctbBF-zIkSz4_aklfbFY2CU,713
39
39
  synapse_sdk/clients/backend/integration.py,sha256=IdjPkllvHJ_vASHSmxsWO3CRlZz2L4eWkMOch7bHWok,2744
40
40
  synapse_sdk/clients/backend/ml.py,sha256=ynm1UQ-gJkJ-n1wU_Hjcxdhe8VC1LliNWOUJfurOrRE,1197
@@ -50,10 +50,10 @@ synapse_sdk/devtools/server.py,sha256=tj-9ICg1bSECvDD1yUZnLeiH7qpUcwrJ6jaD9C1Ba_
50
50
  synapse_sdk/devtools/streamlit_app.py,sha256=fa17_8NUDCClWp8ESLkPEUD5CTo6bisTFEVXniyUhY8,256
51
51
  synapse_sdk/devtools/docs/.gitignore,sha256=fCv2uiY7oUmiiFhHqfcYbg169Y-q4-AfLmmnRl98_sw,233
52
52
  synapse_sdk/devtools/docs/README.md,sha256=yBzWf0K1ef4oymFXDaHo0nYWEgMQJqsOyrkNhIOPQrY,774
53
- synapse_sdk/devtools/docs/docusaurus.config.ts,sha256=yHErHupsRps_NOEgfowwikm6bgW6zyZ3-ckBqRHmkNk,3080
54
- synapse_sdk/devtools/docs/package-lock.json,sha256=FfI_0BxNDB3tupLYxsH2PY4ogaBL6p22ujFWy8rRu88,653289
55
- synapse_sdk/devtools/docs/package.json,sha256=A-eWyz2rQrAsAuitIw64eCeQtKbaTH8HjSqg94gaugA,1143
56
- synapse_sdk/devtools/docs/sidebars.ts,sha256=-DteBl5FSI1bdg9eHC__Q3LjcIUGYUhKjVoz9Xpc0u0,1443
53
+ synapse_sdk/devtools/docs/docusaurus.config.ts,sha256=K1b002RS0x0tsOyib_6CSgUlASEULC9vAX8YDpbsRN4,3229
54
+ synapse_sdk/devtools/docs/package-lock.json,sha256=dtepgbPC8gq5uz-hdcac4hIU-Cs209tX0sfBuB7RfEQ,705694
55
+ synapse_sdk/devtools/docs/package.json,sha256=8veqayA4U3OLpdQaz6AzB59RQwTU-5soeYlYYWIxq28,1187
56
+ synapse_sdk/devtools/docs/sidebars.ts,sha256=ZfHa2kSwhvnDAsTZo6DR3IjeNXC4-J-_jYWSvZOA_zg,1559
57
57
  synapse_sdk/devtools/docs/tsconfig.json,sha256=O9BNlRPjPiaVHW2_boShMbmTnh0Z2k0KQO6Alf9FMVY,215
58
58
  synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md,sha256=iP7gl_FPqo-qX13lkSRcRoT6ayJNmCkXoyvlm7GH248,312
59
59
  synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md,sha256=cM-dhhTeurEWMcdn0Kx-NpNts2YUUraSI_XFk_gVHEE,3122
@@ -65,7 +65,7 @@ synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md,sha256=VEO6buziLWUfcU
65
65
  synapse_sdk/devtools/docs/docs/categories.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
66
  synapse_sdk/devtools/docs/docs/cli-usage.md,sha256=ooFeFINHPwo288WmVkQXs_dee5zDOqo-Cgp186J-3Vo,7258
67
67
  synapse_sdk/devtools/docs/docs/configuration.md,sha256=5tyAg0rl_k8XGYG0RT__r43xLdCBBVLDzS-4d8UZUO0,2222
68
- synapse_sdk/devtools/docs/docs/contributing.md,sha256=Rl1-zA75cJ-YD3V487pjFrSACYJGrGVUQmk7PO9nHuY,7715
68
+ synapse_sdk/devtools/docs/docs/contributing.md,sha256=U-g4rqrZXWSO_EzNh4AoOgZKFBzJ1OqVll_20nkJyWo,7706
69
69
  synapse_sdk/devtools/docs/docs/faq.md,sha256=PZ5JlBQ9BtJ7GWKmyr_X-alHnlIAxPXYwSVpAfHNXg4,4547
70
70
  synapse_sdk/devtools/docs/docs/installation.md,sha256=TUXPQ9zhWW68WdimH85GihGMBG-_XcUUzZG2bd0XKX8,1875
71
71
  synapse_sdk/devtools/docs/docs/introduction.md,sha256=qaZaU9E8raOm3Eqf7Zxpi9qG26gyS91OK1pWHsnPPMA,1581
@@ -85,9 +85,10 @@ synapse_sdk/devtools/docs/docs/api/utils/storage.md,sha256=uIpc37trKUm4XHe1fd4au
85
85
  synapse_sdk/devtools/docs/docs/api/utils/types.md,sha256=l84J1Ooa40xBYdvK1YpeKBT9kaqaWQUMNIFPUiC2e_U,1046
86
86
  synapse_sdk/devtools/docs/docs/concepts/index.md,sha256=ezn67P568PvFRPVE4T74j5MuEikgVOX7DV6MxIQBOHo,760
87
87
  synapse_sdk/devtools/docs/docs/examples/index.md,sha256=IZnF8veO7PqJYtAQevL1VHt1rBzieCSaXoWTQoXS4lA,504
88
- synapse_sdk/devtools/docs/docs/features/index.md,sha256=5OqGtJrs11Sw16vQ75mgt69QxhjS1csAnICj22jU7Tk,951
88
+ synapse_sdk/devtools/docs/docs/features/index.md,sha256=FD2hUzTzFgKa5pcDWPtA6eVw9pLLiRajYi4xA8aJTHg,963
89
89
  synapse_sdk/devtools/docs/docs/features/converters/index.md,sha256=W5d5UO8nbOLWs1G9IgdTutlMl-d6M0hDLMJbg8DrCQ8,12713
90
- synapse_sdk/devtools/docs/docs/features/plugins/index.md,sha256=4w6FXY5JSvPqweGPheVwrpIPaeRihA-124wAXTI1r6E,13212
90
+ synapse_sdk/devtools/docs/docs/plugins/export-plugins.md,sha256=W8u8o9PWZQJ-rBvwuw-daWtqsOfFod_j_4yNj4zbOj0,27028
91
+ synapse_sdk/devtools/docs/docs/plugins/plugins.md,sha256=a1OCSovNXLx8vEkx7qJtxlqEQueGgZ37_xvuZecp4ng,24139
91
92
  synapse_sdk/devtools/docs/docs/tutorial-basics/_category_.json,sha256=qQVHZ1p0CxHg5Gb4CYNxUSeqZ3LVo4nXN_N0yUMVpDM,180
92
93
  synapse_sdk/devtools/docs/docs/tutorial-basics/congratulations.md,sha256=zJbcwKNVYGpLAGJO7e3cTdptFhb6m_NUzYDU5i6MWgc,1078
93
94
  synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-blog-post.md,sha256=FNk-D3eiMmoc7sdVKazXibjsKl7-6b65KuEYkGOwcYk,886
@@ -124,7 +125,8 @@ synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/concept
124
125
  synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/examples/index.md,sha256=pMAc1VLUXnHCv2xvvx-GBqVQ1Uh4h-u4nrco5UZ2z-Y,613
125
126
  synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/index.md,sha256=ogU60hHjgRSUlxdoEFTlM7jwbZ3fharaTFuYHp3vya4,1051
126
127
  synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/converters/index.md,sha256=WpXcLBqC-xlvuoh-AhNOtFSo4qmnBIbR_wqLlazT7zo,1366
127
- synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/plugins/index.md,sha256=-P79uAosy1S4HlEs5dGmFTlG8X_cHeY9bR7mdJtYYzo,1515
128
+ synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md,sha256=f1fe6zWV5t60QZwCev7e-GIW50itfZviZ8zVZTaoka0,28371
129
+ synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md,sha256=63auCIr_5_IFZgvPDd9XSovM1cv3TSx9U0zQRjrsxkI,3108
128
130
  synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/footer.json,sha256=SCLmysIhJ6XEEfnL7cOQb3s08EG4LA-ColdRRxecIH8,1601
129
131
  synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/navbar.json,sha256=M-ly81cWnesYYtCRcfMvOsKl5P0z52K9kiw0T6GIQ60,429
130
132
  synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx,sha256=xaUQaq9OuqoaRAZQo-ZWev0vbmIkn9l04QfUBxlhnnU,1923
@@ -178,10 +180,10 @@ synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py,sh
178
180
  synapse_sdk/plugins/categories/export/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
179
181
  synapse_sdk/plugins/categories/export/enums.py,sha256=gtyngvQ1DKkos9iKGcbecwTVQQ6sDwbrBPSGPNb5Am0,127
180
182
  synapse_sdk/plugins/categories/export/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
181
- synapse_sdk/plugins/categories/export/actions/export.py,sha256=KKBRxTwPCDsmjv1JHgCE-orCYSsQG1RPdhRKtyd71ew,13669
182
- synapse_sdk/plugins/categories/export/templates/config.yaml,sha256=N7YmnFROb3s3M35SA9nmabyzoSb5O2t2TRPicwFNN2o,56
183
- synapse_sdk/plugins/categories/export/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
184
- synapse_sdk/plugins/categories/export/templates/plugin/export.py,sha256=DgoTtJF4Tq5nLUMpq0hF0XSbhXGjDb9XqoUUcrXBbnQ,6860
183
+ synapse_sdk/plugins/categories/export/actions/export.py,sha256=BO8N1LT8X9ImDmsqMdrbCUePsMEtOhazCuVtwp_ZmXs,13706
184
+ synapse_sdk/plugins/categories/export/templates/config.yaml,sha256=fAqi-9dH7qEkFDSDFvt0BcZ72d2qbyt1P83L2ti6ELM,58
185
+ synapse_sdk/plugins/categories/export/templates/plugin/__init__.py,sha256=vsaFmW0X7GvKs1YYocYn1Yfp9bzfLnc9grMp4n9UbWk,15400
186
+ synapse_sdk/plugins/categories/export/templates/plugin/export.py,sha256=3dZUEdhj-4YySJ-cPyNAqQvj5xcAXIX4KmXKcacTtd0,2754
185
187
  synapse_sdk/plugins/categories/neural_net/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
186
188
  synapse_sdk/plugins/categories/neural_net/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
187
189
  synapse_sdk/plugins/categories/neural_net/actions/deployment.py,sha256=njhDp05KXbNB9VCa46VgWa8-ftc_f9HcAVpUr0836AM,1838
@@ -219,10 +221,10 @@ synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py,sha256=47
219
221
  synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py,sha256=eevNg0nOcYFR4z_L_R-sCvVOYoLWSAH1jwDkAf3YCjY,320
220
222
  synapse_sdk/plugins/categories/upload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
223
  synapse_sdk/plugins/categories/upload/actions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
222
- synapse_sdk/plugins/categories/upload/actions/upload.py,sha256=hWL42Uu3E7rghO8Ayebxs4G_WcUNxn_pEXH5pJOPj3E,46969
223
- synapse_sdk/plugins/categories/upload/templates/config.yaml,sha256=6_dRa0_J2aS8NSUfO4MKbPxZcdPS2FpJzzp51edYAZc,281
224
+ synapse_sdk/plugins/categories/upload/actions/upload.py,sha256=lFosLHBC0bAI6rC9BYdrmd47VoQRXDtd6hi-0p7oG04,55001
225
+ synapse_sdk/plugins/categories/upload/templates/config.yaml,sha256=BvW1sqs02IgzO_fndxmtQ9CCmlNPwVIiuptQzzA6uAo,998
224
226
  synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
225
- synapse_sdk/plugins/categories/upload/templates/plugin/upload.py,sha256=IZU4sdSMSLKPCtlNqF7DP2howTdYR6hr74HCUZsGdPk,1559
227
+ synapse_sdk/plugins/categories/upload/templates/plugin/upload.py,sha256=gtKdKVf_PmZ2lRiTVrWT48F1J1yRZ-UGzg4gUgjWE84,1886
226
228
  synapse_sdk/plugins/templates/cookiecutter.json,sha256=NxOWk9A_v1pO0Ny4IYT9Cj5iiJ16--cIQrGC67QdR0I,396
227
229
  synapse_sdk/plugins/templates/plugin-config-schema.json,sha256=_ff1dnHdWPcWjD1Wy8Wn0aT6TnMD5J5Sdms3RTSWCUs,11805
228
230
  synapse_sdk/plugins/templates/schema.json,sha256=E5bZjskN0mqQtk2eLAB1nfXufIoGvyrtkMMP-wGKSdc,14029
@@ -276,9 +278,9 @@ synapse_sdk/utils/storage/providers/gcp.py,sha256=i2BQCu1Kej1If9SuNr2_lEyTcr5M_n
276
278
  synapse_sdk/utils/storage/providers/http.py,sha256=2DhIulND47JOnS5ZY7MZUex7Su3peAPksGo1Wwg07L4,5828
277
279
  synapse_sdk/utils/storage/providers/s3.py,sha256=ZmqekAvIgcQBdRU-QVJYv1Rlp6VHfXwtbtjTSphua94,2573
278
280
  synapse_sdk/utils/storage/providers/sftp.py,sha256=_8s9hf0JXIO21gvm-JVS00FbLsbtvly4c-ETLRax68A,1426
279
- synapse_sdk-1.0.0b17.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
280
- synapse_sdk-1.0.0b17.dist-info/METADATA,sha256=3sI-U96bZxMczG1jBsQnTBY1crQ3_mOoFLVjK-4REtQ,3745
281
- synapse_sdk-1.0.0b17.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
282
- synapse_sdk-1.0.0b17.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
283
- synapse_sdk-1.0.0b17.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
284
- synapse_sdk-1.0.0b17.dist-info/RECORD,,
281
+ synapse_sdk-1.0.0b19.dist-info/licenses/LICENSE,sha256=bKzmC5YAg4V1Fhl8OO_tqY8j62hgdncAkN7VrdjmrGk,1101
282
+ synapse_sdk-1.0.0b19.dist-info/METADATA,sha256=JJmW-pCaz5n8V-rNYjuE3Lq6hBhsGFfUYC9RoLM0YO0,3745
283
+ synapse_sdk-1.0.0b19.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
284
+ synapse_sdk-1.0.0b19.dist-info/entry_points.txt,sha256=VNptJoGoNJI8yLXfBmhgUefMsmGI0m3-0YoMvrOgbxo,48
285
+ synapse_sdk-1.0.0b19.dist-info/top_level.txt,sha256=ytgJMRK1slVOKUpgcw3LEyHHP7S34J6n_gJzdkcSsw8,12
286
+ synapse_sdk-1.0.0b19.dist-info/RECORD,,
@@ -1,30 +0,0 @@
1
- ---
2
- id: plugins
3
- title: 플러그인 시스템
4
- sidebar_position: 2
5
- ---
6
-
7
- # 플러그인 시스템
8
-
9
- Synapse SDK는 다양한 카테고리와 실행 방법에 걸쳐 ML 플러그인을 구축하고 관리하기 위한 포괄적인 플러그인 시스템을 제공합니다. 플러그인 시스템은 다양한 환경에서 배포되고 실행될 수 있는 모듈식, 재사용 가능한 컴포넌트를 가능하게 합니다.
10
-
11
- ## 개요
12
-
13
- 플러그인 시스템은 **액션** 개념을 중심으로 구축됩니다 - 패키징, 배포 및 다양한 컨텍스트에서 실행될 수 있는 개별 작업들입니다. 각 플러그인은 특정 카테고리에 속하며 여러 액션을 지원할 수 있습니다.
14
-
15
- ### 주요 기능
16
-
17
- - **🔌 모듈식 아키텍처**: 플러그인은 자체 종속성과 구성을 가진 자체 포함형입니다
18
- - **⚡ 다중 실행 방법**: Job, Task 및 REST API 엔드포인트 지원
19
- - **📦 분산 실행**: 확장 가능한 분산 컴퓨팅을 위해 구축됨
20
- - **🛠️ 템플릿 시스템**: 신속한 플러그인 개발을 위한 Cookiecutter 기반 스캐폴딩
21
- - **📊 진행률 추적**: 내장된 로깅, 메트릭 및 진행률 모니터링
22
- - **🔄 동적 로딩**: 런타임 플러그인 발견 및 등록
23
-
24
- ## 플러그인 카테고리
25
-
26
- SDK는 플러그인을 특정 카테고리로 구성하며, 각각은 ML 워크플로우의 다양한 측면을 위해 설계되었습니다:
27
-
28
- ### 1. 신경망 (`neural_net`)
29
-
30
- ML 모델 훈련, 추론 및 배포 작업들.