From a28478410612c42d7182794750f1d64a7f8fa614 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Sun, 15 Sep 2024 17:04:33 -0400 Subject: [PATCH 01/16] update profiler args --- opsml/data/interfaces/_base.py | 2 +- opsml/monitor/__init__.py | 0 opsml/monitor/monitor.py | 1 + opsml/profile/profile_data.py | 5 +- pyproject.toml | 2 +- uv.lock | 141 +++++++++++++++++---------------- 6 files changed, 76 insertions(+), 75 deletions(-) create mode 100644 opsml/monitor/__init__.py create mode 100644 opsml/monitor/monitor.py diff --git a/opsml/data/interfaces/_base.py b/opsml/data/interfaces/_base.py index d826766f9..7c56da32d 100644 --- a/opsml/data/interfaces/_base.py +++ b/opsml/data/interfaces/_base.py @@ -170,7 +170,7 @@ def create_data_profile(self, bin_size: int = 20, features: Optional[List[str]] profiler = DataProfiler() if self.data_profile is None: - self.data_profile = profiler.create_profile_report(self.data, bin_size, features) + self.data_profile = profiler.create_profile_report(self.data, bin_size) return self.data_profile logger.info("Data profile already exists") diff --git a/opsml/monitor/__init__.py b/opsml/monitor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/opsml/monitor/monitor.py b/opsml/monitor/monitor.py new file mode 100644 index 000000000..f9cc44a4a --- /dev/null +++ b/opsml/monitor/monitor.py @@ -0,0 +1 @@ +from scouter import Drifter, DriftConfig diff --git a/opsml/profile/profile_data.py b/opsml/profile/profile_data.py index 332b509bb..2f39c03f4 100644 --- a/opsml/profile/profile_data.py +++ b/opsml/profile/profile_data.py @@ -4,7 +4,7 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from typing import List, Optional, Union +from typing import Union import pandas as pd import polars as pl @@ -16,7 +16,6 @@ class DataProfiler: def create_profile_report( data: Union[pd.DataFrame, pl.DataFrame], bin_size: int = 20, - features: Optional[List[str]] = None, ) -> DataProfile: """ Creates a `scouter` data profile report @@ -34,7 +33,7 @@ def create_profile_report( """ profiler = Profiler() - return profiler.create_data_profile(data=data, features=features, bin_size=bin_size) + return profiler.create_data_profile(data=data, bin_size=bin_size) @staticmethod def load_profile(data: str) -> DataProfile: diff --git a/pyproject.toml b/pyproject.toml index afeeae826..615f3fd11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "pyyaml~=6.0.1", "rich~=13.3.5", "rusty-logger~=0.3.0", - "scouter-ml~=0.2.4rc3", + "scouter-ml==0.2.4rc5", "semver~=2.13.0", "tenacity~=8.2.2", "zarr~=2.12.0", diff --git a/uv.lock b/uv.lock index 4820f522d..b7b397ca9 100644 --- a/uv.lock +++ b/uv.lock @@ -3012,7 +3012,7 @@ requires-dist = [ { name = "s3fs", marker = "extra == 'aws-mysql'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 'aws-postgres'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 's3'", specifier = "~=2024.2.0" }, - { name = "scouter-ml", specifier = "~=0.2.4rc3" }, + { name = "scouter-ml", specifier = "==0.2.4rc5" }, { name = "semver", specifier = "~=2.13.0" }, { name = "skl2onnx", marker = "extra == 'sklearn-onnx'", specifier = "==1.16.0" }, { name = "sqlalchemy", extras = ["mypy"], marker = "extra == 'server'", specifier = "~=2.0" }, @@ -4484,84 +4484,85 @@ wheels = [ [[package]] name = "scouter-ml" -version = "0.2.4rc3" +version = "0.2.4rc5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, { name = "pandas" }, { name = "polars" }, + { name = "pyarrow" }, { name = "pydantic" }, { name = "rusty-logger" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/75/0d/3a456cecf04be6355bcf86ef20972dc6d9cf288d5e641f44763eeced334d/scouter_ml-0.2.4rc3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:33fe89f3991968508a7ec682fd3c759c48c308a8e6973f3f2ab3fa9464be4ae2", size = 684144 }, - { url = "https://files.pythonhosted.org/packages/08/ff/04400755f9573c7ea22ae55ce35ef4451a173caa62301d98b8063d3d8e6d/scouter_ml-0.2.4rc3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f90766f17f71b0d326634fd8c8306d7843eb7a796e28aa8266f697c87c714828", size = 639800 }, - { url = "https://files.pythonhosted.org/packages/c8/ea/a09b5486c1e0e7320bf09045ef2a4651d143b162ff849366e6fe3719b5d9/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b4c9245dc95a4bde7606940285e31aabe64d072e54074b4bb8f909057ec2ba63", size = 733531 }, - { url = "https://files.pythonhosted.org/packages/e5/97/67c0facdd6d604476ab2721c2163e2154b1060f4af52aa8357461477a583/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b94332e3e6ebabe016f5e57893c98f5ad4b23434d20e421b970185fb82132ef", size = 666347 }, - { url = "https://files.pythonhosted.org/packages/18/94/734ecf28e8366b838f5d6199dded3e703ffa06a54ebfaac4fe057de99042/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0bc8c05d387b1c14dae38a15e1fa86a9a901ab5cd6a576b8dbb0715ac6b505ab", size = 675851 }, - { url = "https://files.pythonhosted.org/packages/46/e2/4ee7cafedbd3a403577b8edf5fce80b3b79a932cbe5204fe5eef0674b3cf/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f53b17da1cfa4f7c4db706b8c09f9450ff97354a7df7cf77b01c4cc6881b2d", size = 784212 }, - { url = "https://files.pythonhosted.org/packages/8b/17/addad2d5cef2b4e3612f3a5f3967a790f6160ff11145cef0dec4a40c7328/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be240b914f8336bbaaff7bd27e2a39e23b71a2e6ee4628f87c5f62ae6de46b0d", size = 1120480 }, - { url = "https://files.pythonhosted.org/packages/ab/f0/07d373e257861119ef0f1760932e30a8cd89ecf3e1879f88af5a20dd9463/scouter_ml-0.2.4rc3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6f6a8aac181030c960938eafe2dc6a6b62724c98bd48eef5d79a0da6e571a64", size = 728232 }, - { url = "https://files.pythonhosted.org/packages/eb/02/9627ced5a2abffd90a326c65619e97d184816774c8c042ad4c99f799f1dd/scouter_ml-0.2.4rc3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fe2af1a30a07972ef52567a8598045f96a8af60257e51e33bcd5da83cedc4068", size = 846132 }, - { url = "https://files.pythonhosted.org/packages/d2/36/59546485ce0c0dc7f85830300ac20dbd9c3e3a1207a227893e83a35886f9/scouter_ml-0.2.4rc3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ac1d766a281b7b77a7e216fa5f849b643686530e34e47630e6ca98a9d1666471", size = 899736 }, - { url = "https://files.pythonhosted.org/packages/13/05/0473baeb8b17f99380b77be92ab486faf503e2acb78e667f501998fba9c5/scouter_ml-0.2.4rc3-cp310-none-win32.whl", hash = "sha256:48cfeaaf66bda96c7375b2e3d67e2a764ee6d84fac3e7b4949e60369d0e3d916", size = 610074 }, - { url = "https://files.pythonhosted.org/packages/3c/1a/9f3a58b7528ad8fcffb3159359401106ebbb3b0cdbffedd3352002b7267c/scouter_ml-0.2.4rc3-cp310-none-win_amd64.whl", hash = "sha256:f25332705bf5a10950dcc0df8075b94a21d155a62bae507e687c1a41b82b739b", size = 667210 }, - { url = "https://files.pythonhosted.org/packages/b9/47/2d2ff2891412129c1aad0c9f96c530eb85133ffe089e11f936c3bf2e733d/scouter_ml-0.2.4rc3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:52198ce938463930aa7e0018e5fd9ce332e6218ed96d85713a4f6687285f3605", size = 684109 }, - { url = "https://files.pythonhosted.org/packages/a3/ec/9a099a30b822225cfdb2ae039d3215856dbcf5e8552aff6147f2f4373150/scouter_ml-0.2.4rc3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cbeea3c180b3a290ca024a756daf31b20b09eb8fd727acfe81cf2f6bf0de23ed", size = 639894 }, - { url = "https://files.pythonhosted.org/packages/d6/db/ea965a5eff073048a2971f83096fbb4a04e316c545e048e20dc8bd11df4c/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:10c33c434eaae9651baf5361558c2f6984b845216d47759e36190e79c5571651", size = 733532 }, - { url = "https://files.pythonhosted.org/packages/50/72/77a6890cd5f9913b24e3e530b2893759d092172315e7bd24cf920104d441/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86256cec1151bb347d4de14e79a6c7f369a3f179f7542b7643a61503ebe579ad", size = 666387 }, - { url = "https://files.pythonhosted.org/packages/29/6c/0604221cf3689e9329a340a9acea5b988f460ad50efba2aea241537ae813/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8e2785967f312ac60df389cb8964ff9db44be4c8ef98abab344822c30740d9a9", size = 675880 }, - { url = "https://files.pythonhosted.org/packages/74/b3/9522631285e069b518ae8309c278a1cb2b304ad5e2cc95a79c4a5974df32/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32b4f455c8f5d660f8dcb2f83fbf169d4a2d5d2518c3564a9cb009f41b8ba630", size = 784290 }, - { url = "https://files.pythonhosted.org/packages/41/20/01eaad54c1b495bcfa1e34427c196b0f7e294ada9afb4b96bb2b996225b8/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fb44164f8440a6f6fe7edaa3860adc25c2ad4576740628a977be1deeb795568", size = 1120323 }, - { url = "https://files.pythonhosted.org/packages/4f/02/0c1adbcb2146981310bb9ea216ee261351a5127c781d343f96bfa9f44886/scouter_ml-0.2.4rc3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e1f2ef507b657c90f90160f5d7306750e395e9a84fc41df1105b87e1eeb89a3", size = 728393 }, - { url = "https://files.pythonhosted.org/packages/e6/2d/1b5d3607b8166356633d12b6b28765e8820b1b29724fe84b94ccdf51e517/scouter_ml-0.2.4rc3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dbbb2c89e11326575e4b3d46941ef9ab6a48cca04239587758974da4bcc0628a", size = 846100 }, - { url = "https://files.pythonhosted.org/packages/03/17/47c271bd90f353a05c63ffea20b309f65ffbb62f61533e8417dd1154eef8/scouter_ml-0.2.4rc3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c2623aaf06d36e18d7e29dbf99a50e13329b0bca27daba28b30a1ec7b06dad1", size = 899821 }, - { url = "https://files.pythonhosted.org/packages/e5/17/6929392ca54284bab97d57d03e8540cb207e2bf0c1ece93af43a961b95cc/scouter_ml-0.2.4rc3-cp311-none-win32.whl", hash = "sha256:7ddbcf4632a89b246ea7d8a6b1602cbef27c60e678bbe22a3c4687dbc888dae5", size = 609928 }, - { url = "https://files.pythonhosted.org/packages/fb/a8/ec188ba488ee3c76f443a78d9d477b4f542b1a5ebb1bdb82a2f5d89b6712/scouter_ml-0.2.4rc3-cp311-none-win_amd64.whl", hash = "sha256:94cc3647ff382e937f8e9b808989ae0f2c82bf29be47bede22cfc8744ecf3533", size = 667248 }, - { url = "https://files.pythonhosted.org/packages/4b/a0/6e0609b40e44bcb9072cf659f0eae9a43b047e422bb7beafcb2e6ad98856/scouter_ml-0.2.4rc3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:122a41c3c7e088631f5bb981fbcb0cf289c36a61a1c2a3b4d42d7aa920c016d9", size = 678032 }, - { url = "https://files.pythonhosted.org/packages/3c/80/be75dad41632542edbf0927f51a1447b367738f2eedddc5b4ef3ea0c3a87/scouter_ml-0.2.4rc3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:717c6fedd0bbac3ade8ee36501579f57911718562e0e03c7dd4382856b5c1b87", size = 637200 }, - { url = "https://files.pythonhosted.org/packages/ce/80/ea34f72ae16c0b13a6ab67034beefd4c49445478592ba69ebcc5eecf59cd/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6ea67a02ffbe537865e2049e11ef4a8d7c97e8421c9d25d6003ce8f5e10473c1", size = 729767 }, - { url = "https://files.pythonhosted.org/packages/1d/4b/b13ae345e6092721dbfcbadda1aaa745fb33c601dfe24d28685d264b82b5/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d7e69bdf7e414ad1cedc14e20e06078d3e245190b02f3d29599f400197c477f", size = 663238 }, - { url = "https://files.pythonhosted.org/packages/0e/a7/25609c34cb4fb9365d9edfe4ce6570a8e6344a08f1820edf8f6cdf2159d4/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5ba74f38ba2bfe3c95d6389a9a06b1ecec9150e2312d62a2ed76cdafc497daf7", size = 670296 }, - { url = "https://files.pythonhosted.org/packages/e0/02/2aa34f9951519ffb58f02c121abea6a58eaf4784efd6ce505027c3427169/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f512b14442a17c365484a6a9edb82984b806d246405920767ff3128854174bad", size = 778605 }, - { url = "https://files.pythonhosted.org/packages/57/59/f9aa1f6a3a0e7c2d45a79f47041fdf049a9509bc2294d901c9261ab14b85/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f83aa59a9cb2047a4010c77ae2b09b8080ebfaaa672c39892ddc408c5024f72c", size = 1122263 }, - { url = "https://files.pythonhosted.org/packages/d6/59/57d92b920153448b0780d4b1ef19a9372e3257de98fc7386e94bcbae796d/scouter_ml-0.2.4rc3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a8e72b11905582a3e2923d5174b6f2399478a9936dd4cddd762714d4d56b411", size = 724228 }, - { url = "https://files.pythonhosted.org/packages/f4/91/a9ad87991994b8d242f77e5978f42614c48d75395054c180bdd98691fb1b/scouter_ml-0.2.4rc3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:29acaa1b0df281298e5d28fba9f601a707e9ec96ed9fb4f1e4f912abdc351c5f", size = 842568 }, - { url = "https://files.pythonhosted.org/packages/fb/27/110a301c30a63a1b3abf2363e019ebbd29e0e63ad68401f9ea56db33f532/scouter_ml-0.2.4rc3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36caa5fe55ca65479347dc9a321502b72e40185dbca5edfa320a3b83b197a8d1", size = 895838 }, - { url = "https://files.pythonhosted.org/packages/cf/40/2e084ad1adc574799e4ebc7e13207e8b376e9f6847b080a4a66de81662c3/scouter_ml-0.2.4rc3-cp312-none-win32.whl", hash = "sha256:4c5b2d9e0f3e7ea64d4e5e252fb39e7c65cc2726a06a66f2635acd0d6996f871", size = 603787 }, - { url = "https://files.pythonhosted.org/packages/d9/6b/70c43533e2f89a6991eaebe3ec960ec9951ba0fb16c40316064f94b02b1c/scouter_ml-0.2.4rc3-cp312-none-win_amd64.whl", hash = "sha256:6cc9369f63c1a3d1751ba057e1d8ff9d4bdf161c1252ebc35f12287853e4de11", size = 659533 }, - { url = "https://files.pythonhosted.org/packages/df/75/bbcdf5d677ab22cd995becdb0284c5222ea3675f0e8a3d4bc05bac06ca5d/scouter_ml-0.2.4rc3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:150b54a7aed1dbdebf983c1db3d181cbff31dd59be0da1fbeeb9110023125eb2", size = 684740 }, - { url = "https://files.pythonhosted.org/packages/12/e5/33087ff97f548b1076a9a1c9bf88ae7ebad6c0333429cb25b8bbb88f7f39/scouter_ml-0.2.4rc3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a39c1cb3305d17255496c15460812dd95617f6e111c60f8d4af17ac5e4c81d0", size = 640449 }, - { url = "https://files.pythonhosted.org/packages/4a/cb/85033fcb0bbbe4b097cfad304bce88fb082ae24c1c5ef59762ecb36e6a6b/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:01617b901522cb14342b4295e7c1d1cb0e496e199966a70ae9f293f8bcd7c1e7", size = 734150 }, - { url = "https://files.pythonhosted.org/packages/c4/cb/a73883f3f482a4e818c674ae455e1b30eaa8b545763b0f335f9fc9b59844/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b4afe5efeb7b0c621df8da1e0aa67e9186ae55efc67f73956623198f003df0e", size = 666976 }, - { url = "https://files.pythonhosted.org/packages/e1/df/6e8cf1d13617f606736e188a10b15f37890c152b3c716f70f3dbde136a3c/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c93f7d7849f0b645a4c48df96fd552a2b4788794affbbd4e41b3bd4bd8861979", size = 676462 }, - { url = "https://files.pythonhosted.org/packages/86/09/943309073bfbec606818b598978a5ddf3cf8ffc008a569135b2bf35040e8/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:586803d708ab170d64164e546fbac3e85da201034472bf9b6eb3c5c5f886ab6f", size = 784912 }, - { url = "https://files.pythonhosted.org/packages/1c/24/e81bad0d0e69e749f0f74c78cf98fc0157390c971f6e15351adad764191b/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f797be531655bd65af2fbb7fb076de3e42273204e7921f3f5e1c8a79a6f9915e", size = 1121673 }, - { url = "https://files.pythonhosted.org/packages/be/ed/8a1968c3377e479ed764fd888c1f9e1a253c1f37a34a4d174ccec602bfd2/scouter_ml-0.2.4rc3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086cd95fd66f71038c6e4c0b7667f2363abe3792015c31c542fb46377ac33be9", size = 728972 }, - { url = "https://files.pythonhosted.org/packages/a9/1c/ef70f5329994daa137fa4c88483e05d32341289f35ec599e38cb698c7dcf/scouter_ml-0.2.4rc3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bd860f49f5cc8f9a052c7eb596f29f18241551cf010d05b77b61dc7604c3f47d", size = 846533 }, - { url = "https://files.pythonhosted.org/packages/3f/74/0f0cbe2d96cb2f5eb0cc2c85caf91070d595819179740303bf58a97a149b/scouter_ml-0.2.4rc3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c49cbf58886057b8568a247b28d16864e120082756df0508f588e0d7a5c2b729", size = 900330 }, - { url = "https://files.pythonhosted.org/packages/90/b4/ac9682c136774025dfd6b3d8c82e9b759702e5a209d1148ddc5a5f83b7a0/scouter_ml-0.2.4rc3-cp39-none-win32.whl", hash = "sha256:ae85fc2fad54190e7d33d9ce882f547713d0e04e88b0027338b29ae13e8548c5", size = 610348 }, - { url = "https://files.pythonhosted.org/packages/6b/d5/aa4617f081ef827ffdc074c5f456e99612ad6820fd05cfa09038e2d2f76f/scouter_ml-0.2.4rc3-cp39-none-win_amd64.whl", hash = "sha256:c0f2be718e1331f66edb818648c7cf550add876bddf80b2c9f0c2fe71d950b76", size = 667650 }, - { url = "https://files.pythonhosted.org/packages/3b/01/9ef39205c7caca3a46af59321072fdc5a23fcee5e85816064861d136fca9/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ce93b9aa9a43994512432caaa9fdf8675fd4c11d8db1057c11a344996cc2f583", size = 684035 }, - { url = "https://files.pythonhosted.org/packages/b9/1f/214274f1566a58ed84aebab7319cae8295903d0ccedb1548e86ab7d45d7c/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:bbf7f4b269e3470ddc0ba226917450a8962a907ba6fb25974408aff9b4abcce3", size = 639794 }, - { url = "https://files.pythonhosted.org/packages/9c/0b/40c09e93d036e6277cdb3037bf530cde3ab19cf3ee6e603f16c431fffcd0/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5c708381c9066cd689cb63a7f426951856b5933376bc1800f840cfde8a17f7e6", size = 733022 }, - { url = "https://files.pythonhosted.org/packages/61/6a/37d4e0906bcfae528bc84bbc58aee3660612a6416ef1f360622ece3335da/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d3ab64041a15c04533c0b6aeca78e112b86cba44d99cdba96b9462346b139ce", size = 666602 }, - { url = "https://files.pythonhosted.org/packages/aa/19/217930cf8fd4ed69dc936947a9d9b8067ba4fbddcae39694380ee161bfc6/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:711c2bec7af5bcbd0670d622e977eed79a4fb842a60149818f493356e56059f0", size = 675674 }, - { url = "https://files.pythonhosted.org/packages/4c/7e/101c02abfc647abda8ac9d57f74108231913bf666d09271e5ed125287ade/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:989944586181d3d3050f56daa6a922d4cc716b1f614eaabb8fa6844deba75b19", size = 784051 }, - { url = "https://files.pythonhosted.org/packages/d6/a2/afcaae0f8a5724d8b38f66dd157c1c1ebbbf3e258f10842cfa41208fe23b/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b21e5debd5462446b4a6c2aa881c6f9a9f19d09e7b8a6fe7fe884b08e34bab24", size = 1109004 }, - { url = "https://files.pythonhosted.org/packages/31/f0/9b30df712ace74270d583138e416be20ce6ed331dda9295de5f49065aadc/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0330be7e793aa5ede18c69708b973d8580fc62e9a8f4afde1e4e6bb7326d9ee", size = 727973 }, - { url = "https://files.pythonhosted.org/packages/34/b8/21f897e62be88f323c5a73362c2e85bc427c2aa69490624f08aec4667c4d/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5b12aed85f60c5cfaf05294214a664d2a75a5877b7de98321352d5b44684fc21", size = 845845 }, - { url = "https://files.pythonhosted.org/packages/68/96/2d94654a1848bb65255b99524d9bf286e6aca41d02490b266a754de64c1b/scouter_ml-0.2.4rc3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7aa2b837795b6d9434ceec7fc2e3a6d3701bedf89181f123b835127ada98b1a5", size = 899757 }, - { url = "https://files.pythonhosted.org/packages/00/1e/b68967ca46989e375e2a9a608689f6e23090db8a1413362b71da7e96cf0b/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a7b6c3871f55668b623669017d99bc3206025ac798c2d6bb81ef21c04284ee57", size = 684890 }, - { url = "https://files.pythonhosted.org/packages/08/f3/e64ea3f0fb3739579baee8bcb55b850025deafd2a40c9b948a35857cfd25/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:6422c31ebbfe317e29406beb93752477f80ccf732548e33a48ef26170dd62b2b", size = 640553 }, - { url = "https://files.pythonhosted.org/packages/3c/18/fb2e3a01f0a45826c39ea5bab2cd294dcabe8835a7ce9fd2bc3110f98479/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:adb732485ea669117ee73fb59291db322725bc2a8612c83448ec1f885f5b88e5", size = 733954 }, - { url = "https://files.pythonhosted.org/packages/36/b0/0f901f9cd6f941047f96210c7ebc53b83da291a7e5b0fe1666b509b7d230/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aecdc0d8c8a6ef22b546521d6bde94a0ab111c555bc6b0a879d71d5103b6aa89", size = 667121 }, - { url = "https://files.pythonhosted.org/packages/ee/d0/7af98fb9e34b80bb0ac9c4e8491aa8c81799f89c0a529b708277e21b6f97/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e21def19e8d4181e9b6cef73cc795d1befb45ed04d9aaaef851ba26c351499", size = 676386 }, - { url = "https://files.pythonhosted.org/packages/d1/13/c664e0f814dc936e607643344c03e40e7d48681d8a48462886e8e9475d09/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42e34a9f67f95243237469050285ff885d4a5d5f38cf68f0d71b8de78bd5096e", size = 785145 }, - { url = "https://files.pythonhosted.org/packages/12/5c/4406caaa6a0d302033bb792febbb5731a6bb6156460e35f50122db4ba551/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bfc7fb53c2d783e9b1462e47c044314279ce5b587d15a04a5172fb173e4209b", size = 1111089 }, - { url = "https://files.pythonhosted.org/packages/74/94/d56a9984f0ddba6ba8f35a0dcbcf640406e5880722daf306b9d04a1c98e8/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d5acedf2facb220e15203cd2737176fca39716feb82a98f0484a816cab01398", size = 728609 }, - { url = "https://files.pythonhosted.org/packages/c5/4b/d98d0818559f654dbb1b526f2f7cc76d677b97212d3c81c319e5b2e8b462/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4f60514513a09eb81fe81e9d7bb080c4072acf5e8488009e56b3c5fff7b846a8", size = 846833 }, - { url = "https://files.pythonhosted.org/packages/a9/c2/cd32bcb209a79928e8539454ec362a7dd9503169a32af701b17afc96be55/scouter_ml-0.2.4rc3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:c3d3f13af9b1b3e91d1d32d909499c8cbf5cca250f1cad7b8a03a8d634c7067f", size = 900506 }, + { url = "https://files.pythonhosted.org/packages/7d/7c/97181e0c128737b44058b736c43d4c538307742917c765580d4bde5399fe/scouter_ml-0.2.4rc5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:dcd720e30e9534f79c5f61443150e83cd1d7321cea2174dab8c80488063b4a28", size = 861258 }, + { url = "https://files.pythonhosted.org/packages/d9/13/9e5f2a9653a39718e403062c8ec1cfcb1acb980ed1c7f07a8bf5d1a41ea3/scouter_ml-0.2.4rc5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e59263e15d8e5f031a68082af98be445b0e1e003630b29eee49112f419c6f95a", size = 783267 }, + { url = "https://files.pythonhosted.org/packages/24/f7/4a49e70827dafb4367b062ea20efdba4be0e32b78ea8d78b909a9fddfa5e/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3a045b09420509796f31b1c6365d3cff0e3f3997e70d16ce323d1cb4226d0892", size = 887717 }, + { url = "https://files.pythonhosted.org/packages/cd/a5/78a84885c44ecdcb4fa0b375f4d3cf4389ebf3fc290bcb87ad411a7c5709/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6ddab6eff5a33c1bb6eb02b587e93fdea590b7341ca3eea60071c552777c2eb", size = 805151 }, + { url = "https://files.pythonhosted.org/packages/23/9d/a857043e46b685ff40a851833830284a13891b7c8e1bad8e45c24b110bb2/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b9c1646a17fbcfd2ede10e5697a44bf55b5c3736bbc80ee4be7b1026a2660ec5", size = 822321 }, + { url = "https://files.pythonhosted.org/packages/e9/27/efcf03dc8e5d524b06f97c7e2dac7a7e14f6327ccc615d6f34553cd680c5/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e7d1b299b5e21f897487ef72e761db4f6bbcdbfe3f03de707e05ce6741f26e0", size = 958294 }, + { url = "https://files.pythonhosted.org/packages/52/1a/146a6b55a0f70fdc2849ab998f133bf0d076629ea19efab75cde366c6746/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fee760c450b03f0ae7593b3e43d655a3a3b1cb973083b5bf2e11e10375cee003", size = 1486737 }, + { url = "https://files.pythonhosted.org/packages/f3/2c/6f5d8c3d4bf44db3b7023b2cf02f33c0ce36c42644a79cec99c7f5367c9b/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe8acad9a833c896f608bda0fb7e94b20ef47a384c6a64404062244ab274a71", size = 901828 }, + { url = "https://files.pythonhosted.org/packages/70/b6/5a87a0ba950daf78bbf9017ca46e2795561daefed34cb3f39232bf216012/scouter_ml-0.2.4rc5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:edf831faee8413935f793a56a17ec9b3d70cef5efac2cc8f14685396dc71d197", size = 974781 }, + { url = "https://files.pythonhosted.org/packages/e0/bd/5b6fadb6cc87925e20e619e3dc12a2b2e0eaab884192667ed98ea2908224/scouter_ml-0.2.4rc5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:726322cecaa3558172dcac145ef81cc137408b8c1940ab078dc0f22ecbc96ec8", size = 1062411 }, + { url = "https://files.pythonhosted.org/packages/84/98/200d5c27743e77e62422850ad6df4dbdfcb635046ac2779a284aa114db4c/scouter_ml-0.2.4rc5-cp310-none-win32.whl", hash = "sha256:76351728cb6360f0e13032426553d1b46d21c297c3aead06fd6f3d88a0815aa5", size = 762040 }, + { url = "https://files.pythonhosted.org/packages/5c/98/29be713f185cb92b586b1f650b1b1dbd2f341b4ffb5f9e6e62e43b960f1b/scouter_ml-0.2.4rc5-cp310-none-win_amd64.whl", hash = "sha256:63224d5791ee9d52fce84ebdbda5f17e6ed855bec6810a942bc84c3660d7ee96", size = 856771 }, + { url = "https://files.pythonhosted.org/packages/55/16/24b8f604aec04ed48574ea08cb7ed6f3bd5087aa7ff897c888dc93257b2b/scouter_ml-0.2.4rc5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3b2328ee2ed7b86b1ca259b1d0c2ae6e5c31585feaf2436891aa2123a7c731dd", size = 861388 }, + { url = "https://files.pythonhosted.org/packages/7e/33/fd0e336ec57e9f833583f13a268c18c97c6b9afd233c79a4715dacaf5b7f/scouter_ml-0.2.4rc5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1dcf36cdc8f1cbf3313540d58c002860a1a499c1ec6c1c5277c286f1f5c4df36", size = 783303 }, + { url = "https://files.pythonhosted.org/packages/66/8a/7a621bb20543d2236192d94da7411ddf0391aadc0e5971bb6fd60d237bac/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:98b5736e3da41596a1252baa6b660efc966aefafd7280e70b460e30317e1a06e", size = 887712 }, + { url = "https://files.pythonhosted.org/packages/29/b3/393ae3cbc74bfdbcb3e2358d7e372feb0e4fefa8cab06b77d352b6d758a8/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8177093d394a6739a077680b03bcee037b44cf32dadf09b8493f8e8ebc85d0c6", size = 805119 }, + { url = "https://files.pythonhosted.org/packages/f6/47/cbfc6ca833c8c8720c2b8565b61a9b60233b850355543bca386e6bea853f/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:397566f611e6ef7f97feae502d6076766668e665212aa9181b229db005f53ac3", size = 822423 }, + { url = "https://files.pythonhosted.org/packages/53/bb/1ba383fd9a516f22b05c5a25dca0eaa1a96728e8430c7946e0a8bbbbc5bf/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76451c17408b8181c26c4eb49f3e469a8196fd3b656b5d303ded515e622d181a", size = 958258 }, + { url = "https://files.pythonhosted.org/packages/ff/20/6a7e5345a15d58e831d960193025a34751ac1e483236bded6a3651388307/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e8a752b01dd479ee33be1b1badb84048c8eedaa092a9754f1de2d78ba8b3f13", size = 1486605 }, + { url = "https://files.pythonhosted.org/packages/63/c6/c3ffe13126603837310d213de5d7fd7607e6c6f9cd57c251160b47d79bbf/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b38f5c7453a28fccf803da0c9ddf8b1f668db7e82fd6190dcdc341bf48c52fb", size = 901850 }, + { url = "https://files.pythonhosted.org/packages/d3/51/b4160075cd7669b995f178d127fbb5dc06e05ada076c9f7d50c39339e9c6/scouter_ml-0.2.4rc5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:054521ae3d3202cfac0753580f21e33221f025f29b61b979ea7ea40adca02857", size = 974644 }, + { url = "https://files.pythonhosted.org/packages/0c/47/27f0aa4598ffbb979d954b60ed0ff68c9ea14c741244159d70278aa122ab/scouter_ml-0.2.4rc5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e659ac256305693b6fa541cba0083da646cfc08d2243f8d93e9e9dd39fd920db", size = 1062543 }, + { url = "https://files.pythonhosted.org/packages/05/f5/f15a45a95bcfad159d1dc4718ea9182c2a294f3aaca7c3776d74411f7ab0/scouter_ml-0.2.4rc5-cp311-none-win32.whl", hash = "sha256:2795d46a709ba5330d648bdc5e9bd019d4a047c7eabd8ebcc0749611f6576242", size = 762050 }, + { url = "https://files.pythonhosted.org/packages/5d/66/679e845e6480e4e8e10cd045dfde5ecbe6db16d95c77cbe759045f1f2f54/scouter_ml-0.2.4rc5-cp311-none-win_amd64.whl", hash = "sha256:dcc955440c6e52f72d0490b42b927b5fb3cdde810f40deede0a0ceaed27b0cda", size = 856790 }, + { url = "https://files.pythonhosted.org/packages/83/d2/662a7e15c167f492e1bf8e37cc150895fb396255863ef3ec70a465e8bc3b/scouter_ml-0.2.4rc5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:64687f2a165fcaa4f8dbcc1e031410da43bc761bc6beec3fea29b4db3fd5d8a3", size = 857964 }, + { url = "https://files.pythonhosted.org/packages/90/27/044b88977de66d580dd8c411f40d117728ad31021864c8f9b1a95871798e/scouter_ml-0.2.4rc5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:97f6048536eed1ce4432bc3eb1a3002d59882e69921a72d11ae3ff3e7b0899e4", size = 782039 }, + { url = "https://files.pythonhosted.org/packages/90/ab/c2f21353b99a3ebf855b17597099d8236d6c77194409a45b2c175b483110/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7fc2f855774b2d492840224c19d6189a144199d85936790de9cac7ea9ae218a8", size = 887614 }, + { url = "https://files.pythonhosted.org/packages/76/51/cdc5e4f658e401dee6acdb68aa9a5fa9b444182619d7406d8e8e7616bb89/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27562f18d59fb016be4591d2fa271c26e74593ac0172ba5e2648bae43acae499", size = 803144 }, + { url = "https://files.pythonhosted.org/packages/68/13/93e378cc2dac7ddcdc82e97aa9a040f9969ea466271a79ab5195aa058dbd/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b41a80e69e316a6fd84ebaea20962acf93dd9242d092371eb062d8a887bcf887", size = 821499 }, + { url = "https://files.pythonhosted.org/packages/1c/63/23ada3dfb9f9c05b42b967b090a2b222821dec2d50b8ef1ae87c6fef4823/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0b430672f31426baa2b75bd18424fb2ab71ad7476bfe0636a8648df44863eac", size = 954736 }, + { url = "https://files.pythonhosted.org/packages/a3/62/78c8d341fb4ccbd8cb2584bd9607676b2b6f3224d8d1a6806556f5732f50/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a7fcaf230f7688c0c214558821813b60a790b45112f3f0357bcc8056d5ba24c", size = 1452535 }, + { url = "https://files.pythonhosted.org/packages/09/33/7a53a1eace84d4370f6e249917e5557471cb9c712faaab974d7909b5e343/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4e25ee147eb47accd56334602f13423b6c129603d7f2828dec99bc437496b6", size = 901483 }, + { url = "https://files.pythonhosted.org/packages/34/bb/17f00e2d3324f4c535fe8c983af07ff6769179f617921e46cc2a2869c97c/scouter_ml-0.2.4rc5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb175c2dd8788dbd952f1321813417776cfc221351dd3e544fd044034e5877b9", size = 969199 }, + { url = "https://files.pythonhosted.org/packages/3a/5a/df89faf243ccf56a3900dc55b2a7616cbb1faaacb8f3cbd8d509a342782a/scouter_ml-0.2.4rc5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26f7e8251fb19544f583ab4773364236ed3fc98734db67640dda1f6157ac1377", size = 1057058 }, + { url = "https://files.pythonhosted.org/packages/01/a2/dd46ce91d250359dceb38ccbd67825a726621c73708ec510064951cdad32/scouter_ml-0.2.4rc5-cp312-none-win32.whl", hash = "sha256:b91353c834fa117b8e1390832b817fae8df455e726e1482b6ec7a52485714bfd", size = 758287 }, + { url = "https://files.pythonhosted.org/packages/7e/da/1f13c39b760fb5ca7956792a1781c67c0e5b6abebd0394676bb6c86e5df7/scouter_ml-0.2.4rc5-cp312-none-win_amd64.whl", hash = "sha256:a7c7bc3905f6c63b15dd670dd30b1b8759e2cd9196de07dcfb374f1e01fd1501", size = 853272 }, + { url = "https://files.pythonhosted.org/packages/a7/7b/c7bad5976ea8b270f669b53d7ca33c6f33bc99a6f0a4fbe53ca8927aee84/scouter_ml-0.2.4rc5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:771354a43f63f5a69fd203b63ccd5ac8a8cc8743c41c891efe4ea6ef89fd4712", size = 861618 }, + { url = "https://files.pythonhosted.org/packages/f6/d6/276e3eb95e8dfda32088beacbae5c27b99abb057568ffd2db44fe8805ebc/scouter_ml-0.2.4rc5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0b925c342ba413e6e3bdb4dfa7369ca83576385752d9b94c28490b3d421f0a1", size = 783817 }, + { url = "https://files.pythonhosted.org/packages/1a/c9/73890b1942d7b9c9b8e35dd05588d59b69a98ce4ec0f7ee711964f2cf468/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:16821f876e5359699691f50956af7da50908aadbaed069f50322a36e36f9df43", size = 888256 }, + { url = "https://files.pythonhosted.org/packages/93/90/e5b011824b34329c29ddb6ed2f3aa21fcc6243841b9641a16daa2c4e6573/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36d7c8248827c8aba860ac2bc038e956341f3be08b75a8a7eedd24682a98ac3a", size = 805624 }, + { url = "https://files.pythonhosted.org/packages/c7/84/d4a0450a81c25107abc92da24adf7e978129efe4a0e63d9f6e995af39cb6/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8046f6b5b71b99837527237f484586714952a2895031bda311baa787c7e6ae", size = 822657 }, + { url = "https://files.pythonhosted.org/packages/d4/62/b6aa7d8547443a15e1078f6057ebff1a40fb7b702a531438918fd0052183/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:721ba7a844cb9415ac3fa4cb7b214eadbd1296708831c477cbdd19c7c2428828", size = 958883 }, + { url = "https://files.pythonhosted.org/packages/f1/80/d0b5b122c3519cbc63b73ed5a9197567272f86f27c5a31574f8399a9334d/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4679a070cdb38374fe1ead8dc65aa880d93da6607d2518c49fda6f2333f53e12", size = 1487536 }, + { url = "https://files.pythonhosted.org/packages/53/1f/919feb1524d390d1fabb988e81deb2e268085d4d5ff3f0c0858d531c54c2/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a817bd5273692a98b610bd49aa6e4cd47bcf4dcd3a19be20c259d12078f9048e", size = 902256 }, + { url = "https://files.pythonhosted.org/packages/4e/b4/78da541bfca1ee7fbdeedc74ce08281156fe1ac16736a43e3dea7fb1856f/scouter_ml-0.2.4rc5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c83cfa6d11c31463add75e3a6f78a0532cf24bfcb9838e90dcde446245c82861", size = 975236 }, + { url = "https://files.pythonhosted.org/packages/16/a4/492629f406a30aa38f0113da2469ca465fe4542dda7ce18a7f4e9b0da5d1/scouter_ml-0.2.4rc5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f755a3d63947e47e9e8becf6a78832a071add5f92372c656b04fdc98a50350f1", size = 1063020 }, + { url = "https://files.pythonhosted.org/packages/e6/84/17f4116d688eca0334464babf305c2a337c2aa2346d1fb8ce7630cc60784/scouter_ml-0.2.4rc5-cp39-none-win32.whl", hash = "sha256:90f92eb5a3371b39f071ea8cc6b2b555dfb0bb09f0f90eed09662af5b3e8ee51", size = 762368 }, + { url = "https://files.pythonhosted.org/packages/45/a3/4c20629d2dbe9b8ba0a2df9cb299e77dc1bc30868d79e6452fed2e669caa/scouter_ml-0.2.4rc5-cp39-none-win_amd64.whl", hash = "sha256:1bff99fb22acd52c9bf334e903f246f4a336c37352d0875a71d449dbfd1c87ce", size = 857106 }, + { url = "https://files.pythonhosted.org/packages/9f/74/1559d497a0dd4f97c6e9bf1c016cfa8eb08414624bc06fb840c3b2fa0a24/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:751f21f400fcfc6eee48b22af21d59bbb0b81d0d98dc498c95c5d6719b56b7f6", size = 859253 }, + { url = "https://files.pythonhosted.org/packages/91/cf/20effb01deab7d6740b7d8b79c14086c216994b500791698209834d14886/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:31c4f8be7d4186d5ed70dd51435a240c7d425f9e68103ff318bab798f8afec5e", size = 781389 }, + { url = "https://files.pythonhosted.org/packages/f7/1b/02686c76af40e781580ec6a4ddba46728b042d72529e7ae25fce8dc5ffdc/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:946c33cee8a29b84549a604b98abd7e03cfdfb2ae96bc5884448fa4ae225c788", size = 885460 }, + { url = "https://files.pythonhosted.org/packages/9d/cf/795d59a285fbdc046de3897046b076257c7983215402fe45d253ad866a94/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d2e7c97779cc4e93c76dc73fe1f598a1915f64612883c2e5dfa967c5320665a", size = 803188 }, + { url = "https://files.pythonhosted.org/packages/48/9f/6520bbea9a75ee0ae4e5085d94c775cd49c45cc4f6fe71718ef75bf47b14/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:364e0881cfc14d3086afa6331a3a15f4c7796eb18c2c362711fa2942d98e2d8f", size = 820194 }, + { url = "https://files.pythonhosted.org/packages/01/cb/b918823a3abc370e2dc82e1e6c9b3db5bbabeab0fb41dce55e1d133cf9b9/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67441d41dfc6c94f205cfe0f99f91a42753027134e72fd34597852fbb1c10c5d", size = 956092 }, + { url = "https://files.pythonhosted.org/packages/fc/5c/d73611e73ae689a76497864fc6d3ce7d1efd48f5fb8d9ba17fc23c2b9f9f/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:323a4d24277d2e0dfdd8ae5e536cc356b3a2b7c4819f8aa8027c5c04fa686741", size = 1476078 }, + { url = "https://files.pythonhosted.org/packages/0a/26/c44cbbd699e7be0d79c7fb9aa0fa16dd119c5124772d0380664424e31c53/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eda0a5b5f597595f05b00fe59c6cf438f38103f6b167321fd1c3d14cbf9f9002", size = 899757 }, + { url = "https://files.pythonhosted.org/packages/99/1a/b2aaac0df76b84f98f6975a6a1c0ff4f325f527d28a20b93588aa52955ff/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b943d62fe3ba896aed6256cd9d2afffeb96e57d4810bb55a6bdae8e1ff269505", size = 973976 }, + { url = "https://files.pythonhosted.org/packages/4c/c5/e7e6c3f9099dfbfcc8b0725e48742d30b824ab96cfa8bd5520ee2da3af52/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2e2a5589d7afae166bce5230e35f4394d2f3563b494e40228a93dfee556a56e0", size = 1061243 }, + { url = "https://files.pythonhosted.org/packages/52/83/d15e51f45271ddf41ef3e6f12bbfc3c806b7d96e9f49b07a61e44d40e6f6/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d80ae86c76f75a83a0db68954cc79473c2223877cf1feceebcab30da5e174f68", size = 859777 }, + { url = "https://files.pythonhosted.org/packages/8a/28/78f0694a5af424bdc1ee9aca1fcfd2794ed8fcb3e2213576a9b36f85de1b/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:665dcd6e31f9e0a14e161b8b6f96b495080a1add466231cfa12a497cfe99123d", size = 781809 }, + { url = "https://files.pythonhosted.org/packages/1b/c1/4a16e1985f7599458c9076b2eaf731454dfe19d7d24bd25d7abb425f93d5/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a2242018d6c9c9b1e5e5666b2eaad9686b05dccfb169a2eb57baaf36052a096", size = 885893 }, + { url = "https://files.pythonhosted.org/packages/95/6c/f672b3a08192eceb1061b8b380ad861391160a4525808df17d8ea77e5ae6/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50389951af5cfc3881f3c5eb68d7782a0250c79e8cdeaaad4174d9b140e75cd6", size = 803713 }, + { url = "https://files.pythonhosted.org/packages/2d/c8/6fd4fe4410d94d49842e2e3393574608085f83a5bdb7c65569bbae6076dc/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c1256f229ec628e5167fea1abd18ab76dff8f76d27e24538966c27ad70a8536e", size = 820631 }, + { url = "https://files.pythonhosted.org/packages/0b/15/efb0974278324e7dca8f3879edf4e5ecc3fa084b427590c11b7a29fe130c/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03bf0f0298fecb750dcb9037a70a41a7d098bda2e11ecf4bc4de7760b1689038", size = 956949 }, + { url = "https://files.pythonhosted.org/packages/60/e4/b394268a94bd40951b7cfad4917b9d61aa24de4fb9d6737a1fff5ee808df/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a154ed9c7e8e265c90c6e4d6b575c449dcdadb462f296c1c293ddea8419db62", size = 1477782 }, + { url = "https://files.pythonhosted.org/packages/ec/32/1e4fc166a8df8c120b0ffafdb16ab2055a3b0020d0d0585b697c801a02e0/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:350006ac622e147bc829b0df8ae9185fba29829f38920ba7092d762dd20430bf", size = 900186 }, + { url = "https://files.pythonhosted.org/packages/4c/d8/e9eefbbad1b097786e04827272cf20d367374e8fff9fc5af362d61600414/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26061ab9568cc1fd120bf87200ffb8bb1087e568bdb5bf748eb5488d46ba0844", size = 974539 }, + { url = "https://files.pythonhosted.org/packages/78/c1/6d23a2d7799c18a95f18321c27c57e4dc4b9654e8d6a932ef144f8b340ee/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8087e7fd1c165b5a6e7650fd1570d530b84a36973c865491e6cac802fc3a2727", size = 1061946 }, ] [[package]] From de8b3ab88ed47880db6710c45795dfa28f3969f3 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Sun, 15 Sep 2024 17:12:54 -0400 Subject: [PATCH 02/16] add drift profile method to model interface --- opsml/model/interfaces/base.py | 35 ++++++++++++++++++++++++++++++++-- opsml/monitor/__init__.py | 0 opsml/monitor/monitor.py | 1 - 3 files changed, 33 insertions(+), 3 deletions(-) delete mode 100644 opsml/monitor/__init__.py delete mode 100644 opsml/monitor/monitor.py diff --git a/opsml/model/interfaces/base.py b/opsml/model/interfaces/base.py index b432dc065..01bb96828 100644 --- a/opsml/model/interfaces/base.py +++ b/opsml/model/interfaces/base.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from functools import cached_property from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple, cast +from typing import Any, Dict, List, Optional, Tuple, cast, Union from uuid import UUID import joblib @@ -10,7 +10,7 @@ import polars as pl import pyarrow as pa from pydantic import BaseModel, ConfigDict, field_validator, model_validator - +from numpy.typing import NDArray from opsml.data import DataInterface from opsml.helpers.utils import get_class_name from opsml.types import ( @@ -21,6 +21,7 @@ OnnxModel, Suffix, ) +from scouter import Drifter, DriftConfig, DriftProfile def get_processor_name(_class: Optional[Any] = None) -> str: @@ -115,6 +116,7 @@ class ModelInterface(BaseModel): modelcard_uid: str = "" feature_map: Dict[str, Feature] = {} sample_data_interface_type: str = CommonKwargs.UNDEFINED.value + drift_profile: Optional[DriftProfile] = None model_config = ConfigDict( protected_namespaces=("protect_",), @@ -341,6 +343,35 @@ def _prediction_data(self) -> Any: return self.sample_data + def create_drift_profile( + self, + data: Union[pl.DataFrame, pd.DataFrame, NDArray[Any], pa.Table], + monitor_config: DriftConfig, + ) -> DriftProfile: + """Create a drift profile from data to use for model monitoring. + + Args: + data: + Data to create a monitoring profile from. Data can be a numpy array, pyarrow table, + a polars dataframe or pandas dataframe. Data is expected to not contain + any missing values, NaNs or infinities and it typically the data used for training a model. + monitor_config: + Configuration for the monitoring profile. + + """ + + if self.drift_profile is not None: + return self.drift_profile + + drifter = Drifter() + profile = drifter.create_drift_profile( + data=data, + monitor_config=monitor_config, + ) + self.drift_profile = profile + + return profile + @staticmethod def name() -> str: return ModelInterface.__name__ diff --git a/opsml/monitor/__init__.py b/opsml/monitor/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/opsml/monitor/monitor.py b/opsml/monitor/monitor.py deleted file mode 100644 index f9cc44a4a..000000000 --- a/opsml/monitor/monitor.py +++ /dev/null @@ -1 +0,0 @@ -from scouter import Drifter, DriftConfig From 80e0a48267c828a451dfa593862f4b527ecd2122 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Sun, 15 Sep 2024 21:12:30 -0400 Subject: [PATCH 03/16] add drift test --- opsml/model/interfaces/base.py | 7 ++-- opsml/storage/schemas/modelcard.yaml | 2 +- tests/conftest.py | 10 ++--- tests/test_drift/__init__.py | 0 tests/test_drift/test_drift.py | 41 +++++++++++++++++++ tests/test_interface/test_model_interface.py | 2 - ...test_model_interface_saver_loader_local.py | 35 ++++++++-------- 7 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 tests/test_drift/__init__.py create mode 100644 tests/test_drift/test_drift.py diff --git a/opsml/model/interfaces/base.py b/opsml/model/interfaces/base.py index 01bb96828..d05f6a7db 100644 --- a/opsml/model/interfaces/base.py +++ b/opsml/model/interfaces/base.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from functools import cached_property from pathlib import Path -from typing import Any, Dict, List, Optional, Tuple, cast, Union +from typing import Any, Dict, List, Optional, Tuple, Union, cast from uuid import UUID import joblib @@ -9,8 +9,10 @@ import pandas as pd import polars as pl import pyarrow as pa -from pydantic import BaseModel, ConfigDict, field_validator, model_validator from numpy.typing import NDArray +from pydantic import BaseModel, ConfigDict, field_validator, model_validator +from scouter import DriftConfig, Drifter, DriftProfile + from opsml.data import DataInterface from opsml.helpers.utils import get_class_name from opsml.types import ( @@ -21,7 +23,6 @@ OnnxModel, Suffix, ) -from scouter import Drifter, DriftConfig, DriftProfile def get_processor_name(_class: Optional[Any] = None) -> str: diff --git a/opsml/storage/schemas/modelcard.yaml b/opsml/storage/schemas/modelcard.yaml index 74a217ed6..8d752dcbd 100644 --- a/opsml/storage/schemas/modelcard.yaml +++ b/opsml/storage/schemas/modelcard.yaml @@ -24,4 +24,4 @@ keys: - arguments - sample_data_interface_type - feature_map - \ No newline at end of file + - drift_profile diff --git a/tests/conftest.py b/tests/conftest.py index 9bad08584..941ad2e0a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -943,9 +943,7 @@ def sklearn_pipeline() -> Tuple[SklearnModel, PandasData]: transformers=[("cat", categorical_transformer, cat_cols)], remainder="passthrough", ) - pipe = Pipeline( - [("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))] - ) + pipe = Pipeline([("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))]) pipe.fit(train_data, data["y"]) sql_logic = {"test": "SELECT * FROM TEST_TABLE"} @@ -1158,7 +1156,7 @@ def random_forest_classifier(example_dataframe): yield SklearnModel( model=reg, - sample_data=X_train[:100], + sample_data=X_train, task_type="classification", preprocessor=StandardScaler(), ) @@ -2355,9 +2353,7 @@ def stacking_classifier(): ("rf", ensemble.RandomForestClassifier(n_estimators=10, random_state=42)), ("svr", make_pipeline(StandardScaler(), linear_model.LogisticRegression(max_iter=5))), ] - reg = ensemble.StackingClassifier( - estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5) - ) + reg = ensemble.StackingClassifier(estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5)) reg.fit(X, y) return SklearnModel(model=reg, sample_data=X) diff --git a/tests/test_drift/__init__.py b/tests/test_drift/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_drift/test_drift.py b/tests/test_drift/test_drift.py new file mode 100644 index 000000000..af860581b --- /dev/null +++ b/tests/test_drift/test_drift.py @@ -0,0 +1,41 @@ +# type: ignore + +from typing import Tuple +from scouter import DriftConfig, DriftProfile +import pandas as pd +from opsml import SklearnModel +from opsml.helpers.data import create_fake_data + + +def test_scouter( + random_forest_classifier: SklearnModel, + example_dataframe: Tuple[ + pd.DataFrame, + pd.DataFrame, + pd.DataFrame, + pd.DataFrame, + ], +) -> None: + # X, _, _, _ = example_dataframe + X, _ = create_fake_data(n_samples=10_000, n_features=20, n_categorical_features=4) + + model: SklearnModel = random_forest_classifier + config = DriftConfig(name="test", repository="test") + model.create_drift_profile(X, config) + + assert isinstance(model.drift_profile, DriftProfile) + + assert model.drift_profile.config.name == "test" + assert model.drift_profile.config.repository == "test" + + for col in X.columns: + assert col in model.drift_profile.features.keys() + assert model.drift_profile.features[col].center is not None + assert model.drift_profile.features[col].one_lcl is not None + assert model.drift_profile.features[col].one_ucl is not None + assert model.drift_profile.features[col].two_lcl is not None + assert model.drift_profile.features[col].two_ucl is not None + assert model.drift_profile.features[col].three_lcl is not None + assert model.drift_profile.features[col].three_ucl is not None + + assert model.drift_profile.config.feature_map is not None diff --git a/tests/test_interface/test_model_interface.py b/tests/test_interface/test_model_interface.py index d2ec4a944..db4de61b5 100644 --- a/tests/test_interface/test_model_interface.py +++ b/tests/test_interface/test_model_interface.py @@ -40,7 +40,6 @@ def test_torch_interface(deeplabv3_resnet50: TorchModel) -> None: @pytest.mark.flaky(reruns=1, reruns_delay=2) @pytest.mark.skipif(EXCLUDE, reason="skipping") def test_lightning_interface(lightning_regression: Tuple[LightningModel, L.LightningModule]) -> None: - light_model, model = lightning_regression assert isinstance(light_model.sample_data, TorchData) assert light_model.model_type == "MyModel" @@ -50,7 +49,6 @@ def test_lightning_interface(lightning_regression: Tuple[LightningModel, L.Light @pytest.mark.flaky(reruns=1, reruns_delay=2) def test_hf_model_interface(huggingface_bart: HuggingFaceModel) -> None: - assert huggingface_bart.model_type == "BartModel" assert huggingface_bart.model_class == "transformers" assert huggingface_bart.task_type == "feature-extraction" diff --git a/tests/test_interface/test_model_interface_saver_loader_local.py b/tests/test_interface/test_model_interface_saver_loader_local.py index 23244b2d1..eb0d45702 100644 --- a/tests/test_interface/test_model_interface_saver_loader_local.py +++ b/tests/test_interface/test_model_interface_saver_loader_local.py @@ -32,7 +32,7 @@ @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_huggingface_modelcard(huggingface_torch_distilbert: HuggingFaceModel) -> None: +def _test_save_huggingface_modelcard(huggingface_torch_distilbert: HuggingFaceModel) -> None: model: HuggingFaceModel = huggingface_torch_distilbert modelcard = ModelCard( @@ -96,7 +96,7 @@ def test_save_huggingface_modelcard(huggingface_torch_distilbert: HuggingFaceMod @pytest.mark.skipif(EXCLUDE, reason="skipping") -def test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pipeline: HuggingFaceModel) -> None: +def _test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pipeline: HuggingFaceModel) -> None: model: HuggingFaceModel = huggingface_text_classification_pipeline modelcard = ModelCard( @@ -158,6 +158,7 @@ def test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pip def test_save_sklearn_modelcard(random_forest_classifier: SklearnModel) -> None: model: SklearnModel = random_forest_classifier + modelcard = ModelCard( interface=model, name="test_model", @@ -209,7 +210,7 @@ def test_save_sklearn_modelcard(random_forest_classifier: SklearnModel) -> None: # @pytest.mark.skipif(EXCLUDE, reason="skipping") -def test_save_lgb_booster_modelcard(lgb_booster_model: LightGBMModel) -> None: +def _test_save_lgb_booster_modelcard(lgb_booster_model: LightGBMModel) -> None: model: LightGBMModel = lgb_booster_model modelcard = ModelCard( @@ -256,7 +257,7 @@ def test_save_lgb_booster_modelcard(lgb_booster_model: LightGBMModel) -> None: assert loaded_card.interface.onnx_model.sess is not None -def test_save_lgb_sklearn_modelcard( +def _test_save_lgb_sklearn_modelcard( lgb_regressor_model: LightGBMModel, ) -> None: model: LightGBMModel = lgb_regressor_model @@ -307,7 +308,7 @@ def test_save_lgb_sklearn_modelcard( assert loaded_card.interface.onnx_model.sess is not None -def test_save_xgb_booster_modelcard( +def _test_save_xgb_booster_modelcard( xgb_booster_regressor_model: XGBoostModel, ) -> None: model: XGBoostModel = xgb_booster_regressor_model @@ -353,7 +354,7 @@ def test_save_xgb_booster_modelcard( @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_torch_modelcard(pytorch_simple: TorchModel) -> None: +def _test_save_torch_modelcard(pytorch_simple: TorchModel) -> None: model: TorchModel = pytorch_simple modelcard = ModelCard( @@ -411,7 +412,7 @@ def test_save_torch_modelcard(pytorch_simple: TorchModel) -> None: @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_torch_tuple_modelcard(pytorch_simple_tuple: TorchModel) -> None: +def _test_save_torch_tuple_modelcard(pytorch_simple_tuple: TorchModel) -> None: model: TorchModel = pytorch_simple_tuple modelcard = ModelCard( @@ -464,7 +465,7 @@ def test_save_torch_tuple_modelcard(pytorch_simple_tuple: TorchModel) -> None: @pytest.mark.skipif(EXCLUDE, reason="skipping") -def test_save_torch_lightning_modelcard(lightning_regression: LightningModel) -> None: +def _test_save_torch_lightning_modelcard(lightning_regression: LightningModel) -> None: model, model_arch = lightning_regression model = cast(LightningModel, model) @@ -515,7 +516,7 @@ def test_save_torch_lightning_modelcard(lightning_regression: LightningModel) -> @pytest.mark.skipif(EXCLUDE, reason="skipping") -def test_save_tensorflow_modelcard(tf_transformer_example: TensorFlowModel) -> None: +def _test_save_tensorflow_modelcard(tf_transformer_example: TensorFlowModel) -> None: model: TensorFlowModel = tf_transformer_example modelcard = ModelCard( @@ -565,7 +566,7 @@ def test_save_tensorflow_modelcard(tf_transformer_example: TensorFlowModel) -> N @pytest.mark.skipif(EXCLUDE, reason="skipping") -def test_save_tensorflow_multi_input_modelcard(multi_input_tf_example: TensorFlowModel) -> None: +def _test_save_tensorflow_multi_input_modelcard(multi_input_tf_example: TensorFlowModel) -> None: model: TensorFlowModel = multi_input_tf_example modelcard = ModelCard( @@ -615,7 +616,7 @@ def test_save_tensorflow_multi_input_modelcard(multi_input_tf_example: TensorFlo @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pipeline: HuggingFaceModel) -> None: +def _test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pipeline: HuggingFaceModel) -> None: model: HuggingFaceModel = huggingface_text_classification_pipeline modelcard = ModelCard( @@ -670,7 +671,7 @@ def test_save_huggingface_pipeline_modelcard(huggingface_text_classification_pip @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_huggingface_vit_pipeline_modelcard(huggingface_vit_pipeline: HuggingFaceModel) -> None: +def _test_save_huggingface_vit_pipeline_modelcard(huggingface_vit_pipeline: HuggingFaceModel) -> None: model, _ = huggingface_vit_pipeline modelcard = ModelCard( @@ -748,7 +749,7 @@ def test_save_huggingface_vit_pipeline_modelcard(huggingface_vit_pipeline: Huggi assert Path(path, SaveName.MODEL_METADATA.value).with_suffix(Suffix.JSON.value).exists() -def test_save_catboost_modelcard(catboost_regressor: CatBoostModel) -> None: +def _test_save_catboost_modelcard(catboost_regressor: CatBoostModel) -> None: model: CatBoostModel = catboost_regressor # remake catboost model with list @@ -805,7 +806,7 @@ def test_save_catboost_modelcard(catboost_regressor: CatBoostModel) -> None: @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_torch_byo_bytes_modelcard(pytorch_onnx_byo_bytes: TorchModel) -> None: +def _test_save_torch_byo_bytes_modelcard(pytorch_onnx_byo_bytes: TorchModel) -> None: model: TorchModel = pytorch_onnx_byo_bytes modelcard = ModelCard( @@ -864,7 +865,7 @@ def test_save_torch_byo_bytes_modelcard(pytorch_onnx_byo_bytes: TorchModel) -> N @pytest.mark.skipif(WINDOWS_EXCLUDE, reason="skipping") -def test_save_torch_byo_file_modelcard(pytorch_onnx_byo_file: TorchModel) -> None: +def _test_save_torch_byo_file_modelcard(pytorch_onnx_byo_file: TorchModel) -> None: model: TorchModel = pytorch_onnx_byo_file modelcard = ModelCard( @@ -925,7 +926,7 @@ def test_save_torch_byo_file_modelcard(pytorch_onnx_byo_file: TorchModel) -> Non @pytest.mark.skipif(bool(IS_311 or EXCLUDE), reason="vowpal not support for py311") -def test_save_vowpal_modelcard(vowpal_wabbit_cb: VowpalWabbitModel) -> None: +def _test_save_vowpal_modelcard(vowpal_wabbit_cb: VowpalWabbitModel) -> None: model: VowpalWabbitModel = vowpal_wabbit_cb modelcard = ModelCard( @@ -967,7 +968,7 @@ def test_save_vowpal_modelcard(vowpal_wabbit_cb: VowpalWabbitModel) -> None: @pytest.mark.skipif(bool(IS_311 or EXCLUDE), reason="vowpal not support for py311") -def test_save_vowpal_modelcard(vowpal_wabbit_cb: VowpalWabbitModel): +def _test_save_vowpal_modelcard(vowpal_wabbit_cb: VowpalWabbitModel): model: VowpalWabbitModel = vowpal_wabbit_cb modelcard = ModelCard( From 4fa5b768e0dd71507ba8a82501d8a504ad7504d7 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Sun, 15 Sep 2024 21:13:18 -0400 Subject: [PATCH 04/16] remove unused args --- tests/test_drift/test_drift.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_drift/test_drift.py b/tests/test_drift/test_drift.py index af860581b..5789559a9 100644 --- a/tests/test_drift/test_drift.py +++ b/tests/test_drift/test_drift.py @@ -1,22 +1,13 @@ # type: ignore -from typing import Tuple from scouter import DriftConfig, DriftProfile -import pandas as pd from opsml import SklearnModel from opsml.helpers.data import create_fake_data def test_scouter( random_forest_classifier: SklearnModel, - example_dataframe: Tuple[ - pd.DataFrame, - pd.DataFrame, - pd.DataFrame, - pd.DataFrame, - ], ) -> None: - # X, _, _, _ = example_dataframe X, _ = create_fake_data(n_samples=10_000, n_features=20, n_categorical_features=4) model: SklearnModel = random_forest_classifier From 1a0ba4d27bf1b2f44352947bc836a90389893c84 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 09:14:10 -0400 Subject: [PATCH 05/16] update scouter --- pyproject.toml | 2 +- uv.lock | 140 ++++++++++++++++++++++++------------------------- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 615f3fd11..279643da3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "pyyaml~=6.0.1", "rich~=13.3.5", "rusty-logger~=0.3.0", - "scouter-ml==0.2.4rc5", + "scouter-ml==0.2.5", "semver~=2.13.0", "tenacity~=8.2.2", "zarr~=2.12.0", diff --git a/uv.lock b/uv.lock index b7b397ca9..f941e0007 100644 --- a/uv.lock +++ b/uv.lock @@ -3012,7 +3012,7 @@ requires-dist = [ { name = "s3fs", marker = "extra == 'aws-mysql'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 'aws-postgres'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 's3'", specifier = "~=2024.2.0" }, - { name = "scouter-ml", specifier = "==0.2.4rc5" }, + { name = "scouter-ml", specifier = "==0.2.5" }, { name = "semver", specifier = "~=2.13.0" }, { name = "skl2onnx", marker = "extra == 'sklearn-onnx'", specifier = "==1.16.0" }, { name = "sqlalchemy", extras = ["mypy"], marker = "extra == 'server'", specifier = "~=2.0" }, @@ -4484,7 +4484,7 @@ wheels = [ [[package]] name = "scouter-ml" -version = "0.2.4rc5" +version = "0.2.5" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -4495,74 +4495,74 @@ dependencies = [ { name = "rusty-logger" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/7c/97181e0c128737b44058b736c43d4c538307742917c765580d4bde5399fe/scouter_ml-0.2.4rc5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:dcd720e30e9534f79c5f61443150e83cd1d7321cea2174dab8c80488063b4a28", size = 861258 }, - { url = "https://files.pythonhosted.org/packages/d9/13/9e5f2a9653a39718e403062c8ec1cfcb1acb980ed1c7f07a8bf5d1a41ea3/scouter_ml-0.2.4rc5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e59263e15d8e5f031a68082af98be445b0e1e003630b29eee49112f419c6f95a", size = 783267 }, - { url = "https://files.pythonhosted.org/packages/24/f7/4a49e70827dafb4367b062ea20efdba4be0e32b78ea8d78b909a9fddfa5e/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3a045b09420509796f31b1c6365d3cff0e3f3997e70d16ce323d1cb4226d0892", size = 887717 }, - { url = "https://files.pythonhosted.org/packages/cd/a5/78a84885c44ecdcb4fa0b375f4d3cf4389ebf3fc290bcb87ad411a7c5709/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b6ddab6eff5a33c1bb6eb02b587e93fdea590b7341ca3eea60071c552777c2eb", size = 805151 }, - { url = "https://files.pythonhosted.org/packages/23/9d/a857043e46b685ff40a851833830284a13891b7c8e1bad8e45c24b110bb2/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b9c1646a17fbcfd2ede10e5697a44bf55b5c3736bbc80ee4be7b1026a2660ec5", size = 822321 }, - { url = "https://files.pythonhosted.org/packages/e9/27/efcf03dc8e5d524b06f97c7e2dac7a7e14f6327ccc615d6f34553cd680c5/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e7d1b299b5e21f897487ef72e761db4f6bbcdbfe3f03de707e05ce6741f26e0", size = 958294 }, - { url = "https://files.pythonhosted.org/packages/52/1a/146a6b55a0f70fdc2849ab998f133bf0d076629ea19efab75cde366c6746/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fee760c450b03f0ae7593b3e43d655a3a3b1cb973083b5bf2e11e10375cee003", size = 1486737 }, - { url = "https://files.pythonhosted.org/packages/f3/2c/6f5d8c3d4bf44db3b7023b2cf02f33c0ce36c42644a79cec99c7f5367c9b/scouter_ml-0.2.4rc5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe8acad9a833c896f608bda0fb7e94b20ef47a384c6a64404062244ab274a71", size = 901828 }, - { url = "https://files.pythonhosted.org/packages/70/b6/5a87a0ba950daf78bbf9017ca46e2795561daefed34cb3f39232bf216012/scouter_ml-0.2.4rc5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:edf831faee8413935f793a56a17ec9b3d70cef5efac2cc8f14685396dc71d197", size = 974781 }, - { url = "https://files.pythonhosted.org/packages/e0/bd/5b6fadb6cc87925e20e619e3dc12a2b2e0eaab884192667ed98ea2908224/scouter_ml-0.2.4rc5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:726322cecaa3558172dcac145ef81cc137408b8c1940ab078dc0f22ecbc96ec8", size = 1062411 }, - { url = "https://files.pythonhosted.org/packages/84/98/200d5c27743e77e62422850ad6df4dbdfcb635046ac2779a284aa114db4c/scouter_ml-0.2.4rc5-cp310-none-win32.whl", hash = "sha256:76351728cb6360f0e13032426553d1b46d21c297c3aead06fd6f3d88a0815aa5", size = 762040 }, - { url = "https://files.pythonhosted.org/packages/5c/98/29be713f185cb92b586b1f650b1b1dbd2f341b4ffb5f9e6e62e43b960f1b/scouter_ml-0.2.4rc5-cp310-none-win_amd64.whl", hash = "sha256:63224d5791ee9d52fce84ebdbda5f17e6ed855bec6810a942bc84c3660d7ee96", size = 856771 }, - { url = "https://files.pythonhosted.org/packages/55/16/24b8f604aec04ed48574ea08cb7ed6f3bd5087aa7ff897c888dc93257b2b/scouter_ml-0.2.4rc5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3b2328ee2ed7b86b1ca259b1d0c2ae6e5c31585feaf2436891aa2123a7c731dd", size = 861388 }, - { url = "https://files.pythonhosted.org/packages/7e/33/fd0e336ec57e9f833583f13a268c18c97c6b9afd233c79a4715dacaf5b7f/scouter_ml-0.2.4rc5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1dcf36cdc8f1cbf3313540d58c002860a1a499c1ec6c1c5277c286f1f5c4df36", size = 783303 }, - { url = "https://files.pythonhosted.org/packages/66/8a/7a621bb20543d2236192d94da7411ddf0391aadc0e5971bb6fd60d237bac/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:98b5736e3da41596a1252baa6b660efc966aefafd7280e70b460e30317e1a06e", size = 887712 }, - { url = "https://files.pythonhosted.org/packages/29/b3/393ae3cbc74bfdbcb3e2358d7e372feb0e4fefa8cab06b77d352b6d758a8/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8177093d394a6739a077680b03bcee037b44cf32dadf09b8493f8e8ebc85d0c6", size = 805119 }, - { url = "https://files.pythonhosted.org/packages/f6/47/cbfc6ca833c8c8720c2b8565b61a9b60233b850355543bca386e6bea853f/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:397566f611e6ef7f97feae502d6076766668e665212aa9181b229db005f53ac3", size = 822423 }, - { url = "https://files.pythonhosted.org/packages/53/bb/1ba383fd9a516f22b05c5a25dca0eaa1a96728e8430c7946e0a8bbbbc5bf/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76451c17408b8181c26c4eb49f3e469a8196fd3b656b5d303ded515e622d181a", size = 958258 }, - { url = "https://files.pythonhosted.org/packages/ff/20/6a7e5345a15d58e831d960193025a34751ac1e483236bded6a3651388307/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e8a752b01dd479ee33be1b1badb84048c8eedaa092a9754f1de2d78ba8b3f13", size = 1486605 }, - { url = "https://files.pythonhosted.org/packages/63/c6/c3ffe13126603837310d213de5d7fd7607e6c6f9cd57c251160b47d79bbf/scouter_ml-0.2.4rc5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b38f5c7453a28fccf803da0c9ddf8b1f668db7e82fd6190dcdc341bf48c52fb", size = 901850 }, - { url = "https://files.pythonhosted.org/packages/d3/51/b4160075cd7669b995f178d127fbb5dc06e05ada076c9f7d50c39339e9c6/scouter_ml-0.2.4rc5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:054521ae3d3202cfac0753580f21e33221f025f29b61b979ea7ea40adca02857", size = 974644 }, - { url = "https://files.pythonhosted.org/packages/0c/47/27f0aa4598ffbb979d954b60ed0ff68c9ea14c741244159d70278aa122ab/scouter_ml-0.2.4rc5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e659ac256305693b6fa541cba0083da646cfc08d2243f8d93e9e9dd39fd920db", size = 1062543 }, - { url = "https://files.pythonhosted.org/packages/05/f5/f15a45a95bcfad159d1dc4718ea9182c2a294f3aaca7c3776d74411f7ab0/scouter_ml-0.2.4rc5-cp311-none-win32.whl", hash = "sha256:2795d46a709ba5330d648bdc5e9bd019d4a047c7eabd8ebcc0749611f6576242", size = 762050 }, - { url = "https://files.pythonhosted.org/packages/5d/66/679e845e6480e4e8e10cd045dfde5ecbe6db16d95c77cbe759045f1f2f54/scouter_ml-0.2.4rc5-cp311-none-win_amd64.whl", hash = "sha256:dcc955440c6e52f72d0490b42b927b5fb3cdde810f40deede0a0ceaed27b0cda", size = 856790 }, - { url = "https://files.pythonhosted.org/packages/83/d2/662a7e15c167f492e1bf8e37cc150895fb396255863ef3ec70a465e8bc3b/scouter_ml-0.2.4rc5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:64687f2a165fcaa4f8dbcc1e031410da43bc761bc6beec3fea29b4db3fd5d8a3", size = 857964 }, - { url = "https://files.pythonhosted.org/packages/90/27/044b88977de66d580dd8c411f40d117728ad31021864c8f9b1a95871798e/scouter_ml-0.2.4rc5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:97f6048536eed1ce4432bc3eb1a3002d59882e69921a72d11ae3ff3e7b0899e4", size = 782039 }, - { url = "https://files.pythonhosted.org/packages/90/ab/c2f21353b99a3ebf855b17597099d8236d6c77194409a45b2c175b483110/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7fc2f855774b2d492840224c19d6189a144199d85936790de9cac7ea9ae218a8", size = 887614 }, - { url = "https://files.pythonhosted.org/packages/76/51/cdc5e4f658e401dee6acdb68aa9a5fa9b444182619d7406d8e8e7616bb89/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27562f18d59fb016be4591d2fa271c26e74593ac0172ba5e2648bae43acae499", size = 803144 }, - { url = "https://files.pythonhosted.org/packages/68/13/93e378cc2dac7ddcdc82e97aa9a040f9969ea466271a79ab5195aa058dbd/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b41a80e69e316a6fd84ebaea20962acf93dd9242d092371eb062d8a887bcf887", size = 821499 }, - { url = "https://files.pythonhosted.org/packages/1c/63/23ada3dfb9f9c05b42b967b090a2b222821dec2d50b8ef1ae87c6fef4823/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0b430672f31426baa2b75bd18424fb2ab71ad7476bfe0636a8648df44863eac", size = 954736 }, - { url = "https://files.pythonhosted.org/packages/a3/62/78c8d341fb4ccbd8cb2584bd9607676b2b6f3224d8d1a6806556f5732f50/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a7fcaf230f7688c0c214558821813b60a790b45112f3f0357bcc8056d5ba24c", size = 1452535 }, - { url = "https://files.pythonhosted.org/packages/09/33/7a53a1eace84d4370f6e249917e5557471cb9c712faaab974d7909b5e343/scouter_ml-0.2.4rc5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4e25ee147eb47accd56334602f13423b6c129603d7f2828dec99bc437496b6", size = 901483 }, - { url = "https://files.pythonhosted.org/packages/34/bb/17f00e2d3324f4c535fe8c983af07ff6769179f617921e46cc2a2869c97c/scouter_ml-0.2.4rc5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb175c2dd8788dbd952f1321813417776cfc221351dd3e544fd044034e5877b9", size = 969199 }, - { url = "https://files.pythonhosted.org/packages/3a/5a/df89faf243ccf56a3900dc55b2a7616cbb1faaacb8f3cbd8d509a342782a/scouter_ml-0.2.4rc5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26f7e8251fb19544f583ab4773364236ed3fc98734db67640dda1f6157ac1377", size = 1057058 }, - { url = "https://files.pythonhosted.org/packages/01/a2/dd46ce91d250359dceb38ccbd67825a726621c73708ec510064951cdad32/scouter_ml-0.2.4rc5-cp312-none-win32.whl", hash = "sha256:b91353c834fa117b8e1390832b817fae8df455e726e1482b6ec7a52485714bfd", size = 758287 }, - { url = "https://files.pythonhosted.org/packages/7e/da/1f13c39b760fb5ca7956792a1781c67c0e5b6abebd0394676bb6c86e5df7/scouter_ml-0.2.4rc5-cp312-none-win_amd64.whl", hash = "sha256:a7c7bc3905f6c63b15dd670dd30b1b8759e2cd9196de07dcfb374f1e01fd1501", size = 853272 }, - { url = "https://files.pythonhosted.org/packages/a7/7b/c7bad5976ea8b270f669b53d7ca33c6f33bc99a6f0a4fbe53ca8927aee84/scouter_ml-0.2.4rc5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:771354a43f63f5a69fd203b63ccd5ac8a8cc8743c41c891efe4ea6ef89fd4712", size = 861618 }, - { url = "https://files.pythonhosted.org/packages/f6/d6/276e3eb95e8dfda32088beacbae5c27b99abb057568ffd2db44fe8805ebc/scouter_ml-0.2.4rc5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d0b925c342ba413e6e3bdb4dfa7369ca83576385752d9b94c28490b3d421f0a1", size = 783817 }, - { url = "https://files.pythonhosted.org/packages/1a/c9/73890b1942d7b9c9b8e35dd05588d59b69a98ce4ec0f7ee711964f2cf468/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:16821f876e5359699691f50956af7da50908aadbaed069f50322a36e36f9df43", size = 888256 }, - { url = "https://files.pythonhosted.org/packages/93/90/e5b011824b34329c29ddb6ed2f3aa21fcc6243841b9641a16daa2c4e6573/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36d7c8248827c8aba860ac2bc038e956341f3be08b75a8a7eedd24682a98ac3a", size = 805624 }, - { url = "https://files.pythonhosted.org/packages/c7/84/d4a0450a81c25107abc92da24adf7e978129efe4a0e63d9f6e995af39cb6/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8046f6b5b71b99837527237f484586714952a2895031bda311baa787c7e6ae", size = 822657 }, - { url = "https://files.pythonhosted.org/packages/d4/62/b6aa7d8547443a15e1078f6057ebff1a40fb7b702a531438918fd0052183/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:721ba7a844cb9415ac3fa4cb7b214eadbd1296708831c477cbdd19c7c2428828", size = 958883 }, - { url = "https://files.pythonhosted.org/packages/f1/80/d0b5b122c3519cbc63b73ed5a9197567272f86f27c5a31574f8399a9334d/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4679a070cdb38374fe1ead8dc65aa880d93da6607d2518c49fda6f2333f53e12", size = 1487536 }, - { url = "https://files.pythonhosted.org/packages/53/1f/919feb1524d390d1fabb988e81deb2e268085d4d5ff3f0c0858d531c54c2/scouter_ml-0.2.4rc5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a817bd5273692a98b610bd49aa6e4cd47bcf4dcd3a19be20c259d12078f9048e", size = 902256 }, - { url = "https://files.pythonhosted.org/packages/4e/b4/78da541bfca1ee7fbdeedc74ce08281156fe1ac16736a43e3dea7fb1856f/scouter_ml-0.2.4rc5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c83cfa6d11c31463add75e3a6f78a0532cf24bfcb9838e90dcde446245c82861", size = 975236 }, - { url = "https://files.pythonhosted.org/packages/16/a4/492629f406a30aa38f0113da2469ca465fe4542dda7ce18a7f4e9b0da5d1/scouter_ml-0.2.4rc5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f755a3d63947e47e9e8becf6a78832a071add5f92372c656b04fdc98a50350f1", size = 1063020 }, - { url = "https://files.pythonhosted.org/packages/e6/84/17f4116d688eca0334464babf305c2a337c2aa2346d1fb8ce7630cc60784/scouter_ml-0.2.4rc5-cp39-none-win32.whl", hash = "sha256:90f92eb5a3371b39f071ea8cc6b2b555dfb0bb09f0f90eed09662af5b3e8ee51", size = 762368 }, - { url = "https://files.pythonhosted.org/packages/45/a3/4c20629d2dbe9b8ba0a2df9cb299e77dc1bc30868d79e6452fed2e669caa/scouter_ml-0.2.4rc5-cp39-none-win_amd64.whl", hash = "sha256:1bff99fb22acd52c9bf334e903f246f4a336c37352d0875a71d449dbfd1c87ce", size = 857106 }, - { url = "https://files.pythonhosted.org/packages/9f/74/1559d497a0dd4f97c6e9bf1c016cfa8eb08414624bc06fb840c3b2fa0a24/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:751f21f400fcfc6eee48b22af21d59bbb0b81d0d98dc498c95c5d6719b56b7f6", size = 859253 }, - { url = "https://files.pythonhosted.org/packages/91/cf/20effb01deab7d6740b7d8b79c14086c216994b500791698209834d14886/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:31c4f8be7d4186d5ed70dd51435a240c7d425f9e68103ff318bab798f8afec5e", size = 781389 }, - { url = "https://files.pythonhosted.org/packages/f7/1b/02686c76af40e781580ec6a4ddba46728b042d72529e7ae25fce8dc5ffdc/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:946c33cee8a29b84549a604b98abd7e03cfdfb2ae96bc5884448fa4ae225c788", size = 885460 }, - { url = "https://files.pythonhosted.org/packages/9d/cf/795d59a285fbdc046de3897046b076257c7983215402fe45d253ad866a94/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d2e7c97779cc4e93c76dc73fe1f598a1915f64612883c2e5dfa967c5320665a", size = 803188 }, - { url = "https://files.pythonhosted.org/packages/48/9f/6520bbea9a75ee0ae4e5085d94c775cd49c45cc4f6fe71718ef75bf47b14/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:364e0881cfc14d3086afa6331a3a15f4c7796eb18c2c362711fa2942d98e2d8f", size = 820194 }, - { url = "https://files.pythonhosted.org/packages/01/cb/b918823a3abc370e2dc82e1e6c9b3db5bbabeab0fb41dce55e1d133cf9b9/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67441d41dfc6c94f205cfe0f99f91a42753027134e72fd34597852fbb1c10c5d", size = 956092 }, - { url = "https://files.pythonhosted.org/packages/fc/5c/d73611e73ae689a76497864fc6d3ce7d1efd48f5fb8d9ba17fc23c2b9f9f/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:323a4d24277d2e0dfdd8ae5e536cc356b3a2b7c4819f8aa8027c5c04fa686741", size = 1476078 }, - { url = "https://files.pythonhosted.org/packages/0a/26/c44cbbd699e7be0d79c7fb9aa0fa16dd119c5124772d0380664424e31c53/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eda0a5b5f597595f05b00fe59c6cf438f38103f6b167321fd1c3d14cbf9f9002", size = 899757 }, - { url = "https://files.pythonhosted.org/packages/99/1a/b2aaac0df76b84f98f6975a6a1c0ff4f325f527d28a20b93588aa52955ff/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b943d62fe3ba896aed6256cd9d2afffeb96e57d4810bb55a6bdae8e1ff269505", size = 973976 }, - { url = "https://files.pythonhosted.org/packages/4c/c5/e7e6c3f9099dfbfcc8b0725e48742d30b824ab96cfa8bd5520ee2da3af52/scouter_ml-0.2.4rc5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2e2a5589d7afae166bce5230e35f4394d2f3563b494e40228a93dfee556a56e0", size = 1061243 }, - { url = "https://files.pythonhosted.org/packages/52/83/d15e51f45271ddf41ef3e6f12bbfc3c806b7d96e9f49b07a61e44d40e6f6/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d80ae86c76f75a83a0db68954cc79473c2223877cf1feceebcab30da5e174f68", size = 859777 }, - { url = "https://files.pythonhosted.org/packages/8a/28/78f0694a5af424bdc1ee9aca1fcfd2794ed8fcb3e2213576a9b36f85de1b/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:665dcd6e31f9e0a14e161b8b6f96b495080a1add466231cfa12a497cfe99123d", size = 781809 }, - { url = "https://files.pythonhosted.org/packages/1b/c1/4a16e1985f7599458c9076b2eaf731454dfe19d7d24bd25d7abb425f93d5/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0a2242018d6c9c9b1e5e5666b2eaad9686b05dccfb169a2eb57baaf36052a096", size = 885893 }, - { url = "https://files.pythonhosted.org/packages/95/6c/f672b3a08192eceb1061b8b380ad861391160a4525808df17d8ea77e5ae6/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50389951af5cfc3881f3c5eb68d7782a0250c79e8cdeaaad4174d9b140e75cd6", size = 803713 }, - { url = "https://files.pythonhosted.org/packages/2d/c8/6fd4fe4410d94d49842e2e3393574608085f83a5bdb7c65569bbae6076dc/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c1256f229ec628e5167fea1abd18ab76dff8f76d27e24538966c27ad70a8536e", size = 820631 }, - { url = "https://files.pythonhosted.org/packages/0b/15/efb0974278324e7dca8f3879edf4e5ecc3fa084b427590c11b7a29fe130c/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03bf0f0298fecb750dcb9037a70a41a7d098bda2e11ecf4bc4de7760b1689038", size = 956949 }, - { url = "https://files.pythonhosted.org/packages/60/e4/b394268a94bd40951b7cfad4917b9d61aa24de4fb9d6737a1fff5ee808df/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a154ed9c7e8e265c90c6e4d6b575c449dcdadb462f296c1c293ddea8419db62", size = 1477782 }, - { url = "https://files.pythonhosted.org/packages/ec/32/1e4fc166a8df8c120b0ffafdb16ab2055a3b0020d0d0585b697c801a02e0/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:350006ac622e147bc829b0df8ae9185fba29829f38920ba7092d762dd20430bf", size = 900186 }, - { url = "https://files.pythonhosted.org/packages/4c/d8/e9eefbbad1b097786e04827272cf20d367374e8fff9fc5af362d61600414/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26061ab9568cc1fd120bf87200ffb8bb1087e568bdb5bf748eb5488d46ba0844", size = 974539 }, - { url = "https://files.pythonhosted.org/packages/78/c1/6d23a2d7799c18a95f18321c27c57e4dc4b9654e8d6a932ef144f8b340ee/scouter_ml-0.2.4rc5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8087e7fd1c165b5a6e7650fd1570d530b84a36973c865491e6cac802fc3a2727", size = 1061946 }, + { url = "https://files.pythonhosted.org/packages/f9/ce/28d770ac623537afa15e243c8d8ad04256a36aba6d64eff7512c9aa8c29d/scouter_ml-0.2.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a843372ec123c9b5675fccc41babb7374ac647bf87076cbbda74367079b9d228", size = 860913 }, + { url = "https://files.pythonhosted.org/packages/44/02/247cee95fd8c7507b2817c856bfe65fd7662ba2164f41f5e32b2afc1dcdf/scouter_ml-0.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:374d083e5ac80ce3c575f10116f4312b1e3f20f2d61c3774a61690d7838f1bb8", size = 782632 }, + { url = "https://files.pythonhosted.org/packages/6a/aa/6d90b91846ac86c70ee4964319e9b2ee7e02112c1f0c3cb06903f9f03f2d/scouter_ml-0.2.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d2e63597cfb299a191c98293d9473f0d9ec32c86458399584fdeb0a99130bdf5", size = 888504 }, + { url = "https://files.pythonhosted.org/packages/3b/09/3d20025812f0673d9e51bd20bab2efff989d80dd88a1fbc6f28654aa9394/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e2daef794fbd2a546a1286ca40b9456cbbc49ebce457822a38002d9ee602970", size = 804922 }, + { url = "https://files.pythonhosted.org/packages/c0/67/b31ba21172a7377a08ac6ddbeb5f3eef393b5781cc7bcb8b45ea262ac14a/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:93d621f65f310e2307359e1c9f43db5ee556a96865ab62ee76ae6818b217c45d", size = 822248 }, + { url = "https://files.pythonhosted.org/packages/d9/fb/ac6d15b8e33fc6201346b2b826c2f3808121784c6bba2bd04a3b76b320c6/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f13cf477b3f17c8857ad545c00bc8dd815d57a159b5cd07168ecc4f18fa851ab", size = 958087 }, + { url = "https://files.pythonhosted.org/packages/d5/ee/d208f50eb02dac49e34e5adff29be37ef7661e413a4f5fc28cf723f63d39/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7ddf5e642876488f45b20f43240c2bd7bfd2a3567334558486c05320159e684", size = 1487497 }, + { url = "https://files.pythonhosted.org/packages/06/2d/b2a0478d84f659593421c860d5f5ec32f0c5e9dc11a4fab893b02a786913/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d77fecbc9896e9f318e0503d3551369bb059e0e4c3409810d15d6a128c8edbff", size = 901660 }, + { url = "https://files.pythonhosted.org/packages/8b/14/5d06540768d63d5e7cb404c645a2976945c8bd7edcaf2c682b2883d2de5a/scouter_ml-0.2.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9f7db6e88ec74e2ef31108c65c9e2ff3bfe5f48ca11a4244ee7d9fa47e4a994b", size = 974445 }, + { url = "https://files.pythonhosted.org/packages/84/32/7859555ca0edca10270a3888dba6a8a9ac352b55602a1bf2048dfabed692/scouter_ml-0.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5ad867a81ec33877c9119e051c993523b2bbaad22d2424fb5a8918dc4467e865", size = 1062511 }, + { url = "https://files.pythonhosted.org/packages/c8/6d/1e3e018a645663d632797c539ae07f846ef0bbf37ffbedb4271ba2a11c40/scouter_ml-0.2.5-cp310-none-win32.whl", hash = "sha256:1ac839c524c22cb8bbbca16ede4b63f08d1b3beb1826562a09efd2a8fdd205c9", size = 762351 }, + { url = "https://files.pythonhosted.org/packages/9c/8d/6329eee0c1965404775eabd34e68524127a23ece975ff0eb2a7197661485/scouter_ml-0.2.5-cp310-none-win_amd64.whl", hash = "sha256:0103fde40539656b678d44f1cb1ae937a07544761da98208f7839c5b9f99fdc5", size = 856113 }, + { url = "https://files.pythonhosted.org/packages/a5/4d/a5499b24877e46f1fb86121c5fd55f460442be7509c35464cc65bf8e6533/scouter_ml-0.2.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ce328dc9274630dffe90aa151451ac9d9d9ce24977a94230038d4c34a1252cb4", size = 860996 }, + { url = "https://files.pythonhosted.org/packages/eb/ff/10336a0f8806b7cadb4b6f04f21c73b6887927cbdb0d3077ab0111031661/scouter_ml-0.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff773f040bdcd3807bd1d53ef0310630b7f6a6d91cf4ac8063b2a4aff09cbd37", size = 782736 }, + { url = "https://files.pythonhosted.org/packages/32/53/618f11ba5a8accf2b91dc9031ca11c8ed3458260ec61b571c567198715a6/scouter_ml-0.2.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a86d31be60aef498c2fa6b4dcb6972606567f44879ff083604d925ea67ce2461", size = 888531 }, + { url = "https://files.pythonhosted.org/packages/18/af/5795d8abce5cf3bd285cb35708b514982bf1818d3eb37eac20ead225e074/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dcfc2fa756f42bd624fd94601f5b11a23cd5c7356145caa72801dd612fbe7cf", size = 804978 }, + { url = "https://files.pythonhosted.org/packages/9d/20/faa4d51ebbe716bed6dac56f6ccc56a6a2e4adb29adb44bb5788882438dc/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e587f3c7af1853c586235a97b3e7e64ce745985aa63c65137003bd3e959085c", size = 822324 }, + { url = "https://files.pythonhosted.org/packages/05/c5/ca4fb553b8bb17a4659e5adc4286475d6b2fd4ebecd6fb70e8a690004bed/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b7a0792209794069eb1a238fe979f8273a4310ebc205f3870aa3e7b1cca84d3", size = 958080 }, + { url = "https://files.pythonhosted.org/packages/bf/f6/01566eac5c6f624dab05cb44c42fef349d82cfc65b5250279fc7e5ec23a0/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68bcaf1a6faea8d8d8c9045011ac49c9042ad65169f92644ac2605408a7dce1b", size = 1487451 }, + { url = "https://files.pythonhosted.org/packages/ef/1f/776dd1101bb5d33144b66c273212afb6145da7ad4432aa4047e6f5d5a443/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad74ca7d8537ed5b4a383f9fc7d49c30ed830b4bb947b5183117678f3cb3e3c", size = 901670 }, + { url = "https://files.pythonhosted.org/packages/7e/58/896027d505e4c569f81aa04d7fc5f75fd3ffb6f573bf785beb1cb61bba8e/scouter_ml-0.2.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0eb884f84a3f755cea74b00a7a723d824265e06a2b99b6e07a706407d0029e18", size = 974505 }, + { url = "https://files.pythonhosted.org/packages/53/43/10cc2db494adfe8f7e429dc8b52f8d76425f65058ce97cbf8231bebc5471/scouter_ml-0.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f064363b287c9b97e080244b49b55267aec4a89632eb9fb62be74c87b3ebe84c", size = 1062507 }, + { url = "https://files.pythonhosted.org/packages/54/4a/e5d2e059b5ea0d151ee8d6b67c7a229bae9f7de8a9f0efe492264106f05e/scouter_ml-0.2.5-cp311-none-win32.whl", hash = "sha256:590b9cde04650d853bc28eec5908d160402a01ddc903febca38edf1231724684", size = 762169 }, + { url = "https://files.pythonhosted.org/packages/1c/4a/7867c2ec44522ef4ed2871235dba78fb60a202858896ee6871a5a636e0e3/scouter_ml-0.2.5-cp311-none-win_amd64.whl", hash = "sha256:2c6c5b9ffecacad6b2ee28c60586c50c66bcb736ae867120d595e259fb705453", size = 856108 }, + { url = "https://files.pythonhosted.org/packages/33/3c/5eabcf06a79e863b4a8574c6651154bd8b07f152de62a8d813534eeccf26/scouter_ml-0.2.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d7db3dd3fdb65479ce368185aaeadbc21ee835933f299bd404628348c72c3bf1", size = 857493 }, + { url = "https://files.pythonhosted.org/packages/ac/ec/165e205792ff54c33d5316437b111b46597ace63d0cf3660b419d7e55520/scouter_ml-0.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5cb95a3fde44ebfa75283584e3d04666db991eda9ec8297167e6c56935017db", size = 781394 }, + { url = "https://files.pythonhosted.org/packages/cc/17/f5e61e5cbd4cf622b70282af49881bc98b3c333f8008126e70c3a3369be5/scouter_ml-0.2.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1a171e2dda3d666b927abc1afc1dcd4e8a52fb9a08b5212ce0cf362a47f04103", size = 888545 }, + { url = "https://files.pythonhosted.org/packages/b2/76/9574c2deb4abb501b6fb2152e8147850ee310c26bd3605732ac371ae46cb/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bb5241f89a85ca80d23d4b15dec404b424c27a55e1ec5ecb5d2458ef291e095", size = 803001 }, + { url = "https://files.pythonhosted.org/packages/7d/28/a23cd52f90d07fba0a6afecb90b37b2c1bba750d9fd18a944f6b1af66ffe/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a5de31aef269d30d45dd0105b0ae530073ded7ee9929d944f094663a553496e4", size = 821165 }, + { url = "https://files.pythonhosted.org/packages/65/ee/a735d574022794a4d2dcb7364446ef4b615fb34639b5a1de12f6ddcb40f4/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4c46d3b599f45987690ba1d0d09e12c8ea75a9ea4560c007902b5ca1df9aecb", size = 954082 }, + { url = "https://files.pythonhosted.org/packages/82/68/7a1d3e12337cc3ebde4e847de0d33c3378b170992e57bb6425db7a5a39a7/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1db90ad47313c5225156994de884828cd11c646cd802cc4544721ad8f7c61eef", size = 1454134 }, + { url = "https://files.pythonhosted.org/packages/1d/67/04c1ee74c07498f532ff678ff98901ab7cacd360bc14ad6e219d0013bc90/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bc862d21be89c2926d95eae60699f8cf525423733a8f4e6638bcec8ba58817e", size = 901201 }, + { url = "https://files.pythonhosted.org/packages/37/9c/9b9e037b5a967dd14c64edce37221083202ecf0efa76de6f0ba881b3da30/scouter_ml-0.2.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:043929eeb1816c50acdebe601c32c56fa0052845b8450a8090e637c057a5b103", size = 968970 }, + { url = "https://files.pythonhosted.org/packages/6c/fe/efad8ba2c46844c9891dabb8fc7600ed72b89ee0e450ba39b871e29884a7/scouter_ml-0.2.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5d37103cf41b2262dcaf8d038a9599b2adc2ea677824c8fb256f97dca2a77b75", size = 1057204 }, + { url = "https://files.pythonhosted.org/packages/34/d9/7afbb197e55375d3ea7c134bd088a3ccb47f02c342583fd9225552fe3eff/scouter_ml-0.2.5-cp312-none-win32.whl", hash = "sha256:e3abd72651e67871f71662e52e8cbcbd01dedece49efecece2f4fa273d542496", size = 759005 }, + { url = "https://files.pythonhosted.org/packages/8f/06/94c7237fdf53a79326ce197856654a6d14eb62a121e28de5ee37d886f0f3/scouter_ml-0.2.5-cp312-none-win_amd64.whl", hash = "sha256:308aa1c5cd113ec7f8421fd85d837dc53449cebcf11b69394b9a9142c9401d96", size = 852476 }, + { url = "https://files.pythonhosted.org/packages/88/e2/6dec176afee997a2fb67a86b371abc3a338f072cc840ef681e036e6a78c4/scouter_ml-0.2.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6f558294a89ab4e3f50a50966048c233c4850e1825efc86637af6734c933fdc8", size = 861263 }, + { url = "https://files.pythonhosted.org/packages/08/85/69d1e72fd7c10d80256fe47d2c7d94dd03dd6ca45c1e6a8674f859d8a2b8/scouter_ml-0.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a98d2d91bbd7faf0f69b0a1540739d3bae3cc2cbff11e29a5fd57a54c5784e", size = 783144 }, + { url = "https://files.pythonhosted.org/packages/3a/c7/a164e9d0fff3ae5245764579bb51cc69ee441b20d1ecd302338cdc7e4a17/scouter_ml-0.2.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:86e3f87e8cdea7c1bbc83d9012452708cf340a41deb6a96bd5ba043ff90c0018", size = 888938 }, + { url = "https://files.pythonhosted.org/packages/80/b8/f64c259102f785fb0e54e45107100af9b1edeebbdd42e280088b6d1c9e56/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:852cd800b1b2f366b2fe5586d7355d723433154d09bb4ac57e2f346e3acc84d6", size = 805341 }, + { url = "https://files.pythonhosted.org/packages/1d/c9/710842dc4d42651cc64886fe611f3a105d546d3167b03186abda9a68587e/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:838f71ec62520ce6804a3eb2a0718286a11eadb473e77bec2756c84543c0a90d", size = 822702 }, + { url = "https://files.pythonhosted.org/packages/c3/b9/6b4ea6176c39a047966491c176b60236f64b8c95499d1ed7012452bcd0d0/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:efb9fa6b23a7c1fb3152cd7a56ec8ae31eaeb788e1b7ea92d36aa2a1d7b9cdcd", size = 958569 }, + { url = "https://files.pythonhosted.org/packages/05/10/85a6af5ddf6c9d19766cb46526fde35cd126dd63810c61494ce6270174d5/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9976503b0793789e2dc6620a543a9d386a178cf5f47c59aea935fd78be7bd2d4", size = 1488392 }, + { url = "https://files.pythonhosted.org/packages/cc/52/b603f7e7fd820575a77067e641a4bbf3a93f2caa956e9f6f740d82a95a57/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bde24ac2ccf9001598f69723141b3f0710ebf4c42656f276fd36317419f7bef", size = 902206 }, + { url = "https://files.pythonhosted.org/packages/6e/80/7d5b9ff9b9e62a4930da21c182eb57dc71f50858d86a0529c3c5ef810c6e/scouter_ml-0.2.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6673e90d752d71ecd1e3c0050f82e66fb34b2956752e04a94b339d0d7d12537", size = 974961 }, + { url = "https://files.pythonhosted.org/packages/b4/12/e464eb89efeb8aa9204ef4c62bda6a0bcc7f32fbbd19f91cda14f7d24814/scouter_ml-0.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ea347ae031a90fa4cbf43cc19604a46d178323cd9c9cf245a0636d70993e1ca", size = 1063180 }, + { url = "https://files.pythonhosted.org/packages/61/2c/3e739ca58aed3e2c0107ce2b7a17b7587c16ee69980237e18c3a487249d2/scouter_ml-0.2.5-cp39-none-win32.whl", hash = "sha256:e1b143f60f3a84145a79579e7afc33fc90217969adc40adae7ba7a520fdc1238", size = 762797 }, + { url = "https://files.pythonhosted.org/packages/ba/4c/5ef7542e8ea1f8ed666fb23a2a1d3daf96c8186790a5fff52f545cd4c668/scouter_ml-0.2.5-cp39-none-win_amd64.whl", hash = "sha256:b749fa9714d2f655ca38d6383cabf1548042b84579f9cbffac62f32e4b91f1e5", size = 856562 }, + { url = "https://files.pythonhosted.org/packages/65/a0/d7ba23eace465da2ebb1525ad9168c67f4075bf3c57ea590f8d8543f5a63/scouter_ml-0.2.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:057540d4229b5e0a37d27245c1700392f4b9653df0cbec9218592f2e97589cef", size = 858966 }, + { url = "https://files.pythonhosted.org/packages/af/99/c13fa8480452f0f0fb4d7c504b3d51342e4c747363813fab3ffb9bf916b2/scouter_ml-0.2.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0864348a59937b2d750ec2d2d47ea9b4e3308949ec5c1a0d32c6a30e9080c62e", size = 780892 }, + { url = "https://files.pythonhosted.org/packages/66/c5/7b02ddd4c0de7d76f438490d5060968481df25c7bb97aa788b0f2b20de14/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e5b88bedc68b2f6cf96ffec756d47c5283a5eaa9031a8b4c30806e8728d714c4", size = 886369 }, + { url = "https://files.pythonhosted.org/packages/6e/b3/76d96993b16869c218e898c36d0f27cf4d81cf18b7f1be5ced7943ad429d/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d5da688086c812a9aa38fb0f8d5c4a4f53ecdcf6e9fee2dcf96936ed35749ae", size = 802816 }, + { url = "https://files.pythonhosted.org/packages/d9/e6/73be2bd9511144f304f1cd20291685017d77df78878f9ce1ed8befda9155/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8b776128efcca1d6a8150c70d216f9f934ce6355f44b18e02f4f98cd6cd0288", size = 819887 }, + { url = "https://files.pythonhosted.org/packages/18/86/924d51e02f70a83430ae8d36cd46616cd0f1f771455b57707943529414b0/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b1ddcadcc0f06a2d4cddabffe77663362dbe4ae4d04cc28015598a90c4c4663", size = 955617 }, + { url = "https://files.pythonhosted.org/packages/12/70/401b994030532a0bfdec9760289566f4693af1f43fcbaeb9814f3cb8b07d/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fffbb46d9ce273d60fe905f0b2688c875111de1a512db6b71e74047b2b39589", size = 1477186 }, + { url = "https://files.pythonhosted.org/packages/c8/fc/9657bbe138fca5b439384c3d8abbf3e3bc4d768413805e72ce5b6f81eb06/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09ed76e898bc39f8a7d7d93dd058251bf1351832d3a96527cc6dfe443bdb8ec", size = 899540 }, + { url = "https://files.pythonhosted.org/packages/0d/01/184bcced12db3fa0e9ed9618b528af076c456a63f5dad1ae0bea0dc5d818/scouter_ml-0.2.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4fc06a8647e01cf92cb0be780b8c04b4ea64495f68ed924a6b993e8b7476e9ce", size = 973625 }, + { url = "https://files.pythonhosted.org/packages/70/eb/82e0672fe22aaa6136a214ce1e9069ab090cafff75530cafee823adefdd1/scouter_ml-0.2.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0ef5a240625c166c940551bf45ec8992709279a7181f8c8224ab95571eaaeb4f", size = 1061340 }, + { url = "https://files.pythonhosted.org/packages/a0/47/febeb4a258616edc5105a29dcfb3eea52e9a916de04a0ad9d62a2389fae0/scouter_ml-0.2.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e2c3aed8b8ac912b534beeccbf579eabb60ef787b7c576f1a42423900cd04ab0", size = 859518 }, + { url = "https://files.pythonhosted.org/packages/4f/1c/979030047f20f54101be585da9ccb97fe7888789e805d7a0f8323d30add6/scouter_ml-0.2.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a70d2c7d7fc183f619c81a986ca5441c5631f30caf415322cbd326e7508a071b", size = 781352 }, + { url = "https://files.pythonhosted.org/packages/05/88/00a61d67c688157ec9b82a1480153e006a210e54f7898b1a602c13510ad3/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cc4193225d50f4b7413a00beaa0bcf5496bf1bf96bc7a3a9062b59bf2db8e195", size = 886776 }, + { url = "https://files.pythonhosted.org/packages/8e/ab/51e33e5c0153cb19e30566b8be9af0ba7659c9e5fb1243beab34440efa84/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ef771878df0c3f7f89731a108c0e83f5cf7d7588b1ff4e86b022adb75e1656", size = 803357 }, + { url = "https://files.pythonhosted.org/packages/74/3e/bd6a3ac18ef142a4dc9ec4f6dd5a636023ac83d40dfdccd6e0876245b903/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74083de180cafbdbcc605582fb38136c184a9f3922e2c5a5a443401d7755caf4", size = 820446 }, + { url = "https://files.pythonhosted.org/packages/69/22/61579aaec8f313f6f3050d7527099c81a89238c9d4e232888be876f292f8/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a1cdadca01ff3c87c36547b076805cc8cdc6657cba1773e4fb8e2d18f5957a7", size = 956168 }, + { url = "https://files.pythonhosted.org/packages/83/11/36bf1da8a00554ab68e47edb69526d1f43d525ef18df21505a8b16911b0b/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:676beb05ad212c1698c85755adea6c85ac90526d78e1c81ee690bc58ded2106e", size = 1478820 }, + { url = "https://files.pythonhosted.org/packages/19/66/c6939250c44d209ae2f0e055516037e8d253bc859ba025dc582982b4cc9f/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d82cc955f21057630a497651dddac4088817235881556d5cc34b729144acb40d", size = 900289 }, + { url = "https://files.pythonhosted.org/packages/7b/ec/3869a103ff041526db8db21f182f4fb59ee95d35504b8ba6e6a9d79c55c9/scouter_ml-0.2.5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:acb44a7a499ddb99fbc8f5902ffe5fc0c355bdd6f688ef2b8cd396d307e4a766", size = 974405 }, + { url = "https://files.pythonhosted.org/packages/49/49/936dc4a777e8c30576bffcf1da15340cb44897c351a8a26c4be1703859b9/scouter_ml-0.2.5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43e5e01d596bd1330a4f232bdd6b8744acfcd04bdddf4a7e7465a8d64ba9ba41", size = 1061858 }, ] [[package]] From b8fe32a9e349dea4742b59574d9c4679665ca900 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 12:14:56 -0400 Subject: [PATCH 06/16] saving and loading drift logic --- opsml/model/interfaces/base.py | 26 +++++- opsml/profile/profile_data.py | 4 +- opsml/types/extra.py | 1 + pyproject.toml | 2 +- tests/conftest.py | 8 +- tests/test_drift/test_drift.py | 21 +++++ uv.lock | 140 ++++++++++++++++----------------- 7 files changed, 123 insertions(+), 79 deletions(-) diff --git a/opsml/model/interfaces/base.py b/opsml/model/interfaces/base.py index d05f6a7db..248eab65d 100644 --- a/opsml/model/interfaces/base.py +++ b/opsml/model/interfaces/base.py @@ -347,7 +347,7 @@ def _prediction_data(self) -> Any: def create_drift_profile( self, data: Union[pl.DataFrame, pd.DataFrame, NDArray[Any], pa.Table], - monitor_config: DriftConfig, + drift_config: DriftConfig, ) -> DriftProfile: """Create a drift profile from data to use for model monitoring. @@ -356,7 +356,7 @@ def create_drift_profile( Data to create a monitoring profile from. Data can be a numpy array, pyarrow table, a polars dataframe or pandas dataframe. Data is expected to not contain any missing values, NaNs or infinities and it typically the data used for training a model. - monitor_config: + drift_config: Configuration for the monitoring profile. """ @@ -367,12 +367,32 @@ def create_drift_profile( drifter = Drifter() profile = drifter.create_drift_profile( data=data, - monitor_config=monitor_config, + drift_config=drift_config, ) self.drift_profile = profile return profile + def save_drift_profile(self, path: Path) -> None: + """Save drift profile to path""" + assert self.drift_profile is not None, "No drift profile detected in interface" + self.drift_profile.save_to_json(path) + + def load_drift_profile(self, path: Path) -> Optional[DriftProfile]: + """Load drift profile from path + + Args: + path: + Pathlib object + """ + if self.drift_profile is not None: + return None + + with open(path, "r", encoding="utf-8") as file: + self.drift_profile = DriftProfile.model_validate_json(file.read()) + + return self.drift_profile + @staticmethod def name() -> str: return ModelInterface.__name__ diff --git a/opsml/profile/profile_data.py b/opsml/profile/profile_data.py index 2f39c03f4..9b030da95 100644 --- a/opsml/profile/profile_data.py +++ b/opsml/profile/profile_data.py @@ -25,8 +25,6 @@ def create_profile_report( data to profile bin_size: number of bins for histograms. Default is 20 - features: - Optional list of features to profile Returns: `DataProfile` @@ -47,4 +45,4 @@ def load_profile(data: str) -> DataProfile: `DataProfile` """ - return DataProfile.load_from_json(data) + return DataProfile.model_validate_json(data) diff --git a/opsml/types/extra.py b/opsml/types/extra.py index b15a5744c..33ac5838e 100644 --- a/opsml/types/extra.py +++ b/opsml/types/extra.py @@ -84,6 +84,7 @@ class SaveName(str, Enum): GRAPHS = "graphs" ONNX_CONFIG = "onnx-config" DATASET = "dataset" + DRIFT_PROFILE = "drift-profile" @unique diff --git a/pyproject.toml b/pyproject.toml index 279643da3..4799ee927 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "pyyaml~=6.0.1", "rich~=13.3.5", "rusty-logger~=0.3.0", - "scouter-ml==0.2.5", + "scouter-ml==0.3.0rc1", "semver~=2.13.0", "tenacity~=8.2.2", "zarr~=2.12.0", diff --git a/tests/conftest.py b/tests/conftest.py index 941ad2e0a..631e6c314 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -943,7 +943,9 @@ def sklearn_pipeline() -> Tuple[SklearnModel, PandasData]: transformers=[("cat", categorical_transformer, cat_cols)], remainder="passthrough", ) - pipe = Pipeline([("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))]) + pipe = Pipeline( + [("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))] + ) pipe.fit(train_data, data["y"]) sql_logic = {"test": "SELECT * FROM TEST_TABLE"} @@ -2353,7 +2355,9 @@ def stacking_classifier(): ("rf", ensemble.RandomForestClassifier(n_estimators=10, random_state=42)), ("svr", make_pipeline(StandardScaler(), linear_model.LogisticRegression(max_iter=5))), ] - reg = ensemble.StackingClassifier(estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5)) + reg = ensemble.StackingClassifier( + estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5) + ) reg.fit(X, y) return SklearnModel(model=reg, sample_data=X) diff --git a/tests/test_drift/test_drift.py b/tests/test_drift/test_drift.py index 5789559a9..4f45458e9 100644 --- a/tests/test_drift/test_drift.py +++ b/tests/test_drift/test_drift.py @@ -1,8 +1,13 @@ # type: ignore +from pathlib import Path +from tempfile import TemporaryDirectory + from scouter import DriftConfig, DriftProfile + from opsml import SklearnModel from opsml.helpers.data import create_fake_data +from opsml.types import SaveName def test_scouter( @@ -30,3 +35,19 @@ def test_scouter( assert model.drift_profile.features[col].three_ucl is not None assert model.drift_profile.config.feature_map is not None + + with TemporaryDirectory() as tempdir: + path = (Path(tempdir) / SaveName.DRIFT_PROFILE.value).with_suffix(".json") + + model.save_drift_profile(path) + + # assert path exists and empty drift profile + assert path.exists() + model.drift_profile = None + assert model.drift_profile is None + + model.load_drift_profile(path) + assert model.drift_profile is not None + + # load again + model.load_drift_profile(path) diff --git a/uv.lock b/uv.lock index f941e0007..d795528bc 100644 --- a/uv.lock +++ b/uv.lock @@ -3012,7 +3012,7 @@ requires-dist = [ { name = "s3fs", marker = "extra == 'aws-mysql'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 'aws-postgres'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 's3'", specifier = "~=2024.2.0" }, - { name = "scouter-ml", specifier = "==0.2.5" }, + { name = "scouter-ml", specifier = "==0.3.0rc1" }, { name = "semver", specifier = "~=2.13.0" }, { name = "skl2onnx", marker = "extra == 'sklearn-onnx'", specifier = "==1.16.0" }, { name = "sqlalchemy", extras = ["mypy"], marker = "extra == 'server'", specifier = "~=2.0" }, @@ -4484,7 +4484,7 @@ wheels = [ [[package]] name = "scouter-ml" -version = "0.2.5" +version = "0.3.0rc1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -4495,74 +4495,74 @@ dependencies = [ { name = "rusty-logger" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/ce/28d770ac623537afa15e243c8d8ad04256a36aba6d64eff7512c9aa8c29d/scouter_ml-0.2.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a843372ec123c9b5675fccc41babb7374ac647bf87076cbbda74367079b9d228", size = 860913 }, - { url = "https://files.pythonhosted.org/packages/44/02/247cee95fd8c7507b2817c856bfe65fd7662ba2164f41f5e32b2afc1dcdf/scouter_ml-0.2.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:374d083e5ac80ce3c575f10116f4312b1e3f20f2d61c3774a61690d7838f1bb8", size = 782632 }, - { url = "https://files.pythonhosted.org/packages/6a/aa/6d90b91846ac86c70ee4964319e9b2ee7e02112c1f0c3cb06903f9f03f2d/scouter_ml-0.2.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d2e63597cfb299a191c98293d9473f0d9ec32c86458399584fdeb0a99130bdf5", size = 888504 }, - { url = "https://files.pythonhosted.org/packages/3b/09/3d20025812f0673d9e51bd20bab2efff989d80dd88a1fbc6f28654aa9394/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e2daef794fbd2a546a1286ca40b9456cbbc49ebce457822a38002d9ee602970", size = 804922 }, - { url = "https://files.pythonhosted.org/packages/c0/67/b31ba21172a7377a08ac6ddbeb5f3eef393b5781cc7bcb8b45ea262ac14a/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:93d621f65f310e2307359e1c9f43db5ee556a96865ab62ee76ae6818b217c45d", size = 822248 }, - { url = "https://files.pythonhosted.org/packages/d9/fb/ac6d15b8e33fc6201346b2b826c2f3808121784c6bba2bd04a3b76b320c6/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f13cf477b3f17c8857ad545c00bc8dd815d57a159b5cd07168ecc4f18fa851ab", size = 958087 }, - { url = "https://files.pythonhosted.org/packages/d5/ee/d208f50eb02dac49e34e5adff29be37ef7661e413a4f5fc28cf723f63d39/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7ddf5e642876488f45b20f43240c2bd7bfd2a3567334558486c05320159e684", size = 1487497 }, - { url = "https://files.pythonhosted.org/packages/06/2d/b2a0478d84f659593421c860d5f5ec32f0c5e9dc11a4fab893b02a786913/scouter_ml-0.2.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d77fecbc9896e9f318e0503d3551369bb059e0e4c3409810d15d6a128c8edbff", size = 901660 }, - { url = "https://files.pythonhosted.org/packages/8b/14/5d06540768d63d5e7cb404c645a2976945c8bd7edcaf2c682b2883d2de5a/scouter_ml-0.2.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9f7db6e88ec74e2ef31108c65c9e2ff3bfe5f48ca11a4244ee7d9fa47e4a994b", size = 974445 }, - { url = "https://files.pythonhosted.org/packages/84/32/7859555ca0edca10270a3888dba6a8a9ac352b55602a1bf2048dfabed692/scouter_ml-0.2.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5ad867a81ec33877c9119e051c993523b2bbaad22d2424fb5a8918dc4467e865", size = 1062511 }, - { url = "https://files.pythonhosted.org/packages/c8/6d/1e3e018a645663d632797c539ae07f846ef0bbf37ffbedb4271ba2a11c40/scouter_ml-0.2.5-cp310-none-win32.whl", hash = "sha256:1ac839c524c22cb8bbbca16ede4b63f08d1b3beb1826562a09efd2a8fdd205c9", size = 762351 }, - { url = "https://files.pythonhosted.org/packages/9c/8d/6329eee0c1965404775eabd34e68524127a23ece975ff0eb2a7197661485/scouter_ml-0.2.5-cp310-none-win_amd64.whl", hash = "sha256:0103fde40539656b678d44f1cb1ae937a07544761da98208f7839c5b9f99fdc5", size = 856113 }, - { url = "https://files.pythonhosted.org/packages/a5/4d/a5499b24877e46f1fb86121c5fd55f460442be7509c35464cc65bf8e6533/scouter_ml-0.2.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ce328dc9274630dffe90aa151451ac9d9d9ce24977a94230038d4c34a1252cb4", size = 860996 }, - { url = "https://files.pythonhosted.org/packages/eb/ff/10336a0f8806b7cadb4b6f04f21c73b6887927cbdb0d3077ab0111031661/scouter_ml-0.2.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff773f040bdcd3807bd1d53ef0310630b7f6a6d91cf4ac8063b2a4aff09cbd37", size = 782736 }, - { url = "https://files.pythonhosted.org/packages/32/53/618f11ba5a8accf2b91dc9031ca11c8ed3458260ec61b571c567198715a6/scouter_ml-0.2.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a86d31be60aef498c2fa6b4dcb6972606567f44879ff083604d925ea67ce2461", size = 888531 }, - { url = "https://files.pythonhosted.org/packages/18/af/5795d8abce5cf3bd285cb35708b514982bf1818d3eb37eac20ead225e074/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6dcfc2fa756f42bd624fd94601f5b11a23cd5c7356145caa72801dd612fbe7cf", size = 804978 }, - { url = "https://files.pythonhosted.org/packages/9d/20/faa4d51ebbe716bed6dac56f6ccc56a6a2e4adb29adb44bb5788882438dc/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e587f3c7af1853c586235a97b3e7e64ce745985aa63c65137003bd3e959085c", size = 822324 }, - { url = "https://files.pythonhosted.org/packages/05/c5/ca4fb553b8bb17a4659e5adc4286475d6b2fd4ebecd6fb70e8a690004bed/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b7a0792209794069eb1a238fe979f8273a4310ebc205f3870aa3e7b1cca84d3", size = 958080 }, - { url = "https://files.pythonhosted.org/packages/bf/f6/01566eac5c6f624dab05cb44c42fef349d82cfc65b5250279fc7e5ec23a0/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:68bcaf1a6faea8d8d8c9045011ac49c9042ad65169f92644ac2605408a7dce1b", size = 1487451 }, - { url = "https://files.pythonhosted.org/packages/ef/1f/776dd1101bb5d33144b66c273212afb6145da7ad4432aa4047e6f5d5a443/scouter_ml-0.2.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cad74ca7d8537ed5b4a383f9fc7d49c30ed830b4bb947b5183117678f3cb3e3c", size = 901670 }, - { url = "https://files.pythonhosted.org/packages/7e/58/896027d505e4c569f81aa04d7fc5f75fd3ffb6f573bf785beb1cb61bba8e/scouter_ml-0.2.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0eb884f84a3f755cea74b00a7a723d824265e06a2b99b6e07a706407d0029e18", size = 974505 }, - { url = "https://files.pythonhosted.org/packages/53/43/10cc2db494adfe8f7e429dc8b52f8d76425f65058ce97cbf8231bebc5471/scouter_ml-0.2.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f064363b287c9b97e080244b49b55267aec4a89632eb9fb62be74c87b3ebe84c", size = 1062507 }, - { url = "https://files.pythonhosted.org/packages/54/4a/e5d2e059b5ea0d151ee8d6b67c7a229bae9f7de8a9f0efe492264106f05e/scouter_ml-0.2.5-cp311-none-win32.whl", hash = "sha256:590b9cde04650d853bc28eec5908d160402a01ddc903febca38edf1231724684", size = 762169 }, - { url = "https://files.pythonhosted.org/packages/1c/4a/7867c2ec44522ef4ed2871235dba78fb60a202858896ee6871a5a636e0e3/scouter_ml-0.2.5-cp311-none-win_amd64.whl", hash = "sha256:2c6c5b9ffecacad6b2ee28c60586c50c66bcb736ae867120d595e259fb705453", size = 856108 }, - { url = "https://files.pythonhosted.org/packages/33/3c/5eabcf06a79e863b4a8574c6651154bd8b07f152de62a8d813534eeccf26/scouter_ml-0.2.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d7db3dd3fdb65479ce368185aaeadbc21ee835933f299bd404628348c72c3bf1", size = 857493 }, - { url = "https://files.pythonhosted.org/packages/ac/ec/165e205792ff54c33d5316437b111b46597ace63d0cf3660b419d7e55520/scouter_ml-0.2.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5cb95a3fde44ebfa75283584e3d04666db991eda9ec8297167e6c56935017db", size = 781394 }, - { url = "https://files.pythonhosted.org/packages/cc/17/f5e61e5cbd4cf622b70282af49881bc98b3c333f8008126e70c3a3369be5/scouter_ml-0.2.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1a171e2dda3d666b927abc1afc1dcd4e8a52fb9a08b5212ce0cf362a47f04103", size = 888545 }, - { url = "https://files.pythonhosted.org/packages/b2/76/9574c2deb4abb501b6fb2152e8147850ee310c26bd3605732ac371ae46cb/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bb5241f89a85ca80d23d4b15dec404b424c27a55e1ec5ecb5d2458ef291e095", size = 803001 }, - { url = "https://files.pythonhosted.org/packages/7d/28/a23cd52f90d07fba0a6afecb90b37b2c1bba750d9fd18a944f6b1af66ffe/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a5de31aef269d30d45dd0105b0ae530073ded7ee9929d944f094663a553496e4", size = 821165 }, - { url = "https://files.pythonhosted.org/packages/65/ee/a735d574022794a4d2dcb7364446ef4b615fb34639b5a1de12f6ddcb40f4/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4c46d3b599f45987690ba1d0d09e12c8ea75a9ea4560c007902b5ca1df9aecb", size = 954082 }, - { url = "https://files.pythonhosted.org/packages/82/68/7a1d3e12337cc3ebde4e847de0d33c3378b170992e57bb6425db7a5a39a7/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1db90ad47313c5225156994de884828cd11c646cd802cc4544721ad8f7c61eef", size = 1454134 }, - { url = "https://files.pythonhosted.org/packages/1d/67/04c1ee74c07498f532ff678ff98901ab7cacd360bc14ad6e219d0013bc90/scouter_ml-0.2.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bc862d21be89c2926d95eae60699f8cf525423733a8f4e6638bcec8ba58817e", size = 901201 }, - { url = "https://files.pythonhosted.org/packages/37/9c/9b9e037b5a967dd14c64edce37221083202ecf0efa76de6f0ba881b3da30/scouter_ml-0.2.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:043929eeb1816c50acdebe601c32c56fa0052845b8450a8090e637c057a5b103", size = 968970 }, - { url = "https://files.pythonhosted.org/packages/6c/fe/efad8ba2c46844c9891dabb8fc7600ed72b89ee0e450ba39b871e29884a7/scouter_ml-0.2.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5d37103cf41b2262dcaf8d038a9599b2adc2ea677824c8fb256f97dca2a77b75", size = 1057204 }, - { url = "https://files.pythonhosted.org/packages/34/d9/7afbb197e55375d3ea7c134bd088a3ccb47f02c342583fd9225552fe3eff/scouter_ml-0.2.5-cp312-none-win32.whl", hash = "sha256:e3abd72651e67871f71662e52e8cbcbd01dedece49efecece2f4fa273d542496", size = 759005 }, - { url = "https://files.pythonhosted.org/packages/8f/06/94c7237fdf53a79326ce197856654a6d14eb62a121e28de5ee37d886f0f3/scouter_ml-0.2.5-cp312-none-win_amd64.whl", hash = "sha256:308aa1c5cd113ec7f8421fd85d837dc53449cebcf11b69394b9a9142c9401d96", size = 852476 }, - { url = "https://files.pythonhosted.org/packages/88/e2/6dec176afee997a2fb67a86b371abc3a338f072cc840ef681e036e6a78c4/scouter_ml-0.2.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6f558294a89ab4e3f50a50966048c233c4850e1825efc86637af6734c933fdc8", size = 861263 }, - { url = "https://files.pythonhosted.org/packages/08/85/69d1e72fd7c10d80256fe47d2c7d94dd03dd6ca45c1e6a8674f859d8a2b8/scouter_ml-0.2.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a98d2d91bbd7faf0f69b0a1540739d3bae3cc2cbff11e29a5fd57a54c5784e", size = 783144 }, - { url = "https://files.pythonhosted.org/packages/3a/c7/a164e9d0fff3ae5245764579bb51cc69ee441b20d1ecd302338cdc7e4a17/scouter_ml-0.2.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:86e3f87e8cdea7c1bbc83d9012452708cf340a41deb6a96bd5ba043ff90c0018", size = 888938 }, - { url = "https://files.pythonhosted.org/packages/80/b8/f64c259102f785fb0e54e45107100af9b1edeebbdd42e280088b6d1c9e56/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:852cd800b1b2f366b2fe5586d7355d723433154d09bb4ac57e2f346e3acc84d6", size = 805341 }, - { url = "https://files.pythonhosted.org/packages/1d/c9/710842dc4d42651cc64886fe611f3a105d546d3167b03186abda9a68587e/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:838f71ec62520ce6804a3eb2a0718286a11eadb473e77bec2756c84543c0a90d", size = 822702 }, - { url = "https://files.pythonhosted.org/packages/c3/b9/6b4ea6176c39a047966491c176b60236f64b8c95499d1ed7012452bcd0d0/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:efb9fa6b23a7c1fb3152cd7a56ec8ae31eaeb788e1b7ea92d36aa2a1d7b9cdcd", size = 958569 }, - { url = "https://files.pythonhosted.org/packages/05/10/85a6af5ddf6c9d19766cb46526fde35cd126dd63810c61494ce6270174d5/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9976503b0793789e2dc6620a543a9d386a178cf5f47c59aea935fd78be7bd2d4", size = 1488392 }, - { url = "https://files.pythonhosted.org/packages/cc/52/b603f7e7fd820575a77067e641a4bbf3a93f2caa956e9f6f740d82a95a57/scouter_ml-0.2.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4bde24ac2ccf9001598f69723141b3f0710ebf4c42656f276fd36317419f7bef", size = 902206 }, - { url = "https://files.pythonhosted.org/packages/6e/80/7d5b9ff9b9e62a4930da21c182eb57dc71f50858d86a0529c3c5ef810c6e/scouter_ml-0.2.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b6673e90d752d71ecd1e3c0050f82e66fb34b2956752e04a94b339d0d7d12537", size = 974961 }, - { url = "https://files.pythonhosted.org/packages/b4/12/e464eb89efeb8aa9204ef4c62bda6a0bcc7f32fbbd19f91cda14f7d24814/scouter_ml-0.2.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ea347ae031a90fa4cbf43cc19604a46d178323cd9c9cf245a0636d70993e1ca", size = 1063180 }, - { url = "https://files.pythonhosted.org/packages/61/2c/3e739ca58aed3e2c0107ce2b7a17b7587c16ee69980237e18c3a487249d2/scouter_ml-0.2.5-cp39-none-win32.whl", hash = "sha256:e1b143f60f3a84145a79579e7afc33fc90217969adc40adae7ba7a520fdc1238", size = 762797 }, - { url = "https://files.pythonhosted.org/packages/ba/4c/5ef7542e8ea1f8ed666fb23a2a1d3daf96c8186790a5fff52f545cd4c668/scouter_ml-0.2.5-cp39-none-win_amd64.whl", hash = "sha256:b749fa9714d2f655ca38d6383cabf1548042b84579f9cbffac62f32e4b91f1e5", size = 856562 }, - { url = "https://files.pythonhosted.org/packages/65/a0/d7ba23eace465da2ebb1525ad9168c67f4075bf3c57ea590f8d8543f5a63/scouter_ml-0.2.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:057540d4229b5e0a37d27245c1700392f4b9653df0cbec9218592f2e97589cef", size = 858966 }, - { url = "https://files.pythonhosted.org/packages/af/99/c13fa8480452f0f0fb4d7c504b3d51342e4c747363813fab3ffb9bf916b2/scouter_ml-0.2.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:0864348a59937b2d750ec2d2d47ea9b4e3308949ec5c1a0d32c6a30e9080c62e", size = 780892 }, - { url = "https://files.pythonhosted.org/packages/66/c5/7b02ddd4c0de7d76f438490d5060968481df25c7bb97aa788b0f2b20de14/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e5b88bedc68b2f6cf96ffec756d47c5283a5eaa9031a8b4c30806e8728d714c4", size = 886369 }, - { url = "https://files.pythonhosted.org/packages/6e/b3/76d96993b16869c218e898c36d0f27cf4d81cf18b7f1be5ced7943ad429d/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7d5da688086c812a9aa38fb0f8d5c4a4f53ecdcf6e9fee2dcf96936ed35749ae", size = 802816 }, - { url = "https://files.pythonhosted.org/packages/d9/e6/73be2bd9511144f304f1cd20291685017d77df78878f9ce1ed8befda9155/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8b776128efcca1d6a8150c70d216f9f934ce6355f44b18e02f4f98cd6cd0288", size = 819887 }, - { url = "https://files.pythonhosted.org/packages/18/86/924d51e02f70a83430ae8d36cd46616cd0f1f771455b57707943529414b0/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b1ddcadcc0f06a2d4cddabffe77663362dbe4ae4d04cc28015598a90c4c4663", size = 955617 }, - { url = "https://files.pythonhosted.org/packages/12/70/401b994030532a0bfdec9760289566f4693af1f43fcbaeb9814f3cb8b07d/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fffbb46d9ce273d60fe905f0b2688c875111de1a512db6b71e74047b2b39589", size = 1477186 }, - { url = "https://files.pythonhosted.org/packages/c8/fc/9657bbe138fca5b439384c3d8abbf3e3bc4d768413805e72ce5b6f81eb06/scouter_ml-0.2.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d09ed76e898bc39f8a7d7d93dd058251bf1351832d3a96527cc6dfe443bdb8ec", size = 899540 }, - { url = "https://files.pythonhosted.org/packages/0d/01/184bcced12db3fa0e9ed9618b528af076c456a63f5dad1ae0bea0dc5d818/scouter_ml-0.2.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4fc06a8647e01cf92cb0be780b8c04b4ea64495f68ed924a6b993e8b7476e9ce", size = 973625 }, - { url = "https://files.pythonhosted.org/packages/70/eb/82e0672fe22aaa6136a214ce1e9069ab090cafff75530cafee823adefdd1/scouter_ml-0.2.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0ef5a240625c166c940551bf45ec8992709279a7181f8c8224ab95571eaaeb4f", size = 1061340 }, - { url = "https://files.pythonhosted.org/packages/a0/47/febeb4a258616edc5105a29dcfb3eea52e9a916de04a0ad9d62a2389fae0/scouter_ml-0.2.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e2c3aed8b8ac912b534beeccbf579eabb60ef787b7c576f1a42423900cd04ab0", size = 859518 }, - { url = "https://files.pythonhosted.org/packages/4f/1c/979030047f20f54101be585da9ccb97fe7888789e805d7a0f8323d30add6/scouter_ml-0.2.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a70d2c7d7fc183f619c81a986ca5441c5631f30caf415322cbd326e7508a071b", size = 781352 }, - { url = "https://files.pythonhosted.org/packages/05/88/00a61d67c688157ec9b82a1480153e006a210e54f7898b1a602c13510ad3/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cc4193225d50f4b7413a00beaa0bcf5496bf1bf96bc7a3a9062b59bf2db8e195", size = 886776 }, - { url = "https://files.pythonhosted.org/packages/8e/ab/51e33e5c0153cb19e30566b8be9af0ba7659c9e5fb1243beab34440efa84/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ef771878df0c3f7f89731a108c0e83f5cf7d7588b1ff4e86b022adb75e1656", size = 803357 }, - { url = "https://files.pythonhosted.org/packages/74/3e/bd6a3ac18ef142a4dc9ec4f6dd5a636023ac83d40dfdccd6e0876245b903/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74083de180cafbdbcc605582fb38136c184a9f3922e2c5a5a443401d7755caf4", size = 820446 }, - { url = "https://files.pythonhosted.org/packages/69/22/61579aaec8f313f6f3050d7527099c81a89238c9d4e232888be876f292f8/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a1cdadca01ff3c87c36547b076805cc8cdc6657cba1773e4fb8e2d18f5957a7", size = 956168 }, - { url = "https://files.pythonhosted.org/packages/83/11/36bf1da8a00554ab68e47edb69526d1f43d525ef18df21505a8b16911b0b/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:676beb05ad212c1698c85755adea6c85ac90526d78e1c81ee690bc58ded2106e", size = 1478820 }, - { url = "https://files.pythonhosted.org/packages/19/66/c6939250c44d209ae2f0e055516037e8d253bc859ba025dc582982b4cc9f/scouter_ml-0.2.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d82cc955f21057630a497651dddac4088817235881556d5cc34b729144acb40d", size = 900289 }, - { url = "https://files.pythonhosted.org/packages/7b/ec/3869a103ff041526db8db21f182f4fb59ee95d35504b8ba6e6a9d79c55c9/scouter_ml-0.2.5-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:acb44a7a499ddb99fbc8f5902ffe5fc0c355bdd6f688ef2b8cd396d307e4a766", size = 974405 }, - { url = "https://files.pythonhosted.org/packages/49/49/936dc4a777e8c30576bffcf1da15340cb44897c351a8a26c4be1703859b9/scouter_ml-0.2.5-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43e5e01d596bd1330a4f232bdd6b8744acfcd04bdddf4a7e7465a8d64ba9ba41", size = 1061858 }, + { url = "https://files.pythonhosted.org/packages/74/ef/9a416a579dc30701195639ce1d340f7ca8e2b39701706e57c40269091843/scouter_ml-0.3.0rc1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b24f3263886a427c1f51843069407be33af0db820d5f2150a71b956360eb5f0c", size = 861458 }, + { url = "https://files.pythonhosted.org/packages/00/fe/557cb8c514e39f64a979ffd9379a01f1beed2617e60725251e657dcb6412/scouter_ml-0.3.0rc1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6065b337d4e0fecb4232c2fa3c1dca5cd139ecb6820cc638462a4af0c9f69169", size = 782778 }, + { url = "https://files.pythonhosted.org/packages/5f/ce/c93ddfde112e72bb24dd9a728e1df174d24313d333ee15245d14897a21cd/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2b343ad3212004b19a6c34b2dc0a1b07d5bc5d6efef61eb488bbb9adb7473e5c", size = 888333 }, + { url = "https://files.pythonhosted.org/packages/fc/4f/6920cdbcdccc7f82868215266775ac251ab7593b43ee3719495fb6c6cc27/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc90d06bd216734c434c728b529ba8911237440eba8e0500ad2397bcb8ac3d6d", size = 804708 }, + { url = "https://files.pythonhosted.org/packages/1d/4a/ea2ac3f6e08a292e0ce720ab1c616d88409312a1377a1a14621f17ff357c/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f129fb437beef38857529d7ad45d0932c8d86a2354e856e3ab8a848ffa3e0b08", size = 822281 }, + { url = "https://files.pythonhosted.org/packages/6e/43/7ddd690e5256581aac2d3740b95e12286082b9d94a90ffcb01f025d80628/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86e4c2b32fb332fba202002b8903e0304278ffca9b0ac1995cb465388ad58d49", size = 958415 }, + { url = "https://files.pythonhosted.org/packages/98/af/35f62abc0275f12e1a17a536ebadbc6f1728e70e1dbecf28d5edcaa02302/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28e97a1df50f52a99f237d1ec665db4fa4ded4d6de06e38aa21af23f32b20d81", size = 1488211 }, + { url = "https://files.pythonhosted.org/packages/58/f8/ccc50e38535da657723a3947f310e4115352fd2198ca24fe752b090e9387/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5998209686282af16d2f748be747e80fd149703b87639990888ed8340b6605a1", size = 902545 }, + { url = "https://files.pythonhosted.org/packages/ba/53/d968c164f9b81a2a81c4a2a8c29edef5b58c1393f56dc9a3aba396d1c35c/scouter_ml-0.3.0rc1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f23845f6030371f14bfa66de9faccc430cfe6da919548e2014a519ff4d73853", size = 974403 }, + { url = "https://files.pythonhosted.org/packages/1f/94/fbe125fb6cc8ac2b824c018fb72d067a6d226e4f8a84477b14e8842710aa/scouter_ml-0.3.0rc1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a3922fad8e6402fcda4ce702187b035ebcf23c88064615a09286619c6bfe805", size = 1063027 }, + { url = "https://files.pythonhosted.org/packages/27/6a/f0b35a2ef6031492ce263920a0c657e81061271584dd7d916ab0cada3ea6/scouter_ml-0.3.0rc1-cp310-none-win32.whl", hash = "sha256:7ef6dca2752173dd5f828ce79c80fa4ad4f0e33090fc5b5095a27c23a9e674bf", size = 763384 }, + { url = "https://files.pythonhosted.org/packages/a0/20/ebb123c0ffc6a4a489e6189ed0465f16f73fdc12873535a3275c1fd67a89/scouter_ml-0.3.0rc1-cp310-none-win_amd64.whl", hash = "sha256:b671f9a1b13d6ac5b1cd9ccff1d1dbb3a4b4e8e9b982e8b501818be17aac798c", size = 856554 }, + { url = "https://files.pythonhosted.org/packages/e8/dd/e01993b6f5fc04da85d51a116a42e3f7ea96390347c52e7666b6689ccbc9/scouter_ml-0.3.0rc1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8cae153a1a199a80b25e826c43a9272417b7c07a5a38d09dd03a70399324ee48", size = 861502 }, + { url = "https://files.pythonhosted.org/packages/ae/5b/387a2546efaf1558398b49b06234cf5992cbafb76b0a2af469cb1404d27a/scouter_ml-0.3.0rc1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612a50094904ee85ad782395bec8a6be2ed9b1a016604d1814793d1098cf9ba1", size = 782910 }, + { url = "https://files.pythonhosted.org/packages/78/36/4dd3e4e2967d9c729bf37a1e1d24a0b1f4461948ce5e2e544644c0e7213d/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:89b14e54577d6efb356d4315598fcf889d059ee02c7edaec1d0a55cbedbca22f", size = 888442 }, + { url = "https://files.pythonhosted.org/packages/7c/f9/b5610e0e81c9f22965b3cc44f5f7a23b5fcb0e674db4bc6c2050d9295d67/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:298e879556e8eb1abfa2bc8add534b033fc319838700deddb58c4f40c628e3ca", size = 804756 }, + { url = "https://files.pythonhosted.org/packages/c1/d6/9c9bbd728e7c9f4afdaf56f78b65ca99d2e4a2128f485c245cfa871f3c40/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7dae35a42b0fe546cf8eb984776ab3408025f56a9b024e650fc307ffa2962462", size = 822392 }, + { url = "https://files.pythonhosted.org/packages/d2/c1/8e293ca715d0715e7ad77201a36958aeef0d37988fe258d429441dd4977c/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63b2d84a37c523bd78c2e97b8ece1609ecbea2c6d77d6d24b17afd5b4ba98380", size = 958648 }, + { url = "https://files.pythonhosted.org/packages/44/d3/793393f5bcc3dc6c5c95fa7ccfd1c7dc8e4a82a42a52ce22ad0fdeb9bc58/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42110357f80e44991cb7bf3ec3c0f5adfa406148e23044f3a0b66ac2646bd0bd", size = 1488007 }, + { url = "https://files.pythonhosted.org/packages/b4/c6/20d9bfee981d9b76fbbd86d88df2ae102f12ca90c5819fc39464d0c530df/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b34d76788b7413966a24cf35e4d84d4389d58a8810b59ef919ba2ceccf80cba3", size = 902576 }, + { url = "https://files.pythonhosted.org/packages/91/d9/7446e7a8b4650fe166048b25b09456869337f6ea7b56c3b5f0d0541eb175/scouter_ml-0.3.0rc1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a8337a783cb4c3983d9828e87f1f908349008dda456457dbde01447da17bd49a", size = 974344 }, + { url = "https://files.pythonhosted.org/packages/f1/a2/22f23f19fd14cfcaec28ee9604e8aba1b8f69a28297f24d1323ffac78567/scouter_ml-0.3.0rc1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4b95752d718cac033997097ac23f71ab081644fa4ff94acf7cf7b37490803ee1", size = 1063146 }, + { url = "https://files.pythonhosted.org/packages/c3/09/e0323090cdd61d736a6671465d50bdad45d68c40b17eed0f8c031957755d/scouter_ml-0.3.0rc1-cp311-none-win32.whl", hash = "sha256:43e915b1442dd27cf9bbfc89f436ec4f535122a0ad3bdeec61d9093b742c31e9", size = 763436 }, + { url = "https://files.pythonhosted.org/packages/a4/62/09b128618cf40e2c58a5228ae2d7ff60ad421fbd8b432cf51dcd38daa53d/scouter_ml-0.3.0rc1-cp311-none-win_amd64.whl", hash = "sha256:989b8ddfe52e4190e225d51e01343933524cd2b078248bdc7c89229beeae25c8", size = 856524 }, + { url = "https://files.pythonhosted.org/packages/65/59/ed732d9cb13686a0a539caffce24edc8d821a46ad175cf3b399ebdb0a591/scouter_ml-0.3.0rc1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:272c1532318fdd39f66f04f83dce3dfbcb2ff6c77fda7058b3987d6775262e6f", size = 857850 }, + { url = "https://files.pythonhosted.org/packages/cc/3d/1a29fb8140b92443bfd6ca23fde293de84eddc930063cb2a1db1d2731994/scouter_ml-0.3.0rc1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:69f03c87562335f079341bef849c0a177b8f1a04e9d283a7c509ccde85c98e4b", size = 781495 }, + { url = "https://files.pythonhosted.org/packages/ae/87/eb4378690079b768ab8a81c274a67d7b03fff892dddd978975e48cbcf2ad/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a1546d298fe2a2cf0545e989b98e1712ae34c98de5406135b962e91b911cbf5", size = 888209 }, + { url = "https://files.pythonhosted.org/packages/ae/dc/9ee66175aa9e784436cf01e15ccf152fed194c7a13925f95e16ded5b6943/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e84e0960e83f7af5d29c99ad2ca7cfe31ca7e53280bb7189872357e0e1ea787a", size = 802771 }, + { url = "https://files.pythonhosted.org/packages/21/d0/449a79d66607dda4c0eed86c56727ff05021be893fc58a4d18d92a0f9641/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc437e2c3ebc5be558fd52e60571b26ba6e00f891d65b8af46c69f41b5ad82a3", size = 821440 }, + { url = "https://files.pythonhosted.org/packages/ab/79/96468b47ba71646cd6e1cee198127d696a7ff8a5dbe8090c415483f6bab1/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ca81a1e448c9cd9e9db1811b7c915ced4c61773690266ea32c851a9a6963599", size = 954686 }, + { url = "https://files.pythonhosted.org/packages/6e/2d/115bb60b6ad7e7787b655a04b83ce48d1256b9807af20d27f5c4b5bf16e2/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:527540d48ec9624001ae7054eb726b39d2803d2c61722f437880c7678ea0fd78", size = 1454551 }, + { url = "https://files.pythonhosted.org/packages/5d/38/fe93b1badfe554cc5c12f6c20f5cddd422c2778fe838ef62c556fb713d8e/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c939fd75b1771d5e5fd93c2c31949c765fa5a495e10eafbde067353aeebabbad", size = 901858 }, + { url = "https://files.pythonhosted.org/packages/61/71/6d92b184c522fe2c05ad01a2bf0c15ea0f92a92633182076614afd35ae48/scouter_ml-0.3.0rc1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a4992531f60b89d5b205513574600d888c13460b2e51a0b71888149b1ce5c2f2", size = 968645 }, + { url = "https://files.pythonhosted.org/packages/10/21/7d153ce2e9c738574915a60af0e915ed8636e2634cdc855e1da362019825/scouter_ml-0.3.0rc1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37b6a74d4493c2c530ef4f1488793ee12541b4ede7fba066931ec8c757283663", size = 1057270 }, + { url = "https://files.pythonhosted.org/packages/1a/9c/abd3bb59dd311fe79ea35e70c6e6392882abcdc5b15e637ce18e1c740813/scouter_ml-0.3.0rc1-cp312-none-win32.whl", hash = "sha256:ff7478a8a98fe8d1872e77b1151bb612eee61cd452760cc79f6eeeb8ce7e11e9", size = 759354 }, + { url = "https://files.pythonhosted.org/packages/9c/7d/eec5b17baa7e44cf4af917e2c32567cde772dfb161663cce6cf2989dbf4a/scouter_ml-0.3.0rc1-cp312-none-win_amd64.whl", hash = "sha256:e5c75abe5d3bdade7790eef1a9674f17d7a95355f741c618d383f9f2dc558027", size = 852882 }, + { url = "https://files.pythonhosted.org/packages/b1/3e/cb2c422d583dee10b672fbd954ee48461b001932bfab1d2dd82a7212ac88/scouter_ml-0.3.0rc1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c9fabf723569830b4955d708f955cec7f4ecb8c942bd63fa9d50546214bd7502", size = 861855 }, + { url = "https://files.pythonhosted.org/packages/15/14/2134e615e9c22520ef3e2ac490320ef97de70cf85a37886004000f6187f8/scouter_ml-0.3.0rc1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18cbf73cf7df25d7171465672738876d10e4c5f1bc70ce05c6e1ff38782b7a7c", size = 783404 }, + { url = "https://files.pythonhosted.org/packages/ae/dc/3699cfed42f72f94e77314fb696279a3ecf7a469b64c31d79008a87a194e/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:59649ef5637e8f36149cfb40bd7cdc6146a9bd4e950ae5bbddb2a6c0234030d0", size = 888820 }, + { url = "https://files.pythonhosted.org/packages/2f/1c/63d9345f8e14649e8dbf1acac225885a6e8441621972fdc1a4103ffc9e93/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff1a5fc00eeac140f626446d1977e08cb0dd01d87d7184d311d4522a8f8c9cb0", size = 805203 }, + { url = "https://files.pythonhosted.org/packages/08/90/5c055c6c1a2d02d26be9f1edfd2bc422a705448a5c9d159ef2d5e60ba25e/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:64e7ab63eb86f88dfaf45f3fad68db241880fa68c61531be955d32f58e206465", size = 822692 }, + { url = "https://files.pythonhosted.org/packages/86/bd/368a15ffe3b5cba64bba06fcb6ab510aefdb103c710b312ed6bd09d613a0/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff227f5bee418ec4c5f6177861da86dd700f21cd5c276abba143d987b8169941", size = 959071 }, + { url = "https://files.pythonhosted.org/packages/c5/77/eba72de5c05993f80835755dcddad4c634f3ec9067c5a853e63edbf083fa/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e140d282d697eff8bad9001e80989c1002ebd742c35dd824f8f76d2b330b857f", size = 1489115 }, + { url = "https://files.pythonhosted.org/packages/0e/1b/d90f5ff16a0d1eb1c8d812e277fa171c90d2193eca5017f70379f602b0fb/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfbd32685e272d1d538a06646566fd8472d71ad61922afacb7e717bb72ed7603", size = 902998 }, + { url = "https://files.pythonhosted.org/packages/cf/c4/738b8225a431d3f55b698b2b72574ed4aadb13166dbd020d94baf04db993/scouter_ml-0.3.0rc1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a4d981d511a937c01b36edf26574bc8a3dc2058d444ef01224accc26cdfc9fa", size = 974841 }, + { url = "https://files.pythonhosted.org/packages/b0/82/c57bddd4c82d5d160e870216dc92cabe0547458056c86a180f23b6da879d/scouter_ml-0.3.0rc1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed0ec477174d6e3255166091a02673292ee66113cdd4dae70f08cb1caafbf770", size = 1063777 }, + { url = "https://files.pythonhosted.org/packages/04/92/3ea1d720c7e77a87823390162279859557925755ac252105ab162414d74b/scouter_ml-0.3.0rc1-cp39-none-win32.whl", hash = "sha256:15a7ede080d102d7fab7a8d5422cf59f48fb5200bc78eb9e1847910497b6682d", size = 763866 }, + { url = "https://files.pythonhosted.org/packages/c5/fd/5cb7fc34a868708a8cdfe98c0d6e73c92eff1674314dd0e6e7150641b1f4/scouter_ml-0.3.0rc1-cp39-none-win_amd64.whl", hash = "sha256:3181aef530906a59a1d369d4bbf9b0b53c6f27ae7dfa8be3c06174f0a24b2227", size = 856819 }, + { url = "https://files.pythonhosted.org/packages/35/a9/04b7c4b0e1f700e6344b50566df49670a8fb90757302de9fe4ca7dd9e201/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:79a521973ec2ebcfea1b2edd7260d2a652bd4d76ddd06a569c500fa8d8779601", size = 859498 }, + { url = "https://files.pythonhosted.org/packages/fa/57/b64d7b7eef5da1a06178efd14a83040669833799b9cc231ede34b36cde8f/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:126872e331109eef88cc010ccddbfd36bd2ba249ec7ab74560b6b52d25136173", size = 780678 }, + { url = "https://files.pythonhosted.org/packages/38/ac/ecde78570970c4d771a74855968691ccfd64b62b14492c844cc4ffdb3db6/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2b322b14686150d435f94c71415a848f24f8513c0f8a44971188ac1d92b4496a", size = 886096 }, + { url = "https://files.pythonhosted.org/packages/4b/e7/b0a6c52ca5804b7714a1d105e490d2f0b1150d2715fc32da4353e1030389/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7976690bae1a3736a313b9b19d9ba6a470d313b06d3f0d731d2c051e0ccd0ef8", size = 802849 }, + { url = "https://files.pythonhosted.org/packages/25/d8/4ad26de104bd5a0a155b8b97bcabbc3d82d56be9e579578cbd7840fa50c3/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:247591197ddef54e5ef5d95f998147b28632241b503835053f61a18969dbae90", size = 820325 }, + { url = "https://files.pythonhosted.org/packages/fa/b9/534e3cc20eb6271dfc0c802463521124e00da44e27bbe878e48b0cf6d608/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31d30ed8669bc22b59926d90c74e48d804747ba560f42ce19ebcba3178871274", size = 956059 }, + { url = "https://files.pythonhosted.org/packages/ff/aa/1d30fe4e4a6a4e797bdd6387c839084ca8f949a7619776c0c28c63ec68a1/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b36c579be06265b1f1d7055b46a5a36f777e7669f74e96f92c8af716f8e572c8", size = 1477878 }, + { url = "https://files.pythonhosted.org/packages/27/fe/6969eebd5bc0cebf6df18ba8e65584c133e6cd3c25e39f664b4cc1581e53/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa3baa7362df7b7a061fae46a7da924a505d04ed3306bb28a4ea9caf79321f7f", size = 900388 }, + { url = "https://files.pythonhosted.org/packages/2d/37/d53226918a3e2a6c316ced4e64817ccada4acdda271887cc8bc7cd9e04c2/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:849804b2a8c3e77a33ea284e329d50496e9e4e4796c3fc7e269bb45144f71ebc", size = 973538 }, + { url = "https://files.pythonhosted.org/packages/f3/14/b572498a6c17e17c97ced82bfae98a869d19b9e6cfb4195cd9596412fff5/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4f2b3514bb66aef20a85d231c3b1c41f59940976d8f06a377a63b49139c4d881", size = 1061597 }, + { url = "https://files.pythonhosted.org/packages/ad/8c/e8dfe22bef2c7623b62b78e2e910e3447a012dc5c7d9707d2fec662485e1/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78255788464d664530295838e04b0c6e536e45bcdea33bd9c12ee7e699c4a43f", size = 860104 }, + { url = "https://files.pythonhosted.org/packages/f7/fa/fcfe4aa18c1c50e723499ea9b571612708e4c7e9bf1280f51ed1518f58b2/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c79416838ab1e3a5bb8a9fa7720d3d09a18ff8ba6a141d8091edd1c045f6139f", size = 781449 }, + { url = "https://files.pythonhosted.org/packages/03/d7/76da89e407403d7bf5d286bc8bd51487995f654a4877ce5666914d183894/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3030fc07eaefd002626de45e13ce41400d88d059fbe0d962634125362c93973d", size = 886827 }, + { url = "https://files.pythonhosted.org/packages/22/e8/55ba004ef54d01a5f258b1d12a905dca7921567685d35716d1a1d69956c7/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38448f5119022bdbfb825bdfa5613d2eca7bd93a4fbfd43919f0b09511c549e0", size = 803195 }, + { url = "https://files.pythonhosted.org/packages/36/54/f612299ab5a21164d732c42775a4a159eeadc018bc0502eddf260e6bd132/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:100418a01c8c17aff84c45972c58d50b63a7e9504b6afcf412d8ba3c363097ce", size = 820714 }, + { url = "https://files.pythonhosted.org/packages/57/dc/6767afe2675ab79d5d3ff459460e67b41badc35c5e5b3a64ad6a12bb4019/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaec0da37a8cab8a7b6e29aaea9fadf4a9552e078eb68a18d21b929691ac8894", size = 956731 }, + { url = "https://files.pythonhosted.org/packages/aa/e1/c1261ce6cff2d9d2036193ac959d14c003e1bbf5aa88b4d537fa67973cd2/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c577ff976a4c6e278c43e021ed38a811606ad88010eab6e12d3f7c6601745130", size = 1479557 }, + { url = "https://files.pythonhosted.org/packages/78/c3/56c66fa54ea417ee7d97530d7544db34459154508cb34f4e57933f9121cd/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:287638bd8c8c6bf40bb40ed5bb0bb3633942193400f70be41789f68702a7643b", size = 901086 }, + { url = "https://files.pythonhosted.org/packages/de/f1/9b0609e1c3b790e4e4553662d6bdba0986d759122048ea8fac907f00b69b/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:8c4fed79d7f9e10d365a4331947317fb05745c94b82ab8ea72508528b9afe09f", size = 974081 }, + { url = "https://files.pythonhosted.org/packages/a3/ee/c09692143babf783f14fed4345a05faa4dfde62ac975524e04e8bd43012f/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8fff39e4307e7bf78af2e6d733259bba73ec873120145704527fe4677352e568", size = 1062517 }, ] [[package]] From eadbd05bcb0302637fd14a00dee524eddce535a3 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 12:39:40 -0400 Subject: [PATCH 07/16] add save logic --- opsml/storage/card_saver.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/opsml/storage/card_saver.py b/opsml/storage/card_saver.py index b9250e905..42545d479 100644 --- a/opsml/storage/card_saver.py +++ b/opsml/storage/card_saver.py @@ -404,6 +404,21 @@ def _save_modelcard(self) -> None: with save_path.open("w", encoding="utf-8") as file_: json.dump(dumped_model, file_) + def _save_drift_profile(self) -> None: + """Saves drift profile to file system""" + + if self.card.interface.drift_profile is None: + return + + assert self.card.interface.drift_profile is not None, "Drift Profile must be set on Model Interface" + # update drift profile repository, name and version + self.card.interface.drift_profile.config.repository = self.card.repository + self.card.interface.drift_profile.config.name = self.card.name + self.card.interface.drift_profile.config.version = self.card.version + + save_path = Path(self.lpath / SaveName.DRIFT_PROFILE.value).with_suffix(Suffix.JSON.value) + self.card.interface.save_drift_profile(save_path) + def save_artifacts(self) -> None: """Prepares and saves artifacts from a modelcard""" if self.card.interface is None: @@ -417,6 +432,7 @@ def save_artifacts(self) -> None: self.card_uris.lpath = Path(tmp_dir) self.card_uris.rpath = self.card.uri + self._save_drift_profile() self._save_model() self._save_preprocessor() self._save_onnx_model() @@ -552,9 +568,7 @@ def save_card_artifacts(card: Card) -> None: """ - card_saver = next( - card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type) - ) + card_saver = next(card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type)) saver = card_saver(card=card) From acf325bce1d6fa138ba960b31cd0c93fdca90313 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 15:48:19 -0400 Subject: [PATCH 08/16] add client integration --- opsml/registry/sql/base/client.py | 16 ++- opsml/registry/sql/base/registry_base.py | 19 +++ opsml/registry/sql/base/server.py | 15 ++- opsml/settings/config.py | 8 ++ opsml/storage/api.py | 6 +- opsml/storage/card_saver.py | 5 +- opsml/storage/client.py | 1 + opsml/storage/scouter.py | 34 ++++++ pyproject.toml | 2 +- uv.lock | 140 +++++++++++------------ 10 files changed, 162 insertions(+), 84 deletions(-) create mode 100644 opsml/storage/scouter.py diff --git a/opsml/registry/sql/base/client.py b/opsml/registry/sql/base/client.py index c8bda0fd1..2ecb27c10 100644 --- a/opsml/registry/sql/base/client.py +++ b/opsml/registry/sql/base/client.py @@ -19,6 +19,7 @@ from opsml.registry.semver import CardVersion, VersionType from opsml.registry.sql.base.registry_base import SQLRegistryBase from opsml.registry.sql.base.utils import log_card_change +from opsml.settings.config import config from opsml.storage.api import RequestType, api_routes from opsml.storage.client import ApiStorageClient, StorageClient from opsml.types import RegistryType @@ -292,9 +293,9 @@ def register_card( ) else: - model_card = cast(ModelCard, card) + card = cast(ModelCard, card) - if model_card.to_onnx: + if card.to_onnx: if not check_package_exists("onnx"): raise ModuleNotFoundError( """To convert a model to onnx, please install onnx via one of the extras @@ -302,8 +303,8 @@ def register_card( """ ) - if model_card.datacard_uid is not None: - self._validate_datacard_uid(uid=model_card.datacard_uid) + if card.datacard_uid is not None: + self._validate_datacard_uid(uid=card.datacard_uid) super().register_card( card=card, @@ -312,6 +313,13 @@ def register_card( build_tag=build_tag, ) + # write profile to scouter + if card.interface.drift_profile is not None and config.scouter_server_uri is not None: + try: + self._insert_drift_profile(drift_profile=card.interface.drift_profile) + except Exception as exc: # pylint: disable=broad-except + logger.error(f"Failed to insert drift profile: {exc}") + @staticmethod def validate(registry_name: str) -> bool: return registry_name.lower() == RegistryType.MODEL.value diff --git a/opsml/registry/sql/base/registry_base.py b/opsml/registry/sql/base/registry_base.py index 90f775ffb..6613ddb2e 100644 --- a/opsml/registry/sql/base/registry_base.py +++ b/opsml/registry/sql/base/registry_base.py @@ -6,6 +6,7 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Sequence, Tuple, Union +from scouter import DriftProfile from semver import VersionInfo from opsml.cards import Card @@ -16,6 +17,8 @@ from opsml.settings.config import config from opsml.storage.card_saver import save_card_artifacts from opsml.storage.client import StorageClient +from opsml.storage.scouter import SCOUTER_CLIENT as scouter_client +from opsml.storage.scouter import ScouterClient from opsml.types import RegistryTableNames, RegistryType from opsml.types.extra import CommonKwargs @@ -34,6 +37,7 @@ def __init__(self, registry_type: RegistryType, storage_client: StorageClient): self.storage_client = storage_client self._table_name = RegistryTableNames[registry_type.value.upper()].value self._registry_type = registry_type + self._scouter_client = scouter_client @property def unique_repositories(self) -> Sequence[str]: @@ -45,6 +49,21 @@ def get_unique_card_names(self, repository: Optional[str] = None) -> Sequence[st def query_stats(self, search_term: Optional[str]) -> Dict[str, int]: raise NotImplementedError + @property + def scouter_client(self) -> Optional[ScouterClient]: + return self._scouter_client + + def _insert_drift_profile(self, drift_profile: DriftProfile) -> None: + """Insert drift profile into scouter server + + Args: + drift_profile: + drift profile + """ + + if self.scouter_client is not None: + self.scouter_client.insert_drift_profile(drift_profile=drift_profile) + def query_page( self, sort_by: str, diff --git a/opsml/registry/sql/base/server.py b/opsml/registry/sql/base/server.py index 31e380680..bd332bb23 100644 --- a/opsml/registry/sql/base/server.py +++ b/opsml/registry/sql/base/server.py @@ -356,9 +356,9 @@ def register_card( ) else: - model_card = cast(ModelCard, card) + card = cast(ModelCard, card) - if model_card.to_onnx: + if card.to_onnx: if not check_package_exists("onnx"): raise ModuleNotFoundError( """To convert a model to onnx, please install onnx via one of the extras @@ -366,8 +366,8 @@ def register_card( """ ) - if model_card.datacard_uid is not None: - self._validate_datacard_uid(uid=model_card.datacard_uid) + if card.datacard_uid is not None: + self._validate_datacard_uid(uid=card.datacard_uid) super().register_card( card=card, @@ -376,6 +376,13 @@ def register_card( build_tag=build_tag, ) + # write profile to scouter + if card.interface.drift_profile is not None and config.scouter_server_uri is not None: + try: + self._insert_drift_profile(drift_profile=card.interface.drift_profile) + except Exception as exc: # pylint: disable=broad-except + logger.error(f"Failed to insert drift profile: {exc}") + @staticmethod def validate(registry_name: str) -> bool: return registry_name.lower() == RegistryType.MODEL.value diff --git a/opsml/settings/config.py b/opsml/settings/config.py index 7b225e1c1..dd27477d1 100644 --- a/opsml/settings/config.py +++ b/opsml/settings/config.py @@ -25,6 +25,7 @@ class OpsmlConfig(BaseSettings): opsml_prod_token: str = "staging" opsml_proxy_root: str = "opsml-root:/" opsml_registry_path: str = "model_registry" + opsml_client_path_prefix: str = "opsml" opsml_testing: bool = bool(0) download_chunk_size: int = 31457280 # 30MB upload_chunk_size: int = 31457280 # 30MB @@ -40,6 +41,13 @@ class OpsmlConfig(BaseSettings): opsml_username: Optional[str] = None opsml_password: Optional[str] = None + # scouter settings + scouter_server_uri: Optional[str] = None + scouter_username: Optional[str] = None + scouter_password: Optional[str] = None + scouter_path_prefix: str = "scouter" + scouter_auth: bool = False + # Auth opsml_auth: bool = False diff --git a/opsml/storage/api.py b/opsml/storage/api.py index 276f09909..9dab44f30 100644 --- a/opsml/storage/api.py +++ b/opsml/storage/api.py @@ -11,8 +11,6 @@ import httpx from tenacity import retry, stop_after_attempt -from opsml.settings.config import config - # httpx outputs a lot of logs logging.getLogger("httpx").propagate = False @@ -66,7 +64,7 @@ def __init__( password: Optional[str], use_auth: bool, token: Optional[str], - path_prefix: str = PATH_PREFIX, + path_prefix: str, ): """Instantiates Api client for interacting with opsml server @@ -91,7 +89,7 @@ def __init__( username is not None and password is not None ), "Username and password must be provided when using authentication" self._requires_auth = True - self.form_data = {"username": config.opsml_username, "password": config.opsml_password} + self.form_data = {"username": username, "password": password} self.refresh_token() self.client.timeout = _TIMEOUT_CONFIG diff --git a/opsml/storage/card_saver.py b/opsml/storage/card_saver.py index 42545d479..7fb2f285f 100644 --- a/opsml/storage/card_saver.py +++ b/opsml/storage/card_saver.py @@ -411,6 +411,7 @@ def _save_drift_profile(self) -> None: return assert self.card.interface.drift_profile is not None, "Drift Profile must be set on Model Interface" + # update drift profile repository, name and version self.card.interface.drift_profile.config.repository = self.card.repository self.card.interface.drift_profile.config.name = self.card.name @@ -568,7 +569,9 @@ def save_card_artifacts(card: Card) -> None: """ - card_saver = next(card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type)) + card_saver = next( + card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type) + ) saver = card_saver(card=card) diff --git a/opsml/storage/client.py b/opsml/storage/client.py index 084d6ba7a..8e5b2edc2 100644 --- a/opsml/storage/client.py +++ b/opsml/storage/client.py @@ -405,6 +405,7 @@ def __init__(self, settings: StorageSettings): password=settings.opsml_password, use_auth=settings.opsml_auth, token=settings.opsml_prod_token, + path_prefix=config.opsml_client_path_prefix, ) def get(self, rpath: Path, lpath: Path, recursive: bool = True) -> None: diff --git a/opsml/storage/scouter.py b/opsml/storage/scouter.py new file mode 100644 index 000000000..4779c4382 --- /dev/null +++ b/opsml/storage/scouter.py @@ -0,0 +1,34 @@ +import json + +from scouter import DriftProfile + +from opsml.settings.config import config +from opsml.storage.api import ApiClient, RequestType + + +class ScouterClient(ApiClient): + def insert_drift_profile(self, drift_profile: DriftProfile) -> None: + """Inserts drift profile into scouter server + + Args: + drift_profile: + Drift profile to insert + """ + + self.request( + route="/profile", + request_type=RequestType.POST, + json=json.loads(drift_profile.model_dump_json()), + ) + + +SCOUTER_CLIENT = None +if config.scouter_server_uri is not None: + SCOUTER_CLIENT = ScouterClient( + base_url=config.scouter_server_uri, + username=config.scouter_username, + password=config.scouter_password, + use_auth=config.scouter_auth, + token=None, + path_prefix=config.scouter_path_prefix, + ) diff --git a/pyproject.toml b/pyproject.toml index 4799ee927..ca8174920 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,7 @@ dependencies = [ "pyyaml~=6.0.1", "rich~=13.3.5", "rusty-logger~=0.3.0", - "scouter-ml==0.3.0rc1", + "scouter-ml==0.3.0rc2", "semver~=2.13.0", "tenacity~=8.2.2", "zarr~=2.12.0", diff --git a/uv.lock b/uv.lock index d795528bc..76a0c0390 100644 --- a/uv.lock +++ b/uv.lock @@ -3012,7 +3012,7 @@ requires-dist = [ { name = "s3fs", marker = "extra == 'aws-mysql'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 'aws-postgres'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 's3'", specifier = "~=2024.2.0" }, - { name = "scouter-ml", specifier = "==0.3.0rc1" }, + { name = "scouter-ml", specifier = "==0.3.0rc2" }, { name = "semver", specifier = "~=2.13.0" }, { name = "skl2onnx", marker = "extra == 'sklearn-onnx'", specifier = "==1.16.0" }, { name = "sqlalchemy", extras = ["mypy"], marker = "extra == 'server'", specifier = "~=2.0" }, @@ -4484,7 +4484,7 @@ wheels = [ [[package]] name = "scouter-ml" -version = "0.3.0rc1" +version = "0.3.0rc2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -4495,74 +4495,74 @@ dependencies = [ { name = "rusty-logger" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/74/ef/9a416a579dc30701195639ce1d340f7ca8e2b39701706e57c40269091843/scouter_ml-0.3.0rc1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b24f3263886a427c1f51843069407be33af0db820d5f2150a71b956360eb5f0c", size = 861458 }, - { url = "https://files.pythonhosted.org/packages/00/fe/557cb8c514e39f64a979ffd9379a01f1beed2617e60725251e657dcb6412/scouter_ml-0.3.0rc1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6065b337d4e0fecb4232c2fa3c1dca5cd139ecb6820cc638462a4af0c9f69169", size = 782778 }, - { url = "https://files.pythonhosted.org/packages/5f/ce/c93ddfde112e72bb24dd9a728e1df174d24313d333ee15245d14897a21cd/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2b343ad3212004b19a6c34b2dc0a1b07d5bc5d6efef61eb488bbb9adb7473e5c", size = 888333 }, - { url = "https://files.pythonhosted.org/packages/fc/4f/6920cdbcdccc7f82868215266775ac251ab7593b43ee3719495fb6c6cc27/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc90d06bd216734c434c728b529ba8911237440eba8e0500ad2397bcb8ac3d6d", size = 804708 }, - { url = "https://files.pythonhosted.org/packages/1d/4a/ea2ac3f6e08a292e0ce720ab1c616d88409312a1377a1a14621f17ff357c/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f129fb437beef38857529d7ad45d0932c8d86a2354e856e3ab8a848ffa3e0b08", size = 822281 }, - { url = "https://files.pythonhosted.org/packages/6e/43/7ddd690e5256581aac2d3740b95e12286082b9d94a90ffcb01f025d80628/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86e4c2b32fb332fba202002b8903e0304278ffca9b0ac1995cb465388ad58d49", size = 958415 }, - { url = "https://files.pythonhosted.org/packages/98/af/35f62abc0275f12e1a17a536ebadbc6f1728e70e1dbecf28d5edcaa02302/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28e97a1df50f52a99f237d1ec665db4fa4ded4d6de06e38aa21af23f32b20d81", size = 1488211 }, - { url = "https://files.pythonhosted.org/packages/58/f8/ccc50e38535da657723a3947f310e4115352fd2198ca24fe752b090e9387/scouter_ml-0.3.0rc1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5998209686282af16d2f748be747e80fd149703b87639990888ed8340b6605a1", size = 902545 }, - { url = "https://files.pythonhosted.org/packages/ba/53/d968c164f9b81a2a81c4a2a8c29edef5b58c1393f56dc9a3aba396d1c35c/scouter_ml-0.3.0rc1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f23845f6030371f14bfa66de9faccc430cfe6da919548e2014a519ff4d73853", size = 974403 }, - { url = "https://files.pythonhosted.org/packages/1f/94/fbe125fb6cc8ac2b824c018fb72d067a6d226e4f8a84477b14e8842710aa/scouter_ml-0.3.0rc1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a3922fad8e6402fcda4ce702187b035ebcf23c88064615a09286619c6bfe805", size = 1063027 }, - { url = "https://files.pythonhosted.org/packages/27/6a/f0b35a2ef6031492ce263920a0c657e81061271584dd7d916ab0cada3ea6/scouter_ml-0.3.0rc1-cp310-none-win32.whl", hash = "sha256:7ef6dca2752173dd5f828ce79c80fa4ad4f0e33090fc5b5095a27c23a9e674bf", size = 763384 }, - { url = "https://files.pythonhosted.org/packages/a0/20/ebb123c0ffc6a4a489e6189ed0465f16f73fdc12873535a3275c1fd67a89/scouter_ml-0.3.0rc1-cp310-none-win_amd64.whl", hash = "sha256:b671f9a1b13d6ac5b1cd9ccff1d1dbb3a4b4e8e9b982e8b501818be17aac798c", size = 856554 }, - { url = "https://files.pythonhosted.org/packages/e8/dd/e01993b6f5fc04da85d51a116a42e3f7ea96390347c52e7666b6689ccbc9/scouter_ml-0.3.0rc1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8cae153a1a199a80b25e826c43a9272417b7c07a5a38d09dd03a70399324ee48", size = 861502 }, - { url = "https://files.pythonhosted.org/packages/ae/5b/387a2546efaf1558398b49b06234cf5992cbafb76b0a2af469cb1404d27a/scouter_ml-0.3.0rc1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612a50094904ee85ad782395bec8a6be2ed9b1a016604d1814793d1098cf9ba1", size = 782910 }, - { url = "https://files.pythonhosted.org/packages/78/36/4dd3e4e2967d9c729bf37a1e1d24a0b1f4461948ce5e2e544644c0e7213d/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:89b14e54577d6efb356d4315598fcf889d059ee02c7edaec1d0a55cbedbca22f", size = 888442 }, - { url = "https://files.pythonhosted.org/packages/7c/f9/b5610e0e81c9f22965b3cc44f5f7a23b5fcb0e674db4bc6c2050d9295d67/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:298e879556e8eb1abfa2bc8add534b033fc319838700deddb58c4f40c628e3ca", size = 804756 }, - { url = "https://files.pythonhosted.org/packages/c1/d6/9c9bbd728e7c9f4afdaf56f78b65ca99d2e4a2128f485c245cfa871f3c40/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7dae35a42b0fe546cf8eb984776ab3408025f56a9b024e650fc307ffa2962462", size = 822392 }, - { url = "https://files.pythonhosted.org/packages/d2/c1/8e293ca715d0715e7ad77201a36958aeef0d37988fe258d429441dd4977c/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63b2d84a37c523bd78c2e97b8ece1609ecbea2c6d77d6d24b17afd5b4ba98380", size = 958648 }, - { url = "https://files.pythonhosted.org/packages/44/d3/793393f5bcc3dc6c5c95fa7ccfd1c7dc8e4a82a42a52ce22ad0fdeb9bc58/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:42110357f80e44991cb7bf3ec3c0f5adfa406148e23044f3a0b66ac2646bd0bd", size = 1488007 }, - { url = "https://files.pythonhosted.org/packages/b4/c6/20d9bfee981d9b76fbbd86d88df2ae102f12ca90c5819fc39464d0c530df/scouter_ml-0.3.0rc1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b34d76788b7413966a24cf35e4d84d4389d58a8810b59ef919ba2ceccf80cba3", size = 902576 }, - { url = "https://files.pythonhosted.org/packages/91/d9/7446e7a8b4650fe166048b25b09456869337f6ea7b56c3b5f0d0541eb175/scouter_ml-0.3.0rc1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a8337a783cb4c3983d9828e87f1f908349008dda456457dbde01447da17bd49a", size = 974344 }, - { url = "https://files.pythonhosted.org/packages/f1/a2/22f23f19fd14cfcaec28ee9604e8aba1b8f69a28297f24d1323ffac78567/scouter_ml-0.3.0rc1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4b95752d718cac033997097ac23f71ab081644fa4ff94acf7cf7b37490803ee1", size = 1063146 }, - { url = "https://files.pythonhosted.org/packages/c3/09/e0323090cdd61d736a6671465d50bdad45d68c40b17eed0f8c031957755d/scouter_ml-0.3.0rc1-cp311-none-win32.whl", hash = "sha256:43e915b1442dd27cf9bbfc89f436ec4f535122a0ad3bdeec61d9093b742c31e9", size = 763436 }, - { url = "https://files.pythonhosted.org/packages/a4/62/09b128618cf40e2c58a5228ae2d7ff60ad421fbd8b432cf51dcd38daa53d/scouter_ml-0.3.0rc1-cp311-none-win_amd64.whl", hash = "sha256:989b8ddfe52e4190e225d51e01343933524cd2b078248bdc7c89229beeae25c8", size = 856524 }, - { url = "https://files.pythonhosted.org/packages/65/59/ed732d9cb13686a0a539caffce24edc8d821a46ad175cf3b399ebdb0a591/scouter_ml-0.3.0rc1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:272c1532318fdd39f66f04f83dce3dfbcb2ff6c77fda7058b3987d6775262e6f", size = 857850 }, - { url = "https://files.pythonhosted.org/packages/cc/3d/1a29fb8140b92443bfd6ca23fde293de84eddc930063cb2a1db1d2731994/scouter_ml-0.3.0rc1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:69f03c87562335f079341bef849c0a177b8f1a04e9d283a7c509ccde85c98e4b", size = 781495 }, - { url = "https://files.pythonhosted.org/packages/ae/87/eb4378690079b768ab8a81c274a67d7b03fff892dddd978975e48cbcf2ad/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2a1546d298fe2a2cf0545e989b98e1712ae34c98de5406135b962e91b911cbf5", size = 888209 }, - { url = "https://files.pythonhosted.org/packages/ae/dc/9ee66175aa9e784436cf01e15ccf152fed194c7a13925f95e16ded5b6943/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e84e0960e83f7af5d29c99ad2ca7cfe31ca7e53280bb7189872357e0e1ea787a", size = 802771 }, - { url = "https://files.pythonhosted.org/packages/21/d0/449a79d66607dda4c0eed86c56727ff05021be893fc58a4d18d92a0f9641/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc437e2c3ebc5be558fd52e60571b26ba6e00f891d65b8af46c69f41b5ad82a3", size = 821440 }, - { url = "https://files.pythonhosted.org/packages/ab/79/96468b47ba71646cd6e1cee198127d696a7ff8a5dbe8090c415483f6bab1/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ca81a1e448c9cd9e9db1811b7c915ced4c61773690266ea32c851a9a6963599", size = 954686 }, - { url = "https://files.pythonhosted.org/packages/6e/2d/115bb60b6ad7e7787b655a04b83ce48d1256b9807af20d27f5c4b5bf16e2/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:527540d48ec9624001ae7054eb726b39d2803d2c61722f437880c7678ea0fd78", size = 1454551 }, - { url = "https://files.pythonhosted.org/packages/5d/38/fe93b1badfe554cc5c12f6c20f5cddd422c2778fe838ef62c556fb713d8e/scouter_ml-0.3.0rc1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c939fd75b1771d5e5fd93c2c31949c765fa5a495e10eafbde067353aeebabbad", size = 901858 }, - { url = "https://files.pythonhosted.org/packages/61/71/6d92b184c522fe2c05ad01a2bf0c15ea0f92a92633182076614afd35ae48/scouter_ml-0.3.0rc1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a4992531f60b89d5b205513574600d888c13460b2e51a0b71888149b1ce5c2f2", size = 968645 }, - { url = "https://files.pythonhosted.org/packages/10/21/7d153ce2e9c738574915a60af0e915ed8636e2634cdc855e1da362019825/scouter_ml-0.3.0rc1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:37b6a74d4493c2c530ef4f1488793ee12541b4ede7fba066931ec8c757283663", size = 1057270 }, - { url = "https://files.pythonhosted.org/packages/1a/9c/abd3bb59dd311fe79ea35e70c6e6392882abcdc5b15e637ce18e1c740813/scouter_ml-0.3.0rc1-cp312-none-win32.whl", hash = "sha256:ff7478a8a98fe8d1872e77b1151bb612eee61cd452760cc79f6eeeb8ce7e11e9", size = 759354 }, - { url = "https://files.pythonhosted.org/packages/9c/7d/eec5b17baa7e44cf4af917e2c32567cde772dfb161663cce6cf2989dbf4a/scouter_ml-0.3.0rc1-cp312-none-win_amd64.whl", hash = "sha256:e5c75abe5d3bdade7790eef1a9674f17d7a95355f741c618d383f9f2dc558027", size = 852882 }, - { url = "https://files.pythonhosted.org/packages/b1/3e/cb2c422d583dee10b672fbd954ee48461b001932bfab1d2dd82a7212ac88/scouter_ml-0.3.0rc1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c9fabf723569830b4955d708f955cec7f4ecb8c942bd63fa9d50546214bd7502", size = 861855 }, - { url = "https://files.pythonhosted.org/packages/15/14/2134e615e9c22520ef3e2ac490320ef97de70cf85a37886004000f6187f8/scouter_ml-0.3.0rc1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:18cbf73cf7df25d7171465672738876d10e4c5f1bc70ce05c6e1ff38782b7a7c", size = 783404 }, - { url = "https://files.pythonhosted.org/packages/ae/dc/3699cfed42f72f94e77314fb696279a3ecf7a469b64c31d79008a87a194e/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:59649ef5637e8f36149cfb40bd7cdc6146a9bd4e950ae5bbddb2a6c0234030d0", size = 888820 }, - { url = "https://files.pythonhosted.org/packages/2f/1c/63d9345f8e14649e8dbf1acac225885a6e8441621972fdc1a4103ffc9e93/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff1a5fc00eeac140f626446d1977e08cb0dd01d87d7184d311d4522a8f8c9cb0", size = 805203 }, - { url = "https://files.pythonhosted.org/packages/08/90/5c055c6c1a2d02d26be9f1edfd2bc422a705448a5c9d159ef2d5e60ba25e/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:64e7ab63eb86f88dfaf45f3fad68db241880fa68c61531be955d32f58e206465", size = 822692 }, - { url = "https://files.pythonhosted.org/packages/86/bd/368a15ffe3b5cba64bba06fcb6ab510aefdb103c710b312ed6bd09d613a0/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff227f5bee418ec4c5f6177861da86dd700f21cd5c276abba143d987b8169941", size = 959071 }, - { url = "https://files.pythonhosted.org/packages/c5/77/eba72de5c05993f80835755dcddad4c634f3ec9067c5a853e63edbf083fa/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e140d282d697eff8bad9001e80989c1002ebd742c35dd824f8f76d2b330b857f", size = 1489115 }, - { url = "https://files.pythonhosted.org/packages/0e/1b/d90f5ff16a0d1eb1c8d812e277fa171c90d2193eca5017f70379f602b0fb/scouter_ml-0.3.0rc1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfbd32685e272d1d538a06646566fd8472d71ad61922afacb7e717bb72ed7603", size = 902998 }, - { url = "https://files.pythonhosted.org/packages/cf/c4/738b8225a431d3f55b698b2b72574ed4aadb13166dbd020d94baf04db993/scouter_ml-0.3.0rc1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a4d981d511a937c01b36edf26574bc8a3dc2058d444ef01224accc26cdfc9fa", size = 974841 }, - { url = "https://files.pythonhosted.org/packages/b0/82/c57bddd4c82d5d160e870216dc92cabe0547458056c86a180f23b6da879d/scouter_ml-0.3.0rc1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed0ec477174d6e3255166091a02673292ee66113cdd4dae70f08cb1caafbf770", size = 1063777 }, - { url = "https://files.pythonhosted.org/packages/04/92/3ea1d720c7e77a87823390162279859557925755ac252105ab162414d74b/scouter_ml-0.3.0rc1-cp39-none-win32.whl", hash = "sha256:15a7ede080d102d7fab7a8d5422cf59f48fb5200bc78eb9e1847910497b6682d", size = 763866 }, - { url = "https://files.pythonhosted.org/packages/c5/fd/5cb7fc34a868708a8cdfe98c0d6e73c92eff1674314dd0e6e7150641b1f4/scouter_ml-0.3.0rc1-cp39-none-win_amd64.whl", hash = "sha256:3181aef530906a59a1d369d4bbf9b0b53c6f27ae7dfa8be3c06174f0a24b2227", size = 856819 }, - { url = "https://files.pythonhosted.org/packages/35/a9/04b7c4b0e1f700e6344b50566df49670a8fb90757302de9fe4ca7dd9e201/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:79a521973ec2ebcfea1b2edd7260d2a652bd4d76ddd06a569c500fa8d8779601", size = 859498 }, - { url = "https://files.pythonhosted.org/packages/fa/57/b64d7b7eef5da1a06178efd14a83040669833799b9cc231ede34b36cde8f/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:126872e331109eef88cc010ccddbfd36bd2ba249ec7ab74560b6b52d25136173", size = 780678 }, - { url = "https://files.pythonhosted.org/packages/38/ac/ecde78570970c4d771a74855968691ccfd64b62b14492c844cc4ffdb3db6/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2b322b14686150d435f94c71415a848f24f8513c0f8a44971188ac1d92b4496a", size = 886096 }, - { url = "https://files.pythonhosted.org/packages/4b/e7/b0a6c52ca5804b7714a1d105e490d2f0b1150d2715fc32da4353e1030389/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7976690bae1a3736a313b9b19d9ba6a470d313b06d3f0d731d2c051e0ccd0ef8", size = 802849 }, - { url = "https://files.pythonhosted.org/packages/25/d8/4ad26de104bd5a0a155b8b97bcabbc3d82d56be9e579578cbd7840fa50c3/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:247591197ddef54e5ef5d95f998147b28632241b503835053f61a18969dbae90", size = 820325 }, - { url = "https://files.pythonhosted.org/packages/fa/b9/534e3cc20eb6271dfc0c802463521124e00da44e27bbe878e48b0cf6d608/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31d30ed8669bc22b59926d90c74e48d804747ba560f42ce19ebcba3178871274", size = 956059 }, - { url = "https://files.pythonhosted.org/packages/ff/aa/1d30fe4e4a6a4e797bdd6387c839084ca8f949a7619776c0c28c63ec68a1/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b36c579be06265b1f1d7055b46a5a36f777e7669f74e96f92c8af716f8e572c8", size = 1477878 }, - { url = "https://files.pythonhosted.org/packages/27/fe/6969eebd5bc0cebf6df18ba8e65584c133e6cd3c25e39f664b4cc1581e53/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa3baa7362df7b7a061fae46a7da924a505d04ed3306bb28a4ea9caf79321f7f", size = 900388 }, - { url = "https://files.pythonhosted.org/packages/2d/37/d53226918a3e2a6c316ced4e64817ccada4acdda271887cc8bc7cd9e04c2/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:849804b2a8c3e77a33ea284e329d50496e9e4e4796c3fc7e269bb45144f71ebc", size = 973538 }, - { url = "https://files.pythonhosted.org/packages/f3/14/b572498a6c17e17c97ced82bfae98a869d19b9e6cfb4195cd9596412fff5/scouter_ml-0.3.0rc1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4f2b3514bb66aef20a85d231c3b1c41f59940976d8f06a377a63b49139c4d881", size = 1061597 }, - { url = "https://files.pythonhosted.org/packages/ad/8c/e8dfe22bef2c7623b62b78e2e910e3447a012dc5c7d9707d2fec662485e1/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78255788464d664530295838e04b0c6e536e45bcdea33bd9c12ee7e699c4a43f", size = 860104 }, - { url = "https://files.pythonhosted.org/packages/f7/fa/fcfe4aa18c1c50e723499ea9b571612708e4c7e9bf1280f51ed1518f58b2/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c79416838ab1e3a5bb8a9fa7720d3d09a18ff8ba6a141d8091edd1c045f6139f", size = 781449 }, - { url = "https://files.pythonhosted.org/packages/03/d7/76da89e407403d7bf5d286bc8bd51487995f654a4877ce5666914d183894/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3030fc07eaefd002626de45e13ce41400d88d059fbe0d962634125362c93973d", size = 886827 }, - { url = "https://files.pythonhosted.org/packages/22/e8/55ba004ef54d01a5f258b1d12a905dca7921567685d35716d1a1d69956c7/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38448f5119022bdbfb825bdfa5613d2eca7bd93a4fbfd43919f0b09511c549e0", size = 803195 }, - { url = "https://files.pythonhosted.org/packages/36/54/f612299ab5a21164d732c42775a4a159eeadc018bc0502eddf260e6bd132/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:100418a01c8c17aff84c45972c58d50b63a7e9504b6afcf412d8ba3c363097ce", size = 820714 }, - { url = "https://files.pythonhosted.org/packages/57/dc/6767afe2675ab79d5d3ff459460e67b41badc35c5e5b3a64ad6a12bb4019/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaec0da37a8cab8a7b6e29aaea9fadf4a9552e078eb68a18d21b929691ac8894", size = 956731 }, - { url = "https://files.pythonhosted.org/packages/aa/e1/c1261ce6cff2d9d2036193ac959d14c003e1bbf5aa88b4d537fa67973cd2/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c577ff976a4c6e278c43e021ed38a811606ad88010eab6e12d3f7c6601745130", size = 1479557 }, - { url = "https://files.pythonhosted.org/packages/78/c3/56c66fa54ea417ee7d97530d7544db34459154508cb34f4e57933f9121cd/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:287638bd8c8c6bf40bb40ed5bb0bb3633942193400f70be41789f68702a7643b", size = 901086 }, - { url = "https://files.pythonhosted.org/packages/de/f1/9b0609e1c3b790e4e4553662d6bdba0986d759122048ea8fac907f00b69b/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:8c4fed79d7f9e10d365a4331947317fb05745c94b82ab8ea72508528b9afe09f", size = 974081 }, - { url = "https://files.pythonhosted.org/packages/a3/ee/c09692143babf783f14fed4345a05faa4dfde62ac975524e04e8bd43012f/scouter_ml-0.3.0rc1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8fff39e4307e7bf78af2e6d733259bba73ec873120145704527fe4677352e568", size = 1062517 }, + { url = "https://files.pythonhosted.org/packages/df/18/47c3a5936b3904e922b26176c4c5bf70619d8d1b6efa3de105c6d937e707/scouter_ml-0.3.0rc2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:377481e3dd8069be7fb028bcb068473a8e3b0f2e1dcaed82a5094944b4bcd0fe", size = 831669 }, + { url = "https://files.pythonhosted.org/packages/98/7e/bd5531c61000ea17204671e53b34d401d0b2ef9e05accdf0b8ef09c14b7b/scouter_ml-0.3.0rc2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a668f12856b2197c3835a3890158f18909a2c868ef902cde8161a728afb5a44e", size = 756964 }, + { url = "https://files.pythonhosted.org/packages/5e/dc/e853589c3584416f734949ce65866fd699d461170277a8c6e11e0e0ed386/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:44210000bd9a51462ec62ba821e0c8a53ee4b182f3294cbd1e0654410c2e59ec", size = 865467 }, + { url = "https://files.pythonhosted.org/packages/a3/44/dee14b105231eed058ad2469259cde19458d5212a060cb920a700feec16c/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff4c1655e591b664b68d1728729f2fd2f624536e99baee97ea75f9de1fbdba09", size = 781202 }, + { url = "https://files.pythonhosted.org/packages/5a/83/6f54a9618c1104f3dd26dc1187e400eee7b4f429117e9c00165d1b3156ac/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d5c6cef4219404d07c5b7386a0de89b1a5565cbedf3b1c4d9dcc31ef73de6693", size = 794659 }, + { url = "https://files.pythonhosted.org/packages/ba/8b/ddfded5d1a781c4b91870e49c5a95c1fd2400a18d20927f4c723180154df/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca5f482ddd4dba63408eb1a9c2f563d8bc66172eb3749efef106aeb5c04ba14b", size = 928326 }, + { url = "https://files.pythonhosted.org/packages/33/7f/2254aac342cede8aeb4da7248a10ec69944ebb9a9cfe0ca4c075d8ccad21/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e83a16f6d9e82991b8e871193de91ef7083d7e1becf0faccaa50471b3df7deee", size = 1430813 }, + { url = "https://files.pythonhosted.org/packages/d4/dc/29af39281930bdf155f1837df4ad00d701a059b7b35d9f469270fd7a6dc8/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83c1b153ee0119a09c3b95cb62c85324917055b2154983288da90a20a1f32b0b", size = 873968 }, + { url = "https://files.pythonhosted.org/packages/8d/14/2cebf6bdc8a8d2e06386bfeece73fef0df2b47b9f2312612ec303ca7ea8e/scouter_ml-0.3.0rc2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:99bbd7c7ddff11effb4731626f920bd02bcdf0ad0900630f2fa1934742944157", size = 950248 }, + { url = "https://files.pythonhosted.org/packages/ef/a0/571f225972aafda42e5bd4237e9448a366612174b67d06a9cc2e3fa21eae/scouter_ml-0.3.0rc2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a8fb06ec887a82a2c64118a0fc591aa6fe209e9519905b0a5373070d9c063310", size = 1031319 }, + { url = "https://files.pythonhosted.org/packages/75/01/b3d1f13858f6089d12dddc7482a59f11c909d72070ffd757a59655896b1a/scouter_ml-0.3.0rc2-cp310-none-win32.whl", hash = "sha256:9ad1a9fb9670d310b8c9e2322f754bcdce72beff68539b8bfc2559a273ffca52", size = 737796 }, + { url = "https://files.pythonhosted.org/packages/61/ed/13f805f71c40bcba47d4e2df965b32887509f011b25a1cfdbea4269d294c/scouter_ml-0.3.0rc2-cp310-none-win_amd64.whl", hash = "sha256:ba1190ed99747f717cc29f948a228d63cfe67092735c806261e8cfeaaefe5d3c", size = 825060 }, + { url = "https://files.pythonhosted.org/packages/87/ab/2963051fbf2164291745045c43561190892dcb8fc778226477a8634277c2/scouter_ml-0.3.0rc2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:30a891cdb9fa9236c1a3b570960c40e354c5067266970e9a746b2f84d73ba7be", size = 831589 }, + { url = "https://files.pythonhosted.org/packages/63/65/ec62fb098cde8d04d8006c5d5fce2e9d8674bf4f91c9883da579339c281d/scouter_ml-0.3.0rc2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7c31041fbf5777de11feb86c2483dd204453d6ba0f0787929263509f06d7091", size = 756971 }, + { url = "https://files.pythonhosted.org/packages/6f/ea/c129d654581cc3f9ebaee01f22ca438ef3bffaeff935c0b5abe19ba221f3/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d18f8d737cfc09a29f78c03ecabc99f05db0999553b3c1c1d4781a3eb591de63", size = 865562 }, + { url = "https://files.pythonhosted.org/packages/7c/4c/c6be409bab131615a37d4db2390c8f8a0c01ab48948acce3747ad0d6de68/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b02ed51af7e31842e67b4ec936d2bce06f50af538bbc499a881241d35f0cdede", size = 781290 }, + { url = "https://files.pythonhosted.org/packages/6f/8d/b26609f3263f9a58da53e02a45d5f4f8992e43471019480cf793d6e928a9/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a21dba052d79dbf19631b56aa1b562c48f315767b2f20d92beb82ed86c4d3c78", size = 794800 }, + { url = "https://files.pythonhosted.org/packages/7c/b2/fbc0d54f91641815c03355c1b06069aed0f26599a12daaf2c7044bd48372/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89b112113187c04fa39b951f0cd2edaad4af481a3f054d417df0c2624e5a5b7a", size = 928393 }, + { url = "https://files.pythonhosted.org/packages/b3/bb/2d07eb693f8dd9a4c653a54f8f721a48f7381eec1201364aab08ed9d9c2a/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c348ec9ea40e9dcb00afcec5a80adea334f8d699500e07e5b5a8f9f4c033d38", size = 1430693 }, + { url = "https://files.pythonhosted.org/packages/3b/54/38ca0ad74b4e683fa406c42201e9f79f8faaef85201c5907fa03d8d538e7/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1556eda025bbab5b41e05c9773fe12bb2a87b34131b8807593e5bd71fa4e1471", size = 874017 }, + { url = "https://files.pythonhosted.org/packages/2a/fd/44a1663c9f59574a2da09994b77b7ca673d5e1a85f8a37f97e43e78fb89e/scouter_ml-0.3.0rc2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:25ad831c26b9086282b40ba6eadeeda977d816488a1f2b8ae20ccda7fbba292a", size = 950314 }, + { url = "https://files.pythonhosted.org/packages/aa/29/647425fa30874950acc25876b415afa392c3110ed71992850b0a1978479a/scouter_ml-0.3.0rc2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3eafbad481511510be131b3f57a052eb85acf755a9106135a49dd56c0d094455", size = 1031392 }, + { url = "https://files.pythonhosted.org/packages/14/1b/770305395de9921e55b437bfeef3886422531c77de91e87fdd6ccb1bc5ba/scouter_ml-0.3.0rc2-cp311-none-win32.whl", hash = "sha256:92612b1661bbc5889a8527e42fba7b87250de2ed534077f5b43aba706c25f039", size = 737868 }, + { url = "https://files.pythonhosted.org/packages/ae/db/5bc87823f0064b61ac2f7a9dfb27c5d2a6065e89f240d2ec5242cfdaef9e/scouter_ml-0.3.0rc2-cp311-none-win_amd64.whl", hash = "sha256:7fa4abb6ca8271797503fdecbb9163a79b06ac0351a79b15f861c10723a71068", size = 825048 }, + { url = "https://files.pythonhosted.org/packages/50/54/4e9e5b3179ac8eb6ae690ddccc4867c18405b17e5fd71c4e005510655385/scouter_ml-0.3.0rc2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7db89f3d2d963b13b5a7fb10bf5231d9bf1348ca29ab90faed845b684989e44", size = 832168 }, + { url = "https://files.pythonhosted.org/packages/8b/70/c5170a1c06a2ccc5f66c43a37be1a49d414f2f73b4368aee084f4e7ee2df/scouter_ml-0.3.0rc2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0cd7321b207c92a75f4e26aa4242f672d5cfa4a3d837d54d105544cbf3c6b146", size = 757559 }, + { url = "https://files.pythonhosted.org/packages/df/7e/10636a3df0acd5aa60156d272a50530230813c435ded7c39feb5c4119de5/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:30fc71668e1a19ebce5ce85550e1fd501341fb2aff8b3252e998ccd220412c4f", size = 866579 }, + { url = "https://files.pythonhosted.org/packages/25/c5/2fafb6fcede35c9179477349474028a239b28bb21ee4578725cc6ccbe648/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:339c3f817f4b5ad74e339890e2cfeb41a526e27b5bb212e9c0bbe83ce54f080c", size = 781333 }, + { url = "https://files.pythonhosted.org/packages/b2/0f/bc96206c2277e6ec9ef194c4720953dc158a58863730c85508a556407ecb/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:96b5a3fcca4c9d40c39bb142d8672270a8b4f051b90885a1f9e83f77bedf3e1e", size = 795154 }, + { url = "https://files.pythonhosted.org/packages/3b/84/282001c73f1bc70dea3360454a534e92d6be6ef885aa79490762fb7d964d/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e1f702e3c6e48d74ea6f2fdf36136e15a0c9836757fc984564918994c8f9af6e", size = 926475 }, + { url = "https://files.pythonhosted.org/packages/fe/d2/5a25e0b709d9c04241571a9fdf34e8aab9638bfe5b6f2157302c8197d506/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2c4d1eedb462d5cd840d609e46aaab7fb32b32dff4eb266e5eb52cb7cb9558b", size = 1404124 }, + { url = "https://files.pythonhosted.org/packages/0f/f5/d172f47e0cd4862cba1722eca3b3a40a67be72e4802d1f7fecf5e908b18a/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c12f8021b42083616de5f2886193b9bdcf0b92baf0141842960074643498c55", size = 876972 }, + { url = "https://files.pythonhosted.org/packages/99/30/89e5c45e696f9dc483b5c746968ba46402a2c076264d2d6c46563ffe26c5/scouter_ml-0.3.0rc2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9646a6bb2bafa9865136d4596100dbdb07cae76dd7bb43bd5e3acd9188bb8b89", size = 946727 }, + { url = "https://files.pythonhosted.org/packages/68/75/040be29190142496968a242b868ac4db560acec72ae16cd67f97bf0ed77e/scouter_ml-0.3.0rc2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3ee92e4dfa5058c4d8357f12f4107509e8aa5d49d509d81e46efcea35d8ea438", size = 1027703 }, + { url = "https://files.pythonhosted.org/packages/8b/02/b70054cc210fb240e14691aa0b48cfb7f77c6c49622e302991d5ad8a595f/scouter_ml-0.3.0rc2-cp312-none-win32.whl", hash = "sha256:b2f7e444d92c73703640445db9768cf3acd2709fbe2f74b9fb1df2d72ebd55ca", size = 734710 }, + { url = "https://files.pythonhosted.org/packages/55/7e/bc3567c9b4791f50e91f344b693f80376ee22b16c3c8cd21dd86bb131131/scouter_ml-0.3.0rc2-cp312-none-win_amd64.whl", hash = "sha256:9b6d4adda2d00316f06bbab4a1d583e983a1ce19c459666cc075196110183c70", size = 823848 }, + { url = "https://files.pythonhosted.org/packages/ef/a8/a1b96dd70c0c37a77c3cad65648c7b750dca1e9f52389928bd00101dda0d/scouter_ml-0.3.0rc2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a9a445b1a8aee10c22f79ac19520d5a6ec7f661a36aa5cdfaa373b55bd5dc57d", size = 831832 }, + { url = "https://files.pythonhosted.org/packages/19/ea/8bb1d7ce98f595fa6cd4ec1cb77daeb84da6cc2479c85c0cd8dfd54f212e/scouter_ml-0.3.0rc2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6cc1c07a8a39dc27c04f332c7933f267487396a4d9166e9a353606cd192d61b7", size = 757180 }, + { url = "https://files.pythonhosted.org/packages/08/b4/089fc2402958f8c0c35ae210d71bb0e83fd449d2e1608af56d6d15d1b6e4/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfc62c4c26b9e995a2388163719dbe558667b6989be41cb4eb7d9dfacfc5815d", size = 866038 }, + { url = "https://files.pythonhosted.org/packages/b8/22/2b71cdf618210dc3f47606becaab0051d422bf5f4bad59a483740771ad97/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b486fd3fca2ddef4335738a5365d8b1111c5098f005ff848a92c209a8e2cc3b2", size = 781702 }, + { url = "https://files.pythonhosted.org/packages/e7/68/fc6249d2d461bde43b7f1d98a89f84fd9a0ef59c2708b95bdf60cfd0b057/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:690bc35416b5f32e172890fbd2bd72fbd230dbc3c2dce452e9d0da294fe04062", size = 794901 }, + { url = "https://files.pythonhosted.org/packages/6d/6c/76dc76f4c459463e953a67667dc7e1f1a8fd6df6b1a450d0f875b9a63eed/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:da06f483eef3ec4c07e4547f8e70509cf0b01edcfab7e39494d55a9dd906e8ad", size = 928941 }, + { url = "https://files.pythonhosted.org/packages/97/28/2e384d1d31d2210afc2a7e0fc1ca4980e9d00a422755fa5498c4124573a5/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a5ef4e765a8defd71358ec27d1e563e885806d753a704fe1b09b6a094111992", size = 1431570 }, + { url = "https://files.pythonhosted.org/packages/ff/41/b8cb17d1066304971d0b3c9a8a7912cb3678f49ede75dda8fadac8d4fbd2/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66752a0f4d0fd44b31a4874926dad232fff202f38b4d95fcf81d1dc3f4056606", size = 874383 }, + { url = "https://files.pythonhosted.org/packages/fe/14/df40d7b9f36166c63439228bf9cb0c28617b44b4ffec54051914d1a126b2/scouter_ml-0.3.0rc2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aab8b2b577160cec8f61497ba8beb5f56d01c17eb5c22c5129feebadc78896e5", size = 950863 }, + { url = "https://files.pythonhosted.org/packages/29/ac/364efc35eebdb74e939f6a06fb66d441a184dfd93763b21b88d251176d43/scouter_ml-0.3.0rc2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4a622b5457b8436daec735fea2c9ff9137b57091c5f8a36b1f594b4f17644e76", size = 1031670 }, + { url = "https://files.pythonhosted.org/packages/8a/8a/ec47eb6f663dbe9f0827324a6a8afd8c85bb3267d426853b587ed84c794a/scouter_ml-0.3.0rc2-cp39-none-win32.whl", hash = "sha256:e6899ea428ba15cf482cf37cf3f7712870c1059e99cba02da788bfb02c203988", size = 738011 }, + { url = "https://files.pythonhosted.org/packages/24/75/5af207869df16b46be654018af633553729a1ab448fa50266d857b33f530/scouter_ml-0.3.0rc2-cp39-none-win_amd64.whl", hash = "sha256:58f83c9ab9eb24295566aef83c1af8b14f2f62e0aa303596ea9e79cdaf35e17e", size = 825352 }, + { url = "https://files.pythonhosted.org/packages/f2/16/cea55c4c05a0b214bcb1d6207f28c22d88c97e10ac29d9fbfcba6b868184/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6607110f20412b56cd2648f71227b1aaee1d692131941513581c42e0afee4396", size = 830250 }, + { url = "https://files.pythonhosted.org/packages/ce/e8/1f69c5ed8c92400f2ff81e5097d50426c39f0230895dc9b10578562b77d3/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:852c2faebcf93bd890678b8f90b5d0557c0401df0ad85cda5ab1dfcfffb8a2dc", size = 755682 }, + { url = "https://files.pythonhosted.org/packages/69/a6/0079bfed2641dada93f033cda70f87346cdbdb0b6ad9d8ad385ef2a20d16/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:70309b69ded8b3d6cd376bb2904f4b14a51e0d03ea19fcb552c6c84c6f49fac5", size = 863970 }, + { url = "https://files.pythonhosted.org/packages/09/6b/28c373c449b5b32e0ee298747b57c817ebf4529ffb2333a82b5789f602ff/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38513a5b1fb122c694aaacab079411457477ae23c9137899678bf2acdce6155", size = 780028 }, + { url = "https://files.pythonhosted.org/packages/79/01/ba2b1862f9c1060f7eabe9dd024f7efd8a11ea4df0d066008aa606de7a4d/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:164b835ec60559824eff031581f480aa23cb0a5abd652380290cd82827a27259", size = 793409 }, + { url = "https://files.pythonhosted.org/packages/d0/8f/4929f28765471257f8d405fb08b0f5532703291717798bb4186728475b2e/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4fade44aa574ddd8fc6fe326ef8e81211db9dd9e94597355a0f5973509e3b7cb", size = 927122 }, + { url = "https://files.pythonhosted.org/packages/fb/4b/1932b58ff3ceb7708a0d7578ae46586f8d34d25dce4c55da0a6c2e37f4e2/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e32fe180e559263b04871cdcb4d9924f47387feba160cb55d7c402e4e1974194", size = 1418869 }, + { url = "https://files.pythonhosted.org/packages/97/de/0410a4fff13701314d853d816a2cf56224a669d92ee2d486497f343357ea/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c789b2856e4d0005c0b1cbfe418ef6a6f1e67014826b64b80db3989acab65e", size = 872146 }, + { url = "https://files.pythonhosted.org/packages/34/2b/39070565949d6e186c966bddd2a9434229c50379e88c3022d905bf8af9be/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:8a4112268decfb7eefe997aad6b5750fa485246ca32ca7960c7093d9de18d0ed", size = 950000 }, + { url = "https://files.pythonhosted.org/packages/f6/86/9515f7993cffb503995291b874e62b6e2a9f06218eaa5a456185faee6e87/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:348717c14808bb7197e2bcc74107b726710cd05facbd25e0f4e12235dde96820", size = 1030311 }, + { url = "https://files.pythonhosted.org/packages/df/c3/6c0c3bffc1c95d6df9a46b6e63a7711dee32aeed37a1068d242bad2fa988/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0956655d1455cc5a241279d2d1e21a196e1f2eda8a267dbe3ed47f00ff88cabf", size = 830634 }, + { url = "https://files.pythonhosted.org/packages/9d/55/8c2d3c2eca7eaa9d3d4369a4cedfd089db16593ad8332d71830c01e643ed/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:68ac41ef2c763a44dbce2ab1469a6227e17ab224c19388c3cf0a7710c65ed8aa", size = 755945 }, + { url = "https://files.pythonhosted.org/packages/43/45/e27ac6c21d8b901c605a938d7bad1ab0b7c7f2e42b794e09d9baeace9706/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:559dbe95ab6b14cc4720cb7e820037b8887956016e6cf68e855c352c39774215", size = 864395 }, + { url = "https://files.pythonhosted.org/packages/7f/f0/710e0f80f2767fc20d8667be23de25d3b887aaa49fddea7c7077e066de0e/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39e20c2485de99d64dbb01ce9afba044d5fe4d7d0366799f8e253b31eab3755d", size = 780580 }, + { url = "https://files.pythonhosted.org/packages/61/30/5fd0e91c5915af6a67d1ea02d900c70a4060a0161a51ce61ea94cdbbfcf1/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60f4be567fc7546ec184aa6328385b8b162d187f6177dcf5ace6bbf7fc79b929", size = 793861 }, + { url = "https://files.pythonhosted.org/packages/f0/5b/27516852a924aa8163caae1b96d5c342a446eb9a59c6871dacd36dcf8733/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bec1f52f033beceb53afd414065cb3809fd1fa1da4a52e84fc40998c3cd041b7", size = 927628 }, + { url = "https://files.pythonhosted.org/packages/db/28/1b80aab7f5fd3a4337bf3a3ba55b01c76c25a2369541e325136d3106d31b/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08835759a5b51b57c5d1d29e3f57edcabdb5b77939c83a9707ba3cb716ec4924", size = 1420284 }, + { url = "https://files.pythonhosted.org/packages/d4/17/90c78bb600c167ad4983dea2f18373962b39617f2a3f89cdba430036e881/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81e0e4a2f370c76b20012f602febe9528b22b797233cd417a6c248e7a384e6a6", size = 872668 }, + { url = "https://files.pythonhosted.org/packages/10/3b/20a226e2337327f02814decdab878479190272ac266392fc51a99323afc1/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fc9615d538278eecd2deabd41365e43872d71a241545eec11a1ad644e5039bc2", size = 950610 }, + { url = "https://files.pythonhosted.org/packages/66/bf/81805b3c1d3950e87581d10ff66086ba0098679f1c3f1d52b1039502b7fe/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f7641db570e88136c5e68d827feb4babae571e599ae5df73c9aa8e42ffbce792", size = 1030665 }, ] [[package]] From 95931c96f4cddd8a207a182052b357ed1a184a6f Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 16:24:46 -0400 Subject: [PATCH 09/16] integration work --- opsml/storage/card_saver.py | 25 +++++++++++++------ tests/conftest.py | 8 ++---- tests/test_registry/test_registry.py | 37 ++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/opsml/storage/card_saver.py b/opsml/storage/card_saver.py index 7fb2f285f..bfb92c7e8 100644 --- a/opsml/storage/card_saver.py +++ b/opsml/storage/card_saver.py @@ -387,7 +387,15 @@ def _save_modelcard(self) -> None: dumped_model = self.card.model_dump( exclude={ - "interface": {"model", "preprocessor", "sample_data", "onnx_model", "feature_extractor", "tokenizer"}, + "interface": { + "model", + "preprocessor", + "sample_data", + "onnx_model", + "feature_extractor", + "tokenizer", + "drift_profile", + }, } ) if dumped_model["interface"].get("onnx_args") is not None: @@ -412,11 +420,14 @@ def _save_drift_profile(self) -> None: assert self.card.interface.drift_profile is not None, "Drift Profile must be set on Model Interface" - # update drift profile repository, name and version - self.card.interface.drift_profile.config.repository = self.card.repository - self.card.interface.drift_profile.config.name = self.card.name - self.card.interface.drift_profile.config.version = self.card.version + # update config with model name, repository and version + config = self.card.interface.drift_profile.config + config.name = self.card.name + config.repository = self.card.repository + config.version = self.card.version + # update drift profile repository, name and version + self.card.interface.drift_profile.config = config save_path = Path(self.lpath / SaveName.DRIFT_PROFILE.value).with_suffix(Suffix.JSON.value) self.card.interface.save_drift_profile(save_path) @@ -569,9 +580,7 @@ def save_card_artifacts(card: Card) -> None: """ - card_saver = next( - card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type) - ) + card_saver = next(card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type)) saver = card_saver(card=card) diff --git a/tests/conftest.py b/tests/conftest.py index 631e6c314..941ad2e0a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -943,9 +943,7 @@ def sklearn_pipeline() -> Tuple[SklearnModel, PandasData]: transformers=[("cat", categorical_transformer, cat_cols)], remainder="passthrough", ) - pipe = Pipeline( - [("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))] - ) + pipe = Pipeline([("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))]) pipe.fit(train_data, data["y"]) sql_logic = {"test": "SELECT * FROM TEST_TABLE"} @@ -2355,9 +2353,7 @@ def stacking_classifier(): ("rf", ensemble.RandomForestClassifier(n_estimators=10, random_state=42)), ("svr", make_pipeline(StandardScaler(), linear_model.LogisticRegression(max_iter=5))), ] - reg = ensemble.StackingClassifier( - estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5) - ) + reg = ensemble.StackingClassifier(estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5)) reg.fit(X, y) return SklearnModel(model=reg, sample_data=X) diff --git a/tests/test_registry/test_registry.py b/tests/test_registry/test_registry.py index 8f1cfff0a..c3f5f3b13 100644 --- a/tests/test_registry/test_registry.py +++ b/tests/test_registry/test_registry.py @@ -30,6 +30,7 @@ PolarsData, SqlData, ) +from scouter import DriftConfig from opsml.helpers.exceptions import VersionError from opsml.model import ModelInterface, SklearnModel from opsml.registry import CardRegistries @@ -882,3 +883,39 @@ def test_sort_timestamp(sql_data: SqlData, db_registries: CardRegistries) -> Non cards = registry.list_cards(sort_by_timestamp=True) assert cards[0]["name"] == "test2" assert cards[1]["name"] == "test1" + + +def test_model_registry_scouter( + db_registries: CardRegistries, + sklearn_pipeline: Tuple[ModelInterface, DataInterface], +) -> None: + # create data card + data_registry = db_registries.data + model, data = sklearn_pipeline + + data_card = DataCard( + interface=data, + name="pipeline_data", + repository="mlops", + contact="mlops.com", + ) + data_registry.register_card(card=data_card) + + drift_config = DriftConfig() + model.create_drift_profile(data.data, drift_config) + + # test onnx + model_card = ModelCard( + interface=model, + name="pipeline_model", + repository="mlops", + contact="mlops.com", + datacard_uid=data_card.uid, + to_onnx=True, + ) + + model_registry = db_registries.model + model_registry.register_card(card=model_card) + + assert model_card.interface.drift_profile is not None + assert model_card.interface.drift_profile.config.name == model_card.name From a6806605b2bb36d02222e92d11c824e93b76b845 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 20:15:28 -0400 Subject: [PATCH 10/16] update args --- .gitignore | 1 + opsml/storage/card_saver.py | 14 +-- pyproject.toml | 2 +- tests/conftest.py | 8 +- tests/test_registry/test_registry.py | 2 +- uv.lock | 140 +++++++++++++-------------- 6 files changed, 87 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index a3a68ed16..bcd808adb 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,7 @@ notebooks/ .test_local.py lightning_logs/ node_modules/ +target/ # git **/*.orig diff --git a/opsml/storage/card_saver.py b/opsml/storage/card_saver.py index bfb92c7e8..f86cddf3e 100644 --- a/opsml/storage/card_saver.py +++ b/opsml/storage/card_saver.py @@ -421,13 +421,13 @@ def _save_drift_profile(self) -> None: assert self.card.interface.drift_profile is not None, "Drift Profile must be set on Model Interface" # update config with model name, repository and version - config = self.card.interface.drift_profile.config - config.name = self.card.name - config.repository = self.card.repository - config.version = self.card.version + self.card.interface.drift_profile.update_config_args( + name=self.card.name, + repository=self.card.repository, + version=self.card.version, + ) # update drift profile repository, name and version - self.card.interface.drift_profile.config = config save_path = Path(self.lpath / SaveName.DRIFT_PROFILE.value).with_suffix(Suffix.JSON.value) self.card.interface.save_drift_profile(save_path) @@ -580,7 +580,9 @@ def save_card_artifacts(card: Card) -> None: """ - card_saver = next(card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type)) + card_saver = next( + card_saver for card_saver in CardSaver.__subclasses__() if card_saver.validate(card_type=card.card_type) + ) saver = card_saver(card=card) diff --git a/pyproject.toml b/pyproject.toml index ca8174920..f0eab2423 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,7 +18,6 @@ dependencies = [ "pyyaml~=6.0.1", "rich~=13.3.5", "rusty-logger~=0.3.0", - "scouter-ml==0.3.0rc2", "semver~=2.13.0", "tenacity~=8.2.2", "zarr~=2.12.0", @@ -26,6 +25,7 @@ dependencies = [ "PyJWT~=2.8", "nvidia-ml-py>=12.560.30", "pipdeptree>=2.23.1", + "scouter-ml==0.3.0rc3", ] [project.scripts] diff --git a/tests/conftest.py b/tests/conftest.py index 941ad2e0a..631e6c314 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -943,7 +943,9 @@ def sklearn_pipeline() -> Tuple[SklearnModel, PandasData]: transformers=[("cat", categorical_transformer, cat_cols)], remainder="passthrough", ) - pipe = Pipeline([("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))]) + pipe = Pipeline( + [("preprocess", preprocessor), ("rf", lgb.LGBMRegressor(n_estimators=3, max_depth=3, num_leaves=5))] + ) pipe.fit(train_data, data["y"]) sql_logic = {"test": "SELECT * FROM TEST_TABLE"} @@ -2353,7 +2355,9 @@ def stacking_classifier(): ("rf", ensemble.RandomForestClassifier(n_estimators=10, random_state=42)), ("svr", make_pipeline(StandardScaler(), linear_model.LogisticRegression(max_iter=5))), ] - reg = ensemble.StackingClassifier(estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5)) + reg = ensemble.StackingClassifier( + estimators=estimators, final_estimator=linear_model.LogisticRegression(max_iter=5) + ) reg.fit(X, y) return SklearnModel(model=reg, sample_data=X) diff --git a/tests/test_registry/test_registry.py b/tests/test_registry/test_registry.py index c3f5f3b13..8ea61980a 100644 --- a/tests/test_registry/test_registry.py +++ b/tests/test_registry/test_registry.py @@ -12,6 +12,7 @@ import polars as pl import pytest from pytest_lazyfixture import lazy_fixture +from scouter import DriftConfig from sqlalchemy import select from opsml.cards import ( @@ -30,7 +31,6 @@ PolarsData, SqlData, ) -from scouter import DriftConfig from opsml.helpers.exceptions import VersionError from opsml.model import ModelInterface, SklearnModel from opsml.registry import CardRegistries diff --git a/uv.lock b/uv.lock index 76a0c0390..24237c4f2 100644 --- a/uv.lock +++ b/uv.lock @@ -3012,7 +3012,7 @@ requires-dist = [ { name = "s3fs", marker = "extra == 'aws-mysql'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 'aws-postgres'", specifier = "~=2024.2.0" }, { name = "s3fs", marker = "extra == 's3'", specifier = "~=2024.2.0" }, - { name = "scouter-ml", specifier = "==0.3.0rc2" }, + { name = "scouter-ml", specifier = "==0.3.0rc3" }, { name = "semver", specifier = "~=2.13.0" }, { name = "skl2onnx", marker = "extra == 'sklearn-onnx'", specifier = "==1.16.0" }, { name = "sqlalchemy", extras = ["mypy"], marker = "extra == 'server'", specifier = "~=2.0" }, @@ -4484,7 +4484,7 @@ wheels = [ [[package]] name = "scouter-ml" -version = "0.3.0rc2" +version = "0.3.0rc3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy" }, @@ -4495,74 +4495,74 @@ dependencies = [ { name = "rusty-logger" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/df/18/47c3a5936b3904e922b26176c4c5bf70619d8d1b6efa3de105c6d937e707/scouter_ml-0.3.0rc2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:377481e3dd8069be7fb028bcb068473a8e3b0f2e1dcaed82a5094944b4bcd0fe", size = 831669 }, - { url = "https://files.pythonhosted.org/packages/98/7e/bd5531c61000ea17204671e53b34d401d0b2ef9e05accdf0b8ef09c14b7b/scouter_ml-0.3.0rc2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a668f12856b2197c3835a3890158f18909a2c868ef902cde8161a728afb5a44e", size = 756964 }, - { url = "https://files.pythonhosted.org/packages/5e/dc/e853589c3584416f734949ce65866fd699d461170277a8c6e11e0e0ed386/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:44210000bd9a51462ec62ba821e0c8a53ee4b182f3294cbd1e0654410c2e59ec", size = 865467 }, - { url = "https://files.pythonhosted.org/packages/a3/44/dee14b105231eed058ad2469259cde19458d5212a060cb920a700feec16c/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff4c1655e591b664b68d1728729f2fd2f624536e99baee97ea75f9de1fbdba09", size = 781202 }, - { url = "https://files.pythonhosted.org/packages/5a/83/6f54a9618c1104f3dd26dc1187e400eee7b4f429117e9c00165d1b3156ac/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d5c6cef4219404d07c5b7386a0de89b1a5565cbedf3b1c4d9dcc31ef73de6693", size = 794659 }, - { url = "https://files.pythonhosted.org/packages/ba/8b/ddfded5d1a781c4b91870e49c5a95c1fd2400a18d20927f4c723180154df/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca5f482ddd4dba63408eb1a9c2f563d8bc66172eb3749efef106aeb5c04ba14b", size = 928326 }, - { url = "https://files.pythonhosted.org/packages/33/7f/2254aac342cede8aeb4da7248a10ec69944ebb9a9cfe0ca4c075d8ccad21/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e83a16f6d9e82991b8e871193de91ef7083d7e1becf0faccaa50471b3df7deee", size = 1430813 }, - { url = "https://files.pythonhosted.org/packages/d4/dc/29af39281930bdf155f1837df4ad00d701a059b7b35d9f469270fd7a6dc8/scouter_ml-0.3.0rc2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83c1b153ee0119a09c3b95cb62c85324917055b2154983288da90a20a1f32b0b", size = 873968 }, - { url = "https://files.pythonhosted.org/packages/8d/14/2cebf6bdc8a8d2e06386bfeece73fef0df2b47b9f2312612ec303ca7ea8e/scouter_ml-0.3.0rc2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:99bbd7c7ddff11effb4731626f920bd02bcdf0ad0900630f2fa1934742944157", size = 950248 }, - { url = "https://files.pythonhosted.org/packages/ef/a0/571f225972aafda42e5bd4237e9448a366612174b67d06a9cc2e3fa21eae/scouter_ml-0.3.0rc2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a8fb06ec887a82a2c64118a0fc591aa6fe209e9519905b0a5373070d9c063310", size = 1031319 }, - { url = "https://files.pythonhosted.org/packages/75/01/b3d1f13858f6089d12dddc7482a59f11c909d72070ffd757a59655896b1a/scouter_ml-0.3.0rc2-cp310-none-win32.whl", hash = "sha256:9ad1a9fb9670d310b8c9e2322f754bcdce72beff68539b8bfc2559a273ffca52", size = 737796 }, - { url = "https://files.pythonhosted.org/packages/61/ed/13f805f71c40bcba47d4e2df965b32887509f011b25a1cfdbea4269d294c/scouter_ml-0.3.0rc2-cp310-none-win_amd64.whl", hash = "sha256:ba1190ed99747f717cc29f948a228d63cfe67092735c806261e8cfeaaefe5d3c", size = 825060 }, - { url = "https://files.pythonhosted.org/packages/87/ab/2963051fbf2164291745045c43561190892dcb8fc778226477a8634277c2/scouter_ml-0.3.0rc2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:30a891cdb9fa9236c1a3b570960c40e354c5067266970e9a746b2f84d73ba7be", size = 831589 }, - { url = "https://files.pythonhosted.org/packages/63/65/ec62fb098cde8d04d8006c5d5fce2e9d8674bf4f91c9883da579339c281d/scouter_ml-0.3.0rc2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7c31041fbf5777de11feb86c2483dd204453d6ba0f0787929263509f06d7091", size = 756971 }, - { url = "https://files.pythonhosted.org/packages/6f/ea/c129d654581cc3f9ebaee01f22ca438ef3bffaeff935c0b5abe19ba221f3/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d18f8d737cfc09a29f78c03ecabc99f05db0999553b3c1c1d4781a3eb591de63", size = 865562 }, - { url = "https://files.pythonhosted.org/packages/7c/4c/c6be409bab131615a37d4db2390c8f8a0c01ab48948acce3747ad0d6de68/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b02ed51af7e31842e67b4ec936d2bce06f50af538bbc499a881241d35f0cdede", size = 781290 }, - { url = "https://files.pythonhosted.org/packages/6f/8d/b26609f3263f9a58da53e02a45d5f4f8992e43471019480cf793d6e928a9/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a21dba052d79dbf19631b56aa1b562c48f315767b2f20d92beb82ed86c4d3c78", size = 794800 }, - { url = "https://files.pythonhosted.org/packages/7c/b2/fbc0d54f91641815c03355c1b06069aed0f26599a12daaf2c7044bd48372/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89b112113187c04fa39b951f0cd2edaad4af481a3f054d417df0c2624e5a5b7a", size = 928393 }, - { url = "https://files.pythonhosted.org/packages/b3/bb/2d07eb693f8dd9a4c653a54f8f721a48f7381eec1201364aab08ed9d9c2a/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c348ec9ea40e9dcb00afcec5a80adea334f8d699500e07e5b5a8f9f4c033d38", size = 1430693 }, - { url = "https://files.pythonhosted.org/packages/3b/54/38ca0ad74b4e683fa406c42201e9f79f8faaef85201c5907fa03d8d538e7/scouter_ml-0.3.0rc2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1556eda025bbab5b41e05c9773fe12bb2a87b34131b8807593e5bd71fa4e1471", size = 874017 }, - { url = "https://files.pythonhosted.org/packages/2a/fd/44a1663c9f59574a2da09994b77b7ca673d5e1a85f8a37f97e43e78fb89e/scouter_ml-0.3.0rc2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:25ad831c26b9086282b40ba6eadeeda977d816488a1f2b8ae20ccda7fbba292a", size = 950314 }, - { url = "https://files.pythonhosted.org/packages/aa/29/647425fa30874950acc25876b415afa392c3110ed71992850b0a1978479a/scouter_ml-0.3.0rc2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3eafbad481511510be131b3f57a052eb85acf755a9106135a49dd56c0d094455", size = 1031392 }, - { url = "https://files.pythonhosted.org/packages/14/1b/770305395de9921e55b437bfeef3886422531c77de91e87fdd6ccb1bc5ba/scouter_ml-0.3.0rc2-cp311-none-win32.whl", hash = "sha256:92612b1661bbc5889a8527e42fba7b87250de2ed534077f5b43aba706c25f039", size = 737868 }, - { url = "https://files.pythonhosted.org/packages/ae/db/5bc87823f0064b61ac2f7a9dfb27c5d2a6065e89f240d2ec5242cfdaef9e/scouter_ml-0.3.0rc2-cp311-none-win_amd64.whl", hash = "sha256:7fa4abb6ca8271797503fdecbb9163a79b06ac0351a79b15f861c10723a71068", size = 825048 }, - { url = "https://files.pythonhosted.org/packages/50/54/4e9e5b3179ac8eb6ae690ddccc4867c18405b17e5fd71c4e005510655385/scouter_ml-0.3.0rc2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7db89f3d2d963b13b5a7fb10bf5231d9bf1348ca29ab90faed845b684989e44", size = 832168 }, - { url = "https://files.pythonhosted.org/packages/8b/70/c5170a1c06a2ccc5f66c43a37be1a49d414f2f73b4368aee084f4e7ee2df/scouter_ml-0.3.0rc2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0cd7321b207c92a75f4e26aa4242f672d5cfa4a3d837d54d105544cbf3c6b146", size = 757559 }, - { url = "https://files.pythonhosted.org/packages/df/7e/10636a3df0acd5aa60156d272a50530230813c435ded7c39feb5c4119de5/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:30fc71668e1a19ebce5ce85550e1fd501341fb2aff8b3252e998ccd220412c4f", size = 866579 }, - { url = "https://files.pythonhosted.org/packages/25/c5/2fafb6fcede35c9179477349474028a239b28bb21ee4578725cc6ccbe648/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:339c3f817f4b5ad74e339890e2cfeb41a526e27b5bb212e9c0bbe83ce54f080c", size = 781333 }, - { url = "https://files.pythonhosted.org/packages/b2/0f/bc96206c2277e6ec9ef194c4720953dc158a58863730c85508a556407ecb/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:96b5a3fcca4c9d40c39bb142d8672270a8b4f051b90885a1f9e83f77bedf3e1e", size = 795154 }, - { url = "https://files.pythonhosted.org/packages/3b/84/282001c73f1bc70dea3360454a534e92d6be6ef885aa79490762fb7d964d/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e1f702e3c6e48d74ea6f2fdf36136e15a0c9836757fc984564918994c8f9af6e", size = 926475 }, - { url = "https://files.pythonhosted.org/packages/fe/d2/5a25e0b709d9c04241571a9fdf34e8aab9638bfe5b6f2157302c8197d506/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2c4d1eedb462d5cd840d609e46aaab7fb32b32dff4eb266e5eb52cb7cb9558b", size = 1404124 }, - { url = "https://files.pythonhosted.org/packages/0f/f5/d172f47e0cd4862cba1722eca3b3a40a67be72e4802d1f7fecf5e908b18a/scouter_ml-0.3.0rc2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c12f8021b42083616de5f2886193b9bdcf0b92baf0141842960074643498c55", size = 876972 }, - { url = "https://files.pythonhosted.org/packages/99/30/89e5c45e696f9dc483b5c746968ba46402a2c076264d2d6c46563ffe26c5/scouter_ml-0.3.0rc2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9646a6bb2bafa9865136d4596100dbdb07cae76dd7bb43bd5e3acd9188bb8b89", size = 946727 }, - { url = "https://files.pythonhosted.org/packages/68/75/040be29190142496968a242b868ac4db560acec72ae16cd67f97bf0ed77e/scouter_ml-0.3.0rc2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3ee92e4dfa5058c4d8357f12f4107509e8aa5d49d509d81e46efcea35d8ea438", size = 1027703 }, - { url = "https://files.pythonhosted.org/packages/8b/02/b70054cc210fb240e14691aa0b48cfb7f77c6c49622e302991d5ad8a595f/scouter_ml-0.3.0rc2-cp312-none-win32.whl", hash = "sha256:b2f7e444d92c73703640445db9768cf3acd2709fbe2f74b9fb1df2d72ebd55ca", size = 734710 }, - { url = "https://files.pythonhosted.org/packages/55/7e/bc3567c9b4791f50e91f344b693f80376ee22b16c3c8cd21dd86bb131131/scouter_ml-0.3.0rc2-cp312-none-win_amd64.whl", hash = "sha256:9b6d4adda2d00316f06bbab4a1d583e983a1ce19c459666cc075196110183c70", size = 823848 }, - { url = "https://files.pythonhosted.org/packages/ef/a8/a1b96dd70c0c37a77c3cad65648c7b750dca1e9f52389928bd00101dda0d/scouter_ml-0.3.0rc2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a9a445b1a8aee10c22f79ac19520d5a6ec7f661a36aa5cdfaa373b55bd5dc57d", size = 831832 }, - { url = "https://files.pythonhosted.org/packages/19/ea/8bb1d7ce98f595fa6cd4ec1cb77daeb84da6cc2479c85c0cd8dfd54f212e/scouter_ml-0.3.0rc2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6cc1c07a8a39dc27c04f332c7933f267487396a4d9166e9a353606cd192d61b7", size = 757180 }, - { url = "https://files.pythonhosted.org/packages/08/b4/089fc2402958f8c0c35ae210d71bb0e83fd449d2e1608af56d6d15d1b6e4/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cfc62c4c26b9e995a2388163719dbe558667b6989be41cb4eb7d9dfacfc5815d", size = 866038 }, - { url = "https://files.pythonhosted.org/packages/b8/22/2b71cdf618210dc3f47606becaab0051d422bf5f4bad59a483740771ad97/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b486fd3fca2ddef4335738a5365d8b1111c5098f005ff848a92c209a8e2cc3b2", size = 781702 }, - { url = "https://files.pythonhosted.org/packages/e7/68/fc6249d2d461bde43b7f1d98a89f84fd9a0ef59c2708b95bdf60cfd0b057/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:690bc35416b5f32e172890fbd2bd72fbd230dbc3c2dce452e9d0da294fe04062", size = 794901 }, - { url = "https://files.pythonhosted.org/packages/6d/6c/76dc76f4c459463e953a67667dc7e1f1a8fd6df6b1a450d0f875b9a63eed/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:da06f483eef3ec4c07e4547f8e70509cf0b01edcfab7e39494d55a9dd906e8ad", size = 928941 }, - { url = "https://files.pythonhosted.org/packages/97/28/2e384d1d31d2210afc2a7e0fc1ca4980e9d00a422755fa5498c4124573a5/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a5ef4e765a8defd71358ec27d1e563e885806d753a704fe1b09b6a094111992", size = 1431570 }, - { url = "https://files.pythonhosted.org/packages/ff/41/b8cb17d1066304971d0b3c9a8a7912cb3678f49ede75dda8fadac8d4fbd2/scouter_ml-0.3.0rc2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66752a0f4d0fd44b31a4874926dad232fff202f38b4d95fcf81d1dc3f4056606", size = 874383 }, - { url = "https://files.pythonhosted.org/packages/fe/14/df40d7b9f36166c63439228bf9cb0c28617b44b4ffec54051914d1a126b2/scouter_ml-0.3.0rc2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aab8b2b577160cec8f61497ba8beb5f56d01c17eb5c22c5129feebadc78896e5", size = 950863 }, - { url = "https://files.pythonhosted.org/packages/29/ac/364efc35eebdb74e939f6a06fb66d441a184dfd93763b21b88d251176d43/scouter_ml-0.3.0rc2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4a622b5457b8436daec735fea2c9ff9137b57091c5f8a36b1f594b4f17644e76", size = 1031670 }, - { url = "https://files.pythonhosted.org/packages/8a/8a/ec47eb6f663dbe9f0827324a6a8afd8c85bb3267d426853b587ed84c794a/scouter_ml-0.3.0rc2-cp39-none-win32.whl", hash = "sha256:e6899ea428ba15cf482cf37cf3f7712870c1059e99cba02da788bfb02c203988", size = 738011 }, - { url = "https://files.pythonhosted.org/packages/24/75/5af207869df16b46be654018af633553729a1ab448fa50266d857b33f530/scouter_ml-0.3.0rc2-cp39-none-win_amd64.whl", hash = "sha256:58f83c9ab9eb24295566aef83c1af8b14f2f62e0aa303596ea9e79cdaf35e17e", size = 825352 }, - { url = "https://files.pythonhosted.org/packages/f2/16/cea55c4c05a0b214bcb1d6207f28c22d88c97e10ac29d9fbfcba6b868184/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6607110f20412b56cd2648f71227b1aaee1d692131941513581c42e0afee4396", size = 830250 }, - { url = "https://files.pythonhosted.org/packages/ce/e8/1f69c5ed8c92400f2ff81e5097d50426c39f0230895dc9b10578562b77d3/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:852c2faebcf93bd890678b8f90b5d0557c0401df0ad85cda5ab1dfcfffb8a2dc", size = 755682 }, - { url = "https://files.pythonhosted.org/packages/69/a6/0079bfed2641dada93f033cda70f87346cdbdb0b6ad9d8ad385ef2a20d16/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:70309b69ded8b3d6cd376bb2904f4b14a51e0d03ea19fcb552c6c84c6f49fac5", size = 863970 }, - { url = "https://files.pythonhosted.org/packages/09/6b/28c373c449b5b32e0ee298747b57c817ebf4529ffb2333a82b5789f602ff/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38513a5b1fb122c694aaacab079411457477ae23c9137899678bf2acdce6155", size = 780028 }, - { url = "https://files.pythonhosted.org/packages/79/01/ba2b1862f9c1060f7eabe9dd024f7efd8a11ea4df0d066008aa606de7a4d/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:164b835ec60559824eff031581f480aa23cb0a5abd652380290cd82827a27259", size = 793409 }, - { url = "https://files.pythonhosted.org/packages/d0/8f/4929f28765471257f8d405fb08b0f5532703291717798bb4186728475b2e/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4fade44aa574ddd8fc6fe326ef8e81211db9dd9e94597355a0f5973509e3b7cb", size = 927122 }, - { url = "https://files.pythonhosted.org/packages/fb/4b/1932b58ff3ceb7708a0d7578ae46586f8d34d25dce4c55da0a6c2e37f4e2/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e32fe180e559263b04871cdcb4d9924f47387feba160cb55d7c402e4e1974194", size = 1418869 }, - { url = "https://files.pythonhosted.org/packages/97/de/0410a4fff13701314d853d816a2cf56224a669d92ee2d486497f343357ea/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c789b2856e4d0005c0b1cbfe418ef6a6f1e67014826b64b80db3989acab65e", size = 872146 }, - { url = "https://files.pythonhosted.org/packages/34/2b/39070565949d6e186c966bddd2a9434229c50379e88c3022d905bf8af9be/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:8a4112268decfb7eefe997aad6b5750fa485246ca32ca7960c7093d9de18d0ed", size = 950000 }, - { url = "https://files.pythonhosted.org/packages/f6/86/9515f7993cffb503995291b874e62b6e2a9f06218eaa5a456185faee6e87/scouter_ml-0.3.0rc2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:348717c14808bb7197e2bcc74107b726710cd05facbd25e0f4e12235dde96820", size = 1030311 }, - { url = "https://files.pythonhosted.org/packages/df/c3/6c0c3bffc1c95d6df9a46b6e63a7711dee32aeed37a1068d242bad2fa988/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0956655d1455cc5a241279d2d1e21a196e1f2eda8a267dbe3ed47f00ff88cabf", size = 830634 }, - { url = "https://files.pythonhosted.org/packages/9d/55/8c2d3c2eca7eaa9d3d4369a4cedfd089db16593ad8332d71830c01e643ed/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:68ac41ef2c763a44dbce2ab1469a6227e17ab224c19388c3cf0a7710c65ed8aa", size = 755945 }, - { url = "https://files.pythonhosted.org/packages/43/45/e27ac6c21d8b901c605a938d7bad1ab0b7c7f2e42b794e09d9baeace9706/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:559dbe95ab6b14cc4720cb7e820037b8887956016e6cf68e855c352c39774215", size = 864395 }, - { url = "https://files.pythonhosted.org/packages/7f/f0/710e0f80f2767fc20d8667be23de25d3b887aaa49fddea7c7077e066de0e/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39e20c2485de99d64dbb01ce9afba044d5fe4d7d0366799f8e253b31eab3755d", size = 780580 }, - { url = "https://files.pythonhosted.org/packages/61/30/5fd0e91c5915af6a67d1ea02d900c70a4060a0161a51ce61ea94cdbbfcf1/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:60f4be567fc7546ec184aa6328385b8b162d187f6177dcf5ace6bbf7fc79b929", size = 793861 }, - { url = "https://files.pythonhosted.org/packages/f0/5b/27516852a924aa8163caae1b96d5c342a446eb9a59c6871dacd36dcf8733/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bec1f52f033beceb53afd414065cb3809fd1fa1da4a52e84fc40998c3cd041b7", size = 927628 }, - { url = "https://files.pythonhosted.org/packages/db/28/1b80aab7f5fd3a4337bf3a3ba55b01c76c25a2369541e325136d3106d31b/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08835759a5b51b57c5d1d29e3f57edcabdb5b77939c83a9707ba3cb716ec4924", size = 1420284 }, - { url = "https://files.pythonhosted.org/packages/d4/17/90c78bb600c167ad4983dea2f18373962b39617f2a3f89cdba430036e881/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81e0e4a2f370c76b20012f602febe9528b22b797233cd417a6c248e7a384e6a6", size = 872668 }, - { url = "https://files.pythonhosted.org/packages/10/3b/20a226e2337327f02814decdab878479190272ac266392fc51a99323afc1/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fc9615d538278eecd2deabd41365e43872d71a241545eec11a1ad644e5039bc2", size = 950610 }, - { url = "https://files.pythonhosted.org/packages/66/bf/81805b3c1d3950e87581d10ff66086ba0098679f1c3f1d52b1039502b7fe/scouter_ml-0.3.0rc2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f7641db570e88136c5e68d827feb4babae571e599ae5df73c9aa8e42ffbce792", size = 1030665 }, + { url = "https://files.pythonhosted.org/packages/3a/dc/a3b7bf32d70a84a7fb14419e8c5dc4b39b2a5624f23253098fe673800741/scouter_ml-0.3.0rc3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b2eceb5174a0d35508ae2d6ac419e0c331a74a7fe1856a598d37abcfcdeb146e", size = 834301 }, + { url = "https://files.pythonhosted.org/packages/a5/21/342feebd21526b85ab76fcbae3dab65a53fabe55f1089d25b14fb1ccfc87/scouter_ml-0.3.0rc3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e37630189517b6a711e7c73788d2cc38d73b6641468724a9afce773d2950010", size = 760545 }, + { url = "https://files.pythonhosted.org/packages/21/af/aa2b2d296c9930a931612a2d82652a5b1561d1fb60148ef5c7fc999baf94/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1ffd90af5f37b25c5c1324c43f4f0b16a9c6aaef6d0969b4c6711e18f41e9b3a", size = 869121 }, + { url = "https://files.pythonhosted.org/packages/0d/ae/600903c7eed37af74ecf77afd02b5274d53e7ce2327b5358af60c0c353e4/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a14003bf8e9b77387b5ac8069702570d3fc0c9c803b019021cc867fdeced4ad", size = 784166 }, + { url = "https://files.pythonhosted.org/packages/78/6c/43cc018096356e9a9f2cbeefab3dfd917cecc43c3915a36b5b858465f875/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5bdd9c944f7d53f94c0501043a31c4e0e2ae0ebcff93f41836dccaf95c34c16", size = 797571 }, + { url = "https://files.pythonhosted.org/packages/e4/67/c3d1e6505bb8703bd42139f8126e859d8cae64f3812ddbdf488a8ef7bd48/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c074685ddede1657333834878852b3d94d6a4e4a75fc61d2b8ca9e5b488da2a1", size = 933996 }, + { url = "https://files.pythonhosted.org/packages/b9/a6/0e3bd997de57087df9bfca6c017013e5c77f4ca828765e91d742b32b6651/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48abdacf1058244dc3d190fd6fd6d1b891c278d1e97f3dbf00842ea51a5f718f", size = 1441573 }, + { url = "https://files.pythonhosted.org/packages/6d/75/cda43e1903b8ab98fb534902ef0c02506dbc42b613612d993013a5d1cc16/scouter_ml-0.3.0rc3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f843902a13771025f9fdb489eddb9c5e3e614bb413bc17cb63570eb0044fb6cb", size = 878284 }, + { url = "https://files.pythonhosted.org/packages/11/1a/cd4625d462d0264e6aa3bd5d175788c3494ed7db26624a413b80d91de97f/scouter_ml-0.3.0rc3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b60443de35d1181660b6cb49b9a3dff025c5d8d4e43a4a0f90e1102c0ad8013", size = 954904 }, + { url = "https://files.pythonhosted.org/packages/78/3e/dd169102441d45ac764e5df50f71908a6016a5fbdcbdb71b20f4f182d066/scouter_ml-0.3.0rc3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0de51dce5b57169eb55392dd000d03281b982369c57869e3a2f4bb018685301b", size = 1036235 }, + { url = "https://files.pythonhosted.org/packages/72/cb/cda2e3bd82fe8c68218600fceb6a18211da57ffb4daeaa00a432a23ff9e1/scouter_ml-0.3.0rc3-cp310-none-win32.whl", hash = "sha256:c29dc68538c67ebf7668d75dd0e2ef58ea5c1ea6f628cef5e8942873a3b8b0a7", size = 741389 }, + { url = "https://files.pythonhosted.org/packages/19/80/44bd9ff9c41648a5760190eb939360388dd806b9b22b542cb2e416786815/scouter_ml-0.3.0rc3-cp310-none-win_amd64.whl", hash = "sha256:cdc5eb826612d2cb5480795e7bf078c96d8c890e8e242039dca1197ba9bfc320", size = 830307 }, + { url = "https://files.pythonhosted.org/packages/1f/59/0a6eed64a34d578011f03963d12c7e1d3ec48e7b3d845a8886011729e133/scouter_ml-0.3.0rc3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:16f54041b5cbbdf0596eed19773bae8109ea41589ac50722a13e9fc37fb73c12", size = 834280 }, + { url = "https://files.pythonhosted.org/packages/aa/32/3ec3c055a71850497f4dec348518b1892d00bb7c5013b347fe82796bb6d1/scouter_ml-0.3.0rc3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc1329c32181640c9cacd7c74d766b5693612d7595211ac9afd6781b9ef72851", size = 760600 }, + { url = "https://files.pythonhosted.org/packages/46/0f/32ed575586d30bd1a99f6fa5d01b6765aa3db2c845251a536c40dc797bd3/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:df3569790deda70272b52ba844eecf21b429af1bc49cdbf452a109f5b5dccebf", size = 869290 }, + { url = "https://files.pythonhosted.org/packages/a1/0f/f5b3c3a71a27563f2fb827b3b95f5554a654d41a3879eb19191fc1e1907e/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe7b5c7e825598bedf23a075b046481a6fcde582511962dd4f0d9759d6963a2", size = 784250 }, + { url = "https://files.pythonhosted.org/packages/b3/92/2e45b1dc804114a850d9a26d788dc46134c7367caea923dbde7687dbe2c7/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9ae4289341198f21bc2b4c86fee6f596ab5817d03109512d8ecde889f973cd4a", size = 797699 }, + { url = "https://files.pythonhosted.org/packages/c6/e1/affa775b5f807651fcaed51832b15e11126e3dbfe0e3696a17410acaab4c/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c0548e2d0ba98ec65c7ee3a8b927b8f844a35d74f5a03a0c6ca249a52ccb69", size = 933915 }, + { url = "https://files.pythonhosted.org/packages/db/3c/5617fe71b74e7d8b2f217daf7cb7078d52efa58799f4253ebf78b844ec82/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f069b0c8e01cd47f7005f10eb8e8fe4421672bea9b52ee48fb2088bb41ed2730", size = 1441485 }, + { url = "https://files.pythonhosted.org/packages/84/fe/c1ad62652721eadf343e5ff561cc625785486d70c0795743ed6e886ab5a8/scouter_ml-0.3.0rc3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12216cbf7ce90b2d0a114172255ad5ef986f64448360cd5261f8fca7f95febaf", size = 878389 }, + { url = "https://files.pythonhosted.org/packages/0b/2f/a1d7408e81e8d894089f99051839bc48579a5dc2c465e1019815ad19a516/scouter_ml-0.3.0rc3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b753fdd2a18a9b6a3b608d3a1fe1cfbb2790f3c5956f666687819a5e5521e2cd", size = 955047 }, + { url = "https://files.pythonhosted.org/packages/d8/92/e3ef1a8ccb06e1434e2767af8e4feccf5c5dcc2d59cb20d312de65261e09/scouter_ml-0.3.0rc3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3fa5e2f6a01b4af2ab18cd76e48f5c2730782059eb360d1243287d503f82ab4a", size = 1036305 }, + { url = "https://files.pythonhosted.org/packages/8d/b9/f4683d7dfb2044a5eb3e71c2749521f2cd82ba33a833bcc31f33c8d1cb98/scouter_ml-0.3.0rc3-cp311-none-win32.whl", hash = "sha256:4bb20182b3d1d6b81d85e5e18dff8753eb43f46dbf27ea59abe6e668ceb00590", size = 741281 }, + { url = "https://files.pythonhosted.org/packages/ec/af/3ebd30869bba4fded76bd17e68abfbd630e3338648598f11341f3a466cf7/scouter_ml-0.3.0rc3-cp311-none-win_amd64.whl", hash = "sha256:d95b70dca03851a03b4edc806e165a349a056fb2dfcd08333f7b45e97d04c295", size = 830281 }, + { url = "https://files.pythonhosted.org/packages/ef/cb/cca7c6ca773e1ee1feb0dbd2ab1a179a445ef1a7ca108562b9622fc5e7ba/scouter_ml-0.3.0rc3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1d2cf8d77f26ee1961eff96ae14ef1457b7855085ea4dd2dbf5b35f48fe8ce47", size = 834926 }, + { url = "https://files.pythonhosted.org/packages/d6/b4/4d7ba5dbcd9f1f2b0b86e90165f2243a3ec7418e1c99fd1bb835cfa5ed19/scouter_ml-0.3.0rc3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:74d7c0861eca4cc5bc063106c9b9d372c01ca7a064441d20f5b54161ef23e4a5", size = 761167 }, + { url = "https://files.pythonhosted.org/packages/cc/73/b1223e48bb2d4fe5a2b8f53ebe72ac609be48a61b8250b0b709987ea845a/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1613a01c5defc44542cb2de3083ae9257f8aa6e9bce52884f1cae1f9a05a35b8", size = 869832 }, + { url = "https://files.pythonhosted.org/packages/8d/f8/f1f100060dd03f0c02cdf2b70162c46095639cd9f606c723ce3f23adbb13/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c71adcf46b2af111570f84e8684d0ade381228f2d5b6f794a095902bac2322b", size = 784115 }, + { url = "https://files.pythonhosted.org/packages/f8/4e/b8c7c62494349459cda6d1cc2a9680c691ea98fab11441b598e894afca32/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d9a1a714f9954328a82f1546777dd9a61695715e761a06a9093532fafe0b66f2", size = 797492 }, + { url = "https://files.pythonhosted.org/packages/58/84/4f4eb85154ff6e6ace92a49eca396287df1543819f761fe2bd9d6cba5ba1/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d8650e33b3b762bf2c2db11880b47d404170520793bcddada934d4f180eb6ab", size = 931843 }, + { url = "https://files.pythonhosted.org/packages/50/be/c2167b07acddc6afe996e017d0e2f2936f55a6f24c34486f79072c758c42/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:66de23a7c1b41c454e84a509aa13a9af986630ed80c4a3cd5d3ac01d318c072c", size = 1413190 }, + { url = "https://files.pythonhosted.org/packages/30/7f/3e7b8e89bc2177af47325a890663fe6a3ed45f078cb25f59104cf15c6d91/scouter_ml-0.3.0rc3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f6da5b57f5309c3e1c353a2bcea31bb12e0f836a9fc5e2538ebd538bebf6d80", size = 880471 }, + { url = "https://files.pythonhosted.org/packages/ec/1e/a1dc768f5ce2fe2b91a1f844a29acc129b4be6bd6d1dec5a369fd1149dad/scouter_ml-0.3.0rc3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4a42b3eb83fa0ba9920d862a7be553329e757e14416102a4fd871b86e972e257", size = 949509 }, + { url = "https://files.pythonhosted.org/packages/c6/fc/5c549fdf4ba190100c5fa6323406c0a2e1b065009fbfb014f365e1244c0d/scouter_ml-0.3.0rc3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8337b1e3f04656d5cf9b695ba326d83bf114e7a4feff4bee71b02b85c326587", size = 1032024 }, + { url = "https://files.pythonhosted.org/packages/ce/c9/95c8189402aacf664cded5d03b5f2a0843c0b310ef197a9d3904585d1659/scouter_ml-0.3.0rc3-cp312-none-win32.whl", hash = "sha256:ba8c9ff6b8aa639f5dabb2ab84c25a6b9f8ca7b3b6f150d7a2fd2a3f3830ca07", size = 737579 }, + { url = "https://files.pythonhosted.org/packages/0e/9d/5ee99f820920d43943eab6582917074820d9d2aa23993856f24477ac7d26/scouter_ml-0.3.0rc3-cp312-none-win_amd64.whl", hash = "sha256:61c95e514ff50f90e646ed8dc1b253f1a372f79bece8cff761c53dae946e1fb6", size = 829822 }, + { url = "https://files.pythonhosted.org/packages/dd/51/05e9915ba711a3871ab561a3aa50c2e2027b15b125a5ebd686a4fac79fab/scouter_ml-0.3.0rc3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e147bab2028f74c22489fd3b118d28916ab5a6067b9d21da170329c2048419ec", size = 834451 }, + { url = "https://files.pythonhosted.org/packages/d3/28/078c97b97025c50dbc6c058d0c3bac8fbc7a307d061405d662839875ba82/scouter_ml-0.3.0rc3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af6d76d9d3a9bf2fd809b9442e101fab671c37ddf0dcb00b655211920f335c", size = 760772 }, + { url = "https://files.pythonhosted.org/packages/cb/1d/86cff0b5bcd37c4fa8ada2d2d0bb4628ded3c15597a28ec60841da2e473e/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:46fd137a62047c127dd71778bee05187553a7b8cb0d42fc693e43ba55d5d6db9", size = 869639 }, + { url = "https://files.pythonhosted.org/packages/90/58/b6324e6488d90863f127b3b2c73d2d8ec4541d46e2b8624e1cae312b2da1/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bfd8799e4d39c44820446e252d76a9f248986d6400aa6d23ae258db078201b11", size = 784481 }, + { url = "https://files.pythonhosted.org/packages/76/54/22e9fbba8bd6a604286d923893c003b6ece0cccd93da7d0dc116637923d7/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b17e1c4e26182070068a9e1142d45772ac421f50611a206146ba16458e259dcf", size = 797861 }, + { url = "https://files.pythonhosted.org/packages/b9/4f/c772a5dc1a5079c733a3114ba83e93a8716ca9123c1c49e547fea16241f1/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09d2451bf1f0eff6b3ab2cff6ac8920f260993c37c22f6a069266a82c0c13126", size = 934238 }, + { url = "https://files.pythonhosted.org/packages/24/56/3a16f946515f7fbe66071fd57aa76c220438837fe02c678de63c047db19b/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf816a62c320562ab9d653546628c2d1abac9b19d2b7a515a5aa175348d57bb", size = 1442529 }, + { url = "https://files.pythonhosted.org/packages/f7/a0/f5e3f45a0c1fd1812ee3dc0d8283c45bff7247d2f5ec6332e8b4c6a892c4/scouter_ml-0.3.0rc3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4315046738784f323bb8c28a7653d4e1881ec27a4610bf16f76ef2f2a9c6bfe", size = 878590 }, + { url = "https://files.pythonhosted.org/packages/81/48/17768b1920b229d90a6022ceff22d972a60c83693fde2071ffcc347e0886/scouter_ml-0.3.0rc3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6ea7203e0e73c8e8aab6c9247d14be30971fc187b2b5950f7c88a2753393110d", size = 955015 }, + { url = "https://files.pythonhosted.org/packages/87/10/cc7d084f689b4735f8ba3ef56c089dbaae70017e6f105bb067250fd8f9c9/scouter_ml-0.3.0rc3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:486def564a0b4697725cbd746c54fdc65e38bcbc69a6681450e8c89590c4845b", size = 1036669 }, + { url = "https://files.pythonhosted.org/packages/2c/af/72170cb0df741eaa15cb95f0778c889777a894b682bce1c9467052f0928f/scouter_ml-0.3.0rc3-cp39-none-win32.whl", hash = "sha256:6fecd215bf05f2601b3805453d63fc66fdcba7501c17d29cd93ff55c47279050", size = 741877 }, + { url = "https://files.pythonhosted.org/packages/ed/db/979d00583827fa486772135e1d746f859716315f274acd048949b815665c/scouter_ml-0.3.0rc3-cp39-none-win_amd64.whl", hash = "sha256:0d57573361bda9456d8cb8e06cea8bc9c8be0213c52f1b88e65d2444ed0bc586", size = 830494 }, + { url = "https://files.pythonhosted.org/packages/2f/95/99148d8f32e0bbb168e6f62a864a467b29be18f3404a569135716f14d275/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d4d6fa734fddb1da31c407525d417dd58a3dfc5ec1d1d29932353570a4d6ac1c", size = 833258 }, + { url = "https://files.pythonhosted.org/packages/54/14/9b89ab7a06a2697dd5eee6c6d10d13660aa410116b02a3ae2e851e5f07fd/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:cd9c0091e73d1e201d589413185dc453459653134031117b1553a0c65da27f7d", size = 759315 }, + { url = "https://files.pythonhosted.org/packages/2c/a5/89f38982aa5791756dde39987546df7d38dfef4834fc6dcef3c51ab6c702/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b83f3aab903877a72fecf8e7230f205a18e4c2042a4af60c00434552b9762bac", size = 867756 }, + { url = "https://files.pythonhosted.org/packages/0e/79/12c733d2a12b03a83834c060d3dbc18cc93716fa47c61635ff9cca098197/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568cd170142d208bf0e77f4f78ed0d84bd3ad746226832c25b36468b00642282", size = 783023 }, + { url = "https://files.pythonhosted.org/packages/41/86/b95b2a67c6f9c9790b78070d78a125dfad8ebf292b47ddc1bc87cafd2cb3/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6538e6690b4128c38aae6bffddecda0ea790bd77092c3599d6d402418f1527df", size = 796195 }, + { url = "https://files.pythonhosted.org/packages/8a/76/d51ff119e64b2e72a0eadc8ffb2c94561b8b583bc37d9589a71b0d57c9f3/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a30e64b87acec97973da36f8e3afbeea83a7cfbf540cb83a04fe12796e45fe12", size = 932664 }, + { url = "https://files.pythonhosted.org/packages/6d/1b/f3d6e5ba59538a8c3af5069fda73ad92a9005aab983182148066dd09f150/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bcdc3459f8ee416290ec0e01c59fe69cc7e7df01b47c6b2aa0938c77d6fb045", size = 1429353 }, + { url = "https://files.pythonhosted.org/packages/30/fb/92c4cd1757bca128e102f71ce23944c5fa8aca26153be5f7c88baf2561a8/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21700f163fbcc681429b345b0fb94b0dedb93248be34e11f99680d14e1bc8f45", size = 877027 }, + { url = "https://files.pythonhosted.org/packages/e0/98/ac5d3baafc4925a976ec5d8fbca73f8578f88d1539121fea37003f3af864/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:22f28440919450cf88db7ce3e8ac82deb0deb84bda8c0286fba18c63e9277d97", size = 954388 }, + { url = "https://files.pythonhosted.org/packages/e3/1e/465266b840d6cd59319562ac4a5224c146a99d0eac43614d97d17d984dbf/scouter_ml-0.3.0rc3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:8111981a4e451f2fc3b1da55f2de6e7ad8646458aeb60c24f73f88d12b006d42", size = 1035055 }, + { url = "https://files.pythonhosted.org/packages/da/44/0754619418259e4a1b1c5e25964a4d573f15086de9033ab6681febfa70bc/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:afc62ee93af81747093cf41340d7e1c925b884246f1a15b2b024a8d974db39af", size = 833668 }, + { url = "https://files.pythonhosted.org/packages/e9/dd/1f527b7145c28e0b776f9c34370ace1a0b0f3b44aeb19ed80b72499a275b/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ed6ef5eb7df6736e9328efa3de5d0b65449ff9676c44837765f65aa183479aeb", size = 759608 }, + { url = "https://files.pythonhosted.org/packages/ed/1c/cb43e788de9af8a1ed3bfa497a9293f9cfe8a9ecb890a125fb27c962d0e9/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8a7cdb0d6108d05dbbe23650b81f51e006f0c52ca6c7693608069c4b15b9fb87", size = 868238 }, + { url = "https://files.pythonhosted.org/packages/ce/0b/9d586f21c7ecf852925b5f2bb63ffc0218373a0f8fc12f0ae39f20cd7e34/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9e97bd9ebae5963f442fa48122363ddec86084ef1b3e3e02990bfec1d2fcc23", size = 783420 }, + { url = "https://files.pythonhosted.org/packages/ef/e4/03d685084643b6b314fe64a69890f1c1e374253004de87bf3a020aa1a563/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:189bfc358c2d63cbbf46ca0c92a4960361ec44080cc44d0b1a51ba9d9538bbb3", size = 796520 }, + { url = "https://files.pythonhosted.org/packages/05/14/ea8394164098b57fa49160bc103f4d061863985079df9c6df393869c8090/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:18e3a79625fb409198651064b71f0d9d6797bc55ad1a7730aab386a32a0374e8", size = 933160 }, + { url = "https://files.pythonhosted.org/packages/23/3c/730dac928ef59a9896d3c4ca04da1bb95f8378e936c9b7bfddd9ae4dab5b/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6df21dc5b4f18d47611c9ed891d157d2d0e11423bbce2b17db8189aa1929cc1e", size = 1430536 }, + { url = "https://files.pythonhosted.org/packages/d2/73/619b76d1504621953d1d8b5032183a9bf44ff0fa0566dbbb8559ad7126dd/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:feb64341a429c9f1429852fbbb1121e3c76f91bac6c36283d583bd1efed94fb3", size = 877489 }, + { url = "https://files.pythonhosted.org/packages/6b/7c/45d499750969413f5f274536e4bff97b90225e9917a3472902588cac8941/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5b0290776b1342ed36553efd4a5c148566fb7e9c5eda715474eddac407ed5540", size = 954707 }, + { url = "https://files.pythonhosted.org/packages/13/fe/bdf21b251310ca2bda64762e4452f1faa3a27c911ca637168164ef9157b5/scouter_ml-0.3.0rc3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3ac1d4032f4ba8335cd00e106a1ad22c3045898050bfce410aab477178f29b36", size = 1035539 }, ] [[package]] From 921eb4947bd6fe04ec7e8f180bf4579f13d8b5fd Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 20:46:37 -0400 Subject: [PATCH 11/16] add drift route --- opsml/app/routes/drift.py | 39 ++++++++++++++++++++++++ opsml/app/routes/pydantic_models.py | 8 +++-- opsml/registry/sql/base/client.py | 9 +++++- opsml/registry/sql/base/registry_base.py | 27 ++-------------- opsml/registry/sql/base/server.py | 23 ++++++++++++-- opsml/storage/api.py | 1 + opsml/storage/scouter.py | 12 ++------ 7 files changed, 78 insertions(+), 41 deletions(-) create mode 100644 opsml/app/routes/drift.py diff --git a/opsml/app/routes/drift.py b/opsml/app/routes/drift.py new file mode 100644 index 000000000..28bd8a737 --- /dev/null +++ b/opsml/app/routes/drift.py @@ -0,0 +1,39 @@ +# Copyright (c) 2024-current Demml, Inc. +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# pylint: disable=protected-access + +from fastapi import APIRouter, HTTPException, Request, status + +from opsml.app.routes.pydantic_models import DriftProfileRequest, Success +from opsml.helpers.logging import ArtifactLogger +from opsml.registry.sql.base.server import ServerModelCardRegistry + +logger = ArtifactLogger.get_logger() + +router = APIRouter() + + +@router.post("/drift/profile", name="metric_put", response_model=Success) +def insert_metric(request: Request, payload: DriftProfileRequest) -> Success: + """Uploads drift profile to scouter-server + + Args: + request: + FastAPI request object + payload: + DriftProfileRequest + + Returns: + 200 + """ + + model_reg: ServerModelCardRegistry = request.app.state.registries.model._registry + + try: + model_reg.insert_drift_profile(payload.profile) + return Success() + except Exception as error: + logger.error(f"Failed to insert metrics: {error}") + raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to insert drift profile") from error diff --git a/opsml/app/routes/pydantic_models.py b/opsml/app/routes/pydantic_models.py index 20a504716..c86a0925c 100644 --- a/opsml/app/routes/pydantic_models.py +++ b/opsml/app/routes/pydantic_models.py @@ -191,9 +191,7 @@ class RegisterModelRequest(BaseModel): * "1.1.1" = registers 1.1.1 at "1.1.1" """, ) - onnx: bool = Field( - True, description="Flag indicating if the onnx or non-onnx model should be registered. Default True." - ) + onnx: bool = Field(True, description="Flag indicating if the onnx or non-onnx model should be registered. Default True.") ignore_release_candidate: bool = Field(True, description="Flag indicating if release candidates should be ignored.") @@ -517,3 +515,7 @@ class SecurityQuestionResponse(BaseModel): class TempRequest(BaseModel): username: str answer: str + + +class DriftProfileRequest(BaseModel): + profile: str diff --git a/opsml/registry/sql/base/client.py b/opsml/registry/sql/base/client.py index 2ecb27c10..974722741 100644 --- a/opsml/registry/sql/base/client.py +++ b/opsml/registry/sql/base/client.py @@ -8,7 +8,7 @@ import textwrap from functools import cached_property from typing import Any, Dict, List, Optional, Sequence, Tuple, cast - +from scouter import DriftProfile import pandas as pd from opsml.cards import Card, ModelCard @@ -259,6 +259,13 @@ def _validate_datacard_uid(self, uid: str) -> None: if not exists: raise ValueError("ModelCard must be associated with a valid DataCard uid") + def insert_drift_profile(self, drift_profile: DriftProfile) -> None: + self._session.request( + route=api_routes.METRICS, + request_type=RequestType.PUT, + json={"profile": drift_profile.model_dump_json()}, + ) + def register_card( self, card: Card, diff --git a/opsml/registry/sql/base/registry_base.py b/opsml/registry/sql/base/registry_base.py index 6613ddb2e..95ab46a81 100644 --- a/opsml/registry/sql/base/registry_base.py +++ b/opsml/registry/sql/base/registry_base.py @@ -6,7 +6,6 @@ from pathlib import Path from typing import Any, Dict, List, Optional, Sequence, Tuple, Union -from scouter import DriftProfile from semver import VersionInfo from opsml.cards import Card @@ -17,8 +16,6 @@ from opsml.settings.config import config from opsml.storage.card_saver import save_card_artifacts from opsml.storage.client import StorageClient -from opsml.storage.scouter import SCOUTER_CLIENT as scouter_client -from opsml.storage.scouter import ScouterClient from opsml.types import RegistryTableNames, RegistryType from opsml.types.extra import CommonKwargs @@ -37,7 +34,6 @@ def __init__(self, registry_type: RegistryType, storage_client: StorageClient): self.storage_client = storage_client self._table_name = RegistryTableNames[registry_type.value.upper()].value self._registry_type = registry_type - self._scouter_client = scouter_client @property def unique_repositories(self) -> Sequence[str]: @@ -49,21 +45,6 @@ def get_unique_card_names(self, repository: Optional[str] = None) -> Sequence[st def query_stats(self, search_term: Optional[str]) -> Dict[str, int]: raise NotImplementedError - @property - def scouter_client(self) -> Optional[ScouterClient]: - return self._scouter_client - - def _insert_drift_profile(self, drift_profile: DriftProfile) -> None: - """Insert drift profile into scouter server - - Args: - drift_profile: - drift profile - """ - - if self.scouter_client is not None: - self.scouter_client.insert_drift_profile(drift_profile=drift_profile) - def query_page( self, sort_by: str, @@ -331,12 +312,8 @@ def update_card(self, card: Card) -> None: assert bool(record), "Card does not exist in registry. Please use register card first" if self._card_with_diff_uid_already_exists(card): - logger.error( - "Card for {}/{}/{} already exists with a different uid", card.repository, card.name, card.version - ) - raise ValueError( - f"Card for {card.repository}/{card.name}/{card.version} already exists with a different uid" - ) + logger.error("Card for {}/{}/{} already exists with a different uid", card.repository, card.name, card.version) + raise ValueError(f"Card for {card.repository}/{card.name}/{card.version} already exists with a different uid") logger.info("Updating card {}/{} with version {}", card.repository, card.name, card.version) diff --git a/opsml/registry/sql/base/server.py b/opsml/registry/sql/base/server.py index bd332bb23..2265f152f 100644 --- a/opsml/registry/sql/base/server.py +++ b/opsml/registry/sql/base/server.py @@ -37,6 +37,9 @@ from opsml.storage.client import StorageClient from opsml.types import RegistryTableNames, RegistryType from opsml.types.extra import Message, User +from opsml.storage.scouter import SCOUTER_CLIENT as scouter_client +from opsml.storage.scouter import ScouterClient +from scouter import DriftProfile logger = ArtifactLogger.get_logger() @@ -59,6 +62,7 @@ def __init__(self, registry_type: RegistryType, storage_client: StorageClient): self.engine = get_query_engine(db_engine=db_initializer.engine, registry_type=registry_type) self._table = SQLTableGetter.get_table(table_name=self.table_name) + self._scouter_client = scouter_client @property def registry_type(self) -> RegistryType: @@ -69,11 +73,26 @@ def registry_type(self) -> RegistryType: def validate(registry_name: str) -> bool: raise NotImplementedError + @property + def scouter_client(self) -> Optional[ScouterClient]: + return self._scouter_client + @property def unique_repositories(self) -> Sequence[str]: """Returns a list of unique repositories""" return self.engine.get_unique_repositories(table=self._table) + def insert_drift_profile(self, drift_profile: str) -> None: + """Insert drift profile into scouter server + + Args: + drift_profile: + drift profile + """ + + if self.scouter_client is not None: + self.scouter_client.insert_drift_profile(drift_profile=drift_profile) + def query_stats(self, search_term: Optional[str] = None) -> Dict[str, int]: """Query stats from Card Database Args: @@ -393,9 +412,7 @@ class ServerRunCardRegistry(ServerRegistry): def registry_type(self) -> RegistryType: return RegistryType.RUN - def get_metric( - self, run_uid: str, name: Optional[List[str]] = None, names_only: bool = False - ) -> List[Dict[str, Any]]: + def get_metric(self, run_uid: str, name: Optional[List[str]] = None, names_only: bool = False) -> List[Dict[str, Any]]: """Get metric from run card Args: diff --git a/opsml/storage/api.py b/opsml/storage/api.py index 9dab44f30..9498c4a1f 100644 --- a/opsml/storage/api.py +++ b/opsml/storage/api.py @@ -50,6 +50,7 @@ class ApiRoutes: TOKEN = "auth/token" HW_METRICS = "metrics/hardware" PARAMETERS = "parameters" + DRIFT_PROFILE = "profile" api_routes = ApiRoutes() diff --git a/opsml/storage/scouter.py b/opsml/storage/scouter.py index 4779c4382..df5c0752f 100644 --- a/opsml/storage/scouter.py +++ b/opsml/storage/scouter.py @@ -1,25 +1,19 @@ import json -from scouter import DriftProfile - from opsml.settings.config import config from opsml.storage.api import ApiClient, RequestType class ScouterClient(ApiClient): - def insert_drift_profile(self, drift_profile: DriftProfile) -> None: + def insert_drift_profile(self, drift_profile: str) -> None: """Inserts drift profile into scouter server Args: drift_profile: Drift profile to insert """ - - self.request( - route="/profile", - request_type=RequestType.POST, - json=json.loads(drift_profile.model_dump_json()), - ) + profile = json.loads(drift_profile) + self.request(route="/profile", request_type=RequestType.POST, json=profile) SCOUTER_CLIENT = None From c13af52d58f0f935ed141dc79e6e3ddd113ebb97 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 20:58:02 -0400 Subject: [PATCH 12/16] update routes --- opsml/app/routes/drift.py | 4 +++- opsml/app/routes/pydantic_models.py | 4 +++- opsml/registry/sql/base/client.py | 10 +++++----- opsml/registry/sql/base/registry_base.py | 8 ++++++-- opsml/registry/sql/base/server.py | 13 ++++++++----- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/opsml/app/routes/drift.py b/opsml/app/routes/drift.py index 28bd8a737..94669690c 100644 --- a/opsml/app/routes/drift.py +++ b/opsml/app/routes/drift.py @@ -36,4 +36,6 @@ def insert_metric(request: Request, payload: DriftProfileRequest) -> Success: return Success() except Exception as error: logger.error(f"Failed to insert metrics: {error}") - raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to insert drift profile") from error + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to insert drift profile" + ) from error diff --git a/opsml/app/routes/pydantic_models.py b/opsml/app/routes/pydantic_models.py index c86a0925c..da0009e71 100644 --- a/opsml/app/routes/pydantic_models.py +++ b/opsml/app/routes/pydantic_models.py @@ -191,7 +191,9 @@ class RegisterModelRequest(BaseModel): * "1.1.1" = registers 1.1.1 at "1.1.1" """, ) - onnx: bool = Field(True, description="Flag indicating if the onnx or non-onnx model should be registered. Default True.") + onnx: bool = Field( + True, description="Flag indicating if the onnx or non-onnx model should be registered. Default True." + ) ignore_release_candidate: bool = Field(True, description="Flag indicating if release candidates should be ignored.") diff --git a/opsml/registry/sql/base/client.py b/opsml/registry/sql/base/client.py index 974722741..15d6e70da 100644 --- a/opsml/registry/sql/base/client.py +++ b/opsml/registry/sql/base/client.py @@ -8,7 +8,7 @@ import textwrap from functools import cached_property from typing import Any, Dict, List, Optional, Sequence, Tuple, cast -from scouter import DriftProfile + import pandas as pd from opsml.cards import Card, ModelCard @@ -259,11 +259,11 @@ def _validate_datacard_uid(self, uid: str) -> None: if not exists: raise ValueError("ModelCard must be associated with a valid DataCard uid") - def insert_drift_profile(self, drift_profile: DriftProfile) -> None: + def insert_drift_profile(self, drift_profile: str) -> None: self._session.request( - route=api_routes.METRICS, + route=api_routes.DRIFT_PROFILE, request_type=RequestType.PUT, - json={"profile": drift_profile.model_dump_json()}, + json={"profile": drift_profile}, ) def register_card( @@ -323,7 +323,7 @@ def register_card( # write profile to scouter if card.interface.drift_profile is not None and config.scouter_server_uri is not None: try: - self._insert_drift_profile(drift_profile=card.interface.drift_profile) + self.insert_drift_profile(drift_profile=card.interface.drift_profile.model_dump_json()) except Exception as exc: # pylint: disable=broad-except logger.error(f"Failed to insert drift profile: {exc}") diff --git a/opsml/registry/sql/base/registry_base.py b/opsml/registry/sql/base/registry_base.py index 95ab46a81..90f775ffb 100644 --- a/opsml/registry/sql/base/registry_base.py +++ b/opsml/registry/sql/base/registry_base.py @@ -312,8 +312,12 @@ def update_card(self, card: Card) -> None: assert bool(record), "Card does not exist in registry. Please use register card first" if self._card_with_diff_uid_already_exists(card): - logger.error("Card for {}/{}/{} already exists with a different uid", card.repository, card.name, card.version) - raise ValueError(f"Card for {card.repository}/{card.name}/{card.version} already exists with a different uid") + logger.error( + "Card for {}/{}/{} already exists with a different uid", card.repository, card.name, card.version + ) + raise ValueError( + f"Card for {card.repository}/{card.name}/{card.version} already exists with a different uid" + ) logger.info("Updating card {}/{} with version {}", card.repository, card.name, card.version) diff --git a/opsml/registry/sql/base/server.py b/opsml/registry/sql/base/server.py index 2265f152f..074a9a49b 100644 --- a/opsml/registry/sql/base/server.py +++ b/opsml/registry/sql/base/server.py @@ -35,11 +35,10 @@ from opsml.registry.sql.connectors.connector import DefaultConnector from opsml.settings.config import config from opsml.storage.client import StorageClient -from opsml.types import RegistryTableNames, RegistryType -from opsml.types.extra import Message, User from opsml.storage.scouter import SCOUTER_CLIENT as scouter_client from opsml.storage.scouter import ScouterClient -from scouter import DriftProfile +from opsml.types import RegistryTableNames, RegistryType +from opsml.types.extra import Message, User logger = ArtifactLogger.get_logger() @@ -398,7 +397,9 @@ def register_card( # write profile to scouter if card.interface.drift_profile is not None and config.scouter_server_uri is not None: try: - self._insert_drift_profile(drift_profile=card.interface.drift_profile) + self.insert_drift_profile( + drift_profile=card.interface.drift_profile.model_dump_json(), + ) except Exception as exc: # pylint: disable=broad-except logger.error(f"Failed to insert drift profile: {exc}") @@ -412,7 +413,9 @@ class ServerRunCardRegistry(ServerRegistry): def registry_type(self) -> RegistryType: return RegistryType.RUN - def get_metric(self, run_uid: str, name: Optional[List[str]] = None, names_only: bool = False) -> List[Dict[str, Any]]: + def get_metric( + self, run_uid: str, name: Optional[List[str]] = None, names_only: bool = False + ) -> List[Dict[str, Any]]: """Get metric from run card Args: From a12c59b52448ab90b20b21589c69bbc5ef7b19d4 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 21:00:00 -0400 Subject: [PATCH 13/16] add router to app --- opsml/app/routes/router.py | 2 ++ opsml/storage/api.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/opsml/app/routes/router.py b/opsml/app/routes/router.py index 735e2ab28..2a598a06f 100644 --- a/opsml/app/routes/router.py +++ b/opsml/app/routes/router.py @@ -20,6 +20,7 @@ registry, runs, ui, + drift, ) @@ -37,6 +38,7 @@ def build_router(dependencies: Optional[Sequence[Any]] = None) -> APIRouter: api_router.include_router(parameters.router, tags=["parameters"], prefix="/opsml", dependencies=dependencies) api_router.include_router(runs.router, tags=["runs"], prefix="/opsml", dependencies=dependencies) api_router.include_router(ui.router, tags=["ui"], dependencies=dependencies) + api_router.include_router(drift.router, tags=["drift"], prefix="/opsml", dependencies=dependencies) api_router.include_router(auth.router, tags=["auth"], prefix="/opsml") return api_router diff --git a/opsml/storage/api.py b/opsml/storage/api.py index 9498c4a1f..30d674040 100644 --- a/opsml/storage/api.py +++ b/opsml/storage/api.py @@ -50,7 +50,7 @@ class ApiRoutes: TOKEN = "auth/token" HW_METRICS = "metrics/hardware" PARAMETERS = "parameters" - DRIFT_PROFILE = "profile" + DRIFT_PROFILE = "drift/profile" api_routes = ApiRoutes() From 4ca8a86800c4e4b862e76dcac90a1b959b819288 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 22:07:40 -0400 Subject: [PATCH 14/16] add server and client tests --- opsml/app/routes/router.py | 2 +- opsml/registry/sql/base/client.py | 2 +- opsml/registry/sql/base/server.py | 2 ++ tests/conftest.py | 5 ++- tests/test_app/test_client.py | 46 ++++++++++++++++++++++++++-- tests/test_registry/test_registry.py | 6 ++++ 6 files changed, 58 insertions(+), 5 deletions(-) diff --git a/opsml/app/routes/router.py b/opsml/app/routes/router.py index 2a598a06f..48ecfccc8 100644 --- a/opsml/app/routes/router.py +++ b/opsml/app/routes/router.py @@ -11,6 +11,7 @@ auth, cards, data, + drift, files, healthcheck, metrics, @@ -20,7 +21,6 @@ registry, runs, ui, - drift, ) diff --git a/opsml/registry/sql/base/client.py b/opsml/registry/sql/base/client.py index 15d6e70da..c00291ae4 100644 --- a/opsml/registry/sql/base/client.py +++ b/opsml/registry/sql/base/client.py @@ -262,7 +262,7 @@ def _validate_datacard_uid(self, uid: str) -> None: def insert_drift_profile(self, drift_profile: str) -> None: self._session.request( route=api_routes.DRIFT_PROFILE, - request_type=RequestType.PUT, + request_type=RequestType.POST, json={"profile": drift_profile}, ) diff --git a/opsml/registry/sql/base/server.py b/opsml/registry/sql/base/server.py index 074a9a49b..21bcbf01a 100644 --- a/opsml/registry/sql/base/server.py +++ b/opsml/registry/sql/base/server.py @@ -394,6 +394,8 @@ def register_card( build_tag=build_tag, ) + print(config.scouter_server_uri) + # write profile to scouter if card.interface.drift_profile is not None and config.scouter_server_uri is not None: try: diff --git a/tests/conftest.py b/tests/conftest.py index 631e6c314..4e083e305 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,6 +26,7 @@ os.environ["OPSML_PROD_TOKEN"] = "test-token" os.environ["OPSML_TRACKING_URI"] = OPSML_TRACKING_URI os.environ["OPSML_STORAGE_URI"] = OPSML_STORAGE_URI +os.environ["SCOUTER_SERVER_URI"] = "http://testserver" import datetime import shutil @@ -354,10 +355,12 @@ def api_registries(monkeypatch: pytest.MonkeyPatch, test_app: TestClient) -> Yie @pytest.fixture -def db_registries() -> YieldFixture[CardRegistries]: +def db_registries(monkeypatch: pytest.MonkeyPatch) -> YieldFixture[CardRegistries]: """Returns CardRegistries configured with a local client.""" cleanup() + monkeypatch.setattr(config, "scouter_server_uri", "http://testserver") + # CardRegistries rely on global storage state - so set it to local. client.storage_client = client.get_storage_client( OpsmlConfig( diff --git a/tests/test_app/test_client.py b/tests/test_app/test_client.py index b5e770534..0efab9402 100644 --- a/tests/test_app/test_client.py +++ b/tests/test_app/test_client.py @@ -1,8 +1,10 @@ import uuid from pathlib import Path from typing import Any, Dict, Tuple, cast +from unittest import mock import pytest +from scouter import DriftConfig from sklearn.preprocessing import LabelEncoder from starlette.testclient import TestClient @@ -265,8 +267,8 @@ def test_runcard( # Load the card and verify artifacts / metrics loaded_card: RunCard = registry.load_card(uid=run.uid) assert loaded_card.uid == run.uid - assert loaded_card.get_metric("test_metric")[0].value == 10 # type: ignore - assert loaded_card.get_metric("test_metric2")[0].value == 20 # type: ignore + assert loaded_card.get_metric("test_metric")[0].value == 10 + assert loaded_card.get_metric("test_metric2")[0].value == 20 loaded_card.load_artifacts() @@ -538,3 +540,43 @@ def test_register_vit( assert api_storage_client.exists(Path(modelcard.uri, SaveName.TRAINED_MODEL.value).with_suffix(model.model_suffix)) assert api_storage_client.exists(Path(modelcard.uri, SaveName.FEATURE_EXTRACTOR.value).with_suffix("")) + + +@mock.patch("opsml.storage.scouter.ScouterClient.request") +def test_model_registry_scouter( + mock_request: mock.MagicMock, + linear_regression: Tuple[SklearnModel, NumpyData], + api_registries: CardRegistries, +) -> None: + mock_request.return_value = None + + data_registry = api_registries.data + model_registry = api_registries.model + model, data = linear_regression + + datacard = DataCard( + interface=data, + name="scouter_test", + repository="mlops", + contact="mlops.com", + ) + + data_registry.register_card(card=datacard) + + drift_config = DriftConfig() + model.create_drift_profile(data.data, drift_config) + + modelcard = ModelCard( + interface=model, + name="pipeline_model", + repository="mlops", + contact="mlops.com", + datacard_uid=datacard.uid, + to_onnx=True, + ) + + model_registry.register_card(card=modelcard) + + assert modelcard.interface.drift_profile is not None + assert modelcard.interface.drift_profile.config.name == modelcard.name + assert mock_request.called diff --git a/tests/test_registry/test_registry.py b/tests/test_registry/test_registry.py index 8ea61980a..9e3a30066 100644 --- a/tests/test_registry/test_registry.py +++ b/tests/test_registry/test_registry.py @@ -6,6 +6,7 @@ import uuid from pathlib import Path from typing import Tuple +from unittest import mock import joblib import pandas as pd @@ -885,10 +886,14 @@ def test_sort_timestamp(sql_data: SqlData, db_registries: CardRegistries) -> Non assert cards[1]["name"] == "test1" +@mock.patch("opsml.storage.scouter.ScouterClient.request") def test_model_registry_scouter( + mock_request: mock.MagicMock, db_registries: CardRegistries, sklearn_pipeline: Tuple[ModelInterface, DataInterface], ) -> None: + mock_request.return_value = None + # create data card data_registry = db_registries.data model, data = sklearn_pipeline @@ -919,3 +924,4 @@ def test_model_registry_scouter( assert model_card.interface.drift_profile is not None assert model_card.interface.drift_profile.config.name == model_card.name + assert mock_request.called From b441a1b982202fec0971fde8a67a38da1c8fbb5c Mon Sep 17 00:00:00 2001 From: Thorrester Date: Mon, 16 Sep 2024 22:42:32 -0400 Subject: [PATCH 15/16] in compliance --- opsml/registry/sql/base/query_engine.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opsml/registry/sql/base/query_engine.py b/opsml/registry/sql/base/query_engine.py index 415d9b577..e3c60ad9b 100644 --- a/opsml/registry/sql/base/query_engine.py +++ b/opsml/registry/sql/base/query_engine.py @@ -506,6 +506,7 @@ def query_page( Tuple of card summary """ + ## build versions versions = select( table.repository, table.name, @@ -546,6 +547,9 @@ def query_page( ), ) + versions = versions.subquery() + stats = stats.subquery() + filtered_versions = ( select( versions.c.repository, From 1c0aa1aafe4edd160972b6cc020d8368ea26ba82 Mon Sep 17 00:00:00 2001 From: Thorrester Date: Tue, 17 Sep 2024 09:10:15 -0400 Subject: [PATCH 16/16] Update _base.py --- opsml/data/interfaces/_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opsml/data/interfaces/_base.py b/opsml/data/interfaces/_base.py index 7c56da32d..0f2cad3ea 100644 --- a/opsml/data/interfaces/_base.py +++ b/opsml/data/interfaces/_base.py @@ -144,7 +144,7 @@ def load_data_profile(self, path: Path) -> None: Pathlib object """ - profile = DataProfile.load_from_json(path.read_text(encoding="utf-8")) + profile = DataProfile.model_validate_json(path.read_text(encoding="utf-8")) self.data_profile = profile def save_data_profile(self, path: Path) -> None: