digitalkin 0.2.13__tar.gz → 0.2.14__tar.gz
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-0.2.13 → digitalkin-0.2.14}/PKG-INFO +14 -14
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/modules/cpu_intensive_module.py +11 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/modules/minimal_llm_module.py +41 -3
- {digitalkin-0.2.13 → digitalkin-0.2.14}/pyproject.toml +15 -15
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/__version__.py +1 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/module_servicer.py +93 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/utils/exceptions.py +4 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/module/__init__.py +2 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/module/module_types.py +1 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/_base_module.py +80 -2
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/archetype_module.py +11 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/base_job_manager.py +45 -3
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/single_job_manager.py +70 -3
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/taskiq_broker.py +42 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/taskiq_job_manager.py +90 -17
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/tool_module.py +2 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/trigger_module.py +3 -1
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin.egg-info/PKG-INFO +14 -14
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin.egg-info/requires.txt +13 -13
- {digitalkin-0.2.13 → digitalkin-0.2.14}/LICENSE +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/README.md +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/mock/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/mock/mock_pb2.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/mock/mock_pb2_grpc.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/server_async_insecure.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/server_async_secure.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/server_sync_insecure.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/base_server/server_sync_secure.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/modules/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/modules/storage_module.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/examples/modules/text_transform_module.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/setup.cfg +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/_base_server.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/module_server.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/registry_server.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/registry_servicer.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/utils/factory.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/utils/grpc_client_wrapper.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/utils/models.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/grpc_servers/utils/types.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/logger.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/module/module.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/services/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/services/cost.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/models/services/storage.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/job_manager_models.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/py.typed +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/agent/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/agent/agent_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/agent/default_agent.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/base_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/cost/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/cost/cost_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/cost/default_cost.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/cost/grpc_cost.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/filesystem/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/filesystem/default_filesystem.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/filesystem/filesystem_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/filesystem/grpc_filesystem.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/identity/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/identity/default_identity.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/identity/identity_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/registry/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/registry/default_registry.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/registry/registry_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/services_config.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/services_models.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/setup/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/setup/default_setup.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/setup/grpc_setup.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/setup/setup_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/snapshot/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/snapshot/default_snapshot.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/snapshot/snapshot_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/storage/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/storage/default_storage.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/storage/grpc_storage.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/services/storage/storage_strategy.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/utils/__init__.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/utils/arg_parser.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/utils/development_mode_action.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/utils/llm_ready_schema.py +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin.egg-info/SOURCES.txt +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin.egg-info/dependency_links.txt +0 -0
- {digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: digitalkin
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.14
|
|
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,36 +452,36 @@ 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.15
|
|
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
|
|
459
|
-
Requires-Dist: pydantic>=2.11.
|
|
459
|
+
Requires-Dist: pydantic>=2.11.5
|
|
460
460
|
Provides-Extra: dev
|
|
461
|
-
Requires-Dist: typos>=1.
|
|
462
|
-
Requires-Dist: ruff>=0.11.
|
|
463
|
-
Requires-Dist: mypy>=1.
|
|
464
|
-
Requires-Dist: pyright>=1.1.
|
|
461
|
+
Requires-Dist: typos>=1.33.1; extra == "dev"
|
|
462
|
+
Requires-Dist: ruff>=0.11.13; extra == "dev"
|
|
463
|
+
Requires-Dist: mypy>=1.16.0; extra == "dev"
|
|
464
|
+
Requires-Dist: pyright>=1.1.401; extra == "dev"
|
|
465
465
|
Requires-Dist: pre-commit>=4.2.0; extra == "dev"
|
|
466
466
|
Requires-Dist: bump2version>=1.0.1; extra == "dev"
|
|
467
467
|
Requires-Dist: build>=1.2.2; extra == "dev"
|
|
468
468
|
Requires-Dist: twine>=6.1.0; extra == "dev"
|
|
469
|
-
Requires-Dist: cryptography>=
|
|
470
|
-
Requires-Dist: taskiq[reload]>=0.11.17; extra == "dev"
|
|
469
|
+
Requires-Dist: cryptography>=45.0.4; extra == "dev"
|
|
471
470
|
Provides-Extra: examples
|
|
472
471
|
Requires-Dist: openai>=1.75.0; extra == "examples"
|
|
473
472
|
Provides-Extra: tests
|
|
474
|
-
Requires-Dist: freezegun>=1.5.
|
|
473
|
+
Requires-Dist: freezegun>=1.5.2; extra == "tests"
|
|
475
474
|
Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
|
|
476
475
|
Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
|
|
477
476
|
Requires-Dist: psutil>=7.0.0; extra == "tests"
|
|
478
|
-
Requires-Dist: pytest>=8.
|
|
479
|
-
Requires-Dist: pytest-asyncio>=0.
|
|
477
|
+
Requires-Dist: pytest>=8.4.0; extra == "tests"
|
|
478
|
+
Requires-Dist: pytest-asyncio>=1.0.0; extra == "tests"
|
|
480
479
|
Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
|
|
481
480
|
Provides-Extra: taskiq
|
|
482
|
-
Requires-Dist: rstream>=0.
|
|
481
|
+
Requires-Dist: rstream>=0.30.0; extra == "taskiq"
|
|
483
482
|
Requires-Dist: taskiq-aio-pika>=0.4.2; extra == "taskiq"
|
|
484
|
-
Requires-Dist: taskiq-redis>=1.0.
|
|
483
|
+
Requires-Dist: taskiq-redis>=1.0.9; extra == "taskiq"
|
|
484
|
+
Requires-Dist: taskiq[reload]>=0.11.17; extra == "taskiq"
|
|
485
485
|
Dynamic: license-file
|
|
486
486
|
|
|
487
487
|
# DigitalKin Python SDK
|
|
@@ -127,6 +127,16 @@ class CPUOutput(BaseModel):
|
|
|
127
127
|
)
|
|
128
128
|
|
|
129
129
|
|
|
130
|
+
class CPUConfigSetup(BaseModel):
|
|
131
|
+
"""Config Setup model definining data that will be pre-computed for each setup and module instance."""
|
|
132
|
+
|
|
133
|
+
files: list[str] = Field(
|
|
134
|
+
...,
|
|
135
|
+
title="Files to embed",
|
|
136
|
+
description="List of files to embed in the setup lifecycle.",
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
130
140
|
class CPUSetup(BaseModel):
|
|
131
141
|
"""Setup model defining module configuration parameters."""
|
|
132
142
|
|
|
@@ -175,7 +185,7 @@ client_config = ClientConfig(
|
|
|
175
185
|
)
|
|
176
186
|
|
|
177
187
|
|
|
178
|
-
class CPUIntensiveModule(BaseModule[CPUInput, CPUOutput, CPUSetup, CPUToolSecret]):
|
|
188
|
+
class CPUIntensiveModule(BaseModule[CPUInput, CPUOutput, CPUSetup, CPUToolSecret, None]):
|
|
179
189
|
"""A CPU endpoint tool module module."""
|
|
180
190
|
|
|
181
191
|
name = "CPUIntensiveModule"
|
|
@@ -11,7 +11,6 @@ from pydantic import BaseModel, Field
|
|
|
11
11
|
from digitalkin.grpc_servers.utils.models import ClientConfig, SecurityMode, ServerMode
|
|
12
12
|
from digitalkin.modules._base_module import BaseModule
|
|
13
13
|
from digitalkin.services.services_models import ServicesStrategy
|
|
14
|
-
from digitalkin.services.setup.setup_strategy import SetupData
|
|
15
14
|
|
|
16
15
|
# Configure logging with clear formatting
|
|
17
16
|
logging.basicConfig(
|
|
@@ -154,6 +153,16 @@ class OpenAISetup(BaseModel):
|
|
|
154
153
|
)
|
|
155
154
|
|
|
156
155
|
|
|
156
|
+
class OpenAIConfigSetup(BaseModel):
|
|
157
|
+
"""Setup model defining module configuration parameters."""
|
|
158
|
+
|
|
159
|
+
rag_files: list[bytes] = Field(
|
|
160
|
+
...,
|
|
161
|
+
title="RAG Files",
|
|
162
|
+
description="Files used for retrieval-augmented generation (RAG) with the OpenAI module.",
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
|
|
157
166
|
class OpenAIToolSecret(BaseModel):
|
|
158
167
|
"""Secret model defining module configuration parameters."""
|
|
159
168
|
|
|
@@ -167,13 +176,22 @@ client_config = ClientConfig(
|
|
|
167
176
|
)
|
|
168
177
|
|
|
169
178
|
|
|
170
|
-
class OpenAIToolModule(
|
|
179
|
+
class OpenAIToolModule(
|
|
180
|
+
BaseModule[
|
|
181
|
+
OpenAIInput,
|
|
182
|
+
OpenAIOutput,
|
|
183
|
+
OpenAISetup,
|
|
184
|
+
OpenAIToolSecret,
|
|
185
|
+
OpenAIConfigSetup,
|
|
186
|
+
]
|
|
187
|
+
):
|
|
171
188
|
"""A openAI endpoint tool module module."""
|
|
172
189
|
|
|
173
190
|
name = "OpenAIToolModule"
|
|
174
191
|
description = "A module that interacts with OpenAI API to process text"
|
|
175
192
|
|
|
176
193
|
# Define the schema formats for the module
|
|
194
|
+
config_setup_format = OpenAIConfigSetup
|
|
177
195
|
input_format = OpenAIInput
|
|
178
196
|
output_format = OpenAIOutput
|
|
179
197
|
setup_format = OpenAISetup
|
|
@@ -205,7 +223,27 @@ class OpenAIToolModule(BaseModule[OpenAIInput, OpenAIOutput, OpenAISetup, OpenAI
|
|
|
205
223
|
},
|
|
206
224
|
}
|
|
207
225
|
|
|
208
|
-
async def
|
|
226
|
+
async def run_config_setup(
|
|
227
|
+
self,
|
|
228
|
+
config_setup_data: OpenAIConfigSetup,
|
|
229
|
+
setup_data: OpenAISetup,
|
|
230
|
+
callback: Callable,
|
|
231
|
+
) -> None:
|
|
232
|
+
"""Configure the module with additional setup data.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
config_setup_data: Additional configuration content.
|
|
236
|
+
setup_data: Initial setup data for the module.
|
|
237
|
+
callback: Function to send output data back to the client.
|
|
238
|
+
"""
|
|
239
|
+
logger.info("Configuring OpenAIToolModule with additional setup data. %s", config_setup_data)
|
|
240
|
+
|
|
241
|
+
# Here you can process config_content and update setup_data as needed
|
|
242
|
+
# For now, we just return the original setup_data
|
|
243
|
+
setup_data.developer_prompt = "| + |".join(f.decode("utf-8") for f in config_setup_data.rag_files)
|
|
244
|
+
await callback(setup_data)
|
|
245
|
+
|
|
246
|
+
async def initialize(self, setup_data: OpenAISetup) -> None:
|
|
209
247
|
"""Initialize the module capabilities.
|
|
210
248
|
|
|
211
249
|
This method is called when the module is loaded by the server.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
keywords = [ "digitalkin", "kin", "agent", "gprc", "sdk" ]
|
|
14
14
|
# Version of the package automatically updated by bump2version (that is why it is separated)
|
|
15
|
-
version = "0.2.
|
|
15
|
+
version = "0.2.14"
|
|
16
16
|
|
|
17
17
|
classifiers = [
|
|
18
18
|
"Development Status :: 3 - Alpha",
|
|
@@ -29,41 +29,41 @@
|
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
dependencies = [
|
|
32
|
-
"digitalkin-proto>=0.1.
|
|
32
|
+
"digitalkin-proto>=0.1.15",
|
|
33
33
|
"grpcio-health-checking>=1.71.0",
|
|
34
34
|
"grpcio-reflection>=1.71.0",
|
|
35
35
|
"grpcio-status>=1.71.0",
|
|
36
|
-
"pydantic>=2.11.
|
|
36
|
+
"pydantic>=2.11.5",
|
|
37
37
|
]
|
|
38
38
|
|
|
39
39
|
[project.optional-dependencies]
|
|
40
40
|
dev = [
|
|
41
|
-
"typos>=1.
|
|
42
|
-
"ruff>=0.11.
|
|
43
|
-
"mypy>=1.
|
|
44
|
-
"pyright>=1.1.
|
|
41
|
+
"typos>=1.33.1",
|
|
42
|
+
"ruff>=0.11.13",
|
|
43
|
+
"mypy>=1.16.0",
|
|
44
|
+
"pyright>=1.1.401",
|
|
45
45
|
"pre-commit>=4.2.0",
|
|
46
46
|
"bump2version>=1.0.1",
|
|
47
47
|
"build>=1.2.2",
|
|
48
48
|
"twine>=6.1.0",
|
|
49
|
-
"cryptography>=
|
|
50
|
-
"taskiq[reload]>=0.11.17",
|
|
49
|
+
"cryptography>=45.0.4",
|
|
51
50
|
]
|
|
52
51
|
examples = [ "openai>=1.75.0" ]
|
|
53
52
|
tests = [
|
|
54
|
-
"freezegun>=1.5.
|
|
53
|
+
"freezegun>=1.5.2",
|
|
55
54
|
"hdrhistogram>=0.10.3",
|
|
56
55
|
"grpcio-testing>=1.71.0",
|
|
57
56
|
"psutil>=7.0.0",
|
|
58
|
-
"pytest>=8.
|
|
59
|
-
"pytest-asyncio>=0.
|
|
57
|
+
"pytest>=8.4.0",
|
|
58
|
+
"pytest-asyncio>=1.0.0",
|
|
60
59
|
"pytest-cov>=6.1.0",
|
|
61
60
|
]
|
|
62
61
|
taskiq = [
|
|
63
|
-
"rstream>=0.
|
|
62
|
+
"rstream>=0.30.0",
|
|
64
63
|
"taskiq-aio-pika>=0.4.2",
|
|
65
|
-
"taskiq-redis>=1.0.
|
|
66
|
-
]
|
|
64
|
+
"taskiq-redis>=1.0.9",
|
|
65
|
+
"taskiq[reload]>=0.11.17",
|
|
66
|
+
]
|
|
67
67
|
|
|
68
68
|
[project.urls]
|
|
69
69
|
Homepage = "https://github.com/DigitalKin-ai/digitalkin"
|
|
@@ -81,6 +81,62 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
81
81
|
)
|
|
82
82
|
self.setup = GrpcSetup() if self.args.services_mode == ServicesMode.REMOTE else DefaultSetup()
|
|
83
83
|
|
|
84
|
+
async def ConfigSetupModule( # noqa: N802
|
|
85
|
+
self,
|
|
86
|
+
request: lifecycle_pb2.ConfigSetupModuleRequest,
|
|
87
|
+
context: grpc.aio.ServicerContext,
|
|
88
|
+
) -> lifecycle_pb2.ConfigSetupModuleResponse:
|
|
89
|
+
"""Configure the module setup.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
request: The configuration request.
|
|
93
|
+
context: The gRPC context.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
A response indicating success or failure.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
ServicerError: if the setup data is not returned or job creation fails.
|
|
100
|
+
"""
|
|
101
|
+
logger.info("ConfigSetupVersion called for module: '%s'", self.module_class.__name__)
|
|
102
|
+
# Process the module input
|
|
103
|
+
# TODO: Secret should be used here as well
|
|
104
|
+
setup_version = request.setup_version
|
|
105
|
+
config_setup_data = self.module_class.create_config_setup_model(json_format.MessageToDict(request.content))
|
|
106
|
+
setup_version_data = self.module_class.create_setup_model(
|
|
107
|
+
json_format.MessageToDict(request.setup_version.content)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
if not setup_version_data:
|
|
111
|
+
msg = "No setup data returned."
|
|
112
|
+
raise ServicerError(msg)
|
|
113
|
+
|
|
114
|
+
if not config_setup_data:
|
|
115
|
+
msg = "No config setup data returned."
|
|
116
|
+
raise ServicerError(msg)
|
|
117
|
+
|
|
118
|
+
# create a task to run the module in background
|
|
119
|
+
job_id = await self.job_manager.create_config_setup_instance_job(
|
|
120
|
+
config_setup_data,
|
|
121
|
+
setup_version_data,
|
|
122
|
+
request.mission_id,
|
|
123
|
+
setup_version.id,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
if job_id is None:
|
|
127
|
+
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
128
|
+
context.set_details("Failed to create module instance")
|
|
129
|
+
return lifecycle_pb2.ConfigSetupModuleResponse(success=False)
|
|
130
|
+
|
|
131
|
+
updated_setup_data = await self.job_manager.generate_config_setup_module_response(job_id)
|
|
132
|
+
logger.warning(f"Updated setup data: {updated_setup_data=}")
|
|
133
|
+
setup_version.content = json_format.ParseDict(
|
|
134
|
+
updated_setup_data,
|
|
135
|
+
struct_pb2.Struct(),
|
|
136
|
+
ignore_unknown_fields=True,
|
|
137
|
+
)
|
|
138
|
+
return lifecycle_pb2.ConfigSetupModuleResponse(success=True, setup_version=setup_version)
|
|
139
|
+
|
|
84
140
|
async def StartModule( # noqa: N802
|
|
85
141
|
self,
|
|
86
142
|
request: lifecycle_pb2.StartModuleRequest,
|
|
@@ -116,7 +172,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
116
172
|
setup_data = self.module_class.create_setup_model(setup_data_class.current_setup_version.content)
|
|
117
173
|
|
|
118
174
|
# create a task to run the module in background
|
|
119
|
-
job_id = await self.job_manager.
|
|
175
|
+
job_id = await self.job_manager.create_module_instance_job(
|
|
120
176
|
input_data,
|
|
121
177
|
setup_data,
|
|
122
178
|
mission_id=request.mission_id,
|
|
@@ -391,3 +447,39 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer, ArgParser):
|
|
|
391
447
|
success=True,
|
|
392
448
|
secret_schema=secret_format_struct,
|
|
393
449
|
)
|
|
450
|
+
|
|
451
|
+
async def GetConfigSetupModule( # noqa: N802
|
|
452
|
+
self,
|
|
453
|
+
request: information_pb2.GetConfigSetupModuleRequest,
|
|
454
|
+
context: grpc.ServicerContext,
|
|
455
|
+
) -> information_pb2.GetConfigSetupModuleResponse:
|
|
456
|
+
"""Get information about the module's setup and configuration.
|
|
457
|
+
|
|
458
|
+
Args:
|
|
459
|
+
request: The get module setup request.
|
|
460
|
+
context: The gRPC context.
|
|
461
|
+
|
|
462
|
+
Returns:
|
|
463
|
+
A response with the module's setup information.
|
|
464
|
+
"""
|
|
465
|
+
logger.debug("GetConfigSetupModule called for module: '%s'", self.module_class.__name__)
|
|
466
|
+
|
|
467
|
+
# Get setup schema if available
|
|
468
|
+
try:
|
|
469
|
+
# Convert schema to proto format
|
|
470
|
+
config_setup_schema_proto = self.module_class.get_config_setup_format(llm_format=request.llm_format)
|
|
471
|
+
config_setup_format_struct = json_format.Parse(
|
|
472
|
+
text=config_setup_schema_proto,
|
|
473
|
+
message=struct_pb2.Struct(), # pylint: disable=no-member
|
|
474
|
+
ignore_unknown_fields=True,
|
|
475
|
+
)
|
|
476
|
+
except NotImplementedError as e:
|
|
477
|
+
logger.warning(e)
|
|
478
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
479
|
+
context.set_details(e)
|
|
480
|
+
return information_pb2.GetConfigSetupModuleResponse()
|
|
481
|
+
|
|
482
|
+
return information_pb2.GetConfigSetupModuleResponse(
|
|
483
|
+
success=True,
|
|
484
|
+
config_setup_schema=config_setup_format_struct,
|
|
485
|
+
)
|
|
@@ -31,3 +31,7 @@ class ReflectionError(ServerError):
|
|
|
31
31
|
|
|
32
32
|
class HealthCheckError(ServerError):
|
|
33
33
|
"""Error related to gRPC health check service."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class OptionalFeatureNotImplementedError(NotImplementedError):
|
|
37
|
+
"""Raised when an optional feature is not implemented, but was requested."""
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from digitalkin.models.module.module import Module, ModuleStatus
|
|
4
4
|
from digitalkin.models.module.module_types import (
|
|
5
|
+
ConfigSetupModelT,
|
|
5
6
|
InputModelT,
|
|
6
7
|
OutputModelT,
|
|
7
8
|
SecretModelT,
|
|
8
9
|
SetupModelT,
|
|
9
10
|
)
|
|
10
11
|
|
|
11
|
-
__all__ = ["InputModelT", "Module", "ModuleStatus", "OutputModelT", "SecretModelT", "SetupModelT"]
|
|
12
|
+
__all__ = ["ConfigSetupModelT", "InputModelT", "Module", "ModuleStatus", "OutputModelT", "SecretModelT", "SetupModelT"]
|
|
@@ -4,6 +4,7 @@ from typing import TypeVar
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
|
+
ConfigSetupModelT = TypeVar("ConfigSetupModelT", bound=BaseModel | None)
|
|
7
8
|
InputModelT = TypeVar("InputModelT", bound=BaseModel)
|
|
8
9
|
OutputModelT = TypeVar("OutputModelT", bound=BaseModel)
|
|
9
10
|
SetupModelT = TypeVar("SetupModelT", bound=BaseModel)
|
|
@@ -9,8 +9,16 @@ from typing import Any, ClassVar, Generic
|
|
|
9
9
|
|
|
10
10
|
from pydantic import BaseModel
|
|
11
11
|
|
|
12
|
+
from digitalkin.grpc_servers.utils.exceptions import OptionalFeatureNotImplementedError
|
|
12
13
|
from digitalkin.logger import logger
|
|
13
|
-
from digitalkin.models.module import
|
|
14
|
+
from digitalkin.models.module import (
|
|
15
|
+
ConfigSetupModelT,
|
|
16
|
+
InputModelT,
|
|
17
|
+
ModuleStatus,
|
|
18
|
+
OutputModelT,
|
|
19
|
+
SecretModelT,
|
|
20
|
+
SetupModelT,
|
|
21
|
+
)
|
|
14
22
|
from digitalkin.services.agent.agent_strategy import AgentStrategy
|
|
15
23
|
from digitalkin.services.cost.cost_strategy import CostStrategy
|
|
16
24
|
from digitalkin.services.filesystem.filesystem_strategy import FilesystemStrategy
|
|
@@ -30,11 +38,22 @@ class ModuleErrorModel(BaseModel):
|
|
|
30
38
|
short_description: str
|
|
31
39
|
|
|
32
40
|
|
|
33
|
-
class BaseModule(
|
|
41
|
+
class BaseModule(
|
|
42
|
+
ABC,
|
|
43
|
+
Generic[
|
|
44
|
+
InputModelT,
|
|
45
|
+
OutputModelT,
|
|
46
|
+
SetupModelT,
|
|
47
|
+
SecretModelT,
|
|
48
|
+
ConfigSetupModelT,
|
|
49
|
+
],
|
|
50
|
+
):
|
|
34
51
|
"""BaseModule is the abstract base for all modules in the DigitalKin SDK."""
|
|
35
52
|
|
|
36
53
|
name: str
|
|
37
54
|
description: str
|
|
55
|
+
|
|
56
|
+
config_setup_format: type[ConfigSetupModelT]
|
|
38
57
|
input_format: type[InputModelT]
|
|
39
58
|
output_format: type[OutputModelT]
|
|
40
59
|
setup_format: type[SetupModelT]
|
|
@@ -136,6 +155,23 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
136
155
|
msg = "'%s' class does not define an 'output_format'."
|
|
137
156
|
raise NotImplementedError(msg)
|
|
138
157
|
|
|
158
|
+
@classmethod
|
|
159
|
+
def get_config_setup_format(cls, *, llm_format: bool) -> str:
|
|
160
|
+
"""Gets the JSON schema of the config setup format model.
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
OptionalFeatureNotImplementedError: If the `config_setup_format` is not defined.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
The JSON schema of the config setup format as a string.
|
|
167
|
+
"""
|
|
168
|
+
if cls.config_setup_format is not None:
|
|
169
|
+
if llm_format:
|
|
170
|
+
return json.dumps(llm_ready_schema(cls.config_setup_format), indent=2)
|
|
171
|
+
return json.dumps(cls.config_setup_format.model_json_schema(), indent=2)
|
|
172
|
+
msg = "'%s' class does not define an 'config_setup_format'."
|
|
173
|
+
raise OptionalFeatureNotImplementedError(msg)
|
|
174
|
+
|
|
139
175
|
@classmethod
|
|
140
176
|
def get_setup_format(cls, *, llm_format: bool) -> str:
|
|
141
177
|
"""Gets the JSON schema of the setup format model.
|
|
@@ -153,6 +189,18 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
153
189
|
msg = "'%s' class does not define an 'setup_format'."
|
|
154
190
|
raise NotImplementedError(msg)
|
|
155
191
|
|
|
192
|
+
@classmethod
|
|
193
|
+
def create_config_setup_model(cls, config_setup_data: dict[str, Any]) -> ConfigSetupModelT:
|
|
194
|
+
"""Create the setup model from the setup data.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
config_setup_data: The setup data to create the model from.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
The setup model.
|
|
201
|
+
"""
|
|
202
|
+
return cls.config_setup_format(**config_setup_data)
|
|
203
|
+
|
|
156
204
|
@classmethod
|
|
157
205
|
def create_input_model(cls, input_data: dict[str, Any]) -> InputModelT:
|
|
158
206
|
"""Create the input model from the input data.
|
|
@@ -201,6 +249,21 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
201
249
|
"""
|
|
202
250
|
return cls.output_format(**output_data)
|
|
203
251
|
|
|
252
|
+
@abstractmethod
|
|
253
|
+
async def run_config_setup(
|
|
254
|
+
self,
|
|
255
|
+
config_setup_data: ConfigSetupModelT,
|
|
256
|
+
setup_data: SetupModelT,
|
|
257
|
+
callback: Callable,
|
|
258
|
+
) -> None:
|
|
259
|
+
"""Run config setup the module.
|
|
260
|
+
|
|
261
|
+
Raises:
|
|
262
|
+
OptionalFeatureNotImplementedError: If the config setup feature is not implemented.
|
|
263
|
+
"""
|
|
264
|
+
msg = f"'{self}' class does not define an optional 'run_config_setup' attribute."
|
|
265
|
+
raise OptionalFeatureNotImplementedError(msg)
|
|
266
|
+
|
|
204
267
|
@abstractmethod
|
|
205
268
|
async def initialize(self, setup_data: SetupModelT) -> None:
|
|
206
269
|
"""Initialize the module."""
|
|
@@ -302,3 +365,18 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
302
365
|
except Exception:
|
|
303
366
|
self._status = ModuleStatus.FAILED
|
|
304
367
|
logger.exception("Error stopping module")
|
|
368
|
+
|
|
369
|
+
async def start_config_setup(
|
|
370
|
+
self,
|
|
371
|
+
config_setup_data: ConfigSetupModelT,
|
|
372
|
+
setup_data: SetupModelT,
|
|
373
|
+
callback: Callable[[OutputModelT | ModuleErrorModel], Coroutine[Any, Any, None]],
|
|
374
|
+
) -> None:
|
|
375
|
+
"""Start the module."""
|
|
376
|
+
try:
|
|
377
|
+
logger.info("Run Config Setup lifecycle")
|
|
378
|
+
self._status = ModuleStatus.RUNNING
|
|
379
|
+
await self.run_config_setup(config_setup_data, setup_data, callback)
|
|
380
|
+
except Exception:
|
|
381
|
+
self._status = ModuleStatus.FAILED
|
|
382
|
+
logger.exception("Error during module lifecyle")
|
|
@@ -3,8 +3,18 @@
|
|
|
3
3
|
from abc import ABC
|
|
4
4
|
|
|
5
5
|
from digitalkin.models.module import InputModelT, OutputModelT, SecretModelT, SetupModelT
|
|
6
|
+
from digitalkin.models.module.module_types import ConfigSetupModelT
|
|
6
7
|
from digitalkin.modules._base_module import BaseModule
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
class ArchetypeModule(
|
|
10
|
+
class ArchetypeModule(
|
|
11
|
+
BaseModule[
|
|
12
|
+
InputModelT,
|
|
13
|
+
OutputModelT,
|
|
14
|
+
SetupModelT,
|
|
15
|
+
SecretModelT,
|
|
16
|
+
ConfigSetupModelT,
|
|
17
|
+
],
|
|
18
|
+
ABC,
|
|
19
|
+
):
|
|
10
20
|
"""ArchetypeModule extends BaseModule to implement specific module types."""
|
{digitalkin-0.2.13 → digitalkin-0.2.14}/src/digitalkin/modules/job_manager/base_job_manager.py
RENAMED
|
@@ -7,12 +7,13 @@ from typing import Any, Generic
|
|
|
7
7
|
|
|
8
8
|
from digitalkin.models import ModuleStatus
|
|
9
9
|
from digitalkin.models.module import InputModelT, OutputModelT, SetupModelT
|
|
10
|
+
from digitalkin.models.module.module_types import ConfigSetupModelT
|
|
10
11
|
from digitalkin.modules._base_module import BaseModule
|
|
11
12
|
from digitalkin.services.services_config import ServicesConfig
|
|
12
13
|
from digitalkin.services.services_models import ServicesMode
|
|
13
14
|
|
|
14
15
|
|
|
15
|
-
class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
|
|
16
|
+
class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT, ConfigSetupModelT]):
|
|
16
17
|
"""Abstract base class for managing background module jobs."""
|
|
17
18
|
|
|
18
19
|
async def _start(self) -> None:
|
|
@@ -82,14 +83,14 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
|
|
|
82
83
|
"""
|
|
83
84
|
|
|
84
85
|
@abc.abstractmethod
|
|
85
|
-
async def
|
|
86
|
+
async def create_module_instance_job(
|
|
86
87
|
self,
|
|
87
88
|
input_data: InputModelT,
|
|
88
89
|
setup_data: SetupModelT,
|
|
89
90
|
mission_id: str,
|
|
90
91
|
setup_version_id: str,
|
|
91
92
|
) -> str:
|
|
92
|
-
"""Create and start a new job for the module.
|
|
93
|
+
"""Create and start a new job for the module's instance.
|
|
93
94
|
|
|
94
95
|
Args:
|
|
95
96
|
input_data: The input data required to start the job.
|
|
@@ -101,6 +102,47 @@ class BaseJobManager(abc.ABC, Generic[InputModelT, SetupModelT]):
|
|
|
101
102
|
str: The unique identifier (job ID) of the created job.
|
|
102
103
|
"""
|
|
103
104
|
|
|
105
|
+
@abc.abstractmethod
|
|
106
|
+
async def generate_config_setup_module_response(self, job_id: str) -> SetupModelT:
|
|
107
|
+
"""Generate a stream consumer for a module's output data.
|
|
108
|
+
|
|
109
|
+
This method creates an asynchronous generator that streams output data
|
|
110
|
+
from a specific module job. If the module does not exist, it generates
|
|
111
|
+
an error message.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
job_id: The unique identifier of the job.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
SetupModelT: the SetupModelT object fully processed.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
@abc.abstractmethod
|
|
121
|
+
async def create_config_setup_instance_job(
|
|
122
|
+
self,
|
|
123
|
+
config_setup_data: ConfigSetupModelT,
|
|
124
|
+
setup_data: SetupModelT,
|
|
125
|
+
mission_id: str,
|
|
126
|
+
setup_version_id: str,
|
|
127
|
+
) -> str:
|
|
128
|
+
"""Create and start a new module job.
|
|
129
|
+
|
|
130
|
+
This method initializes a new module job, assigns it a unique job ID,
|
|
131
|
+
and starts it in the background.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
config_setup_data: The input data required to start the job.
|
|
135
|
+
setup_data: The setup configuration for the module.
|
|
136
|
+
mission_id: The mission ID associated with the job.
|
|
137
|
+
setup_version_id: The setup ID.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
str: The unique identifier (job ID) of the created job.
|
|
141
|
+
|
|
142
|
+
Raises:
|
|
143
|
+
Exception: If the module fails to start.
|
|
144
|
+
"""
|
|
145
|
+
|
|
104
146
|
@abc.abstractmethod
|
|
105
147
|
async def stop_module(self, job_id: str) -> bool:
|
|
106
148
|
"""Stop a running module job.
|