digitalkin 0.2.3__py3-none-any.whl → 0.2.4__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.
- digitalkin/__version__.py +1 -1
- digitalkin/grpc_servers/module_servicer.py +27 -14
- digitalkin/modules/_base_module.py +48 -0
- digitalkin/modules/job_manager.py +3 -3
- {digitalkin-0.2.3.dist-info → digitalkin-0.2.4.dist-info}/METADATA +2 -2
- {digitalkin-0.2.3.dist-info → digitalkin-0.2.4.dist-info}/RECORD +11 -11
- modules/minimal_llm_module.py +5 -1
- modules/storage_module.py +4 -4
- {digitalkin-0.2.3.dist-info → digitalkin-0.2.4.dist-info}/WHEEL +0 -0
- {digitalkin-0.2.3.dist-info → digitalkin-0.2.4.dist-info}/licenses/LICENSE +0 -0
- {digitalkin-0.2.3.dist-info → digitalkin-0.2.4.dist-info}/top_level.txt +0 -0
digitalkin/__version__.py
CHANGED
|
@@ -51,7 +51,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
51
51
|
self.job_manager = JobManager(module_class)
|
|
52
52
|
self.setup = GrpcSetup() if self.job_manager.args.services_mode == ServicesMode.REMOTE else DefaultSetup()
|
|
53
53
|
|
|
54
|
-
async def add_to_queue(self, job_id: str, output_data: OutputModelT) -> None:
|
|
54
|
+
async def add_to_queue(self, job_id: str, output_data: OutputModelT) -> None: # type: ignore
|
|
55
55
|
"""Callback used to add the output data to the queue of messages."""
|
|
56
56
|
logger.info("JOB: %s added an output_data: %s", job_id, output_data)
|
|
57
57
|
await self.queue.put({job_id: output_data})
|
|
@@ -76,11 +76,11 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
76
76
|
logger.info("StartModule called for module: '%s'", self.module_class.__name__)
|
|
77
77
|
# Process the module input
|
|
78
78
|
# TODO: Check failure of input data format
|
|
79
|
-
input_data = self.module_class.
|
|
79
|
+
input_data = self.module_class.create_input_model(dict(request.input.items()))
|
|
80
80
|
setup_data_class = self.setup.get_setup(
|
|
81
81
|
setup_dict={
|
|
82
82
|
"setup_id": request.setup_id,
|
|
83
|
-
"mission_id":
|
|
83
|
+
"mission_id": request.mission_id,
|
|
84
84
|
}
|
|
85
85
|
)
|
|
86
86
|
|
|
@@ -88,31 +88,44 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
88
88
|
msg = "No setup data returned."
|
|
89
89
|
raise ServicerError(msg)
|
|
90
90
|
# TODO: Check failure of setup data format
|
|
91
|
-
setup_data = self.module_class.
|
|
91
|
+
setup_data = self.module_class.create_setup_model(setup_data_class.current_setup_version.content)
|
|
92
92
|
|
|
93
93
|
# setup_id should be use to request a precise setup from the module
|
|
94
94
|
# Create a job for this execution
|
|
95
|
-
|
|
95
|
+
result: tuple[str, BaseModule] = await self.job_manager.create_job(
|
|
96
96
|
input_data,
|
|
97
97
|
setup_data,
|
|
98
|
+
mission_id=request.mission_id,
|
|
98
99
|
callback=self.add_to_queue,
|
|
99
100
|
)
|
|
101
|
+
job_id, module = result
|
|
100
102
|
|
|
101
103
|
while module.status == ModuleStatus.RUNNING or not self.queue.empty():
|
|
102
|
-
output_data = await self.queue.get()
|
|
104
|
+
output_data: dict = await self.queue.get()
|
|
105
|
+
if job_id not in output_data or output_data[job_id] not in self.job_manager.modules:
|
|
106
|
+
message = f"Job {job_id} not found"
|
|
107
|
+
logger.warning(message)
|
|
108
|
+
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
109
|
+
context.set_details(message)
|
|
110
|
+
yield lifecycle_pb2.StartModuleResponse(success=False)
|
|
111
|
+
return
|
|
112
|
+
|
|
103
113
|
if output_data[job_id].get("error", None) is not None:
|
|
104
114
|
context.set_code(output_data[job_id]["error"]["code"])
|
|
105
115
|
context.set_details(output_data[job_id]["error"]["error_message"])
|
|
106
116
|
yield lifecycle_pb2.StartModuleResponse(success=False)
|
|
107
117
|
return
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
118
|
+
|
|
119
|
+
output_proto = json_format.ParseDict(
|
|
120
|
+
output_data[job_id],
|
|
121
|
+
struct_pb2.Struct(),
|
|
122
|
+
ignore_unknown_fields=True,
|
|
123
|
+
)
|
|
124
|
+
yield lifecycle_pb2.StartModuleResponse(
|
|
125
|
+
success=True,
|
|
126
|
+
output=output_proto,
|
|
127
|
+
job_id=job_id,
|
|
128
|
+
)
|
|
116
129
|
|
|
117
130
|
async def StopModule( # noqa: N802
|
|
118
131
|
self,
|
|
@@ -140,6 +140,54 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
140
140
|
msg = "'%s' class does not define an 'setup_format'."
|
|
141
141
|
raise NotImplementedError(msg)
|
|
142
142
|
|
|
143
|
+
@classmethod
|
|
144
|
+
def create_input_model(cls, input_data: dict[str, Any]) -> InputModelT:
|
|
145
|
+
"""Create the input model from the input data.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
input_data: The input data to create the model from.
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
The input model.
|
|
152
|
+
"""
|
|
153
|
+
return cls.input_format(**input_data)
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
def create_setup_model(cls, setup_data: dict[str, Any]) -> SetupModelT:
|
|
157
|
+
"""Create the setup model from the setup data.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
setup_data: The setup data to create the model from.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
The setup model.
|
|
164
|
+
"""
|
|
165
|
+
return cls.setup_format(**setup_data)
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def create_secret_model(cls, secret_data: dict[str, Any]) -> SecretModelT:
|
|
169
|
+
"""Create the secret model from the secret data.
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
secret_data: The secret data to create the model from.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
The secret model.
|
|
176
|
+
"""
|
|
177
|
+
return cls.secret_format(**secret_data)
|
|
178
|
+
|
|
179
|
+
@classmethod
|
|
180
|
+
def create_output_model(cls, output_data: dict[str, Any]) -> OutputModelT:
|
|
181
|
+
"""Create the output model from the output data.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
output_data: The output data to create the model from.
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
The output model.
|
|
188
|
+
"""
|
|
189
|
+
return cls.output_format(**output_data)
|
|
190
|
+
|
|
143
191
|
@abstractmethod
|
|
144
192
|
async def initialize(self, setup_data: SetupModelT) -> None:
|
|
145
193
|
"""Initialize the module."""
|
|
@@ -8,7 +8,7 @@ from typing import Any
|
|
|
8
8
|
|
|
9
9
|
from digitalkin.logger import logger
|
|
10
10
|
from digitalkin.models import ModuleStatus
|
|
11
|
-
from digitalkin.models.module import InputModelT, OutputModelT, SetupModelT
|
|
11
|
+
from digitalkin.models.module import InputModelT, OutputModelT, SecretModelT, SetupModelT
|
|
12
12
|
from digitalkin.modules._base_module import BaseModule
|
|
13
13
|
from digitalkin.services.services_config import ServicesConfig
|
|
14
14
|
from digitalkin.services.services_models import ServicesMode
|
|
@@ -78,8 +78,9 @@ class JobManager(ArgParser):
|
|
|
78
78
|
self,
|
|
79
79
|
input_data: InputModelT,
|
|
80
80
|
setup_data: SetupModelT,
|
|
81
|
+
mission_id: str,
|
|
81
82
|
callback: Callable[[str, OutputModelT], Coroutine[Any, Any, None]],
|
|
82
|
-
) -> tuple[str, BaseModule]:
|
|
83
|
+
) -> tuple[str, BaseModule[InputModelT, OutputModelT, SetupModelT, SecretModelT]]: # type: ignore
|
|
83
84
|
"""Start new module job in background (asyncio).
|
|
84
85
|
|
|
85
86
|
Args:
|
|
@@ -91,7 +92,6 @@ class JobManager(ArgParser):
|
|
|
91
92
|
str: job_id of the module entity
|
|
92
93
|
"""
|
|
93
94
|
job_id = str(uuid.uuid4())
|
|
94
|
-
mission_id = "missions:test_demo"
|
|
95
95
|
"""TODO: check uniqueness of the job_id"""
|
|
96
96
|
# Création et démarrage du module
|
|
97
97
|
module = self.module_class(job_id, mission_id=mission_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digitalkin
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: SDK to build kin used in DigitalKin
|
|
5
5
|
Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
|
|
6
6
|
License: Attribution-NonCommercial-ShareAlike 4.0 International
|
|
@@ -452,7 +452,7 @@ Classifier: License :: Other/Proprietary License
|
|
|
452
452
|
Requires-Python: >=3.10
|
|
453
453
|
Description-Content-Type: text/markdown
|
|
454
454
|
License-File: LICENSE
|
|
455
|
-
Requires-Dist: digitalkin-proto>=0.1.
|
|
455
|
+
Requires-Dist: digitalkin-proto>=0.1.7
|
|
456
456
|
Requires-Dist: grpcio-health-checking>=1.71.0
|
|
457
457
|
Requires-Dist: grpcio-reflection>=1.71.0
|
|
458
458
|
Requires-Dist: grpcio-status>=1.71.0
|
|
@@ -7,13 +7,13 @@ base_server/mock/__init__.py,sha256=YZFT-F1l_TpvJYuIPX-7kTeE1CfOjhx9YmNRXVoi-jQ,
|
|
|
7
7
|
base_server/mock/mock_pb2.py,sha256=sETakcS3PAAm4E-hTCV1jIVaQTPEAIoVVHupB8Z_k7Y,1843
|
|
8
8
|
base_server/mock/mock_pb2_grpc.py,sha256=BbOT70H6q3laKgkHfOx1QdfmCS_HxCY4wCOX84YAdG4,3180
|
|
9
9
|
digitalkin/__init__.py,sha256=7LLBAba0th-3SGqcpqFO-lopWdUkVLKzLZiMtB-mW3M,162
|
|
10
|
-
digitalkin/__version__.py,sha256=
|
|
10
|
+
digitalkin/__version__.py,sha256=mR_bGYOQA3eO6IjqeeDDhhBptzMqVTzT6k-jTNiddLY,190
|
|
11
11
|
digitalkin/logger.py,sha256=9cDgyJV2QXXT8F--xRODFlZyDgjuTTXNdpCU3GdqCsk,382
|
|
12
12
|
digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
digitalkin/grpc_servers/__init__.py,sha256=0cJBlwipSmFdXkyH3T0i6OJ1WpAtNsZgYX7JaSnkbtg,804
|
|
14
14
|
digitalkin/grpc_servers/_base_server.py,sha256=ec4xmgAuOMVg45a63O_PEa2T7mI4tJ6boxcXauFyZ5g,18649
|
|
15
15
|
digitalkin/grpc_servers/module_server.py,sha256=23Q6F9mSO9bCu2MmsLqM9WeviIzwfhDiBFrVspy0PCI,9065
|
|
16
|
-
digitalkin/grpc_servers/module_servicer.py,sha256=
|
|
16
|
+
digitalkin/grpc_servers/module_servicer.py,sha256=FMzB2E1dQZck34vGWf9OXNXEIfu_KhTdZ_Kn79XEowc,12306
|
|
17
17
|
digitalkin/grpc_servers/registry_server.py,sha256=PmWaH4Xmg5Sj7NtFVLBNTOzkOfqo7dw_qyVBnaW4jy4,2238
|
|
18
18
|
digitalkin/grpc_servers/registry_servicer.py,sha256=mCAjNhdMq5DozZMEPsJK__DIxePEYxSWV-gAq-Xctk4,16469
|
|
19
19
|
digitalkin/grpc_servers/utils/exceptions.py,sha256=I00OM8p8up20He4dU1fiHsvdLj1DymjR_UmoeUm2MSA,785
|
|
@@ -29,9 +29,9 @@ digitalkin/models/services/__init__.py,sha256=HsW7MUGFPvH7Ri28WN4BHHBfEQk5dzU_9F
|
|
|
29
29
|
digitalkin/models/services/cost.py,sha256=QTEuFD6xz62nob0z4ksE-INJWcZ-iFiuNW5mvXhpFes,1599
|
|
30
30
|
digitalkin/models/services/storage.py,sha256=cYTVIriGKiprF9OerhSxmc_jM6fUTVwmeon1yQCinkE,143
|
|
31
31
|
digitalkin/modules/__init__.py,sha256=ppYARmhvdVi55ofC0QZerIempSlcJYDeCXhcl4qXObw,278
|
|
32
|
-
digitalkin/modules/_base_module.py,sha256=
|
|
32
|
+
digitalkin/modules/_base_module.py,sha256=iVPRlooAGIW4_3lN9loUPe1q6uf62-vSsEE5THvn8eU,9007
|
|
33
33
|
digitalkin/modules/archetype_module.py,sha256=T2Ehj7EpAC2MO9WQbJv39hqRw7rh3exhVZTEL3JPM8U,421
|
|
34
|
-
digitalkin/modules/job_manager.py,sha256=
|
|
34
|
+
digitalkin/modules/job_manager.py,sha256=QHcrm3F99I9tlNzXefkyhkkwPITf_H1bEb_obMDbUic,6177
|
|
35
35
|
digitalkin/modules/tool_module.py,sha256=86g0M1wHZ1ReIc7AkKfyjnlGN2QYJBGxrEQpKVlyrZI,421
|
|
36
36
|
digitalkin/modules/trigger_module.py,sha256=kVoI4Gdkw7WWUP5T6hSCNqw5FxibTxL6Tpq9KP7gg78,379
|
|
37
37
|
digitalkin/services/__init__.py,sha256=LqGk_5DJy8Bzz62ajIq9jCeYNKQUIgtSCpafZk15FLc,910
|
|
@@ -67,12 +67,12 @@ digitalkin/services/storage/grpc_storage.py,sha256=BqWLK9w_03BEjlJCVbdrlbMvh2szG
|
|
|
67
67
|
digitalkin/services/storage/storage_strategy.py,sha256=vGo4aYkEp_GZV11m7vd-xY_Z3gVa5K0gMTzbj2Au_3o,6600
|
|
68
68
|
digitalkin/utils/__init__.py,sha256=sJnY-ZUgsjMfojAjONC1VN14mhgIDnzyOlGkw21rRnM,28
|
|
69
69
|
digitalkin/utils/arg_parser.py,sha256=3YyI6oZhhrlTmPTrzlwpQzbCNWDFAT3pggcLxNtJoc0,4388
|
|
70
|
-
digitalkin-0.2.
|
|
70
|
+
digitalkin-0.2.4.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
|
|
71
71
|
modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
|
-
modules/minimal_llm_module.py,sha256=
|
|
73
|
-
modules/storage_module.py,sha256=
|
|
72
|
+
modules/minimal_llm_module.py,sha256=i9KTbv8w1ekzRYWDiRsxD6xLCoZ3uDjD_hWgfY2PRys,5637
|
|
73
|
+
modules/storage_module.py,sha256=bu52lW4RFcWB8VFDhrpBFfCaTSkVL6so3zrkfW4LO9E,6270
|
|
74
74
|
modules/text_transform_module.py,sha256=fAC6r_Ujca1Tz1qdWL4hTPZFn3gFWIVNj5-rytQMObE,7191
|
|
75
|
-
digitalkin-0.2.
|
|
76
|
-
digitalkin-0.2.
|
|
77
|
-
digitalkin-0.2.
|
|
78
|
-
digitalkin-0.2.
|
|
75
|
+
digitalkin-0.2.4.dist-info/METADATA,sha256=h_9hJnMdGTJZwkr0b5IZwSEO5l70sbtJmd5PNZhY0VI,29095
|
|
76
|
+
digitalkin-0.2.4.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
77
|
+
digitalkin-0.2.4.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
|
|
78
|
+
digitalkin-0.2.4.dist-info/RECORD,,
|
modules/minimal_llm_module.py
CHANGED
|
@@ -82,7 +82,11 @@ class OpenAIToolModule(BaseModule[OpenAIToolInput, OpenAIToolOutput, OpenAIToolS
|
|
|
82
82
|
"storage": {
|
|
83
83
|
"config": {"setups": OpenAIToolSetup},
|
|
84
84
|
"server_config": server_config,
|
|
85
|
-
}
|
|
85
|
+
},
|
|
86
|
+
"filesystem": {
|
|
87
|
+
"config": {},
|
|
88
|
+
"server_config": server_config,
|
|
89
|
+
},
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
async def initialize(self, setup_data: SetupData) -> None:
|
modules/storage_module.py
CHANGED
|
@@ -12,7 +12,7 @@ from digitalkin.models.module import ModuleStatus
|
|
|
12
12
|
from digitalkin.modules.archetype_module import ArchetypeModule
|
|
13
13
|
from digitalkin.services.services_config import ServicesConfig
|
|
14
14
|
from digitalkin.services.services_models import ServicesMode
|
|
15
|
-
from digitalkin.services.storage.storage_strategy import
|
|
15
|
+
from digitalkin.services.storage.storage_strategy import StorageRecord
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class ExampleInput(BaseModel):
|
|
@@ -62,7 +62,7 @@ class ExampleModule(ArchetypeModule[ExampleInput, ExampleOutput, ExampleSetup, E
|
|
|
62
62
|
|
|
63
63
|
# Define services_config_params with default values
|
|
64
64
|
services_config_strategies = {}
|
|
65
|
-
services_config_params = {"storage": {"config": {"example_outputs": ExampleOutput}}}
|
|
65
|
+
services_config_params = {"storage": {"config": {"example_outputs": ExampleOutput}}, "filesystem": {"config": {}}}
|
|
66
66
|
|
|
67
67
|
def __init__(self, job_id: str, mission_id: str) -> None:
|
|
68
68
|
"""Initialize the example module.
|
|
@@ -119,7 +119,7 @@ class ExampleModule(ArchetypeModule[ExampleInput, ExampleOutput, ExampleSetup, E
|
|
|
119
119
|
)
|
|
120
120
|
|
|
121
121
|
# Store the output data in storage
|
|
122
|
-
storage_id = self.storage.store("example_outputs", output_data.model_dump(), data_type=
|
|
122
|
+
storage_id = self.storage.store("example_outputs", output_data.model_dump(), data_type="OUTPUT")
|
|
123
123
|
|
|
124
124
|
logger.info("Stored output data with ID: %s", storage_id)
|
|
125
125
|
|
|
@@ -170,7 +170,7 @@ def test_storage_directly() -> None:
|
|
|
170
170
|
storage = ServicesConfig().storage(mission_id="test-mission", config={"test_table": ExampleStorage})
|
|
171
171
|
|
|
172
172
|
# Create a test record
|
|
173
|
-
storage.store("test_table", {"test_key": "test_value"},
|
|
173
|
+
storage.store("test_table", {"test_key": "test_value"}, "OUTPUT")
|
|
174
174
|
|
|
175
175
|
# Retrieve the record
|
|
176
176
|
retrieved = storage.read("test_table")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|