From 52e4f6c6d6a05a9546d4d714f990058ba22d4742 Mon Sep 17 00:00:00 2001 From: John Harrison <604697+bloomonkey@users.noreply.github.com> Date: Fri, 13 Jan 2023 12:02:54 +0000 Subject: [PATCH] Support string in array-like predictions (#7) Fix bug identified in #6 whereby models that returns predictions in array-like structures, containing values unsupported by `numpy.isnan` would error at runtime. Solution is to use `pandas.isnull` which has support for a broader range of types. Thanks to @1inuxoid for the PR that identified this bug! --- CHANGELOG.md | 4 ++++ fastapi_mlflow/predictors.py | 2 +- pyproject.toml | 2 +- tests/test_predictors.py | 20 ++++++++++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7150d01..b3fdc91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.2] - 2022-01-13 +### Fixed +- Support strings for predictions in array-like structures + ## [0.3.1] - 2022-11-24 ### Fixed - Assume that prediction output field(s) may be nullable. It's not uncommon to want ML models to return null or nan values at inference time (e.g. extrapolation outside of training data range). diff --git a/fastapi_mlflow/predictors.py b/fastapi_mlflow/predictors.py index 89b998f..eb8b8fc 100644 --- a/fastapi_mlflow/predictors.py +++ b/fastapi_mlflow/predictors.py @@ -87,6 +87,6 @@ def convert_predictions_to_python(results) -> List[Dict[str, Any]]: # Replace NaN with None response_data = [] for row in results: - value = row if not np.isnan(row) else None + value = row if not pd.isnull(row) else None response_data.append({"prediction": value}) return response_data diff --git a/pyproject.toml b/pyproject.toml index 8bc3221..f487f5a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "fastapi-mlflow" -version = "0.3.1" +version = "0.3.2" description = "Deploy mlflow models as JSON APIs with minimal new code." authors = ["John Harrison "] readme = "README.md" diff --git a/tests/test_predictors.py b/tests/test_predictors.py index f1a1be5..bd1013f 100644 --- a/tests/test_predictors.py +++ b/tests/test_predictors.py @@ -4,6 +4,7 @@ Copyright (C) 2022, Auto Trader UK """ +from datetime import datetime from inspect import signature from typing import Union @@ -158,6 +159,25 @@ def test_convert_predictions_to_python_ndarray(): ] == response_data +def test_convert_predictions_to_python_ndarray_strings(): + predictions = np.array(["foo", "bar", None]) + response_data = convert_predictions_to_python(predictions) + assert [ + {"prediction": "foo"}, + {"prediction": "bar"}, + {"prediction": None}, + ] == response_data + + +def test_convert_predictions_to_python_ndarray_datetimes(): + predictions = np.array([datetime(2023, 1, 1), None]) + response_data = convert_predictions_to_python(predictions) + assert [ + {"prediction": datetime(2023, 1, 1)}, + {"prediction": None}, + ] == response_data + + def test_convert_predictions_to_python_series(): predictions = pd.Series([1, 2, 3, np.nan]) response_data = convert_predictions_to_python(predictions)