`_MultimetricScorer` deals with `_accept_sample_weights` inconsistently

### Describe the bug

When one of the scorers in `_MultimetricScorer` is not a `Scorer` object, it is handled incorrectly.

See line [here](https://github.com/scikit-learn/scikit-learn/blob/0fc081a4e131b08cb6d22f77f250733f265097b4/sklearn/metrics/_scorer.py#L143). If the scorers passed to `MultimetricScorer` are of the following type: [`Scorer`, `function`], it raises an error because the attribute `_accept_sample_weight` does not exist for the second scorer (`function` in this case). This (possibly) bug is present only in 1.7.0 since before this, the `sample_weight` kwarg was being passed to all functions without a check of accepting sample weights.

Possible fix: Use `if hasattr(scorer, '_accept_sample_weight'`) or `if isinstance(scorer, _BaseScorer)` _before_ checking for the `_accept_sample_weight` attribute.

### Steps/Code to Reproduce

```python
import numpy as np
from sklearn.base import BaseEstimator, RegressorMixin
from sklearn.metrics._scorer import _BaseScorer, _MultimetricScorer

# Step 1: Define a simple estimator
class SimpleEstimator(BaseEstimator, RegressorMixin):
    def fit(self, X, y):
        self.mean_ = np.mean(y)
        return self

    def predict(self, X):
        return np.full(X.shape[0], self.mean_)

# Step 2: Define a custom scorer inheriting from _BaseScorer and a function which estimates score
class SimpleScorer(_BaseScorer):
    def _score(self, method_caller, estimator, X, y_true, sample_weight=None):
        y_pred = method_caller(estimator, "predict", X)
        return self._score_func(y_true, y_pred, **self._kwargs)

def default_score(estimator, X, y, sample_weight=None, **kws):
    return estimator.score(X, y, sample_weight=sample_weight)

def mse(y, y_pred):
    return np.mean((y - y_pred)**2)

# Step 3: Create a _MultimetricScorer with multiple scorers
scorers = {
    "mse": SimpleScorer(mse, sign=1, kwargs={}),
    "default": default_score
}
multi_scorer = _MultimetricScorer(scorers=scorers)

# Step 4: Generate sample data
X = np.random.rand(10, 2)
y = np.random.rand(10)
sample_weight = np.random.rand(10)

# Step 5: Fit the estimator and evaluate using the multi-scorer
estimator = SimpleEstimator()
estimator.fit(X, y)
scores = multi_scorer(estimator, X, y, sample_weight=sample_weight)

print("Scores:", scores)
```

### Expected Results

Expected result would be scores for each of the scorers without an error being raised.

### Actual Results

```
AttributeError                            Traceback (most recent call last)
Cell In[6], line 4
      2 estimator = SimpleEstimator()
      3 estimator.fit(X, y)
----> 4 scores = multi_scorer(estimator, X, y, sample_weight=sample_weight)
      6 print("Scores:", scores)

File ~/anaconda3/envs/scoring-311-2/lib/python3.11/site-packages/sklearn/metrics/_scorer.py:144, in _MultimetricScorer.__call__(self, estimator, *args, **kwargs)
    142     if "sample_weight" in kwargs:
    143         for name, scorer in self._scorers.items():
--> 144             if scorer._accept_sample_weight():
    145                 routed_params[name].score["sample_weight"] = kwargs[
    146                     "sample_weight"
    147                 ]
    149 for name, scorer in self._scorers.items():

AttributeError: 'function' object has no attribute '_accept_sample_weight'
```

### Versions

```shell
The `***` below is to obscure some personal details.


System:
    python: 3.11.13 | packaged by conda-forge | (main, Jun  4 2025, 14:52:34) [Clang 18.1.8 ]
executable: /Users/***/anaconda3/envs/***/bin/python3.11
   machine: macOS-15.5-arm64-arm-64bit

Python dependencies:
      sklearn: 1.7.0
          pip: 25.1.1
   setuptools: 80.9.0
        numpy: 2.2.6
        scipy: 1.15.2
       Cython: None
       pandas: 2.3.0
   matplotlib: None
       joblib: 1.5.1
threadpoolctl: 3.6.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 14
         prefix: libopenblas
       filepath: /Users/***/anaconda3/envs/***/lib/libopenblas.0.dylib
        version: 0.3.29
threading_layer: openmp
   architecture: VORTEX

       user_api: openmp
   internal_api: openmp
    num_threads: 14
         prefix: libomp
       filepath: /Users/***/anaconda3/envs/***/lib/libomp.dylib
        version: None
```

COMMENT:
Both approaches seem reasonable to me, I don't have a clear nor informed opinion about the best way to deal with the scorer API.

1. @lesteve seems a more straightforward and easy way to fix the issue on the short term, indeed adding `PassthroughScorer` and maybe raising an error if not a valid scorer option, eg
```python
def _accept_sample_weight(scorer):
    if isinstance(scorer, _MultimetricScorer):
        return any(_accept_sample_weight(each) for each in scorer.values())
    elif isinstance(scorer, _BaseScorer):
        return "sample_weight" in signature(self._score_func).parameters
    elif isinstance(scorer, _PassthroughScorer):
        return "sample_weight" in signature(self._estimator.score).parameters
    elif callable(scorer): # or maybe isinstance(scorer, FunctionType) ?
        return "sample_weight" in signature(score).parameters
    else:
       raise ValueError(f"{scorer=} should be a _MultimetricScorer, _BaseScorer, _PassthroughScorer or a callable. ")
```
2. @adrinjalali on harmonizing and validating the `scoring` param is better but more involved as there are several estimators to consider
```python
from sklearn.utils import all_estimators
from inspect import signature
[name for name, klass in all_estimators() if "scoring" in signature(klass).parameters]
```
```
['GridSearchCV',
 'HistGradientBoostingClassifier',
 'HistGradientBoostingRegressor',
 'LogisticRegressionCV',
 'RFECV',
 'RandomizedSearchCV',
 'RidgeCV',
 'RidgeClassifierCV',
 'SequentialFeatureSelector',
 'TunedThresholdClassifierCV']
``` 
Some have special keywords (eg "loss" in `HistGradientBoostingClassifier`), and some can handle a multimetric scorer (`GridSearchCV`).

Labels: Bug, module:metrics, Needs Investigation