code: def _plot_feature_interaction(
      exp: Explanation,
      features: List[int],
      targets: List[Union[str, int]],
      summarise=True,
      n_cols: int = 3,
      sort: bool = True,
      top_k: Optional[int] = None,
      plot_limits: Optional[Tuple[float, float]] = None,
      ax: Optional[Union["plt.Axes", np.ndarray]] = None,
      sharey: Optional[Literal["all", "row"]] = "all",
      bar_kw: Optional[dict] = None,
      line_kw: Optional[dict] = None,
      fig_kw: Optional[dict] = None,
  ):
      """
      Horizontal bar plot for feature interaction.
  
      Parameters
      ----------
      exp, features, targets, summarise, n_cols, sort, top_k, plot_limits, ax, sharey, bar_kw, line_kw, fig_kw
          See :py:meth:`alibi.explainers.pd_variance.plot_pd_variance`.
  
      Returns
      -------
      `plt.Axes` with the feature interaction plot.
      """
      if summarise:
          feature_names = [
              "({}, {})".format(*fs)
              for fs in exp.data["feature_names"]
              if isinstance(fs, tuple)
          ]
          return _plot_hbar(
              exp_values=exp.data["feature_interaction"],
              exp_feature_names=feature_names,
              exp_target_names=exp.meta["params"]["target_names"],
              features=features,
              targets=targets,
              n_cols=n_cols,
              sort=sort,
              top_k=top_k,
              title="Feature interaction",
              ax=ax,
              bar_kw=bar_kw,
              fig_kw=fig_kw,
          )
  
      # unpack explanation
      target = targets[0]
  
      feature_names = exp.data["feature_names"]
      feature_values = exp.data["feature_values"]
      feature_deciles = exp.data["feature_deciles"]
      pd_values = exp.data["pd_values"]
  
      conditional_importance = exp.data["conditional_importance"]
      conditional_importance_values = exp.data[
          "conditional_importance_values"
      ]
  
      target_idx = (
          exp.meta["params"]["target_names"].index(target)
          if isinstance(target, str)
          else target
      )
      feature_interaction = exp.data["feature_interaction"][target_idx][
          features
      ]
  
      if sort:
          sorted_indices = np.argsort(feature_interaction)[::-1]
          features = [features[i] for i in sorted_indices][:top_k]
          feature_interaction = feature_interaction[sorted_indices][
              :top_k
          ]
          conditional_importance = [
              conditional_importance[i] for i in sorted_indices
          ][:top_k]
  
      # merge `pd_values` and `conditional_importance`
      merged_pd_values = [
          [pd, *cond_imp_vals]
          for pd, cond_imp_vals in zip(
              pd_values, conditional_importance_values
          )
      ]
      merged_pd_values = list(
          itertools.chain.from_iterable(merged_pd_values)
      )
  
      # construct `feature_names` for the `merged_pd_values`
      merged_feature_names = [
          [ft_names, *ft_names] for ft_names in feature_names
      ]
      merged_feature_names = list(
          itertools.chain.from_iterable(merged_feature_names)
      )
  
      # construct `feature_values` for the `merged_pd_values`
      merged_feature_values = [
          [ft_values, *ft_values] for ft_values in feature_values
      ]
      merged_feature_values = list(
          itertools.chain.from_iterable(merged_feature_values)
      )
  
      # construct `feature_deciles` for the `merged_pd_values`
      merged_feature_deciles = [
          [ft_deciles, *ft_deciles] for ft_deciles in feature_deciles
      ]
      merged_feature_deciles = list(
          itertools.chain.from_iterable(merged_feature_deciles)
      )
  
      # construct `features` for the `merged_features`
      step = 3  # because we have a 2-way pdp followed by two conditional feature importance
      merged_features = [
          [step * ft, step * ft + 1, step * ft + 2] for ft in features
      ]
      merged_features = list(itertools.chain.from_iterable(merged_features))  # type: ignore[arg-type]
  
      # construct pd explanation object to reuse `plot_pd` function
      meta = copy.deepcopy(exp.meta)
      meta["params"]["kind"] = "average"
      data = copy.deepcopy(DEFAULT_DATA_PD)
      data.update(
          feature_names=merged_feature_names,
          feature_values=merged_feature_values,
          pd_values=merged_pd_values,
          feature_deciles=merged_feature_deciles,
      )
      exp_pd = Explanation(meta=meta, data=data)
  
      # plot the partial dependence
      axes = plot_pd(
          exp=exp_pd,
          features=merged_features,
          target=target,
          n_cols=n_cols,
          pd_limits=plot_limits,
          ax=ax,
          sharey=sharey,
          pd_num_kw=line_kw,
          fig_kw=fig_kw,
      )
  
      # add title to each plot with the feature importance
      axes_flatten = axes.flatten()
      for i in range(len(features)):
          # set title for the 2-way pdp
          ax = axes_flatten[step * i]
          (ft_name1, ft_name2) = feature_names[
              features[i]
          ]  # type: Tuple[str, str]  # type: ignore[misc]
          ax.set_title(
              "inter({},{}) = {:.3f}".format(
                  ft_name1,
                  ft_name2,  # type: ignore[union-attr]
                  feature_interaction[i],
              )
          )
  
          # set title for the first conditional importance plot
          ax = axes.flatten()[step * i + 1]
          ax.set_title(
              "inter({}|{}) = {:.3f}".format(
                  ft_name2,
                  ft_name1,  # type: ignore[union-attr]
                  conditional_importance[i][0][target_idx],
              )
          )
  
          # set title for the second conditional importance plot
          ax = axes.flatten()[step * i + 2]
          ax.set_title(
              "inter({}|{}) = {:.3f}".format(
                  ft_name1,
                  ft_name2,  # type: ignore[union-attr]
                  conditional_importance[i][1][target_idx],
              )
          )
  
      return axes
  
imports: import copy
  import itertools
  import logging
  import math
  import numbers
  import sys
  from enum import Enum
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import matplotlib.pyplot
  import numpy
  from sklearn.base import BaseEstimator
  from alibi.api.defaults import DEFAULT_DATA_PD, DEFAULT_DATA_PDVARIANCE, DEFAULT_META_PDVARIANCE
  from alibi.api.interfaces import Explainer, Explanation
  from alibi.explainers import plot_pd
  from alibi.explainers.partial_dependence import Kind, PartialDependence, TreePartialDependence
  from alibi.utils import _get_options_string
label_desc: Use image node_id 3 for calling a global function with example usage: _plot_feature_interaction(exp, features, targets, summarise, n_cols, sort, top_k, plot_limits, ax, sharey, bar_kw, line_kw, fig_kw) and returns: axes, _plot_hbar