class_docstr: A DoFn that extracts slice keys in batch.
class_docstr_tok: ["A","DoFn","that","extracts","slice","keys","in","batch","."]
code: def process(
      self, batched_extract: types.Extracts
  ) -> List[types.Extracts]:
      features = batched_extract[constants.FEATURES_KEY]
      # Slice on transformed features if available.
      if (
          constants.TRANSFORMED_FEATURES_KEY in batched_extract
          and batched_extract[constants.TRANSFORMED_FEATURES_KEY]
          is not None
      ):
          transformed_features = batched_extract[
              constants.TRANSFORMED_FEATURES_KEY
          ]
          # If only one model, the output is stored without keying on model name.
          if (
              not self._eval_config
              or len(self._eval_config.model_specs) == 1
          ):
              features.update(transformed_features)
          else:
              # Models listed earlier have precedence in feature lookup.
              for spec in reversed(self._eval_config.model_specs):
                  if spec.name in transformed_features:
                      features.update(transformed_features[spec.name])
  
      tensors = util.to_tensorflow_tensors(features)
      tensor_specs = util.infer_tensor_specs(tensors)
  
      if _TF_MAJOR_VERSION < 2 or not tf.executing_eagerly():
          # TODO(b/228456048): TFX-BSL doesn't support passing tensorflow tensors
          # for non-sparse/ragged values in TF 1.x (i.e. it only accepts np.ndarray
          # for dense) so we need to convert dense tensors to numpy.
          sess = tf.compat.v1.Session()
  
          def _convert_dense_to_numpy(
              values,
          ):  # pylint: disable=invalid-name
              if isinstance(values, Mapping):
                  for k, v in values.items():
                      if isinstance(v, Mapping):
                          values[k] = _convert_dense_to_numpy(v)
                      elif isinstance(v, tf.Tensor):
                          values[k] = v.eval(session=sess)
              return values
  
          tensors = _convert_dense_to_numpy(tensors)
  
      converter = tensor_to_arrow.TensorsToRecordBatchConverter(
          tensor_specs
      )
      record_batch = converter.convert(tensors)
      sql_slice_keys = [[] for _ in range(record_batch.num_rows)]
  
      for query in self._cached_queries(record_batch.schema):
          # Example of result with batch size = 3:
          # result = [[[('feature', 'value_1')]],
          #           [[('feature', 'value_2')]],
          #           []
          #          ]
          result = query.Execute(record_batch)
          for row_index, row_result in enumerate(result):
              sql_slice_keys[row_index].extend(
                  [tuple(s) for s in row_result]
              )
  
      # convert sql_slice_keys into a VarLenTensorValue where each row has dtype
      # object.
      dense_rows = []
      for row_slice_keys in sql_slice_keys:
          dense_rows.append(
              slicer_lib.slice_keys_to_numpy_array(row_slice_keys)
          )
      varlen_sql_slice_keys = types.VarLenTensorValue.from_dense_rows(
          dense_rows
      )
  
      # Make a a shallow copy, so we don't mutate the original.
      batched_extract_copy = copy.copy(batched_extract)
      batched_extract_copy[
          constants.SLICE_KEY_TYPES_KEY
      ] = varlen_sql_slice_keys
  
      self._sql_slicer_num_record_batch_schemas.update(
          self._cached_queries.cache_info().currsize
      )
  
      return [batched_extract_copy]
  
imports: import copy
  import functools
  from typing import List, Mapping
  import apache_beam
  import pyarrow
  import tensorflow
  from tensorflow_model_analysis import constants
  from tensorflow_model_analysis.api import types
  from tensorflow_model_analysis.extractors import extractor
  from tensorflow_model_analysis.proto import config_pb2
  from tensorflow_model_analysis.slicer import slicer_lib
  from tensorflow_model_analysis.utils import util
  from tfx_bsl.arrow import sql_util
  from tfx_bsl.tfxio import tensor_to_arrow
label_desc: Use image node_id 3 for calling the ExtractSqlSliceKeyFn obj's underlying member method code with example usage: obj.process(batched_extract) and returns: list, values