Skip to content

Commit

Permalink
fix: remove noop model logic
Browse files Browse the repository at this point in the history
  • Loading branch information
drduhe committed Oct 1, 2024
1 parent 1d2cbe2 commit 66749f0
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 446 deletions.
2 changes: 0 additions & 2 deletions src/aws/osml/model_runner/app_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ class ServiceConfig:
kinesis_max_record_size_batch: str = "5242880" # 5 MB in bytes
kinesis_max_record_size: str = "1048576" # 1 MB in bytes
ddb_max_item_size: str = "200000"
noop_bounds_model_name: str = "NOOP_BOUNDS_MODEL_NAME"
noop_geom_model_name: str = "NOOP_GEOM_MODEL_NAME"


@dataclass
Expand Down
28 changes: 11 additions & 17 deletions src/aws/osml/model_runner/inference/http_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
from urllib3.util.retry import Retry

from aws.osml.model_runner.api import ModelInvokeMode
from aws.osml.model_runner.app_config import MetricLabels, ServiceConfig
from aws.osml.model_runner.app_config import MetricLabels
from aws.osml.model_runner.common import Timer

from .detector import Detector
from .endpoint_builder import FeatureEndpointBuilder
from .feature_utils import create_mock_feature_collection

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -153,21 +152,16 @@ def find_features(self, payload: BufferedReader, metrics: MetricsLogger) -> Feat
logger=logger,
metrics_logger=metrics,
):
if self.endpoint == ServiceConfig.noop_geom_model_name:
return create_mock_feature_collection(payload, geom=True)
elif self.endpoint == ServiceConfig.noop_bounds_model_name:
return create_mock_feature_collection(payload)
else:
response = self.http_pool.request(
method="POST",
url=self.endpoint,
body=payload,
)
retry_count = self.retry.retry_counts
if isinstance(metrics, MetricsLogger):
metrics.put_metric(MetricLabels.RETRIES, retry_count, str(Unit.COUNT.value))

return geojson.loads(response.data.decode("utf-8"))
response = self.http_pool.request(
method="POST",
url=self.endpoint,
body=payload,
)
retry_count = self.retry.retry_counts
if isinstance(metrics, MetricsLogger):
metrics.put_metric(MetricLabels.RETRIES, retry_count, str(Unit.COUNT.value))

return geojson.loads(response.data.decode("utf-8"))

except RetryError as err:
if isinstance(metrics, MetricsLogger):
Expand Down
25 changes: 9 additions & 16 deletions src/aws/osml/model_runner/inference/sm_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,11 @@
from geojson import FeatureCollection

from aws.osml.model_runner.api import ModelInvokeMode
from aws.osml.model_runner.app_config import BotoConfig, MetricLabels, ServiceConfig
from aws.osml.model_runner.app_config import BotoConfig, MetricLabels
from aws.osml.model_runner.common import Timer

from .detector import Detector
from .endpoint_builder import FeatureEndpointBuilder
from .feature_utils import create_mock_feature_collection

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -100,20 +99,14 @@ def find_features(self, payload: BufferedReader, metrics: MetricsLogger) -> Feat
logger=logger,
metrics_logger=metrics,
):
# Handle mock models for testing purposes
if self.endpoint == ServiceConfig.noop_bounds_model_name:
return create_mock_feature_collection(payload)
elif self.endpoint == ServiceConfig.noop_geom_model_name:
return create_mock_feature_collection(payload, geom=True)
else:
# Invoke the real SageMaker model endpoint
model_response = self.sm_client.invoke_endpoint(EndpointName=self.endpoint, Body=payload)
retry_count = model_response.get("ResponseMetadata", {}).get("RetryAttempts", 0)
if isinstance(metrics, MetricsLogger):
metrics.put_metric(MetricLabels.RETRIES, retry_count, str(Unit.COUNT.value))

# Parse the model's response as a geojson FeatureCollection
return geojson.loads(model_response.get("Body").read())
# Invoke the real SageMaker model endpoint
model_response = self.sm_client.invoke_endpoint(EndpointName=self.endpoint, Body=payload)
retry_count = model_response.get("ResponseMetadata", {}).get("RetryAttempts", 0)
if isinstance(metrics, MetricsLogger):
metrics.put_metric(MetricLabels.RETRIES, retry_count, str(Unit.COUNT.value))

