We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Support MLflow current protocol
As a follow-up to #167, it would be interesting to explore adding a custom endpoint to the `mlserver-mlflow` runtime which supports [MLflow's existing API](https://www.mlflow.org/docs/latest/models.html#deploy-mlflow-models). This would help reduce friction on user adoption of MLSever, as well as a temporary stopgap for users while they adopt the V2 protocol.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `runtimes/mlflow/mlserver_mlflow/runtime.py`
Content:
```
1 import mlflow
2 
3 from mlserver.types import InferenceRequest, InferenceResponse
4 from mlserver.model import MLModel
5 from mlserver.utils import get_model_uri
6 from mlserver.codecs import get_decoded_or_raw
7 
8 from .encoding import to_outputs
9 
10 
11 class MLflowRuntime(MLModel):
12     """
13     Implementation of the MLModel interface to load and serve `scikit-learn`
14     models persisted with `joblib`.
15     """
16 
17     async def load(self) -> bool:
18         # TODO: Log info message
19         model_uri = await get_model_uri(self._settings)
20         self._model = mlflow.pyfunc.load_model(model_uri)
21 
22         self.ready = True
23         return self.ready
24 
25     async def predict(self, payload: InferenceRequest) -> InferenceResponse:
26         decoded_payload = get_decoded_or_raw(payload)
27 
28         # TODO: Can `output` be a dictionary of tensors?
29         model_output = self._model.predict(decoded_payload)
30 
31         return InferenceResponse(
32             model_name=self.name,
33             model_version=self.version,
34             outputs=to_outputs(model_output),
35         )
36
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py
--- a/runtimes/mlflow/mlserver_mlflow/runtime.py
+++ b/runtimes/mlflow/mlserver_mlflow/runtime.py
@@ -1,9 +1,29 @@
 import mlflow
 
+from io import StringIO
+from fastapi import Request, Response
+
+from mlflow.exceptions import MlflowException
+from mlflow.pyfunc.scoring_server import (
+    CONTENT_TYPES,
+    CONTENT_TYPE_CSV,
+    CONTENT_TYPE_JSON,
+    CONTENT_TYPE_JSON_SPLIT_ORIENTED,
+    CONTENT_TYPE_JSON_RECORDS_ORIENTED,
+    CONTENT_TYPE_JSON_SPLIT_NUMPY,
+    parse_csv_input,
+    infer_and_parse_json_input,
+    parse_json_input,
+    parse_split_oriented_json_input_to_numpy,
+    predictions_to_json,
+)
+
 from mlserver.types import InferenceRequest, InferenceResponse
 from mlserver.model import MLModel
 from mlserver.utils import get_model_uri
 from mlserver.codecs import get_decoded_or_raw
+from mlserver.handlers import custom_handler
+from mlserver.errors import InferenceError
 
 from .encoding import to_outputs
 
@@ -14,10 +34,68 @@
     models persisted with `joblib`.
     """
 
+    # TODO: Decouple from REST
+    @custom_handler(rest_path="/invocations")
+    async def invocations(self, request: Request) -> Response:
+        """
+        This custom handler is meant to mimic the behaviour of the existing
+        scoring server in MLflow.
+        For details about its implementation, please consult the original
+        implementation in the MLflow repository:
+
+            https://github.com/mlflow/mlflow/blob/master/mlflow/pyfunc/scoring_server/__init__.py
+        """
+        content_type = request.headers.get("content-type", None)
+        raw_data = await request.body()
+        as_str = raw_data.decode("utf-8")
+
+        if content_type == CONTENT_TYPE_CSV:
+            csv_input = StringIO(as_str)
+            data = parse_csv_input(csv_input=csv_input)
+        elif content_type == CONTENT_TYPE_JSON:
+            data = infer_and_parse_json_input(as_str, self._input_schema)
+        elif content_type == CONTENT_TYPE_JSON_SPLIT_ORIENTED:
+            data = parse_json_input(
+                json_input=StringIO(as_str),
+                orient="split",
+                schema=self._input_schema,
+            )
+        elif content_type == CONTENT_TYPE_JSON_RECORDS_ORIENTED:
+            data = parse_json_input(
+                json_input=StringIO(as_str),
+                orient="records",
+                schema=self._input_schema,
+            )
+        elif content_type == CONTENT_TYPE_JSON_SPLIT_NUMPY:
+            data = parse_split_oriented_json_input_to_numpy(as_str)
+        else:
+            content_type_error_message = (
+                "This predictor only supports the following content types, "
+                f"{CONTENT_TYPES}. Got '{content_type}'."
+            )
+            raise InferenceError(content_type_error_message)
+
+        try:
+            raw_predictions = self._model.predict(data)
+        except MlflowException as e:
+            raise InferenceError(e.message)
+        except Exception:
+            error_message = (
+                "Encountered an unexpected error while evaluating the model. Verify"
+                " that the serialized input Dataframe is compatible with the model for"
+                " inference."
+            )
+            raise InferenceError(error_message)
+
+        result = StringIO()
+        predictions_to_json(raw_predictions, result)
+        return Response(content=result.getvalue(), media_type="application/json")
+
     async def load(self) -> bool:
         # TODO: Log info message
         model_uri = await get_model_uri(self._settings)
         self._model = mlflow.pyfunc.load_model(model_uri)
+        self._input_schema = self._model.metadata.get_input_schema()
 
         self.ready = True
         return self.ready

{"golden_diff": "diff --git a/runtimes/mlflow/mlserver_mlflow/runtime.py b/runtimes/mlflow/mlserver_mlflow/runtime.py\n--- a/runtimes/mlflow/mlserver_mlflow/runtime.py\n+++ b/runtimes/mlflow/mlserver_mlflow/runtime.py\n@@ -1,9 +1,29 @@\n import mlflow\n \n+from io import StringIO\n+from fastapi import Request, Response\n+\n+from mlflow.exceptions import MlflowException\n+from mlflow.pyfunc.scoring_server import (\n+    CONTENT_TYPES,\n+    CONTENT_TYPE_CSV,\n+    CONTENT_TYPE_JSON,\n+    CONTENT_TYPE_JSON_SPLIT_ORIENTED,\n+    CONTENT_TYPE_JSON_RECORDS_ORIENTED,\n+    CONTENT_TYPE_JSON_SPLIT_NUMPY,\n+    parse_csv_input,\n+    infer_and_parse_json_input,\n+    parse_json_input,\n+    parse_split_oriented_json_input_to_numpy,\n+    predictions_to_json,\n+)\n+\n from mlserver.types import InferenceRequest, InferenceResponse\n from mlserver.model import MLModel\n from mlserver.utils import get_model_uri\n from mlserver.codecs import get_decoded_or_raw\n+from mlserver.handlers import custom_handler\n+from mlserver.errors import InferenceError\n \n from .encoding import to_outputs\n \n@@ -14,10 +34,68 @@\n     models persisted with `joblib`.\n     \"\"\"\n \n+    # TODO: Decouple from REST\n+    @custom_handler(rest_path=\"/invocations\")\n+    async def invocations(self, request: Request) -> Response:\n+        \"\"\"\n+        This custom handler is meant to mimic the behaviour of the existing\n+        scoring server in MLflow.\n+        For details about its implementation, please consult the original\n+        implementation in the MLflow repository:\n+\n+            https://github.com/mlflow/mlflow/blob/master/mlflow/pyfunc/scoring_server/__init__.py\n+        \"\"\"\n+        content_type = request.headers.get(\"content-type\", None)\n+        raw_data = await request.body()\n+        as_str = raw_data.decode(\"utf-8\")\n+\n+        if content_type == CONTENT_TYPE_CSV:\n+            csv_input = StringIO(as_str)\n+            data = parse_csv_input(csv_input=csv_input)\n+        elif content_type == CONTENT_TYPE_JSON:\n+            data = infer_and_parse_json_input(as_str, self._input_schema)\n+        elif content_type == CONTENT_TYPE_JSON_SPLIT_ORIENTED:\n+            data = parse_json_input(\n+                json_input=StringIO(as_str),\n+                orient=\"split\",\n+                schema=self._input_schema,\n+            )\n+        elif content_type == CONTENT_TYPE_JSON_RECORDS_ORIENTED:\n+            data = parse_json_input(\n+                json_input=StringIO(as_str),\n+                orient=\"records\",\n+                schema=self._input_schema,\n+            )\n+        elif content_type == CONTENT_TYPE_JSON_SPLIT_NUMPY:\n+            data = parse_split_oriented_json_input_to_numpy(as_str)\n+        else:\n+            content_type_error_message = (\n+                \"This predictor only supports the following content types, \"\n+                f\"{CONTENT_TYPES}. Got '{content_type}'.\"\n+            )\n+            raise InferenceError(content_type_error_message)\n+\n+        try:\n+            raw_predictions = self._model.predict(data)\n+        except MlflowException as e:\n+            raise InferenceError(e.message)\n+        except Exception:\n+            error_message = (\n+                \"Encountered an unexpected error while evaluating the model. Verify\"\n+                \" that the serialized input Dataframe is compatible with the model for\"\n+                \" inference.\"\n+            )\n+            raise InferenceError(error_message)\n+\n+        result = StringIO()\n+        predictions_to_json(raw_predictions, result)\n+        return Response(content=result.getvalue(), media_type=\"application/json\")\n+\n     async def load(self) -> bool:\n         # TODO: Log info message\n         model_uri = await get_model_uri(self._settings)\n         self._model = mlflow.pyfunc.load_model(model_uri)\n+        self._input_schema = self._model.metadata.get_input_schema()\n \n         self.ready = True\n         return self.ready\n", "issue": "Support MLflow current protocol\nAs a follow-up to #167, it would be interesting to explore adding a custom endpoint to the `mlserver-mlflow` runtime which supports [MLflow's existing API](https://www.mlflow.org/docs/latest/models.html#deploy-mlflow-models). This would help reduce friction on user adoption of MLSever, as well as a temporary stopgap for users while they adopt the V2 protocol.\n", "before_files": [{"content": "import mlflow\n\nfrom mlserver.types import InferenceRequest, InferenceResponse\nfrom mlserver.model import MLModel\nfrom mlserver.utils import get_model_uri\nfrom mlserver.codecs import get_decoded_or_raw\n\nfrom .encoding import to_outputs\n\n\nclass MLflowRuntime(MLModel):\n    \"\"\"\n    Implementation of the MLModel interface to load and serve `scikit-learn`\n    models persisted with `joblib`.\n    \"\"\"\n\n    async def load(self) -> bool:\n        # TODO: Log info message\n        model_uri = await get_model_uri(self._settings)\n        self._model = mlflow.pyfunc.load_model(model_uri)\n\n        self.ready = True\n        return self.ready\n\n    async def predict(self, payload: InferenceRequest) -> InferenceResponse:\n        decoded_payload = get_decoded_or_raw(payload)\n\n        # TODO: Can `output` be a dictionary of tensors?\n        model_output = self._model.predict(decoded_payload)\n\n        return InferenceResponse(\n            model_name=self.name,\n            model_version=self.version,\n            outputs=to_outputs(model_output),\n        )\n", "path": "runtimes/mlflow/mlserver_mlflow/runtime.py"}], "after_files": [{"content": "import mlflow\n\nfrom io import StringIO\nfrom fastapi import Request, Response\n\nfrom mlflow.exceptions import MlflowException\nfrom mlflow.pyfunc.scoring_server import (\n    CONTENT_TYPES,\n    CONTENT_TYPE_CSV,\n    CONTENT_TYPE_JSON,\n    CONTENT_TYPE_JSON_SPLIT_ORIENTED,\n    CONTENT_TYPE_JSON_RECORDS_ORIENTED,\n    CONTENT_TYPE_JSON_SPLIT_NUMPY,\n    parse_csv_input,\n    infer_and_parse_json_input,\n    parse_json_input,\n    parse_split_oriented_json_input_to_numpy,\n    predictions_to_json,\n)\n\nfrom mlserver.types import InferenceRequest, InferenceResponse\nfrom mlserver.model import MLModel\nfrom mlserver.utils import get_model_uri\nfrom mlserver.codecs import get_decoded_or_raw\nfrom mlserver.handlers import custom_handler\nfrom mlserver.errors import InferenceError\n\nfrom .encoding import to_outputs\n\n\nclass MLflowRuntime(MLModel):\n    \"\"\"\n    Implementation of the MLModel interface to load and serve `scikit-learn`\n    models persisted with `joblib`.\n    \"\"\"\n\n    # TODO: Decouple from REST\n    @custom_handler(rest_path=\"/invocations\")\n    async def invocations(self, request: Request) -> Response:\n        \"\"\"\n        This custom handler is meant to mimic the behaviour of the existing\n        scoring server in MLflow.\n        For details about its implementation, please consult the original\n        implementation in the MLflow repository:\n\n            https://github.com/mlflow/mlflow/blob/master/mlflow/pyfunc/scoring_server/__init__.py\n        \"\"\"\n        content_type = request.headers.get(\"content-type\", None)\n        raw_data = await request.body()\n        as_str = raw_data.decode(\"utf-8\")\n\n        if content_type == CONTENT_TYPE_CSV:\n            csv_input = StringIO(as_str)\n            data = parse_csv_input(csv_input=csv_input)\n        elif content_type == CONTENT_TYPE_JSON:\n            data = infer_and_parse_json_input(as_str, self._input_schema)\n        elif content_type == CONTENT_TYPE_JSON_SPLIT_ORIENTED:\n            data = parse_json_input(\n                json_input=StringIO(as_str),\n                orient=\"split\",\n                schema=self._input_schema,\n            )\n        elif content_type == CONTENT_TYPE_JSON_RECORDS_ORIENTED:\n            data = parse_json_input(\n                json_input=StringIO(as_str),\n                orient=\"records\",\n                schema=self._input_schema,\n            )\n        elif content_type == CONTENT_TYPE_JSON_SPLIT_NUMPY:\n            data = parse_split_oriented_json_input_to_numpy(as_str)\n        else:\n            content_type_error_message = (\n                \"This predictor only supports the following content types, \"\n                f\"{CONTENT_TYPES}. Got '{content_type}'.\"\n            )\n            raise InferenceError(content_type_error_message)\n\n        try:\n            raw_predictions = self._model.predict(data)\n        except MlflowException as e:\n            raise InferenceError(e.message)\n        except Exception:\n            error_message = (\n                \"Encountered an unexpected error while evaluating the model. Verify\"\n                \" that the serialized input Dataframe is compatible with the model for\"\n                \" inference.\"\n            )\n            raise InferenceError(error_message)\n\n        result = StringIO()\n        predictions_to_json(raw_predictions, result)\n        return Response(content=result.getvalue(), media_type=\"application/json\")\n\n    async def load(self) -> bool:\n        # TODO: Log info message\n        model_uri = await get_model_uri(self._settings)\n        self._model = mlflow.pyfunc.load_model(model_uri)\n        self._input_schema = self._model.metadata.get_input_schema()\n\n        self.ready = True\n        return self.ready\n\n    async def predict(self, payload: InferenceRequest) -> InferenceResponse:\n        decoded_payload = get_decoded_or_raw(payload)\n\n        # TODO: Can `output` be a dictionary of tensors?\n        model_output = self._model.predict(decoded_payload)\n\n        return InferenceResponse(\n            model_name=self.name,\n            model_version=self.version,\n            outputs=to_outputs(model_output),\n        )\n", "path": "runtimes/mlflow/mlserver_mlflow/runtime.py"}]}