Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions generated/docs/DetectorCreationInputRequest.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Name | Type | Description | Notes
**metadata** | **str** | Base64-encoded metadata for the detector. This should be a JSON object with string keys. The size after encoding should not exceed 1362 bytes, corresponding to 1KiB before encoding. | [optional]
**mode** | **bool, date, datetime, dict, float, int, list, str, none_type** | Mode in which this detector will work. * `BINARY` - BINARY * `COUNT` - COUNT * `MULTI_CLASS` - MULTI_CLASS * `TEXT` - TEXT * `BOUNDING_BOX` - BOUNDING_BOX | [optional]
**mode_configuration** | **bool, date, datetime, dict, float, int, list, str, none_type** | | [optional]
**priming_group_id** | **str, none_type** | ID of an existing PrimingGroup to associate with this detector (optional). | [optional]
**any string name** | **bool, date, datetime, dict, float, int, list, str, none_type** | any string name can be used but the value must be the correct type | [optional]

[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
Expand Down
1 change: 1 addition & 0 deletions generated/docs/DetectorsApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ with groundlight_openapi_client.ApiClient(configuration) as api_client:
metadata="metadata_example",
mode=None,
mode_configuration=None,
priming_group_id="priming_group_id_example",
) # DetectorCreationInputRequest |

# example passing only required values which don't have defaults set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ class DetectorCreationInputRequest(ModelNormal):
"max_length": 1362,
"min_length": 1,
},
("priming_group_id",): {
"max_length": 44,
"min_length": 1,
},
}

@cached_property
Expand Down Expand Up @@ -164,6 +168,10 @@ def openapi_types():
str,
none_type,
), # noqa: E501
"priming_group_id": (
str,
none_type,
), # noqa: E501
}

@cached_property
Expand All @@ -180,6 +188,7 @@ def discriminator():
"metadata": "metadata", # noqa: E501
"mode": "mode", # noqa: E501
"mode_configuration": "mode_configuration", # noqa: E501
"priming_group_id": "priming_group_id", # noqa: E501
}

read_only_vars = {}
Expand Down Expand Up @@ -233,6 +242,7 @@ def _from_openapi_data(cls, name, query, *args, **kwargs): # noqa: E501
metadata (str): Base64-encoded metadata for the detector. This should be a JSON object with string keys. The size after encoding should not exceed 1362 bytes, corresponding to 1KiB before encoding.. [optional] # noqa: E501
mode (bool, date, datetime, dict, float, int, list, str, none_type): Mode in which this detector will work. * `BINARY` - BINARY * `COUNT` - COUNT * `MULTI_CLASS` - MULTI_CLASS * `TEXT` - TEXT * `BOUNDING_BOX` - BOUNDING_BOX. [optional] # noqa: E501
mode_configuration (bool, date, datetime, dict, float, int, list, str, none_type): [optional] # noqa: E501
priming_group_id (str, none_type): ID of an existing PrimingGroup to associate with this detector (optional).. [optional] # noqa: E501
"""

_check_type = kwargs.pop("_check_type", True)
Expand Down Expand Up @@ -330,6 +340,7 @@ def __init__(self, name, query, *args, **kwargs): # noqa: E501
metadata (str): Base64-encoded metadata for the detector. This should be a JSON object with string keys. The size after encoding should not exceed 1362 bytes, corresponding to 1KiB before encoding.. [optional] # noqa: E501
mode (bool, date, datetime, dict, float, int, list, str, none_type): Mode in which this detector will work. * `BINARY` - BINARY * `COUNT` - COUNT * `MULTI_CLASS` - MULTI_CLASS * `TEXT` - TEXT * `BOUNDING_BOX` - BOUNDING_BOX. [optional] # noqa: E501
mode_configuration (bool, date, datetime, dict, float, int, list, str, none_type): [optional] # noqa: E501
priming_group_id (str, none_type): ID of an existing PrimingGroup to associate with this detector (optional).. [optional] # noqa: E501
"""

_check_type = kwargs.pop("_check_type", True)
Expand Down
5 changes: 4 additions & 1 deletion generated/model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# generated by datamodel-codegen:
# filename: public-api.yaml
# timestamp: 2026-01-13T18:34:24+00:00
# timestamp: 2026-03-10T18:06:07+00:00

from __future__ import annotations

Expand Down Expand Up @@ -429,6 +429,9 @@ class DetectorCreationInputRequest(BaseModel):
mode_configuration: Optional[
Union[CountModeConfiguration, MultiClassModeConfiguration, TextModeConfiguration, BoundingBoxModeConfiguration]
] = None
priming_group_id: Optional[constr(min_length=1, max_length=44)] = Field(
None, description="ID of an existing PrimingGroup to associate with this detector (optional)."
)


class ImageQuery(BaseModel):
Expand Down
6 changes: 5 additions & 1 deletion package-lock.json
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been a little while since we ran make generate, slight changes to the npm metadata file

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions spec/public-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,13 @@ components:
- $ref: '#/components/schemas/TextModeConfiguration'
- $ref: '#/components/schemas/BoundingBoxModeConfiguration'
nullable: true
priming_group_id:
type: string
nullable: true
minLength: 1
description: ID of an existing PrimingGroup to associate with this detector
(optional).
maxLength: 44
required:
- name
- query
Expand Down
16 changes: 16 additions & 0 deletions src/groundlight/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def _prep_create_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
A helper function to prepare the input for creating a detector. Individual create_detector
Expand All @@ -372,6 +373,8 @@ def _prep_create_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments
patience_time = float(patience_time)
if patience_time:
detector_creation_input.patience_time = patience_time
if priming_group_id is not None:
detector_creation_input.priming_group_id = priming_group_id
return detector_creation_input