# Parse the model's response as a geojson FeatureCollection
return geojson.loads(model_response.get("Body").read())

except ClientError as ce:
error_code = ce.response.get("Error", {}).get("Code")
Expand Down
2 changes: 1 addition & 1 deletion src/aws/osml/model_runner/tile_worker/tile_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def process_tile(self, image_info: Dict, metrics: MetricsLogger = None) -> None:
)
except Exception as e:
self.failed_tile_count += 1
logging.error(f"Failed to process region tile with error: {e.with_traceback()}")
logging.error(f"Failed to process region tile with error: {e}", exc_info=True)
self.region_request_table.add_tile(
image_info.get("image_id"), image_info.get("region_id"), image_info.get("region"), TileState.FAILED
)
Expand Down
31 changes: 19 additions & 12 deletions test/aws/osml/model_runner/inference/test_feature_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
import numpy as np
import pytest
import shapely
from osgeo import gdal

# GDAL 4.0 will begin using exceptions as the default; at this point the software is written to assume
# no exceptions so we call this explicitly until the software can be updated to match.
gdal.DontUseExceptions()


class TestFeatureUtils(unittest.TestCase):
Expand Down Expand Up @@ -100,12 +105,13 @@ def test_calculate_processing_bounds_full_image(self):
chip_lr = sensor_model.image_to_world(ImageCoordinate([101, 101]))
min_vals = np.minimum(chip_ul.coordinate, chip_lr.coordinate)
max_vals = np.maximum(chip_ul.coordinate, chip_lr.coordinate)
polygon_coords = []
polygon_coords.append([degrees(min_vals[0]), degrees(min_vals[1])])
polygon_coords.append([degrees(min_vals[0]), degrees(max_vals[1])])
polygon_coords.append([degrees(max_vals[0]), degrees(max_vals[1])])
polygon_coords.append([degrees(max_vals[0]), degrees(min_vals[1])])
polygon_coords.append([degrees(min_vals[0]), degrees(min_vals[1])])
polygon_coords = [
[degrees(min_vals[0]), degrees(min_vals[1])],
[degrees(min_vals[0]), degrees(max_vals[1])],
[degrees(max_vals[0]), degrees(max_vals[1])],
[degrees(max_vals[0]), degrees(min_vals[1])],
[degrees(min_vals[0]), degrees(min_vals[1])],
]
roi = shapely.geometry.Polygon(polygon_coords)

processing_bounds = calculate_processing_bounds(ds, roi, sensor_model)
Expand All @@ -122,12 +128,13 @@ def test_calculate_processing_bounds_intersect(self):
chip_lr = sensor_model.image_to_world(ImageCoordinate([50, 50]))
min_vals = np.minimum(chip_ul.coordinate, chip_lr.coordinate)
max_vals = np.maximum(chip_ul.coordinate, chip_lr.coordinate)
polygon_coords = []
polygon_coords.append([degrees(min_vals[0]), degrees(min_vals[1])])
polygon_coords.append([degrees(min_vals[0]), degrees(max_vals[1])])
polygon_coords.append([degrees(max_vals[0]), degrees(max_vals[1])])
polygon_coords.append([degrees(max_vals[0]), degrees(min_vals[1])])
polygon_coords.append([degrees(min_vals[0]), degrees(min_vals[1])])
polygon_coords = [
[degrees(min_vals[0]), degrees(min_vals[1])],
[degrees(min_vals[0]), degrees(max_vals[1])],
[degrees(max_vals[0]), degrees(max_vals[1])],
[degrees(max_vals[0]), degrees(min_vals[1])],
[degrees(min_vals[0]), degrees(min_vals[1])],
]
roi = shapely.geometry.Polygon(polygon_coords)

processing_bounds = calculate_processing_bounds(ds, roi, sensor_model)
Expand Down
15 changes: 8 additions & 7 deletions test/aws/osml/model_runner/inference/test_sm_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from botocore.exceptions import ClientError
from botocore.stub import ANY, Stubber

