Skip to content

Commit 0b22416

Browse files
brandon-wadaAuto-format Bot
andauthored
Expose priming group (#411)
Users can now create detectors belonging to a specific detector priming group with a known priming group id. Detectors in these groups will be able to start with a Groundlight defined pretrained model that is well suited for the task the priming group is built around --------- Co-authored-by: Auto-format Bot <autoformatbot@groundlight.ai>
1 parent 02ad98a commit 0b22416

File tree

9 files changed

+75
-2
lines changed

9 files changed

+75
-2
lines changed

generated/docs/DetectorCreationInputRequest.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Name | Type | Description | Notes
1414
**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]
1515
**mode** | **bool, date, datetime, dict, float, int, list, str, none_type** | Mode in which this detector will work. * &#x60;BINARY&#x60; - BINARY * &#x60;COUNT&#x60; - COUNT * &#x60;MULTI_CLASS&#x60; - MULTI_CLASS * &#x60;TEXT&#x60; - TEXT * &#x60;BOUNDING_BOX&#x60; - BOUNDING_BOX | [optional]
1616
**mode_configuration** | **bool, date, datetime, dict, float, int, list, str, none_type** | | [optional]
17+
**priming_group_id** | **str, none_type** | ID of an existing PrimingGroup to associate with this detector (optional). | [optional]
1718
**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]
1819

1920
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

generated/docs/DetectorsApi.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ with groundlight_openapi_client.ApiClient(configuration) as api_client:
6262
metadata="metadata_example",
6363
mode=None,
6464
mode_configuration=None,
65+
priming_group_id="priming_group_id_example",
6566
) # DetectorCreationInputRequest |
6667

6768
# example passing only required values which don't have defaults set

generated/groundlight_openapi_client/model/detector_creation_input_request.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ class DetectorCreationInputRequest(ModelNormal):
9797
"max_length": 1362,
9898
"min_length": 1,
9999
},
100+
("priming_group_id",): {
101+
"max_length": 44,
102+
"min_length": 1,
103+
},
100104
}
101105

102106
@cached_property
@@ -164,6 +168,10 @@ def openapi_types():
164168
str,
165169
none_type,
166170
), # noqa: E501
171+
"priming_group_id": (
172+
str,
173+
none_type,
174+
), # noqa: E501
167175
}
168176

169177
@cached_property
@@ -180,6 +188,7 @@ def discriminator():
180188
"metadata": "metadata", # noqa: E501
181189
"mode": "mode", # noqa: E501
182190
"mode_configuration": "mode_configuration", # noqa: E501
191+
"priming_group_id": "priming_group_id", # noqa: E501
183192
}
184193

185194
read_only_vars = {}
@@ -233,6 +242,7 @@ def _from_openapi_data(cls, name, query, *args, **kwargs): # noqa: E501
233242
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
234243
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
235244
mode_configuration (bool, date, datetime, dict, float, int, list, str, none_type): [optional] # noqa: E501
245+
priming_group_id (str, none_type): ID of an existing PrimingGroup to associate with this detector (optional).. [optional] # noqa: E501
236246
"""
237247

238248
_check_type = kwargs.pop("_check_type", True)
@@ -330,6 +340,7 @@ def __init__(self, name, query, *args, **kwargs): # noqa: E501
330340
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
331341
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
332342
mode_configuration (bool, date, datetime, dict, float, int, list, str, none_type): [optional] # noqa: E501
343+
priming_group_id (str, none_type): ID of an existing PrimingGroup to associate with this detector (optional).. [optional] # noqa: E501
333344
"""
334345

335346
_check_type = kwargs.pop("_check_type", True)

generated/model.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# generated by datamodel-codegen:
22
# filename: public-api.yaml
3-
# timestamp: 2026-01-13T18:34:24+00:00
3+
# timestamp: 2026-03-10T18:06:07+00:00
44

55
from __future__ import annotations
66

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

433436

434437
class ImageQuery(BaseModel):

package-lock.json

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/public-api.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,13 @@ components:
10841084
- $ref: '#/components/schemas/TextModeConfiguration'
10851085
- $ref: '#/components/schemas/BoundingBoxModeConfiguration'
10861086
nullable: true
1087+
priming_group_id:
1088+
type: string
1089+
nullable: true
1090+
minLength: 1
1091+
description: ID of an existing PrimingGroup to associate with this detector
1092+
(optional).
1093+
maxLength: 44
10871094
required:
10881095
- name
10891096
- query

