|
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,
|
@@ -770,7 +771,7 @@ def validate_region(self, region) -> bool:
|
770 | 771 | return False
|
771 | 772 |
|
772 | 773 | # type of the region should match the tag name
|
773 |
| - if control.tag.lower() != region["type"]: |
| 774 | + if control.tag.lower() != region["type"].lower(): |
774 | 775 | return False
|
775 | 776 |
|
776 | 777 | # make sure that in config it connects to the same tag as
|
@@ -839,9 +840,67 @@ def generate_sample_task(self, mode="upload", secure_mode=False):
|
839 | 840 |
|
840 | 841 | return task
|
841 | 842 |
|
842 |
| - def generate_sample_annotation(self): |
843 |
| - """ """ |
844 |
| - raise NotImplemented() |
| 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 |
845 | 904 |
|
846 | 905 | #####
|
847 | 906 | ##### COMPATIBILITY LAYER
|
|
0 commit comments