We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] Model Identification in sklearn Pipeline should look at the last step
```
pipe = Pipeline(steps=[
    ('transform', transformers),
    ('handle_nans', SimpleImputer(strategy='most_frequent')),
    ('modle', clf)
])

```

Boosting Overfit | DeepchecksValueError: Unsupported model of type: SimpleImputer
-- | --

Boosting Overfit check should have identified the pipeline as the last step (`clf` which was `catboost`)



--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `deepchecks/utils/model.py`
Content:
```
1 # ----------------------------------------------------------------------------
2 # Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)
3 #
4 # This file is part of Deepchecks.
5 # Deepchecks is distributed under the terms of the GNU Affero General
6 # Public License (version 3 or later).
7 # You should have received a copy of the GNU Affero General Public License
8 # along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.
9 # ----------------------------------------------------------------------------
10 #
11 """module for model functions utils."""
12 from typing import Union
13 
14 from sklearn.pipeline import Pipeline
15 from sklearn.base import BaseEstimator
16 
17 from deepchecks.errors import DeepchecksValueError
18 
19 
20 __all__ = ['get_model_of_pipeline']
21 
22 
23 def get_model_of_pipeline(model: Union[Pipeline, BaseEstimator]):
24     """Return the model of a given Pipeline or itself if a BaseEstimator is given.
25 
26     Args:
27         model (Union[Pipeline, BaseEstimator]): a Pipeline or a BaseEstimator model
28     Returns:
29         the inner BaseEstimator of the Pipeline or itself
30     """
31     if isinstance(model, Pipeline):
32         # get feature importance from last model in pipeline
33         internal_estimator_list = [x[1] for x in model.steps if isinstance(x[1], BaseEstimator)]
34         if internal_estimator_list:
35             return internal_estimator_list[-1]
36         raise DeepchecksValueError('Received a pipeline without an sklearn compatible model')
37     return model
38
```

Path: `deepchecks/utils/validation.py`
Content:
```
1 # ----------------------------------------------------------------------------
2 # Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)
3 #
4 # This file is part of Deepchecks.
5 # Deepchecks is distributed under the terms of the GNU Affero General
6 # Public License (version 3 or later).
7 # You should have received a copy of the GNU Affero General Public License
8 # along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.
9 # ----------------------------------------------------------------------------
10 #
11 """objects validation utilities."""
12 import typing as t
13 
14 import pandas as pd
15 import sklearn
16 
17 from deepchecks import base  # pylint: disable=unused-import, is used in type annotations
18 from deepchecks import errors
19 from deepchecks.utils.typing import Hashable
20 
21 
22 __all__ = ['model_type_validation', 'ensure_hashable_or_mutable_sequence', 'validate_model', 'ensure_dataframe_type']
23 
24 
25 def model_type_validation(model: t.Any):
26     """Receive any object and check if it's an instance of a model we support.
27 
28     Raises:
29         DeepchecksValueError: If the object is not of a supported type
30     """
31     supported_by_class_name = ('CatBoostClassifier', 'CatBoostRegressor')
32     supported_by_class_instance = (sklearn.base.BaseEstimator,)
33     if (
34         not isinstance(model, supported_by_class_instance)
35         and model.__class__.__name__ not in supported_by_class_name
36     ):
37         raise errors.DeepchecksValueError(
38             'Model must inherit from one of supported '
39             'models: sklearn.base.BaseEstimator or CatBoost, '
40             f'Received: {model.__class__.__name__}'
41         )
42 
43 
44 def validate_model(
45     data: t.Union['base.Dataset', pd.DataFrame],
46     model: t.Any
47 ):
48     """Check model is able to predict on the dataset.
49 
50     Args:
51         data (Dataset, pandas.DataFrame):
52         model (BaseEstimator):
53 
54     Raise:
55         DeepchecksValueError: if dataset does not match model
56     """
57     model_type_validation(model)
58 
59     error_message = (
60         'In order to evaluate model correctness we need not empty dataset '
61         'with the same set of features that was used to fit the model. {0}'
62     )
63 
64     if isinstance(data, base.Dataset):
65         features = data.features_columns
66         features_names = set(data.features)
67     else:
68         features = data
69         features_names = set(data.columns)
70 
71     model_features = getattr(model, 'feature_names_in_', None)
72 
73     if features is None:
74         raise errors.DeepchecksValueError(error_message.format(
75             'But function received dataset without feature columns.'
76         ))
77 
78     if len(features) == 0:
79         raise errors.DeepchecksValueError(error_message.format(
80             'But function received empty dataset.'
81         ))
82 
83     try:
84         model_features = set(model_features)  # type: ignore
85         if model_features != features_names:
86             raise errors.DeepchecksValueError(error_message.format(
87                 'But function received dataset with a different set of features.'
88             ))
89     except (TypeError, ValueError):
90         # in case if 'model.feature_names_in_' was None or not iterable
91         pass
92 
93     try:
94         model.predict(features.head(1))
95     except Exception as exc:
96         raise errors.DeepchecksValueError(
97             f'Got error when trying to predict with model on dataset: {str(exc)}'
98         )
99 
100 
101 T = t.TypeVar('T', bound=Hashable)
102 
103 
104 def ensure_hashable_or_mutable_sequence(
105     value: t.Union[T, t.MutableSequence[T]],
106     message: str = (
107         'Provided value is neither hashable nor mutable '
108         'sequence of hashable items. Got {type}')
109 ) -> t.List[T]:
110     """Validate that provided value is either hashable or mutable sequence of hashable values."""
111     if isinstance(value, Hashable):
112         return [value]
113 
114     if isinstance(value, t.MutableSequence):
115         if len(value) > 0 and not isinstance(value[0], Hashable):
116             raise errors.DeepchecksValueError(message.format(
117                 type=f'MutableSequence[{type(value).__name__}]'
118             ))
119         return list(value)
120 
121     raise errors.DeepchecksValueError(message.format(
122         type=type(value).__name__
123     ))
124 
125 
126 def ensure_dataframe_type(obj: t.Any) -> pd.DataFrame:
127     """Ensure that given object is of type DataFrame or Dataset and return it as DataFrame. else raise error.
128 
129     Args:
130         obj: Object to ensure it is DataFrame or Dataset
131 
132     Returns:
133         (pd.DataFrame)
134     """
135     if isinstance(obj, pd.DataFrame):
136         return obj
137     elif isinstance(obj, base.Dataset):
138         return obj.data
139     else:
140         raise errors.DeepchecksValueError(
141             f'dataset must be of type DataFrame or Dataset, but got: {type(obj).__name__}'
142         )
143
```
--- 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/deepchecks/utils/model.py b/deepchecks/utils/model.py
--- a/deepchecks/utils/model.py
+++ b/deepchecks/utils/model.py
@@ -14,8 +14,6 @@
 from sklearn.pipeline import Pipeline
 from sklearn.base import BaseEstimator
 
