code: def _generate_train_val_dfs(
      self,
      data: TimeSeriesDataFrame,
      max_num_items: Optional[int] = None,
      max_num_samples: Optional[int] = None,
  ) -> Tuple[pd.DataFrame, pd.DataFrame]:
      # Exclude items that are too short for chosen differences - otherwise exception will be raised
      if self._sum_of_differences > 0:
          ts_lengths = data.num_timesteps_per_item()
          items_to_exclude = ts_lengths.index[
              ts_lengths <= self._sum_of_differences
          ]
          if len(items_to_exclude) > 0:
              logger.debug(
                  f"Removing {len(items_to_exclude)} items that are too short for chosen differences"
              )
              data = data.query("item_id not in @items_to_exclude")
  
      if max_num_items is not None and data.num_items > max_num_items:
          items_to_keep = data.item_ids.to_series().sample(
              n=int(max_num_items)
          )  # noqa: F841
          data = data.query("item_id in @items_to_keep")
  
      num_items = data.num_items
      mlforecast_df = self._to_mlforecast_df(data, data.static_features)
  
      # Shorten time series before calling preprocess to avoid high memory usage
      if max_num_samples is not None:
          max_samples_per_ts = max(
              200, math.ceil(max_num_samples / num_items)
          )
          self._max_ts_length = (
              max_samples_per_ts
              + self.prediction_length
              + self._sum_of_differences
          )
          mlforecast_df = self._shorten_all_series(
              mlforecast_df, self._max_ts_length
          )
  
      # Unless we set static_features=[], MLForecast interprets all known covariates as static features
      df = self._mlf.preprocess(
          mlforecast_df, dropna=False, static_features=[]
      )
      # df.query results in 2x memory saving compared to df.dropna(subset="y")
      df = df.query("y.notnull()")
  
      df = self._mask_df(df)
  
      if max_num_samples is not None and len(df) > max_num_samples:
          df = df.sample(n=max_num_samples)
  
      grouped_df = df.groupby(MLF_ITEMID, sort=False)
  
      # Use up to `prediction_length` last rows as validation set (but no more than 50% of the rows)
      val_rows_per_item = min(
          self.prediction_length, math.ceil(0.5 * len(df) / num_items)
      )
      train_df = grouped_df.nth(slice(None, -val_rows_per_item))
      val_df = grouped_df.tail(val_rows_per_item)
      logger.debug(
          f"train_df shape: {train_df.shape}, val_df shape: {val_df.shape}"
      )
  
      return train_df.drop(columns=[MLF_TIMESTAMP]), val_df.drop(
          columns=[MLF_TIMESTAMP]
      )
  
imports: import logging
  import math
  import os
  import time
  from typing import Any, Dict, List, Optional, Tuple
  import numpy
  import pandas
  from sklearn.base import BaseEstimator
  import autogluon.core
  from autogluon.common.utils.log_utils import set_logger_verbosity
  from autogluon.tabular import TabularPredictor
  from autogluon.timeseries.dataset.ts_dataframe import ITEMID, TIMESTAMP, TimeSeriesDataFrame
  from autogluon.timeseries.models.abstract import AbstractTimeSeriesModel
  from autogluon.timeseries.models.local import SeasonalNaiveModel
  from autogluon.timeseries.utils.datetime import get_lags_for_frequency, get_seasonality, get_time_features_for_frequency
  from autogluon.timeseries.utils.forecast import get_forecast_horizon_index_ts_dataframe
  from autogluon.timeseries.utils.warning_filters import warning_filter
label_desc: Use image node_id 7 for calling the AbstractMLForecastModel obj's underlying member method code with example usage: obj._generate_train_val_dfs(data, max_num_items, max_num_samples) and returns: train_df,  val_df