label-studio-sdk 1.0.7__py3-none-any.whl → 1.0.8__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 label-studio-sdk might be problematic. Click here for more details.
- label_studio_sdk/__init__.py +6 -0
- label_studio_sdk/_extensions/label_studio_tools/core/label_config.py +13 -4
- label_studio_sdk/_extensions/label_studio_tools/core/utils/json_schema.py +86 -0
- label_studio_sdk/_legacy/schema/label_config_schema.json +42 -11
- label_studio_sdk/converter/converter.py +10 -5
- label_studio_sdk/core/client_wrapper.py +1 -1
- label_studio_sdk/label_interface/control_tags.py +205 -10
- label_studio_sdk/label_interface/interface.py +80 -6
- label_studio_sdk/label_interface/region.py +1 -10
- label_studio_sdk/model_providers/client.py +520 -2
- label_studio_sdk/prompts/versions/client.py +125 -0
- label_studio_sdk/types/__init__.py +6 -0
- label_studio_sdk/types/inference_run_cost_estimate.py +57 -0
- label_studio_sdk/types/model_provider_connection.py +30 -0
- label_studio_sdk/types/model_provider_connection_budget_reset_period.py +5 -0
- label_studio_sdk/types/model_provider_connection_provider.py +1 -1
- label_studio_sdk/types/refined_prompt_response.py +1 -1
- label_studio_sdk/types/task.py +3 -2
- label_studio_sdk/types/task_comment_authors_item.py +5 -0
- {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.8.dist-info}/METADATA +3 -1
- {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.8.dist-info}/RECORD +23 -19
- {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.8.dist-info}/LICENSE +0 -0
- {label_studio_sdk-1.0.7.dist-info → label_studio_sdk-1.0.8.dist-info}/WHEEL +0 -0
|
@@ -15,6 +15,7 @@ from pydantic import BaseModel
|
|
|
15
15
|
from collections import defaultdict, OrderedDict
|
|
16
16
|
from lxml import etree
|
|
17
17
|
import xmljson
|
|
18
|
+
from jsf import JSF
|
|
18
19
|
|
|
19
20
|
from label_studio_sdk._legacy.exceptions import (
|
|
20
21
|
LSConfigParseException,
|
|
@@ -320,7 +321,7 @@ class LabelInterface:
|
|
|
320
321
|
# 1. we should allow control.label to process custom payload outside of those strictly containing "label"
|
|
321
322
|
# 2. we should be less open regarding the payload type and defining the strict typing elsewhere,
|
|
322
323
|
# but likely that requires rewriting of how ControlTag.label() is working now
|
|
323
|
-
if isinstance(payload, str):
|
|
324
|
+
if isinstance(payload, (str, int, float)):
|
|
324
325
|
payload = {'label': payload}
|
|
325
326
|
elif isinstance(payload, list):
|
|
326
327
|
if len(payload) > 0:
|
|
@@ -331,6 +332,7 @@ class LabelInterface:
|
|
|
331
332
|
|
|
332
333
|
if isinstance(payload, Dict):
|
|
333
334
|
payload = [payload]
|
|
335
|
+
|
|
334
336
|
for item in payload:
|
|
335
337
|
regions.append(control.label(**item))
|
|
336
338
|
|
|
@@ -531,12 +533,26 @@ class LabelInterface:
|
|
|
531
533
|
tree.task_loaded = True
|
|
532
534
|
|
|
533
535
|
for obj in tree.objects:
|
|
534
|
-
print(obj.value_is_variable, obj.value_name)
|
|
535
536
|
if obj.value_is_variable and obj.value_name in task:
|
|
536
537
|
obj.value = task.get(obj.value_name)
|
|
537
538
|
|
|
538
539
|
return tree
|
|
539
540
|
|
|
541
|
+
def to_json_schema(self):
|
|
542
|
+
"""
|
|
543
|
+
Converts the current LabelInterface instance into a JSON Schema.
|
|
544
|
+
|
|
545
|
+
Returns:
|
|
546
|
+
dict: A dictionary representing the JSON Schema.
|
|
547
|
+
"""
|
|
548
|
+
return {
|
|
549
|
+
"type": "object",
|
|
550
|
+
"properties": {
|
|
551
|
+
name: control.to_json_schema() for name, control in self._controls.items()
|
|
552
|
+
},
|
|
553
|
+
"required": list(self._controls.keys())
|
|
554
|
+
}
|
|
555
|
+
|
|
540
556
|
def parse(self, config_string: str) -> Tuple[Dict, Dict, Dict, etree._Element]:
|
|
541
557
|
"""Parses the received configuration string into dictionaries
|
|
542
558
|
of ControlTags, ObjectTags, and Labels, along with an XML tree
|
|
@@ -755,7 +771,7 @@ class LabelInterface:
|
|
|
755
771
|
return False
|
|
756
772
|
|
|
757
773
|
# type of the region should match the tag name
|
|
758
|
-
if control.tag.lower() != region["type"]:
|
|
774
|
+
if control.tag.lower() != region["type"].lower():
|
|
759
775
|
return False
|
|
760
776
|
|
|
761
777
|
# make sure that in config it connects to the same tag as
|
|
@@ -824,9 +840,67 @@ class LabelInterface:
|
|
|
824
840
|
|
|
825
841
|
return task
|
|
826
842
|
|
|
827
|
-
def
|
|
828
|
-
""" """
|
|
829
|
-
|
|
843
|
+
def _generate_sample_regions(self):
|
|
844
|
+
""" Generate an example of each control tag's JSON schema and validate it as a region"""
|
|
845
|
+
return self.create_regions({
|
|
846
|
+
control.name: JSF(control.to_json_schema()).generate()
|
|
847
|
+
for control in self.controls
|
|
848
|
+
})
|
|
849
|
+
|
|
850
|
+
def generate_sample_prediction(self) -> Optional[dict]:
|
|
851
|
+
"""Generates a sample prediction that is valid for this label config.
|
|
852
|
+
|
|
853
|
+
Example:
|
|
854
|
+
{'model_version': 'sample model version',
|
|
855
|
+
'score': 0.0,
|
|
856
|
+
'result': [{'id': 'e7bd76e6-4e88-4eb3-b433-55e03661bf5d',
|
|
857
|
+
'from_name': 'sentiment',
|
|
858
|
+
'to_name': 'text',
|
|
859
|
+
'type': 'choices',
|
|
860
|
+
'value': {'choices': ['Neutral']}}]}
|
|
861
|
+
|
|
862
|
+
NOTE: `id` field in result is not required when importing predictions; it will be generated automatically.
|
|
863
|
+
NOTE: for each control tag, depends on tag.to_json_schema() being implemented correctly
|
|
864
|
+
"""
|
|
865
|
+
prediction = PredictionValue(
|
|
866
|
+
model_version='sample model version',
|
|
867
|
+
result=self._generate_sample_regions()
|
|
868
|
+
)
|
|
869
|
+
prediction_dct = prediction.model_dump()
|
|
870
|
+
if self.validate_prediction(prediction_dct):
|
|
871
|
+
return prediction_dct
|
|
872
|
+
else:
|
|
873
|
+
logger.debug(f'Sample prediction {prediction_dct} failed validation for label config {self.config}')
|
|
874
|
+
return None
|
|
875
|
+
|
|
876
|
+
def generate_sample_annotation(self) -> Optional[dict]:
|
|
877
|
+
"""Generates a sample annotation that is valid for this label config.
|
|
878
|
+
|
|
879
|
+
Example:
|
|
880
|
+
{'was_cancelled': False,
|
|
881
|
+
'ground_truth': False,
|
|
882
|
+
'lead_time': 0.0,
|
|
883
|
+
'result_count': 0,
|
|
884
|
+
'completed_by': -1,
|
|
885
|
+
'result': [{'id': 'b05da11d-3ffc-4657-8b8d-f5bc37cd59ac',
|
|
886
|
+
'from_name': 'sentiment',
|
|
887
|
+
'to_name': 'text',
|
|
888
|
+
'type': 'choices',
|
|
889
|
+
'value': {'choices': ['Negative']}}]}
|
|
890
|
+
|
|
891
|
+
NOTE: `id` field in result is not required when importing predictions; it will be generated automatically.
|
|
892
|
+
NOTE: for each control tag, depends on tag.to_json_schema() being implemented correctly
|
|
893
|
+
"""
|
|
894
|
+
annotation = AnnotationValue(
|
|
895
|
+
completed_by=-1, # annotator's user id
|
|
896
|
+
result=self._generate_sample_regions()
|
|
897
|
+
)
|
|
898
|
+
annotation_dct = annotation.model_dump()
|
|
899
|
+
if self.validate_annotation(annotation_dct):
|
|
900
|
+
return annotation_dct
|
|
901
|
+
else:
|
|
902
|
+
logger.debug(f'Sample annotation {annotation_dct} failed validation for label config {self.config}')
|
|
903
|
+
return None
|
|
830
904
|
|
|
831
905
|
#####
|
|
832
906
|
##### COMPATIBILITY LAYER
|
|
@@ -10,16 +10,7 @@ from pydantic import BaseModel, Field
|
|
|
10
10
|
|
|
11
11
|
class Region(BaseModel):
|
|
12
12
|
"""
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Attributes:
|
|
16
|
-
-----------
|
|
17
|
-
id: str
|
|
18
|
-
The unique identifier of the region
|
|
19
|
-
x: int
|
|
20
|
-
The x coordinate of the region
|
|
21
|
-
y: int
|
|
22
|
-
|
|
13
|
+
A Region is an item in the `result` list of a PredictionValue or AnnotationValue.
|
|
23
14
|
"""
|
|
24
15
|
|
|
25
16
|
id: str = Field(default_factory=lambda: str(uuid4()))
|