sapiopycommons 2025.7.22a651__py3-none-any.whl → 2025.7.30a660__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 sapiopycommons might be problematic. Click here for more details.
- sapiopycommons/ai/protobuf_utils.py +12 -15
- sapiopycommons/ai/test_client.py +21 -10
- sapiopycommons/ai/tool_service_base.py +17 -9
- {sapiopycommons-2025.7.22a651.dist-info → sapiopycommons-2025.7.30a660.dist-info}/METADATA +1 -1
- {sapiopycommons-2025.7.22a651.dist-info → sapiopycommons-2025.7.30a660.dist-info}/RECORD +7 -7
- {sapiopycommons-2025.7.22a651.dist-info → sapiopycommons-2025.7.30a660.dist-info}/WHEEL +0 -0
- {sapiopycommons-2025.7.22a651.dist-info → sapiopycommons-2025.7.30a660.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from typing import Any
|
|
2
|
-
|
|
3
1
|
from sapiopylib.rest.pojo.Sort import SortDirection
|
|
4
2
|
from sapiopylib.rest.pojo.datatype.FieldDefinition import AbstractVeloxFieldDefinition, FieldType, \
|
|
5
3
|
VeloxBooleanFieldDefinition, VeloxDateFieldDefinition, VeloxAccessionFieldDefinition, VeloxActionFieldDefinition, \
|
|
@@ -435,24 +433,23 @@ class ProtobufUtils:
|
|
|
435
433
|
)
|
|
436
434
|
|
|
437
435
|
@staticmethod
|
|
438
|
-
def field_pbo_to_value(
|
|
436
|
+
def field_pbo_to_value(value: FieldValuePbo) -> FieldValue:
|
|
439
437
|
"""
|
|
440
|
-
Convert a StepRecordFieldValue to its corresponding Python value
|
|
438
|
+
Convert a StepRecordFieldValue to its corresponding Python value.
|
|
441
439
|
|
|
442
|
-
:param field: The VeloxFieldDefPbo or FieldTypePbo object for the given value.
|
|
443
440
|
:param value: The StepRecordFieldValue object.
|
|
444
441
|
:return: The corresponding Python value.
|
|
445
442
|
"""
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
443
|
+
if value.HasField("string_value"):
|
|
444
|
+
return value.string_value
|
|
445
|
+
elif value.HasField("int_value"):
|
|
446
|
+
return value.int_value
|
|
447
|
+
elif value.HasField("double_value"):
|
|
448
|
+
return value.double_value
|
|
449
|
+
elif value.HasField("bool_value"):
|
|
450
|
+
return value.bool_value
|
|
451
|
+
else:
|
|
452
|
+
return None
|
|
456
453
|
|
|
457
454
|
@staticmethod
|
|
458
455
|
def field_def_pbo_to_default_value(field_def: VeloxFieldDefPbo) -> FieldValue:
|
sapiopycommons/ai/test_client.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import base64
|
|
2
2
|
import json
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Any
|
|
4
4
|
|
|
5
5
|
import grpc
|
|
6
6
|
from sapiopylib.rest.User import SapioUser
|
|
7
7
|
|
|
8
|
-
from sapiopycommons.ai.api.fielddefinitions.proto.fields_pb2 import FieldValuePbo
|
|
9
8
|
from sapiopycommons.ai.api.plan.tool.proto.entry_pb2 import DataTypePbo, StepBinaryContainerPbo, StepCsvRowPbo, \
|
|
10
9
|
StepCsvHeaderRowPbo, StepCsvContainerPbo, StepJsonContainerPbo, StepImageContainerPbo, StepTextContainerPbo, \
|
|
11
10
|
StepItemContainerPbo, StepInputBatchPbo
|
|
@@ -13,6 +12,8 @@ from sapiopycommons.ai.api.plan.tool.proto.tool_pb2 import ProcessStepResponsePb
|
|
|
13
12
|
ToolDetailsRequestPbo, ToolDetailsResponsePbo, ProcessStepResponseStatusPbo
|
|
14
13
|
from sapiopycommons.ai.api.plan.tool.proto.tool_pb2_grpc import ToolServiceStub
|
|
15
14
|
from sapiopycommons.ai.api.session.proto.sapio_conn_info_pb2 import SapioConnectionInfoPbo, SapioUserSecretTypePbo
|
|
15
|
+
from sapiopycommons.ai.protobuf_utils import ProtobufUtils
|
|
16
|
+
from sapiopycommons.general.aliases import FieldValue
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
# FR-47422: Created class.
|
|
@@ -32,7 +33,7 @@ class ToolOutput:
|
|
|
32
33
|
image_output: list[bytes]
|
|
33
34
|
text_output: list[str]
|
|
34
35
|
|
|
35
|
-
new_records: list[
|
|
36
|
+
new_records: list[dict[str, FieldValue]]
|
|
36
37
|
|
|
37
38
|
logs: list[str]
|
|
38
39
|
|
|
@@ -51,28 +52,35 @@ class ToolOutput:
|
|
|
51
52
|
ret_val += f"\tStatus: {self.status}\n"
|
|
52
53
|
ret_val += f"\tMessage: {self.message}\n"
|
|
53
54
|
ret_val += "-" * 25 + "\n"
|
|
55
|
+
|
|
54
56
|
ret_val += f"Binary Output: {len(self.binary_output)} item(s)\n"
|
|
55
57
|
for binary in self.binary_output:
|
|
56
58
|
ret_val += f"\t{len(binary)} byte(s)\n"
|
|
57
59
|
ret_val += f"\t{binary[:50]}...\n"
|
|
60
|
+
|
|
58
61
|
ret_val += f"CSV Output: {len(self.csv_output)} item(s)\n"
|
|
59
62
|
if self.csv_output:
|
|
60
63
|
ret_val += f"\tHeaders: {', '.join(self.csv_output[0].keys())}\n"
|
|
61
64
|
for i, csv_row in enumerate(self.csv_output):
|
|
62
65
|
ret_val += f"\t{i}: {', '.join(f'{v}' for k, v in csv_row.items())}\n"
|
|
66
|
+
|
|
63
67
|
ret_val += f"JSON Output: {len(self.json_output)} item(s)\n"
|
|
64
68
|
if self.json_output:
|
|
65
|
-
ret_val += f"
|
|
69
|
+
ret_val += f"{json.dumps(self.json_output, indent=2)}\n"
|
|
70
|
+
|
|
66
71
|
ret_val += f"Image Output: {len(self.image_output)} item(s)\n"
|
|
67
72
|
for image in self.image_output:
|
|
68
73
|
ret_val += f"\t{len(image)} bytes\n"
|
|
69
74
|
ret_val += f"\t{image[:50]}...\n"
|
|
75
|
+
|
|
70
76
|
ret_val += f"Text Output: {len(self.text_output)} item(s)\n"
|
|
71
77
|
for text in self.text_output:
|
|
72
|
-
ret_val += f"\t{text}
|
|
78
|
+
ret_val += f"\t{text}\n"
|
|
79
|
+
|
|
73
80
|
ret_val += f"New Records: {len(self.new_records)} item(s)\n"
|
|
74
81
|
for record in self.new_records:
|
|
75
|
-
ret_val += f"
|
|
82
|
+
ret_val += f"{json.dumps(record, indent=2)}\n"
|
|
83
|
+
|
|
76
84
|
ret_val += f"Logs: {len(self.logs)} item(s)\n"
|
|
77
85
|
for log in self.logs:
|
|
78
86
|
ret_val += f"\t{log}\n"
|
|
@@ -237,16 +245,17 @@ class TestClient:
|
|
|
237
245
|
sapio_user=self.connection,
|
|
238
246
|
tool_name=tool_name,
|
|
239
247
|
config_field_values=self._config_fields,
|
|
248
|
+
dry_run=is_dry_run,
|
|
249
|
+
verbose_logging=True,
|
|
240
250
|
input=[
|
|
241
251
|
StepInputBatchPbo(is_partial=False, item_container=item)
|
|
242
252
|
for item in self._request_inputs
|
|
243
|
-
]
|
|
244
|
-
dry_run=is_dry_run,
|
|
245
|
-
verbose_logging=True
|
|
253
|
+
]
|
|
246
254
|
)
|
|
247
255
|
)
|
|
248
256
|
|
|
249
257
|
results = ToolOutput(tool_name)
|
|
258
|
+
|
|
250
259
|
match response.status:
|
|
251
260
|
case ProcessStepResponseStatusPbo.SUCCESS:
|
|
252
261
|
results.status = "Success"
|
|
@@ -255,6 +264,7 @@ class TestClient:
|
|
|
255
264
|
case _:
|
|
256
265
|
results.status = "Unknown"
|
|
257
266
|
results.message = response.status_message
|
|
267
|
+
|
|
258
268
|
for item in response.output:
|
|
259
269
|
container = item.item_container
|
|
260
270
|
|
|
@@ -269,7 +279,8 @@ class TestClient:
|
|
|
269
279
|
results.text_output.extend(container.text_container.items)
|
|
270
280
|
|
|
271
281
|
for record in response.new_records:
|
|
272
|
-
|
|
282
|
+
field_map: dict[str, Any] = {x: ProtobufUtils.field_pbo_to_value(y) for x, y in record.fields.items()}
|
|
283
|
+
results.new_records.append(field_map)
|
|
273
284
|
|
|
274
285
|
results.logs.extend(response.log)
|
|
275
286
|
|
|
@@ -289,14 +289,18 @@ class ToolServiceBase(ToolServiceServicer, ABC):
|
|
|
289
289
|
generated by the tool.
|
|
290
290
|
"""
|
|
291
291
|
# Locate the tool named in the request.
|
|
292
|
-
|
|
293
|
-
for t in self.register_tools()
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
292
|
+
find_tool: str = request.tool_name
|
|
293
|
+
registered_tools: dict[str, type[ToolBase]] = {t.name(): t for t in self.register_tools()}
|
|
294
|
+
if find_tool not in registered_tools:
|
|
295
|
+
# If the tool is not found, list all of the registered tools for this service so that the LLM can correct
|
|
296
|
+
# the tool it is requesting.
|
|
297
|
+
all_tool_names: str = "\n".join(registered_tools.keys())
|
|
298
|
+
msg: str = (f"Tool \"{find_tool}\" not found in the registered tools for this service. The registered tools "
|
|
299
|
+
f"for this service are: \n{all_tool_names}")
|
|
300
|
+
return False, msg, [], []
|
|
301
|
+
|
|
302
|
+
# Instantiate the tool class.
|
|
303
|
+
tool: ToolBase = registered_tools[find_tool]()
|
|
300
304
|
try:
|
|
301
305
|
# Setup the tool with details from the request.
|
|
302
306
|
tool.setup(user, request, context)
|
|
@@ -893,7 +897,11 @@ class ToolBase(ABC):
|
|
|
893
897
|
if field_name not in raw_configs:
|
|
894
898
|
config_fields[field_name] = ProtobufUtils.field_def_pbo_to_default_value(field_def)
|
|
895
899
|
else:
|
|
896
|
-
|
|
900
|
+
field_value: Any = ProtobufUtils.field_pbo_to_value(raw_configs[field_name])
|
|
901
|
+
if field_value is not None:
|
|
902
|
+
config_fields[field_name] = field_value
|
|
903
|
+
else:
|
|
904
|
+
config_fields[field_name] = ProtobufUtils.field_def_pbo_to_default_value(field_def)
|
|
897
905
|
return config_fields
|
|
898
906
|
|
|
899
907
|
@staticmethod
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sapiopycommons
|
|
3
|
-
Version: 2025.7.
|
|
3
|
+
Version: 2025.7.30a660
|
|
4
4
|
Summary: Official Sapio Python API Utilities Package
|
|
5
5
|
Project-URL: Homepage, https://github.com/sapiosciences
|
|
6
6
|
Author-email: Jonathan Steck <jsteck@sapiosciences.com>, Yechen Qiao <yqiao@sapiosciences.com>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
sapiopycommons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
sapiopycommons/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
sapiopycommons/ai/protobuf_utils.py,sha256=
|
|
4
|
-
sapiopycommons/ai/test_client.py,sha256=
|
|
5
|
-
sapiopycommons/ai/tool_service_base.py,sha256=
|
|
3
|
+
sapiopycommons/ai/protobuf_utils.py,sha256=yJkKolSfH2a-zk1k7juGh9-xQz6mmsoaJtM91meQIgk,24645
|
|
4
|
+
sapiopycommons/ai/test_client.py,sha256=TBlXeWVAx2OUtCZNry8dNjY9I3NOkySYj_QdQd7xx1A,12050
|
|
5
|
+
sapiopycommons/ai/tool_service_base.py,sha256=n_8UiLD6vuvkobJAHEGybvq5AY-itFCN1IjTiuyjmrU,42584
|
|
6
6
|
sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.py,sha256=YcZjb_YM-XeLErM8hEC_S7vGMVGvcXAMGs2b-u5zvOE,2377
|
|
7
7
|
sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2.pyi,sha256=FwtXmNAf7iYGEFm4kbqb04v77jNHbZg18ZmEDhle_bU,1444
|
|
8
8
|
sapiopycommons/ai/api/fielddefinitions/proto/fields_pb2_grpc.py,sha256=wPImJPdCUZNVEVoUWzsba9kGIXjEKPdUkawP5SnVyiU,932
|
|
@@ -90,7 +90,7 @@ sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
90
90
|
sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
|
|
91
91
|
sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
|
|
92
92
|
sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
|
|
93
|
-
sapiopycommons-2025.7.
|
|
94
|
-
sapiopycommons-2025.7.
|
|
95
|
-
sapiopycommons-2025.7.
|
|
96
|
-
sapiopycommons-2025.7.
|
|
93
|
+
sapiopycommons-2025.7.30a660.dist-info/METADATA,sha256=ARGB8aFkiawv1p5UphWDTJ-5xpFvVjZqoaGLe09mwgE,3143
|
|
94
|
+
sapiopycommons-2025.7.30a660.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
95
|
+
sapiopycommons-2025.7.30a660.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
96
|
+
sapiopycommons-2025.7.30a660.dist-info/RECORD,,
|
|
File without changes
|
{sapiopycommons-2025.7.22a651.dist-info → sapiopycommons-2025.7.30a660.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|