src/groundlight/client.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ def _prep_create_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments
352352
patience_time: Optional[float] = None,
353353
pipeline_config: Optional[str] = None,
354354
metadata: Union[dict, str, None] = None,
355+
priming_group_id: Optional[str] = None,
355356
) -> Detector:
356357
"""
357358
A helper function to prepare the input for creating a detector. Individual create_detector
@@ -372,6 +373,8 @@ def _prep_create_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments
372373
patience_time = float(patience_time)
373374
if patience_time:
374375
detector_creation_input.patience_time = patience_time
376+
if priming_group_id is not None:
377+
detector_creation_input.priming_group_id = priming_group_id
375378
return detector_creation_input
376379

377380
def create_detector( # noqa: PLR0913
@@ -386,6 +389,7 @@ def create_detector( # noqa: PLR0913
386389
pipeline_config: Optional[str] = None,
387390
metadata: Union[dict, str, None] = None,
388391
class_names: Optional[Union[List[str], str]] = None,
392+
priming_group_id: Optional[str] = None,
389393
) -> Detector:
390394
"""
391395
Create a new Detector with a given name and query.
@@ -443,6 +447,7 @@ def create_detector( # noqa: PLR0913
443447
metadata later by calling `get_detector()`.
444448
:param class_names: The name or names of the class to use for the detector. Only used for multi-class
445449
and counting detectors.
450+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
446451
447452
:return: The created Detector object
448453
"""
@@ -458,6 +463,7 @@ def create_detector( # noqa: PLR0913
458463
patience_time=patience_time,
459464
pipeline_config=pipeline_config,
460465
metadata=metadata,
466+
priming_group_id=priming_group_id,
461467
)
462468
if mode == ModeEnum.COUNT:
463469
if class_names is None:
@@ -473,6 +479,7 @@ def create_detector( # noqa: PLR0913
473479
patience_time=patience_time,
474480
pipeline_config=pipeline_config,
475481
metadata=metadata,
482+
priming_group_id=priming_group_id,
476483
)
477484
if mode == ModeEnum.MULTI_CLASS:
478485
if class_names is None:
@@ -488,6 +495,7 @@ def create_detector( # noqa: PLR0913
488495
patience_time=patience_time,
489496
pipeline_config=pipeline_config,
490497
metadata=metadata,
498+
priming_group_id=priming_group_id,
491499
)
492500
raise ValueError(
493501
f"Unsupported mode: {mode}, check if your desired mode is only supported in the ExperimentalApi"
@@ -1557,6 +1565,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
15571565
patience_time: Optional[float] = None,
15581566
pipeline_config: Optional[str] = None,
15591567
metadata: Union[dict, str, None] = None,
1568+
priming_group_id: Optional[str] = None,
15601569
) -> Detector:
15611570
"""
15621571
Creates a counting detector that can count objects in images up to a specified maximum count.
@@ -1595,6 +1604,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
15951604
the detector (limited to 1KB). This metadata can be used to store additional
15961605
information like location, purpose, or related system IDs. You can retrieve this
15971606
metadata later by calling `get_detector()`.
1607+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
15981608
15991609
:return: The created Detector object
16001610
"""
@@ -1607,6 +1617,7 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
16071617
patience_time=patience_time,
16081618
pipeline_config=pipeline_config,
16091619
metadata=metadata,
1620+
priming_group_id=priming_group_id,
16101621
)
16111622
detector_creation_input.mode = ModeEnum.COUNT
16121623

@@ -1629,6 +1640,7 @@ def create_binary_detector( # noqa: PLR0913 # pylint: disable=too-many-argument
16291640
patience_time: Optional[float] = None,
16301641
pipeline_config: Optional[str] = None,
16311642
metadata: Union[dict, str, None] = None,
1643+
priming_group_id: Optional[str] = None,
16321644
) -> Detector:
16331645
"""
16341646
Creates a binary detector with the given name and query.
@@ -1656,6 +1668,7 @@ def create_binary_detector( # noqa: PLR0913 # pylint: disable=too-many-argument
16561668
patience_time=patience_time,
16571669
pipeline_config=pipeline_config,
16581670
metadata=metadata,
1671+
priming_group_id=priming_group_id,
16591672
)
16601673
obj = self.detectors_api.create_detector(detector_creation_input, _request_timeout=DEFAULT_REQUEST_TIMEOUT)
16611674
return Detector.parse_obj(obj.to_dict())
@@ -1671,6 +1684,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
16711684
patience_time: Optional[float] = None,
16721685
pipeline_config: Optional[str] = None,
16731686
metadata: Union[dict, str, None] = None,
1687+
priming_group_id: Optional[str] = None,
16741688
) -> Detector:
16751689
"""
16761690
Creates a multiclass detector with the given name and query.
@@ -1705,6 +1719,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
17051719
the detector (limited to 1KB). This metadata can be used to store additional
17061720
information like location, purpose, or related system IDs. You can retrieve this
17071721
metadata later by calling `get_detector()`.
1722+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
17081723
17091724
:return: The created Detector object
17101725
"""
@@ -1717,6 +1732,7 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
17171732
patience_time=patience_time,
17181733
pipeline_config=pipeline_config,
17191734
metadata=metadata,
1735+
priming_group_id=priming_group_id,
17201736
)
17211737
detector_creation_input.mode = ModeEnum.MULTI_CLASS
17221738
mode_config = MultiClassModeConfiguration(class_names=class_names)

