MLflow2.0: Classical Model ServingにおけるスコアリングAPIのアップデート

MLflow 2.0のリリースに伴い、Classical Model Servingを使用してデプロイされた新しいモデルのスコアリングAPIが変更されています。この変更により、スコアリングのリクエストとレスポンスのフォーマットがより拡張性の高いものになり、将来的にユーザーのアプリケーションを中断させることなく、さらに機能を追加することが可能になります。

従って、Classical Model Servingにデプロイされた新しいモデルはすべて、デフォルトで MLflow2.0スコアリングAPIを使用するようになります。古いスコアリング形式を使用して行われた推論リクエストは以下のエラーになります。

:::note alert
Exception: Request failed with status 400, {"error_code": "BAD_REQUEST", "message": "The input must be a JSON dictionary with exactly one of the input fields {'dataframe_records', 'dataframe_split', 'inputs', 'instances'}. Received dictionary with input fields: ['index', 'columns', 'data']. IMPORTANT: The MLflow Model scoring protocol has changed in MLflow version 2.0. If you are seeing this error, you are likely using an outdated scoring request format. To resolve the error, either update your request format or adjust your MLflow Model's requirements file to specify an older version of MLflow (for example, change the 'mlflow' requirement specifier to 'mlflow==1.30.0'). If you are making a request using the MLflow client (e.g. via `mlflow.pyfunc.spark_udf()`), upgrade your MLflow client to a version >= 2.0 in order to use the new request format. For more information about the updated MLflow Model scoring protocol in MLflow 2.0, see https://mlflow.org/docs/latest/models.html#deploy-mlflow-models."}
:::

### 新しいAPIに対応するために以下の変更が必要になります。
データフレーム入力
●	Input:入力データは、データフレーム・エンコーディング形式を指定するフィールドにネストされるようになりました。サポートしている形式は、dataframe_recordsとdataframe_splitの2つです。
●	Output:出力は、モデルの出力の値（元の出力）を含むpredictionsというフィールドを持つ辞書となります。

#### Pythonの使用例：
- Before (MLflow 1.*:)
```
dataset = pandas.DataFrame(...)
data_json = dataset.to_dict(orient='split')
response = requests.request(method='POST', headers=headers, url=url, json=data_json )
predictions = response.json()
```
- After (MLflow 2.0:)
```
dataset = pandas.DataFrame(...)
data_json = {'dataframe_split': dataset.to_dict(orient='split')}
response = requests.request(method='POST', headers=headers, url=url, json=data_json )
predictions = response.json()['predictions']
```

#### Curlの使用例
- Before (MLflow 1.*:)
```
> curl \
 -u token:$DATABRICKS_TOKEN \
 -X POST \
 -H "Content-Type: application/json; format=pandas-records" \
 -d '[{"sepal length (cm)":5.1, "sepal width (cm)":3.5, ... }]' \
 https://e2-dogfood.staging.cloud.databricks.com/model-endpoint/iris/5/invocations

> ["setosa"] 

```
- After (MLflow 2.0:)
```
> curl \
 -u token:$DATABRICKS_TOKEN \
 -X POST \
 -H 'Content-Type: application/json' \
 -d '{"dataframe_split": {"columns": ["sepal length (cm)", "sepal width (cm)", ...], "data": [[5.1, 3.5, ...]]}}' \
 https://e2-dogfood.staging.cloud.databricks.com/model-endpoint/iris/5/invocations

> {  “predictions”: ["setosa"] }
```

#### Tensor Input
- Input:変更なし
- Output:出力は、モデルの出力の値（元の出力）を含むpredictionsというフィールドを持つ辞書となります。


### この新しいスコアリングフォーマットを使用したくない、MLflow 1.x のスコアリングフォーマットを使い続けたい場合
ワークフロー内のすべての `log_model` API 呼び出しを以下のように修正する必要があります。

- Before (MLflow 1.*:)
```
mlflow.<flavor>.log_model(...)
```
- After (MLflow 2.0:)
```
mlflow.<flavor>.log_model(..., extra_pip_requirements=["mlflow==1.*"])
```
これにより、トラッキングサバーに記録されたモデルがMLflow 1.xの既存のスコアリング・プロトコルを利用できるようになります。