Skip to content

Commit 658d44f

Browse files
authored
First class bbox mode (#412)
Moves bbox mode out of the experimental section of the SDK and makes it generally available under the Groundlight class
1 parent 0b22416 commit 658d44f

File tree

3 files changed

+95
-83
lines changed

3 files changed

+95
-83
lines changed

src/groundlight/client.py

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from groundlight_openapi_client.api.user_api import UserApi
1717
from groundlight_openapi_client.exceptions import NotFoundException, UnauthorizedException
1818
from groundlight_openapi_client.model.b_box_geometry_request import BBoxGeometryRequest
19+
from groundlight_openapi_client.model.bounding_box_mode_configuration import BoundingBoxModeConfiguration
1920
from groundlight_openapi_client.model.count_mode_configuration import CountModeConfiguration
2021
from groundlight_openapi_client.model.detector_creation_input_request import DetectorCreationInputRequest
2122
from groundlight_openapi_client.model.detector_group_request import DetectorGroupRequest
@@ -396,9 +397,8 @@ def create_detector( # noqa: PLR0913
396397
397398
By default will create a binary detector but alternate modes can be created by passing in a mode argument.
398399
399-
Text and Bounding box detectors are in Beta, and can be created through the
400-
ExperimentalApi via the :meth:`ExperimentalApi.create_text_recognition_detector` and
401-
:meth:`ExperimentalApi.create_bounding_box_detector` methods.
400+
Text recognition detectors are in Beta, and can be created through the
401+
ExperimentalApi via the :meth:`ExperimentalApi.create_text_recognition_detector` method.
402402
403403
**Example usage**::
404404
@@ -448,6 +448,8 @@ def create_detector( # noqa: PLR0913
448448
:param class_names: The name or names of the class to use for the detector. Only used for multi-class
449449
and counting detectors.
450450
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
451+
PrimingGroup IDs are provided by Groundlight representatives. If you would like
452+
to use a priming_group_id, please reach out to your Groundlight representative.
451453
452454
:return: The created Detector object
453455
"""
@@ -1605,6 +1607,8 @@ def create_counting_detector( # noqa: PLR0913 # pylint: disable=too-many-argume
16051607
information like location, purpose, or related system IDs. You can retrieve this
16061608
metadata later by calling `get_detector()`.
16071609
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
1610+
PrimingGroup IDs are provided by Groundlight representatives. If you would like
1611+
to use a priming_group_id, please reach out to your Groundlight representative.
16081612
16091613
:return: The created Detector object
16101614
"""
@@ -1720,6 +1724,8 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
17201724
information like location, purpose, or related system IDs. You can retrieve this
17211725
metadata later by calling `get_detector()`.
17221726
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
1727+
PrimingGroup IDs are provided by Groundlight representatives. If you would like
1728+
to use a priming_group_id, please reach out to your Groundlight representative.
17231729
17241730
:return: The created Detector object
17251731
"""
@@ -1739,3 +1745,84 @@ def create_multiclass_detector( # noqa: PLR0913 # pylint: disable=too-many-argu
17391745
detector_creation_input.mode_configuration = mode_config
17401746
obj = self.detectors_api.create_detector(detector_creation_input, _request_timeout=DEFAULT_REQUEST_TIMEOUT)
17411747
return Detector.parse_obj(obj.to_dict())
1748+
1749+
def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments, too-many-locals
1750+
self,
1751+
name: str,
1752+
query: str,
1753+
class_name: str,
1754+
*,
1755+
max_num_bboxes: Optional[int] = None,
1756+
group_name: Optional[str] = None,
1757+
confidence_threshold: Optional[float] = None,
1758+
patience_time: Optional[float] = None,
1759+
pipeline_config: Optional[str] = None,
1760+
metadata: Union[dict, str, None] = None,
1761+
priming_group_id: Optional[str] = None,
1762+
) -> Detector:
1763+
"""
1764+
Creates a bounding box detector that can detect objects in images up to a specified maximum number of bounding
1765+
boxes.
1766+
1767+
**Example usage**::
1768+
1769+
gl = Groundlight()
1770+
1771+
# Create a detector that counts people up to 5
1772+
detector = gl.create_bounding_box_detector(
1773+
name="people_counter",
1774+
query="Draw a bounding box around each person in the image",
1775+
class_name="person",
1776+
max_num_bboxes=5,
1777+
confidence_threshold=0.9,
1778+
patience_time=30.0
1779+
)
1780+
1781+
# Use the detector to find people in an image
1782+
image_query = gl.ask_ml(detector, "path/to/image.jpg")
1783+
print(f"Confidence: {image_query.result.confidence}")
1784+
print(f"Label: {image_query.result.label}")
1785+
print(f"Bounding boxes: {image_query.rois}")
1786+
1787+
:param name: A short, descriptive name for the detector.
1788+
:param query: A question about the object to detect in the image.
1789+
:param class_name: The class name of the object to detect.
1790+
:param max_num_bboxes: Maximum number of bounding boxes to detect (default: 10)
1791+
:param group_name: Optional name of a group to organize related detectors together.
1792+
:param confidence_threshold: A value that sets the minimum confidence level required for the ML model's
1793+
predictions. If confidence is below this threshold, the query may be sent for human review.
1794+
:param patience_time: The maximum time in seconds that Groundlight will attempt to generate a
1795+
confident prediction before falling back to human review. Defaults to 30 seconds.
1796+
:param pipeline_config: Advanced usage only. Configuration string needed to instantiate a specific
1797+
prediction pipeline for this detector.
1798+
:param metadata: A dictionary or JSON string containing custom key/value pairs to associate with
1799+
the detector (limited to 1KB). This metadata can be used to store additional
1800+
information like location, purpose, or related system IDs. You can retrieve this
1801+
metadata later by calling `get_detector()`.
1802+
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
1803+
PrimingGroup IDs are provided by Groundlight representatives. If you would like
1804+
to use a priming_group_id, please reach out to your Groundlight representative.
1805+
1806+
:return: The created Detector object
1807+
"""
1808+
1809+
detector_creation_input = self._prep_create_detector(
1810+
name=name,
1811+
query=query,
1812+
group_name=group_name,
1813+
confidence_threshold=confidence_threshold,
1814+
patience_time=patience_time,
1815+
pipeline_config=pipeline_config,
1816+
metadata=metadata,
1817+
priming_group_id=priming_group_id,
1818+
)
1819+
detector_creation_input.mode = ModeEnum.BOUNDING_BOX
1820+
1821+
if max_num_bboxes is None:
1822+
mode_config = BoundingBoxModeConfiguration(class_name=class_name)
1823+
else:
1824+
mode_config = BoundingBoxModeConfiguration(max_num_bboxes=max_num_bboxes, class_name=class_name)
1825+
1826+
detector_creation_input.mode_configuration = mode_config
1827+
obj = self.detectors_api.create_detector(detector_creation_input, _request_timeout=DEFAULT_REQUEST_TIMEOUT)
1828+
return Detector.parse_obj(obj.to_dict())

src/groundlight/experimental_api.py

Lines changed: 2 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from groundlight_openapi_client.api.edge_api import EdgeApi
2020
from groundlight_openapi_client.api.notes_api import NotesApi
2121
from groundlight_openapi_client.model.action_request import ActionRequest
22-
from groundlight_openapi_client.model.bounding_box_mode_configuration import BoundingBoxModeConfiguration
2322
from groundlight_openapi_client.model.channel_enum import ChannelEnum
2423
from groundlight_openapi_client.model.condition_request import ConditionRequest
2524
from groundlight_openapi_client.model.patched_detector_request import PatchedDetectorRequest
@@ -632,85 +631,6 @@ def update_detector_name(self, detector: Union[str, Detector], name: str) -> Non
632631
detector = detector.id
633632
self.detectors_api.update_detector(detector, patched_detector_request=PatchedDetectorRequest(name=name))
634633

635-
def create_bounding_box_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments, too-many-locals
636-
self,
637-
name: str,
638-
query: str,
639-
class_name: str,
640-
*,
641-
max_num_bboxes: Optional[int] = None,
642-
group_name: Optional[str] = None,
643-
confidence_threshold: Optional[float] = None,
644-
patience_time: Optional[float] = None,
645-
pipeline_config: Optional[str] = None,
646-
metadata: Union[dict, str, None] = None,
647-
priming_group_id: Optional[str] = None,
648-
) -> Detector:
649-
"""
650-
Creates a bounding box detector that can detect objects in images up to a specified maximum number of bounding
651-
boxes.
652-
653-
**Example usage**::
654-
655-
gl = ExperimentalApi()
656-
657-
# Create a detector that counts people up to 5
658-
detector = gl.create_bounding_box_detector(
659-
name="people_counter",
660-
query="Draw a bounding box around each person in the image",
661-
class_name="person",
662-
max_num_bboxes=5,
663-
confidence_threshold=0.9,
664-
patience_time=30.0
665-
)
666-
667-
# Use the detector to find people in an image
668-
image_query = gl.ask_ml(detector, "path/to/image.jpg")
669-
print(f"Confidence: {image_query.result.confidence}")
670-
print(f"Label: {image_query.result.label}")
671-
print(f"Bounding boxes: {image_query.rois}")
672-
673-
:param name: A short, descriptive name for the detector.
674-
:param query: A question about the object to detect in the image.
675-
:param class_name: The class name of the object to detect.
676-
:param max_num_bboxes: Maximum number of bounding boxes to detect (default: 10)
677-
:param group_name: Optional name of a group to organize related detectors together.
678-
:param confidence_threshold: A value that sets the minimum confidence level required for the ML model's
679-
predictions. If confidence is below this threshold, the query may be sent for human review.
680-
:param patience_time: The maximum time in seconds that Groundlight will attempt to generate a
681-
confident prediction before falling back to human review. Defaults to 30 seconds.
682-
:param pipeline_config: Advanced usage only. Configuration string needed to instantiate a specific
683-
prediction pipeline for this detector.
684-
:param metadata: A dictionary or JSON string containing custom key/value pairs to associate with
685-
the detector (limited to 1KB). This metadata can be used to store additional
686-
information like location, purpose, or related system IDs. You can retrieve this
687-
metadata later by calling `get_detector()`.
688-
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
689-
690-
:return: The created Detector object
691-
"""
692-
693-
detector_creation_input = self._prep_create_detector(
694-
name=name,
695-
query=query,
696-
group_name=group_name,
697-
confidence_threshold=confidence_threshold,
698-
patience_time=patience_time,
699-
pipeline_config=pipeline_config,
700-
metadata=metadata,
701-
priming_group_id=priming_group_id,
702-
)
703-
detector_creation_input.mode = ModeEnum.BOUNDING_BOX
704-
705-
if max_num_bboxes is None:
706-
mode_config = BoundingBoxModeConfiguration(class_name=class_name)
707-
else:
708-
mode_config = BoundingBoxModeConfiguration(max_num_bboxes=max_num_bboxes, class_name=class_name)
709-
710-
detector_creation_input.mode_configuration = mode_config
711-
obj = self.detectors_api.create_detector(detector_creation_input, _request_timeout=DEFAULT_REQUEST_TIMEOUT)
712-
return Detector.parse_obj(obj.to_dict())
713-
714634
def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-many-arguments, too-many-locals
715635
self,
716636
name: str,
@@ -750,6 +670,8 @@ def create_text_recognition_detector( # noqa: PLR0913 # pylint: disable=too-man
750670
information like location, purpose, or related system IDs. You can retrieve this
751671
metadata later by calling `get_detector()`.
752672
:param priming_group_id: Optional ID of an existing PrimingGroup to associate with this detector.
673+
PrimingGroup IDs are provided by Groundlight representatives. If you would like
674+
to use a priming_group_id, please reach out to your Groundlight representative.
753675
754676
:return: The created Detector object
755677
"""

test/integration/test_groundlight.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,9 @@ def test_delete_detector(gl: Groundlight):
942942
def test_create_detector_with_invalid_priming_group_id(gl: Groundlight):
943943
"""
944944
Test that creating a detector with a non-existent priming_group_id returns an appropriate error.
945+
946+
Note: PrimingGroup IDs are provided by Groundlight representatives. If you would like to
947+
use a priming_group_id, please reach out to your Groundlight representative.
945948
"""
946949
name = f"Test invalid priming {datetime.utcnow()}"
947950
query = "Is there a dog?"

0 commit comments

Comments
 (0)