MOCK_RESPONSE = {
MOCK_MODEL_RESPONSE = {
"Body": io.StringIO(
json.dumps(
{
Expand All @@ -21,12 +21,13 @@
{
"type": "Feature",
"id": "1cc5e6d6-e12f-430d-adf0-8d2276ce8c5a",
"geometry": {"type": "Point", "coordinates": [0.0, 0.0]},
"geometry": {"type": "Point", "coordinates": [-43.679691, -22.941953]},
"properties": {
"bounds_imcoords": [429, 553, 440, 561],
"feature_types": {"ground_motor_passenger_vehicle": 0.2961518168449402},
"geom_imcoords": [[429, 553], [429, 561], [440, 561], [440, 553], [429, 553]],
"featureClasses": [{"iri": "ground_motor_passenger_vehicle", "score": 0.2961518168449402}],
"detection_score": 0.2961518168449402,
"image_id": "test-image-id",
"image_id": "2pp5e6d6-e12f-430d-adf0-8d2276ceadf0",
},
}
],
Expand Down Expand Up @@ -68,7 +69,7 @@ def test_find_features(self):
sm_runtime_stub.add_response(
"invoke_endpoint",
expected_params={"EndpointName": "test-endpoint", "Body": ANY},
service_response=MOCK_RESPONSE,
service_response=MOCK_MODEL_RESPONSE,
)
sm_runtime_stub.activate()

Expand All @@ -87,7 +88,7 @@ def test_find_features_throw_json_exception(self):
sm_runtime_stub.add_response(
"invoke_endpoint",
expected_params={"EndpointName": "test-endpoint", "Body": ANY},
service_response=MOCK_RESPONSE,
service_response=MOCK_MODEL_RESPONSE,
)
sm_runtime_stub.add_client_error(str(JSONDecodeError))
sm_runtime_stub.activate()
Expand All @@ -106,7 +107,7 @@ def test_find_features_throw_client_exception(self):
sm_client_stub.add_response(
"invoke_endpoint",
expected_params={"EndpointName": "test-endpoint", "Body": ANY},
service_response=MOCK_RESPONSE,
service_response=MOCK_MODEL_RESPONSE,
)
sm_client_stub.add_client_error(str(ClientError({"Error": {"Code": 500, "Message": "ClientError"}}, "update_item")))
feature_detector.sm_client.invoke_endpoint = Mock(
Expand Down
15 changes: 7 additions & 8 deletions test/aws/osml/model_runner/status/test_image_status_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os
import unittest
from decimal import Decimal

import boto3
from moto import mock_aws
Expand All @@ -29,10 +28,10 @@ def setUp(self):
self.test_job_item = JobItem(
job_id="test-job",
image_id="test-image",
processing_duration=Decimal(1000),
region_success=Decimal(5),
region_error=Decimal(0),
region_count=Decimal(5),
processing_duration=1000,
region_success=5,
region_error=0,
region_count=5,
)

def test_process_event_success(self):
Expand All @@ -56,9 +55,9 @@ def test_process_event_failure(self):
job_id=None,
image_id="test-image",
processing_duration=None,
region_success=Decimal(0),
region_error=Decimal(5),
region_count=Decimal(5),
region_success=0,
region_error=5,
region_count=5,
)
status = RequestStatus.FAILED
message = "Processing failed."
Expand Down
11 changes: 5 additions & 6 deletions test/aws/osml/model_runner/status/test_region_status_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import os
import unittest
from decimal import Decimal

import boto3
from moto import mock_aws
Expand Down Expand Up @@ -30,12 +29,12 @@ def setUp(self):
job_id="test-job",
image_id="test-image",
region_id="test-region",
processing_duration=Decimal(1000),
failed_tile_count=Decimal(0),
processing_duration=1000,
failed_tile_count=0,
failed_tiles=[],
succeeded_tile_count=Decimal(0),
succeeded_tile_count=0,
succeeded_tiles=[],
total_tiles=Decimal(10),
total_tiles=10,
)

def test_process_event_success(self):
Expand All @@ -61,7 +60,7 @@ def test_process_event_failure(self):
region_id="test-region",
processing_duration=None, # Required field
failed_tiles=[],
total_tiles=Decimal(10),
total_tiles=10,
)
status = RequestStatus.FAILED
message = "Processing failed."
Expand Down
Loading

0 comments on commit 66749f0

Please sign in to comment.