digitalkin 0.2.6__py3-none-any.whl → 0.2.7__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 +39 -3
- digitalkin/modules/_base_module.py +9 -8
- digitalkin/utils/llm_ready_schema.py +75 -0
- {digitalkin-0.2.6.dist-info → digitalkin-0.2.7.dist-info}/METADATA +1 -1
- {digitalkin-0.2.6.dist-info → digitalkin-0.2.7.dist-info}/RECORD +9 -8
- {digitalkin-0.2.6.dist-info → digitalkin-0.2.7.dist-info}/WHEEL +1 -1
- {digitalkin-0.2.6.dist-info → digitalkin-0.2.7.dist-info}/licenses/LICENSE +0 -0
- {digitalkin-0.2.6.dist-info → digitalkin-0.2.7.dist-info}/top_level.txt +0 -0
digitalkin/__version__.py
CHANGED
|
@@ -244,7 +244,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
244
244
|
# Get input schema if available
|
|
245
245
|
try:
|
|
246
246
|
# Convert schema to proto format
|
|
247
|
-
input_schema_proto = self.module_class.get_input_format(request.llm_format)
|
|
247
|
+
input_schema_proto = self.module_class.get_input_format(llm_format=request.llm_format)
|
|
248
248
|
input_format_struct = json_format.Parse(
|
|
249
249
|
text=input_schema_proto,
|
|
250
250
|
message=struct_pb2.Struct(), # pylint: disable=no-member
|
|
@@ -280,7 +280,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
280
280
|
# Get output schema if available
|
|
281
281
|
try:
|
|
282
282
|
# Convert schema to proto format
|
|
283
|
-
output_schema_proto = self.module_class.get_output_format(request.llm_format)
|
|
283
|
+
output_schema_proto = self.module_class.get_output_format(llm_format=request.llm_format)
|
|
284
284
|
output_format_struct = json_format.Parse(
|
|
285
285
|
text=output_schema_proto,
|
|
286
286
|
message=struct_pb2.Struct(), # pylint: disable=no-member
|
|
@@ -316,7 +316,7 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
316
316
|
# Get setup schema if available
|
|
317
317
|
try:
|
|
318
318
|
# Convert schema to proto format
|
|
319
|
-
setup_schema_proto = self.module_class.get_setup_format(request.llm_format)
|
|
319
|
+
setup_schema_proto = self.module_class.get_setup_format(llm_format=request.llm_format)
|
|
320
320
|
setup_format_struct = json_format.Parse(
|
|
321
321
|
text=setup_schema_proto,
|
|
322
322
|
message=struct_pb2.Struct(), # pylint: disable=no-member
|
|
@@ -332,3 +332,39 @@ class ModuleServicer(module_service_pb2_grpc.ModuleServiceServicer):
|
|
|
332
332
|
success=True,
|
|
333
333
|
setup_schema=setup_format_struct,
|
|
334
334
|
)
|
|
335
|
+
|
|
336
|
+
def GetModuleSecret( # noqa: N802
|
|
337
|
+
self,
|
|
338
|
+
request: information_pb2.GetModuleSecretRequest,
|
|
339
|
+
context: grpc.ServicerContext,
|
|
340
|
+
) -> information_pb2.GetModuleSecretResponse:
|
|
341
|
+
"""Get information about the module's secrets.
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
request: The get module secret request.
|
|
345
|
+
context: The gRPC context.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
A response with the module's secret schema.
|
|
349
|
+
"""
|
|
350
|
+
logger.info("GetModuleSecret called for module: '%s'", self.module_class.__name__)
|
|
351
|
+
|
|
352
|
+
# Get secret schema if available
|
|
353
|
+
try:
|
|
354
|
+
# Convert schema to proto format
|
|
355
|
+
secret_schema_proto = self.module_class.get_secret_format(llm_format=request.llm_format)
|
|
356
|
+
secret_format_struct = json_format.Parse(
|
|
357
|
+
text=secret_schema_proto,
|
|
358
|
+
message=struct_pb2.Struct(), # pylint: disable=no-member
|
|
359
|
+
ignore_unknown_fields=True,
|
|
360
|
+
)
|
|
361
|
+
except NotImplementedError as e:
|
|
362
|
+
logger.warning(e)
|
|
363
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
364
|
+
context.set_details(e)
|
|
365
|
+
return information_pb2.GetModuleSecretResponse()
|
|
366
|
+
|
|
367
|
+
return information_pb2.GetModuleSecretResponse(
|
|
368
|
+
success=True,
|
|
369
|
+
secret_schema=secret_format_struct,
|
|
370
|
+
)
|
|
@@ -17,6 +17,7 @@ from digitalkin.services.registry.registry_strategy import RegistryStrategy
|
|
|
17
17
|
from digitalkin.services.services_config import ServicesConfig, ServicesStrategy
|
|
18
18
|
from digitalkin.services.snapshot.snapshot_strategy import SnapshotStrategy
|
|
19
19
|
from digitalkin.services.storage.storage_strategy import StorageStrategy
|
|
20
|
+
from digitalkin.utils.llm_ready_schema import llm_ready_schema
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretModelT]):
|
|
@@ -73,7 +74,7 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
73
74
|
return self._status
|
|
74
75
|
|
|
75
76
|
@classmethod
|
|
76
|
-
def get_secret_format(cls, llm_format: bool) -> str:
|
|
77
|
+
def get_secret_format(cls, *, llm_format: bool) -> str:
|
|
77
78
|
"""Get the JSON schema of the secret format model.
|
|
78
79
|
|
|
79
80
|
Raises:
|
|
@@ -84,13 +85,13 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
84
85
|
"""
|
|
85
86
|
if cls.secret_format is not None:
|
|
86
87
|
if llm_format:
|
|
87
|
-
return json.dumps(cls.secret_format, indent=2)
|
|
88
|
+
return json.dumps(llm_ready_schema(cls.secret_format), indent=2)
|
|
88
89
|
return json.dumps(cls.secret_format.model_json_schema(), indent=2)
|
|
89
90
|
msg = f"{cls.__name__}' class does not define a 'secret_format'."
|
|
90
91
|
raise NotImplementedError(msg)
|
|
91
92
|
|
|
92
93
|
@classmethod
|
|
93
|
-
def get_input_format(cls, llm_format: bool) -> str:
|
|
94
|
+
def get_input_format(cls, *, llm_format: bool) -> str:
|
|
94
95
|
"""Get the JSON schema of the input format model.
|
|
95
96
|
|
|
96
97
|
Raises:
|
|
@@ -101,13 +102,13 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
101
102
|
"""
|
|
102
103
|
if cls.input_format is not None:
|
|
103
104
|
if llm_format:
|
|
104
|
-
return json.dumps(cls.input_format, indent=2)
|
|
105
|
+
return json.dumps(llm_ready_schema(cls.input_format), indent=2)
|
|
105
106
|
return json.dumps(cls.input_format.model_json_schema(), indent=2)
|
|
106
107
|
msg = f"{cls.__name__}' class does not define an 'input_format'."
|
|
107
108
|
raise NotImplementedError(msg)
|
|
108
109
|
|
|
109
110
|
@classmethod
|
|
110
|
-
def get_output_format(cls, llm_format: bool) -> str:
|
|
111
|
+
def get_output_format(cls, *, llm_format: bool) -> str:
|
|
111
112
|
"""Get the JSON schema of the output format model.
|
|
112
113
|
|
|
113
114
|
Raises:
|
|
@@ -118,13 +119,13 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
118
119
|
"""
|
|
119
120
|
if cls.output_format is not None:
|
|
120
121
|
if llm_format:
|
|
121
|
-
return json.dumps(cls.output_format, indent=2)
|
|
122
|
+
return json.dumps(llm_ready_schema(cls.output_format), indent=2)
|
|
122
123
|
return json.dumps(cls.output_format.model_json_schema(), indent=2)
|
|
123
124
|
msg = "'%s' class does not define an 'output_format'."
|
|
124
125
|
raise NotImplementedError(msg)
|
|
125
126
|
|
|
126
127
|
@classmethod
|
|
127
|
-
def get_setup_format(cls, llm_format: bool) -> str:
|
|
128
|
+
def get_setup_format(cls, *, llm_format: bool) -> str:
|
|
128
129
|
"""Gets the JSON schema of the setup format model.
|
|
129
130
|
|
|
130
131
|
Raises:
|
|
@@ -135,7 +136,7 @@ class BaseModule(ABC, Generic[InputModelT, OutputModelT, SetupModelT, SecretMode
|
|
|
135
136
|
"""
|
|
136
137
|
if cls.setup_format is not None:
|
|
137
138
|
if llm_format:
|
|
138
|
-
return json.dumps(cls.setup_format, indent=2)
|
|
139
|
+
return json.dumps(llm_ready_schema(cls.setup_format), indent=2)
|
|
139
140
|
return json.dumps(cls.setup_format.model_json_schema(), indent=2)
|
|
140
141
|
msg = "'%s' class does not define an 'setup_format'."
|
|
141
142
|
raise NotImplementedError(msg)
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""LLM format schema for Pydantic models.
|
|
2
|
+
|
|
3
|
+
This module provides functionality to generate JSON schemas for Pydantic models ready for LLMs.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import copy
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
from pydantic.json_schema import GenerateJsonSchema, JsonSchemaValue
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class CustomOrderSchema(GenerateJsonSchema):
|
|
14
|
+
"""Custom schema generator to sort keys in a specific order."""
|
|
15
|
+
|
|
16
|
+
def sort(self, value: JsonSchemaValue, parent_key: str | None = None) -> JsonSchemaValue: # noqa: ARG002
|
|
17
|
+
"""Sort the keys of the schema in a specific order.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
value: The schema value to sort.
|
|
21
|
+
parent_key: The parent key of the schema value.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
The sorted schema value.
|
|
25
|
+
"""
|
|
26
|
+
if isinstance(value, dict):
|
|
27
|
+
# Define your preferred order
|
|
28
|
+
preferred = ["title", "description", "type", "examples", "properties"]
|
|
29
|
+
# Collect all keys, putting preferred ones first
|
|
30
|
+
keys = preferred + [k for k in value if k not in preferred]
|
|
31
|
+
# Recurse for each value
|
|
32
|
+
return {k: self.sort(value[k], k) for k in keys if k in value}
|
|
33
|
+
if isinstance(value, list):
|
|
34
|
+
return [self.sort(v) for v in value]
|
|
35
|
+
return value
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def inline_refs(schema: dict) -> dict:
|
|
39
|
+
"""Recursively resolve and inline all $ref in the schema.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
schema: The JSON schema to inline.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
The inlined JSON schema.
|
|
46
|
+
"""
|
|
47
|
+
schema = copy.deepcopy(schema)
|
|
48
|
+
defs = schema.pop("$defs", {})
|
|
49
|
+
|
|
50
|
+
def _resolve(obj: Any) -> Any: # noqa: ANN401
|
|
51
|
+
if isinstance(obj, dict):
|
|
52
|
+
if "$ref" in obj:
|
|
53
|
+
ref = obj["$ref"]
|
|
54
|
+
if ref.startswith("#/$defs/"):
|
|
55
|
+
key = ref.split("/")[-1]
|
|
56
|
+
return _resolve(defs[key])
|
|
57
|
+
return {k: _resolve(v) for k, v in obj.items()}
|
|
58
|
+
if isinstance(obj, list):
|
|
59
|
+
return [_resolve(item) for item in obj]
|
|
60
|
+
return obj
|
|
61
|
+
|
|
62
|
+
return _resolve(schema)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def llm_ready_schema(model: type[BaseModel]) -> dict:
|
|
66
|
+
"""Convert a Pydantic model to a JSON schema ready for LLMs.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
model: The Pydantic model to convert.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
The JSON schema as a dictionary.
|
|
73
|
+
"""
|
|
74
|
+
schema = model.model_json_schema(schema_generator=CustomOrderSchema)
|
|
75
|
+
return inline_refs(schema)
|
|
@@ -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=sq3ZYGvIa5rczwcukAFcGJdR0MZ8h0cIPYmDlhbjOP4,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=0jC5MN-H4MGA9O9J87gnlM8EHcbrkb0chuCm8yZh7gI,10232
|
|
16
|
-
digitalkin/grpc_servers/module_servicer.py,sha256=
|
|
16
|
+
digitalkin/grpc_servers/module_servicer.py,sha256=gm1dhmHhBGqY2xlhAp5i15O6waOA1mDHbFJxsT2RUT8,13662
|
|
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,7 +29,7 @@ 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=WU2oUW4-FjFtieuyRfXv3R3P4N1xT78zzMWrSTdhmAg,9090
|
|
33
33
|
digitalkin/modules/archetype_module.py,sha256=T2Ehj7EpAC2MO9WQbJv39hqRw7rh3exhVZTEL3JPM8U,421
|
|
34
34
|
digitalkin/modules/job_manager.py,sha256=QHcrm3F99I9tlNzXefkyhkkwPITf_H1bEb_obMDbUic,6177
|
|
35
35
|
digitalkin/modules/tool_module.py,sha256=86g0M1wHZ1ReIc7AkKfyjnlGN2QYJBGxrEQpKVlyrZI,421
|
|
@@ -67,12 +67,13 @@ digitalkin/services/storage/grpc_storage.py,sha256=eSadiI3JuveItx8LdiC3GbjbjnB8G
|
|
|
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
|
|
70
|
+
digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
|
|
71
|
+
digitalkin-0.2.7.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
|
|
71
72
|
modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
73
|
modules/minimal_llm_module.py,sha256=W-E3OrRbAsRJ6hvSeTU8pzmacdJC_PbcWfDapRv5A1A,5617
|
|
73
74
|
modules/storage_module.py,sha256=bu52lW4RFcWB8VFDhrpBFfCaTSkVL6so3zrkfW4LO9E,6270
|
|
74
75
|
modules/text_transform_module.py,sha256=1KaA7abwxltKKtbmiW1rkkIK3BTYFPegUq54px0LOQs,7277
|
|
75
|
-
digitalkin-0.2.
|
|
76
|
-
digitalkin-0.2.
|
|
77
|
-
digitalkin-0.2.
|
|
78
|
-
digitalkin-0.2.
|
|
76
|
+
digitalkin-0.2.7.dist-info/METADATA,sha256=1-9MQvIcY6e4S5Cfzea9Nk2lHFx7coGQZ935DzJ00zg,29125
|
|
77
|
+
digitalkin-0.2.7.dist-info/WHEEL,sha256=ck4Vq1_RXyvS4Jt6SI0Vz6fyVs4GWg7AINwpsaGEgPE,91
|
|
78
|
+
digitalkin-0.2.7.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
|
|
79
|
+
digitalkin-0.2.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|