-from deepchecks.errors import DeepchecksValueError
-
 
 __all__ = ['get_model_of_pipeline']
 
@@ -29,9 +27,6 @@
         the inner BaseEstimator of the Pipeline or itself
     """
     if isinstance(model, Pipeline):
-        # get feature importance from last model in pipeline
-        internal_estimator_list = [x[1] for x in model.steps if isinstance(x[1], BaseEstimator)]
-        if internal_estimator_list:
-            return internal_estimator_list[-1]
-        raise DeepchecksValueError('Received a pipeline without an sklearn compatible model')
+        # get model type from last step in pipeline
+        return model.steps[-1][1]
     return model
diff --git a/deepchecks/utils/validation.py b/deepchecks/utils/validation.py
--- a/deepchecks/utils/validation.py
+++ b/deepchecks/utils/validation.py
@@ -16,6 +16,7 @@
 
 from deepchecks import base  # pylint: disable=unused-import, is used in type annotations
 from deepchecks import errors
+from deepchecks.utils.model import get_model_of_pipeline
 from deepchecks.utils.typing import Hashable
 
 
@@ -30,6 +31,8 @@
     """
     supported_by_class_name = ('CatBoostClassifier', 'CatBoostRegressor')
     supported_by_class_instance = (sklearn.base.BaseEstimator,)