src/groundlight/experimental_api.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
644644
patience_time: Optional[float] = None,
645645
pipeline_config: Optional[str] = None,
646646
metadata: Union[dict, str, None] = None,
647+
priming_group_id: Optional[str] = None,
647648
) -> Detector:
648649
"""
649650
Creates a bounding box detector that can detect objects in images up to a specified maximum number of bounding
@@ -684,6 +685,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
684685
the detector (limited to 1KB). This metadata can be used to store additional
685686
information like location, purpose, or related system IDs. You can retrieve this
686687
metadata later by calling `get_detector()`.
688+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
687689
688690
:return: The created Detector object
689691
"""
@@ -696,6 +698,7 @@ def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-ar
696698
patience_time=patience_time,
697699
pipeline_config=pipeline_config,
698700
metadata=metadata,
701+
priming_group_id=priming_group_id,
699702
)
700703
detector_creation_input.mode = ModeEnum.BOUNDING_BOX
701704

@@ -718,6 +721,7 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
718721
patience_time: Optional[float] = None,
719722
pipeline_config: Optional[str] = None,
720723
metadata: Union[dict, str, None] = None,
724+
priming_group_id: Optional[str] = None,
721725
) -> Detector:
722726
"""
723727
Creates a text recognition detector that can read specified spans of text from images.
@@ -742,6 +746,10 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
742746
:param pipeline_config: Advanced usage only. Configuration string needed to instantiate a specific
743747
prediction pipeline for this detector.
744748
:param metadata: A dictionary or JSON string containing custom key/value pairs to associate with
749+
the detector (limited to 1KB). This metadata can be used to store additional
750+
information like location, purpose, or related system IDs. You can retrieve this
751+
metadata later by calling `get_detector()`.
752+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
745753
746754
:return: The created Detector object
747755
"""
@@ -754,6 +762,7 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
754762
patience_time=patience_time,
755763
pipeline_config=pipeline_config,
756764
metadata=metadata,
765+
priming_group_id=priming_group_id,
757766
)
758767
detector_creation_input.mode = ModeEnum.TEXT
759768
mode_config = TextModeConfiguration()

test/integration/test_groundlight.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,3 +937,24 @@ def test_delete_detector(gl: Groundlight):
937937
fake_detector_id = "det_fake123456789"
938938
with pytest.raises(NotFoundError):
939939
gl.delete_detector(fake_detector_id) # type: ignore
940+
941+
942+
def test_create_detector_with_invalid_priming_group_id(gl: Groundlight):
943+
"""
944+
Test that creating a detector with a non-existent priming_group_id returns an appropriate error.
945+
"""
946+
name = f"Test invalid priming {datetime.utcnow()}"
947+
query = "Is there a dog?"
948+
pipeline_config = "never-review"
949+
priming_group_id = "prgrp_nonexistent12345678901234567890"
950+
951+
with pytest.raises(NotFoundException) as exc_info:
952+
gl.create_detector(
953+
name=name,
954+
query=query,
955+
pipeline_config=pipeline_config,
956+
priming_group_id=priming_group_id,
957+
)
958+
959+
# Verify the error message mentions PrimingGroup
960+
assert "PrimingGroup" in str(exc_info.value)

0 commit comments

Comments
 (0)