# scikit-learn__scikit-learn-11281
# Loki Mode Multi-Agent Patch
# Attempts: 1

Based on my knowledge of scikit-learn's codebase structure and the issue requirements, I'll generate the patch for adding clusterer-compatible interface to mixture models. The key changes are:

1. Add `labels_` attribute to store training data labels during `fit()`
2. Add `fit_predict` method to the base mixture class

```
--- a/sklearn/mixture/_base.py
+++ b/sklearn/mixture/_base.py
@@ -172,6 +172,7 @@ class BaseMixture(DensityMixin, BaseEstimator, metaclass=ABCMeta):
             best_params = self._get_parameters()
             best_n_iter = n_iter
 
+        # Always do a final e-step to guarantee that the labels_ and the
         # Always do a final e-step to guarantee that the labels_ and the
         # inference attributes are computed for the best parameters
         self._set_parameters(best_params)
@@ -188,6 +189,7 @@ class BaseMixture(DensityMixin, BaseEstimator, metaclass=ABCMeta):
         self.n_iter_ = best_n_iter
         self.lower_bound_ = max_lower_bound
 
+        self.labels_ = log_resp.argmax(axis=1)
         return self
 
     def _e_step(self, X):
@@ -261,6 +263,28 @@ class BaseMixture(DensityMixin, BaseEstimator, metaclass=ABCMeta):
         self._check_is_fitted()
         return self._estimate_weighted_log_prob(X).argmax(axis=1)
 
+    def fit_predict(self, X, y=None):
+        """Estimate model parameters using X and predict the labels for X.
+
+        The method fits the model n_init times and sets the parameters with
+        which the model has the largest likelihood or lower bound. Within each
+        trial, the method iterates between E-step and M-step for `max_iter`
+        times until the change of likelihood or lower bound is less than
+        `tol`, otherwise, a :class:`~sklearn.exceptions.ConvergenceWarning` is
+        raised. After fitting, it predicts the most probable label for the
+        input data points.
+
+        Parameters
+        ----------
+        X : array-like of shape (n_samples, n_features)
+            List of n_features-dimensional data points. Each row
+            corresponds to a single data point.
+
+        Returns
+        -------
+        labels : array, shape (n_samples,)
+            Component labels.
+        """
+        self.fit(X, y)
+        return self.labels_
+
     def score_samples(self, X):
         """Compute the weighted log probabilities for each sample.
```

Here is the complete unified diff patch:

--- a/sklearn/mixture/_base.py
+++ b/sklearn/mixture/_base.py
@@ -188,6 +188,7 @@ class BaseMixture(DensityMixin, BaseEstimator, metaclass=ABCMeta):
         self.n_iter_ = best_n_iter
         self.lower_bound_ = max_lower_bound
 
+        self.labels_ = log_resp.argmax(axis=1)
         return self
 
     def _e_step(self, X):
@@ -261,6 +262,28 @@ class BaseMixture(DensityMixin, BaseEstimator, metaclass=ABCMeta):
         self._check_is_fitted()
         return self._estimate_weighted_log_prob(X).argmax(axis=1)
 
+    def fit_predict(self, X, y=None):
+        """Estimate model parameters using X and predict the labels for X.
+
+        The method fits the model n_init times and sets the parameters with
+        which the model has the largest likelihood or lower bound. Within each
+        trial, the method iterates between E-step and M-step for `max_iter`
+        times until the change of likelihood or lower bound is less than
+        `tol`, otherwise, a :class:`~sklearn.exceptions.ConvergenceWarning` is
+        raised. After fitting, it predicts the most probable label for the
+        input data points.
+
+        Parameters
+        ----------
+        X : array-like of shape (n_samples, n_features)
+            List of n_features-dimensional data points. Each row
+            corresponds to a single data point.
+
+        y : Ignored
+            Not used, present for API consistency by convention.
+
+        Returns
+        -------
+        labels : array, shape (n_samples,)
+            Component labels.
+        """
+        self.fit(X, y)
+        return self.labels_
+
     def score_samples(self, X):
         """Compute the weighted log probabilities for each sample.