Skip to content

Commit

Permalink
Deprecate /device-api/posichecks endpoint (#164)
Browse files Browse the repository at this point in the history
* deprecating old posichecks endpoint

* adjusting public-api.yaml

* Automatically reformatting code

* appeasing the linter

* Automatically reformatting code

* fixing linting issue

* Automatically reformatting code

* reverting some changes to package.json and package-lock.json

* adding retry decorator back to start_inspection

---------

Co-authored-by: Tim Huff <[email protected]>
Co-authored-by: Auto-format Bot <[email protected]>
  • Loading branch information
3 people authored Feb 19, 2024
1 parent 237f12c commit dfd0a17
Show file tree
Hide file tree
Showing 7 changed files with 28 additions and 79 deletions.
4 changes: 3 additions & 1 deletion generated/docs/ImageQueriesApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = image_queries_api.ImageQueriesApi(api_client)
detector_id = "detector_id_example" # str | Choose a detector by its ID.
inspection_id = "inspection_id_example" # str | Associate the image query with an inspection. (optional)
human_review = "human_review_example" # str | If set to `DEFAULT`, use the regular escalation logic (i.e., send the image query for human review if the ML model is not confident). If set to `ALWAYS`, always send the image query for human review even if the ML model is confident. If set to `NEVER`, never send the image query for human review even if the ML model is not confident. (optional)
patience_time = 3.14 # float | How long to wait for a confident response. (optional)
want_async = "want_async_example" # str | If \"true\" then submitting an image query returns immediately without a result. The result will be computed asynchronously and can be retrieved later. (optional)
Expand All @@ -221,7 +222,7 @@ with openapi_client.ApiClient(configuration) as api_client:
# example passing only required values which don't have defaults set
# and optional values
try:
api_response = api_instance.submit_image_query(detector_id, human_review=human_review, patience_time=patience_time, want_async=want_async, metadata=metadata, body=body)
api_response = api_instance.submit_image_query(detector_id, inspection_id=inspection_id, human_review=human_review, patience_time=patience_time, want_async=want_async, metadata=metadata, body=body)
pprint(api_response)
except openapi_client.ApiException as e:
print("Exception when calling ImageQueriesApi->submit_image_query: %s\n" % e)
Expand All @@ -233,6 +234,7 @@ with openapi_client.ApiClient(configuration) as api_client:
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**detector_id** | **str**| Choose a detector by its ID. |
**inspection_id** | **str**| Associate the image query with an inspection. | [optional]
**human_review** | **str**| If set to &#x60;DEFAULT&#x60;, use the regular escalation logic (i.e., send the image query for human review if the ML model is not confident). If set to &#x60;ALWAYS&#x60;, always send the image query for human review even if the ML model is confident. If set to &#x60;NEVER&#x60;, never send the image query for human review even if the ML model is not confident. | [optional]
**patience_time** | **float**| How long to wait for a confident response. | [optional]
**want_async** | **str**| If \&quot;true\&quot; then submitting an image query returns immediately without a result. The result will be computed asynchronously and can be retrieved later. | [optional]
Expand Down
2 changes: 1 addition & 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: 2024-02-19T17:48:07+00:00
# timestamp: 2024-02-19T18:25:15+00:00

from __future__ import annotations

Expand Down
5 changes: 5 additions & 0 deletions generated/openapi_client/api/image_queries_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ def __init__(self, api_client=None):
params_map={
"all": [
"detector_id",
"inspection_id",
"human_review",
"patience_time",
"want_async",
Expand All @@ -149,6 +150,7 @@ def __init__(self, api_client=None):
"allowed_values": {},
"openapi_types": {
"detector_id": (str,),
"inspection_id": (str,),
"human_review": (str,),
"patience_time": (float,),
"want_async": (str,),
Expand All @@ -157,13 +159,15 @@ def __init__(self, api_client=None):
},
"attribute_map": {
"detector_id": "detector_id",
"inspection_id": "inspection_id",
"human_review": "human_review",
"patience_time": "patience_time",
"want_async": "want_async",
"metadata": "metadata",
},
"location_map": {
"detector_id": "query",
"inspection_id": "query",
"human_review": "query",
"patience_time": "query",
"want_async": "query",
Expand Down Expand Up @@ -305,6 +309,7 @@ def submit_image_query(self, detector_id, **kwargs):
detector_id (str): Choose a detector by its ID.
Keyword Args:
inspection_id (str): Associate the image query with an inspection.. [optional]
human_review (str): If set to `DEFAULT`, use the regular escalation logic (i.e., send the image query for human review if the ML model is not confident). If set to `ALWAYS`, always send the image query for human review even if the ML model is confident. If set to `NEVER`, never send the image query for human review even if the ML model is not confident. . [optional]
patience_time (float): How long to wait for a confident response.. [optional]
want_async (str): If \"true\" then submitting an image query returns immediately without a result. The result will be computed asynchronously and can be retrieved later.. [optional]
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

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

5 changes: 5 additions & 0 deletions spec/public-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ paths:
type: string
description: Choose a detector by its ID.
required: true
- in: query
name: inspection_id
schema:
type: string
description: Associate the image query with an inspection.
- in: query
name: human_review
schema:
Expand Down
25 changes: 12 additions & 13 deletions src/groundlight/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,9 @@ def submit_image_query( # noqa: PLR0913 # pylint: disable=too-many-arguments, t
if human_review is not None:
params["human_review"] = human_review

if inspection_id is not None:
params["inspection_id"] = inspection_id

if want_async is True:
# If want_async is True, we don't want to wait for a result. As a result wait must be set to 0 to use
# want_async.
Expand All @@ -436,18 +439,8 @@ def submit_image_query( # noqa: PLR0913 # pylint: disable=too-many-arguments, t
# url- and base64-encode the metadata.
params["metadata"] = url_encode_dict(metadata, name="metadata", size_limit_bytes=1024)

params["_request_timeout"] = DEFAULT_REQUEST_TIMEOUT

# If no inspection_id is provided, we submit the image query using image_queries_api (autogenerated via OpenAPI)
# However, our autogenerated code does not currently support inspection_id, so if an inspection_id was
# provided, we use the private API client instead.
if inspection_id is None:
raw_image_query = self.image_queries_api.submit_image_query(**params)
image_query = ImageQuery.parse_obj(raw_image_query.to_dict())
else:
params["inspection_id"] = inspection_id
iq_id = self.api_client.submit_image_query_with_inspection(**params)
image_query = self.get_image_query(iq_id)
raw_image_query = self.image_queries_api.submit_image_query(**params)
image_query = ImageQuery.parse_obj(raw_image_query.to_dict())

if wait > 0:
if confidence_threshold is None:
Expand All @@ -465,6 +458,7 @@ def ask_confident( # noqa: PLR0913 # pylint: disable=too-many-arguments
confidence_threshold: Optional[float] = None,
wait: Optional[float] = None,
metadata: Union[dict, str, None] = None,
inspection_id: Optional[str] = None,
) -> ImageQuery:
"""
Evaluates an image with Groundlight waiting until an answer above the confidence threshold
Expand Down Expand Up @@ -500,14 +494,16 @@ def ask_confident( # noqa: PLR0913 # pylint: disable=too-many-arguments
patience_time=wait,
human_review=None,
metadata=metadata,
inspection_id=inspection_id,
)

def ask_ml(
def ask_ml( # noqa: PLR0913 # pylint: disable=too-many-arguments, too-many-locals
self,
detector: Union[Detector, str],
image: Union[str, bytes, Image.Image, BytesIO, BufferedReader, np.ndarray],
wait: Optional[float] = None,
metadata: Union[dict, str, None] = None,
inspection_id: Optional[str] = None,
) -> ImageQuery:
"""
Evaluates an image with Groundlight, getting the first answer Groundlight can provide.
Expand Down Expand Up @@ -536,6 +532,7 @@ def ask_ml(
image,
wait=0,
metadata=metadata,
inspection_id=inspection_id,
)
if iq_is_answered(iq):
return iq
Expand All @@ -550,6 +547,7 @@ def ask_async( # noqa: PLR0913 # pylint: disable=too-many-arguments
confidence_threshold: Optional[float] = None,
human_review: Optional[str] = None,
metadata: Union[dict, str, None] = None,
inspection_id: Optional[str] = None,
) -> ImageQuery:
"""
Convenience method for submitting an `ImageQuery` asynchronously. This is equivalent to calling
Expand Down Expand Up @@ -632,6 +630,7 @@ def ask_async( # noqa: PLR0913 # pylint: disable=too-many-arguments
human_review=human_review,
want_async=True,
metadata=metadata,
inspection_id=inspection_id,
)

def wait_for_confident_result(
Expand Down
64 changes: 1 addition & 63 deletions src/groundlight/internalapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
import uuid
from enum import Enum
from functools import wraps
from typing import Any, Callable, Dict, Optional, Union
from typing import Callable, Optional
from urllib.parse import urlsplit, urlunsplit

import requests
from model import Detector, ImageQuery
from openapi_client.api_client import ApiClient, ApiException

from groundlight.images import ByteStreamWrapper
from groundlight.status_codes import is_ok
from groundlight.version import get_version

Expand Down Expand Up @@ -248,67 +247,6 @@ def _get_detector_by_name(self, name: str) -> Detector:
)
return Detector.parse_obj(parsed["results"][0])

@RequestsRetryDecorator()
def submit_image_query_with_inspection( # noqa: PLR0913 # pylint: disable=too-many-arguments
self,
detector_id: str,
body: ByteStreamWrapper,
inspection_id: str,
patience_time: Optional[float] = None,
human_review: str = "DEFAULT",
metadata: Optional[dict] = None,
want_async: Optional[bool] = False,
_request_timeout: Optional[float] = None,
) -> str:
"""Submits an image query to the API and returns the ID of the image query.
The image query will be associated to the inspection_id provided.
"""

url = f"{self.configuration.host}/posichecks"

params: Dict[str, Union[str, float, bool, Dict[Any, Any], None]] = {
"inspection_id": inspection_id,
"predictor_id": detector_id,
"want_async": want_async,
}

if metadata is not None:
params["metadata"] = metadata
if patience_time is not None:
params["patience_time"] = float(patience_time)

# In the API, 'send_notification' is used to control human_review escalation. This will eventually
# be deprecated, but for now we need to support it in the following manner:
if human_review == "ALWAYS":
params["send_notification"] = True
elif human_review == "NEVER":
params["send_notification"] = False
else:
pass # don't send the send_notifications param, allow "DEFAULT" behavior

headers = self._headers()
headers["Content-Type"] = "image/jpeg"

response = requests.request(
"POST",
url,
headers=headers,
params=params,
data=body.read(),
verify=self.configuration.verify_ssl,
timeout=_request_timeout,
)

if not is_ok(response.status_code):
logger.info(response)
raise InternalApiError(
status=response.status_code,
reason=f"Error submitting image query with inspection ID {inspection_id} on detector {detector_id}",
http_resp=response,
)

return response.json()["id"]

@RequestsRetryDecorator()
def start_inspection(self) -> str:
"""Starts an inspection, returns the ID."""
Expand Down

0 comments on commit dfd0a17

Please sign in to comment.