def create_detector( # noqa: PLR0913
Expand All @@ -386,6 +389,7 @@ def create_detector( # noqa: PLR0913
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
class_names: Optional[Union[List[str], str]] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Create a new Detector with a given name and query.
Expand Down Expand Up @@ -443,6 +447,7 @@ def create_detector( # noqa: PLR0913
metadata later by calling `get_detector()`.
:param class_names: The name or names of the class to use for the detector. Only used for multi-class
and counting detectors.
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should callout that a 3rd party won't know what valid ones are and not to use it.


:return: The created Detector object
"""
Expand All @@ -458,6 +463,7 @@ def create_detector( # noqa: PLR0913
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
if mode == ModeEnum.COUNT:
if class_names is None:
Expand All @@ -473,6 +479,7 @@ def create_detector( # noqa: PLR0913
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
if mode == ModeEnum.MULTI_CLASS:
if class_names is None:
Expand All @@ -488,6 +495,7 @@ def create_detector( # noqa: PLR0913
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
raise ValueError(
f"Unsupported mode: {mode}, check if your desired mode is only supported in the ExperimentalApi"
Expand Down Expand Up @@ -1557,6 +1565,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Creates a counting detector that can count objects in images up to a specified maximum count.
Expand Down Expand Up @@ -1595,6 +1604,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
the detector (limited to 1KB). This metadata can be used to store additional
information like location, purpose, or related system IDs. You can retrieve this
metadata later by calling `get_detector()`.
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should callout that a 3rd party won't know what valid ones are and not to use it.


:return: The created Detector object
"""
Expand All @@ -1607,6 +1617,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
detector_creation_input.mode = ModeEnum.COUNT

Expand All @@ -1629,6 +1640,7 @@ def create_binary_detector( # noqa: PLR0913 # pylint: disable=too-many-argument
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Creates a binary detector with the given name and query.
Expand Down Expand Up @@ -1656,6 +1668,7 @@ def create_binary_detector( # noqa: PLR0913 # pylint: disable=too-many-argument
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
obj = self.detectors_api.create_detector(detector_creation_input, _request_timeout=DEFAULT_REQUEST_TIMEOUT)
return Detector.parse_obj(obj.to_dict())
Expand All @@ -1671,6 +1684,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Creates a multiclass detector with the given name and query.
Expand Down Expand Up @@ -1705,6 +1719,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
the detector (limited to 1KB). This metadata can be used to store additional
information like location, purpose, or related system IDs. You can retrieve this
metadata later by calling `get_detector()`.
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should callout that a 3rd party won't know what valid ones are and not to use it.


:return: The created Detector object
"""
Expand All @@ -1717,6 +1732,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
detector_creation_input.mode = ModeEnum.MULTI_CLASS
mode_config = MultiClassModeConfiguration(class_names=class_names)
Expand Down
9 changes: 9 additions & 0 deletions src/groundlight/experimental_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Creates a bounding box detector that can detect objects in images up to a specified maximum number of bounding
Expand Down Expand Up @@ -684,6 +685,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
the detector (limited to 1KB). This metadata can be used to store additional
information like location, purpose, or related system IDs. You can retrieve this
metadata later by calling `get_detector()`.
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should callout that a 3rd party won't know what valid ones are and not to use it.


:return: The created Detector object
"""
Expand All @@ -696,6 +698,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
detector_creation_input.mode = ModeEnum.BOUNDING_BOX

Expand All @@ -718,6 +721,7 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
patience_time: Optional[float] = None,
pipeline_config: Optional[str] = None,
metadata: Union[dict, str, None] = None,
priming_group_id: Optional[str] = None,
) -> Detector:
"""
Creates a text recognition detector that can read specified spans of text from images.
Expand All @@ -742,6 +746,10 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
:param pipeline_config: Advanced usage only. Configuration string needed to instantiate a specific
prediction pipeline for this detector.
:param metadata: A dictionary or JSON string containing custom key/value pairs to associate with
the detector (limited to 1KB). This metadata can be used to store additional
information like location, purpose, or related system IDs. You can retrieve this
metadata later by calling `get_detector()`.
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.

:return: The created Detector object
"""
Expand All @@ -754,6 +762,7 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
patience_time=patience_time,
pipeline_config=pipeline_config,
metadata=metadata,
priming_group_id=priming_group_id,
)
detector_creation_input.mode = ModeEnum.TEXT
mode_config = TextModeConfiguration()
Expand Down
21 changes: 21 additions & 0 deletions test/integration/test_groundlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -937,3 +937,24 @@ def test_delete_detector(gl: Groundlight):
fake_detector_id = "det_fake123456789"
with pytest.raises(NotFoundError):
gl.delete_detector(fake_detector_id) # type: ignore


def test_create_detector_with_invalid_priming_group_id(gl: Groundlight):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no happy path test is strange.

"""
Test that creating a detector with a non-existent priming_group_id returns an appropriate error.
"""
name = f"Test invalid priming {datetime.utcnow()}"
query = "Is there a dog?"
pipeline_config = "never-review"
priming_group_id = "prgrp_nonexistent12345678901234567890"

with pytest.raises(NotFoundException) as exc_info:
gl.create_detector(
name=name,
query=query,
pipeline_config=pipeline_config,
priming_group_id=priming_group_id,
)

# Verify the error message mentions PrimingGroup
assert "PrimingGroup" in str(exc_info.value)
Loading