HumanSignal / label-studio-sdk

Label Studio SDK
https://api.labelstud.io
77 stars 50 forks source link

Relations tag requires name and toName attributes #211

Open maggiorante opened 1 month ago

maggiorante commented 1 month ago

Hi,

I was following the SAM tutorial at https://labelstud.io/tutorials/segment_anything_model and i watched the linked video to get the sample label configuration since the link did not work. This is the configuration:

<View>
  <Image name="image" value="$image" zoom="true"/>
  <BrushLabels name="brush" toName="image">
    <Label value="1" hint="brush" background="blue" alias="1_brush"/>
    <Label value="2" hint="brush" background="purple" alias="2_brush"/>
  </BrushLabels>
  <Relations>
    <Relation value="similar"/>
  </Relations>
  <KeyPointLabels name="tag2" toName="image">
    <Label value="(+1)" hint="keypoint" background="blue" alias="1"/>
    <Label value="(-1)" hint="keypoint" background="red" alias="-1"/>
    <Label value="(+2)" hint="keypoint" background="blue" alias="2"/>
    <Label value="(-2)" hint="keypoint" background="red" alias="-2"/>
  </KeyPointLabels>
  <RectangleLabels name="tag4" toName="image">
    <Label value="[1]" hint="rectangle" background="blue" alias="1"/>
    <Label value="[2]" hint="rectangle" background="purple" alias="2"/>
  </RectangleLabels>
</View>

I did not know what the Relations tag was so i went and checked on the documentation and it does not require any name or toName attribute to be set. This configuration does work inside labelstudio but when i try to add the ml backend i get this error:

Traceback (most recent call last):
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_ml\exceptions.py", line 39, in exception_f
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_ml\api.py", line 99, in _setup
    model = MODEL_CLASS(project_id=project_id,
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_ml\model.py", line 79, in __init__
    self.use_label_config(label_config)
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_ml\model.py", line 104, in use_label_config
    self.label_interface = LabelInterface(config=label_config)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_sdk\label_interface\interface.py", line 215, in __init__
    controls, objects, labels, tree = self.parse(config)
                                      ^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\my_ml_backend\venv\Lib\site-packages\label_studio_sdk\label_interface\interface.py", line 432, in parse
    labels[lb.parent_name][lb.value] = lb
           ^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'parent_name'

I tried debugging with a simplified configuration

<View>
  <Image name="image" value="$image" zoom="true"/>
  <Relations>
    <Relation value="similar"/>
  </Relations>
</View>

and discovered that the Relations elements needs the attributes name and toName to be set in order to work (which are not specified inside the documentation).

This is because in label_studio_sdk/label_interface/control_tags.py ControlTag.validate_node() is written like this:

 return bool(
    tag.attrib.get("name")
    and tag.attrib.get("toName")
    and tag.tag not in _NOT_CONTROL_TAGS
)

Relations tag is a ControlTag but it is never recognized as such hence inside label_studio_sdk/label_interface/interface.py the loop on the xml_tree (lines 420 to 434) never adds it to the controls. A Relation tag is detected as a LabelTag so we enter the second elif. LabelTag.parse_node() needs the controls array as an argument but the Relations control tag is not inside it. Inside label_studio_sdk/label_interface/label_tags.py LabelTag.parse_node() makes a call to _get_parent_control_tag_name() passing tag and controls array but this function returns None (traversing the whole tree to the root) and parse_node finally returns None. lb.parent_name causes the crash since lb is None.

Hope this is as detailed and helpful as possible. This may not be an error but i hope the documentation can be updated if this was the case!

edit 1,2: make paths generic

maggiorante commented 1 month ago

Label studio works just fine but i did not look into how it does so. I quickly saw that there is a call that only validates the configuration template with a json schema though. I suppose this validation is successful but the crash may trigger after the configuration is set.