+    model = get_model_of_pipeline(model)
+
     if (
         not isinstance(model, supported_by_class_instance)
         and model.__class__.__name__ not in supported_by_class_name

{"golden_diff": "diff --git a/deepchecks/utils/model.py b/deepchecks/utils/model.py\n--- a/deepchecks/utils/model.py\n+++ b/deepchecks/utils/model.py\n@@ -14,8 +14,6 @@\n from sklearn.pipeline import Pipeline\n from sklearn.base import BaseEstimator\n \n-from deepchecks.errors import DeepchecksValueError\n-\n \n __all__ = ['get_model_of_pipeline']\n \n@@ -29,9 +27,6 @@\n         the inner BaseEstimator of the Pipeline or itself\n     \"\"\"\n     if isinstance(model, Pipeline):\n-        # get feature importance from last model in pipeline\n-        internal_estimator_list = [x[1] for x in model.steps if isinstance(x[1], BaseEstimator)]\n-        if internal_estimator_list:\n-            return internal_estimator_list[-1]\n-        raise DeepchecksValueError('Received a pipeline without an sklearn compatible model')\n+        # get model type from last step in pipeline\n+        return model.steps[-1][1]\n     return model\ndiff --git a/deepchecks/utils/validation.py b/deepchecks/utils/validation.py\n--- a/deepchecks/utils/validation.py\n+++ b/deepchecks/utils/validation.py\n@@ -16,6 +16,7 @@\n \n from deepchecks import base  # pylint: disable=unused-import, is used in type annotations\n from deepchecks import errors\n+from deepchecks.utils.model import get_model_of_pipeline\n from deepchecks.utils.typing import Hashable\n \n \n@@ -30,6 +31,8 @@\n     \"\"\"\n     supported_by_class_name = ('CatBoostClassifier', 'CatBoostRegressor')\n     supported_by_class_instance = (sklearn.base.BaseEstimator,)\n+    model = get_model_of_pipeline(model)\n+\n     if (\n         not isinstance(model, supported_by_class_instance)\n         and model.__class__.__name__ not in supported_by_class_name\n", "issue": "[BUG] Model Identification in sklearn Pipeline should look at the last step\n```\r\npipe = Pipeline(steps=[\r\n    ('transform', transformers),\r\n    ('handle_nans', SimpleImputer(strategy='most_frequent')),\r\n    ('modle', clf)\r\n])\r\n\r\n```\r\n\r\nBoosting Overfit | DeepchecksValueError: Unsupported model of type: SimpleImputer\r\n-- | --\r\n\r\nBoosting Overfit check should have identified the pipeline as the last step (`clf` which was `catboost`)\r\n\r\n\n", "before_files": [{"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"module for model functions utils.\"\"\"\nfrom typing import Union\n\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.base import BaseEstimator\n\nfrom deepchecks.errors import DeepchecksValueError\n\n\n__all__ = ['get_model_of_pipeline']\n\n\ndef get_model_of_pipeline(model: Union[Pipeline, BaseEstimator]):\n    \"\"\"Return the model of a given Pipeline or itself if a BaseEstimator is given.\n\n    Args:\n        model (Union[Pipeline, BaseEstimator]): a Pipeline or a BaseEstimator model\n    Returns:\n        the inner BaseEstimator of the Pipeline or itself\n    \"\"\"\n    if isinstance(model, Pipeline):\n        # get feature importance from last model in pipeline\n        internal_estimator_list = [x[1] for x in model.steps if isinstance(x[1], BaseEstimator)]\n        if internal_estimator_list:\n            return internal_estimator_list[-1]\n        raise DeepchecksValueError('Received a pipeline without an sklearn compatible model')\n    return model\n", "path": "deepchecks/utils/model.py"}, {"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"objects validation utilities.\"\"\"\nimport typing as t\n\nimport pandas as pd\nimport sklearn\n\nfrom deepchecks import base  # pylint: disable=unused-import, is used in type annotations\nfrom deepchecks import errors\nfrom deepchecks.utils.typing import Hashable\n\n\n__all__ = ['model_type_validation', 'ensure_hashable_or_mutable_sequence', 'validate_model', 'ensure_dataframe_type']\n\n\ndef model_type_validation(model: t.Any):\n    \"\"\"Receive any object and check if it's an instance of a model we support.\n\n    Raises:\n        DeepchecksValueError: If the object is not of a supported type\n    \"\"\"\n    supported_by_class_name = ('CatBoostClassifier', 'CatBoostRegressor')\n    supported_by_class_instance = (sklearn.base.BaseEstimator,)\n    if (\n        not isinstance(model, supported_by_class_instance)\n        and model.__class__.__name__ not in supported_by_class_name\n    ):\n        raise errors.DeepchecksValueError(\n            'Model must inherit from one of supported '\n            'models: sklearn.base.BaseEstimator or CatBoost, '\n            f'Received: {model.__class__.__name__}'\n        )\n\n\ndef validate_model(\n    data: t.Union['base.Dataset', pd.DataFrame],\n    model: t.Any\n):\n    \"\"\"Check model is able to predict on the dataset.\n\n    Args:\n        data (Dataset, pandas.DataFrame):\n        model (BaseEstimator):\n\n    Raise:\n        DeepchecksValueError: if dataset does not match model\n    \"\"\"\n    model_type_validation(model)\n\n    error_message = (\n        'In order to evaluate model correctness we need not empty dataset '\n        'with the same set of features that was used to fit the model. {0}'\n    )\n\n    if isinstance(data, base.Dataset):\n        features = data.features_columns\n        features_names = set(data.features)\n    else:\n        features = data\n        features_names = set(data.columns)\n\n    model_features = getattr(model, 'feature_names_in_', None)\n\n    if features is None:\n        raise errors.DeepchecksValueError(error_message.format(\n            'But function received dataset without feature columns.'\n        ))\n\n    if len(features) == 0:\n        raise errors.DeepchecksValueError(error_message.format(\n            'But function received empty dataset.'\n        ))\n\n    try:\n        model_features = set(model_features)  # type: ignore\n        if model_features != features_names:\n            raise errors.DeepchecksValueError(error_message.format(\n                'But function received dataset with a different set of features.'\n            ))\n    except (TypeError, ValueError):\n        # in case if 'model.feature_names_in_' was None or not iterable\n        pass\n\n    try:\n        model.predict(features.head(1))\n    except Exception as exc:\n        raise errors.DeepchecksValueError(\n            f'Got error when trying to predict with model on dataset: {str(exc)}'\n        )\n\n\nT = t.TypeVar('T', bound=Hashable)\n\n\ndef ensure_hashable_or_mutable_sequence(\n    value: t.Union[T, t.MutableSequence[T]],\n    message: str = (\n        'Provided value is neither hashable nor mutable '\n        'sequence of hashable items. Got {type}')\n) -> t.List[T]:\n    \"\"\"Validate that provided value is either hashable or mutable sequence of hashable values.\"\"\"\n    if isinstance(value, Hashable):\n        return [value]\n\n    if isinstance(value, t.MutableSequence):\n        if len(value) > 0 and not isinstance(value[0], Hashable):\n            raise errors.DeepchecksValueError(message.format(\n                type=f'MutableSequence[{type(value).__name__}]'\n            ))\n        return list(value)\n\n    raise errors.DeepchecksValueError(message.format(\n        type=type(value).__name__\n    ))\n\n\ndef ensure_dataframe_type(obj: t.Any) -> pd.DataFrame:\n    \"\"\"Ensure that given object is of type DataFrame or Dataset and return it as DataFrame. else raise error.\n\n    Args:\n        obj: Object to ensure it is DataFrame or Dataset\n\n    Returns:\n        (pd.DataFrame)\n    \"\"\"\n    if isinstance(obj, pd.DataFrame):\n        return obj\n    elif isinstance(obj, base.Dataset):\n        return obj.data\n    else:\n        raise errors.DeepchecksValueError(\n            f'dataset must be of type DataFrame or Dataset, but got: {type(obj).__name__}'\n        )\n", "path": "deepchecks/utils/validation.py"}], "after_files": [{"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"module for model functions utils.\"\"\"\nfrom typing import Union\n\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.base import BaseEstimator\n\n\n__all__ = ['get_model_of_pipeline']\n\n\ndef get_model_of_pipeline(model: Union[Pipeline, BaseEstimator]):\n    \"\"\"Return the model of a given Pipeline or itself if a BaseEstimator is given.\n\n    Args:\n        model (Union[Pipeline, BaseEstimator]): a Pipeline or a BaseEstimator model\n    Returns:\n        the inner BaseEstimator of the Pipeline or itself\n    \"\"\"\n    if isinstance(model, Pipeline):\n        # get model type from last step in pipeline\n        return model.steps[-1][1]\n    return model\n", "path": "deepchecks/utils/model.py"}, {"content": "# ----------------------------------------------------------------------------\n# Copyright (C) 2021 Deepchecks (https://www.deepchecks.com)\n#\n# This file is part of Deepchecks.\n# Deepchecks is distributed under the terms of the GNU Affero General\n# Public License (version 3 or later).\n# You should have received a copy of the GNU Affero General Public License\n# along with Deepchecks.  If not, see <http://www.gnu.org/licenses/>.\n# ----------------------------------------------------------------------------\n#\n\"\"\"objects validation utilities.\"\"\"\nimport typing as t\n\nimport pandas as pd\nimport sklearn\n\nfrom deepchecks import base  # pylint: disable=unused-import, is used in type annotations\nfrom deepchecks import errors\nfrom deepchecks.utils.model import get_model_of_pipeline\nfrom deepchecks.utils.typing import Hashable\n\n\n__all__ = ['model_type_validation', 'ensure_hashable_or_mutable_sequence', 'validate_model', 'ensure_dataframe_type']\n\n\ndef model_type_validation(model: t.Any):\n    \"\"\"Receive any object and check if it's an instance of a model we support.\n\n    Raises:\n        DeepchecksValueError: If the object is not of a supported type\n    \"\"\"\n    supported_by_class_name = ('CatBoostClassifier', 'CatBoostRegressor')\n    supported_by_class_instance = (sklearn.base.BaseEstimator,)\n    model = get_model_of_pipeline(model)\n\n    if (\n        not isinstance(model, supported_by_class_instance)\n        and model.__class__.__name__ not in supported_by_class_name\n    ):\n        raise errors.DeepchecksValueError(\n            'Model must inherit from one of supported '\n            'models: sklearn.base.BaseEstimator or CatBoost, '\n            f'Received: {model.__class__.__name__}'\n        )\n\n\ndef validate_model(\n    data: t.Union['base.Dataset', pd.DataFrame],\n    model: t.Any\n):\n    \"\"\"Check model is able to predict on the dataset.\n\n    Args:\n        data (Dataset, pandas.DataFrame):\n        model (BaseEstimator):\n\n    Raise:\n        DeepchecksValueError: if dataset does not match model\n    \"\"\"\n    model_type_validation(model)\n\n    error_message = (\n        'In order to evaluate model correctness we need not empty dataset '\n        'with the same set of features that was used to fit the model. {0}'\n    )\n\n    if isinstance(data, base.Dataset):\n        features = data.features_columns\n        features_names = set(data.features)\n    else:\n        features = data\n        features_names = set(data.columns)\n\n    model_features = getattr(model, 'feature_names_in_', None)\n\n    if features is None:\n        raise errors.DeepchecksValueError(error_message.format(\n            'But function received dataset without feature columns.'\n        ))\n\n    if len(features) == 0:\n        raise errors.DeepchecksValueError(error_message.format(\n            'But function received empty dataset.'\n        ))\n\n    try:\n        model_features = set(model_features)  # type: ignore\n        if model_features != features_names:\n            raise errors.DeepchecksValueError(error_message.format(\n                'But function received dataset with a different set of features.'\n            ))\n    except (TypeError, ValueError):\n        # in case if 'model.feature_names_in_' was None or not iterable\n        pass\n\n    try:\n        model.predict(features.head(1))\n    except Exception as exc:\n        raise errors.DeepchecksValueError(\n            f'Got error when trying to predict with model on dataset: {str(exc)}'\n        )\n\n\nT = t.TypeVar('T', bound=Hashable)\n\n\ndef ensure_hashable_or_mutable_sequence(\n    value: t.Union[T, t.MutableSequence[T]],\n    message: str = (\n        'Provided value is neither hashable nor mutable '\n        'sequence of hashable items. Got {type}')\n) -> t.List[T]:\n    \"\"\"Validate that provided value is either hashable or mutable sequence of hashable values.\"\"\"\n    if isinstance(value, Hashable):\n        return [value]\n\n    if isinstance(value, t.MutableSequence):\n        if len(value) > 0 and not isinstance(value[0], Hashable):\n            raise errors.DeepchecksValueError(message.format(\n                type=f'MutableSequence[{type(value).__name__}]'\n            ))\n        return list(value)\n\n    raise errors.DeepchecksValueError(message.format(\n        type=type(value).__name__\n    ))\n\n\ndef ensure_dataframe_type(obj: t.Any) -> pd.DataFrame:\n    \"\"\"Ensure that given object is of type DataFrame or Dataset and return it as DataFrame. else raise error.\n\n    Args:\n        obj: Object to ensure it is DataFrame or Dataset\n\n    Returns:\n        (pd.DataFrame)\n    \"\"\"\n    if isinstance(obj, pd.DataFrame):\n        return obj\n    elif isinstance(obj, base.Dataset):\n        return obj.data\n    else:\n        raise errors.DeepchecksValueError(\n            f'dataset must be of type DataFrame or Dataset, but got: {type(obj).__name__}'\n        )\n", "path": "deepchecks/utils/validation.py"}]}