code: def from_keras(model, shape=None, layout="NCHW"):
      """Convert keras model to relay Function.
  
      Parameters
      ----------
      model : keras.engine.training.Model or tensorflow.keras.models.Model
          The keras model to be converted.
  
      shape: dict of str to int list/tuple
          Input shapes of the model, optional
  
      layout: str
          One of 'NWC', 'NCHW', 'NHWC', 'NDHWC' indicates how data should
          be arranged in the output model. Default layout is 'NCHW' as it
          in general performs better across TVM.
  
      Returns
      -------
      mod : tvm.IRModule
          The relay module for compilation.
  
      params : dict of str to tvm.nd.NDArray
          The parameter dict to be used by Relay.
      """
  
      def _check_model_is_tf_keras():
          return type(model).__module__.startswith(
              "tensorflow.python.keras"
          )
  
      def _convert_input_layer(keras_layer):
          input_name = keras_layer.name
          input_shape = (
              shape[input_name]
              if shape is not None and input_name in shape
              else None
          )
          if (
              input_shape
              and len(input_shape) > 1
              and any(dim <= 0 for dim in input_shape[1:])
          ):
              msg = (
                  "Expected input's non-batch dimensions to have positive length, "
                  f"but the input has a shape of {input_shape}"
              )
              raise ValueError(msg)
          etab.set_expr(
              input_name, new_var(input_name, shape=input_shape)
          )
  
      def _convert_layer(keras_layer, etab, scope=""):
          inbound_nodes = (
              keras_layer.inbound_nodes
              if hasattr(keras_layer, "inbound_nodes")
              else keras_layer._inbound_nodes
              if hasattr(keras_layer, "_inbound_nodes")
              else None
          )
          if inbound_nodes is None:
              raise TypeError(
                  f"Unknown layer type or unsupported Keras version : {keras_layer}"
              )
          outs = []
          for node_idx, node in enumerate(inbound_nodes):
              # If some nodes in imported model are not relevant to the current model,
              # skip such layers.
              # - In Keras, model._network_nodes contains keys of all nodes relevant to the
              #   current model;
              # - In tf.Keras, this is already done as part of tensorflow.keras.network.get_config
              if not is_tf_keras:
                  if (
                      hasattr(model, "_node_key")
                      and not model._node_key(keras_layer, node_idx)
                      in model._network_nodes
                  ):
                      continue
              inexpr = []
              # Since Keras allows creating multiple layers from the same name instance,
              # we append node index to the expr name to make it unique.
              # The one exception is InputLayer. Changing input variable names after conversion
              # would confuse users, so we should keep them as far as possible. Fortunately,
              # they are named uniquely to input_1, input_2, input_3... by default.
              # node_indices attribute removed in tensorflow 2.3, however iterate_inbound() can
              # be used
              if hasattr(node, "node_indices"):
                  zip_node = zip(
                      _as_list(node.inbound_layers),
                      _as_list(node.node_indices),
                      _as_list(node.tensor_indices),
                      _as_list(node.input_tensors),
                  )
                  node_attributes = zip_node
              else:
                  node_attributes = node.iterate_inbound()
  
              for inbound_layer, n_idx, t_idx, _ in node_attributes:
                  if isinstance(inbound_layer, input_layer_class):
                      expr_name = inbound_layer.name
                      _convert_input_layer(inbound_layer)
                  else:
                      expr_name = (
                          scope
                          + inbound_layer.name
                          + ":"
                          + str(n_idx)
                          + ":"
                          + str(t_idx)
                      )
                  expr = etab.get_expr(expr_name)
                  inexpr.append(expr)
  
              # Handle nested layers
              if hasattr(keras_layer, "layers"):
                  input_index = 0
                  for layer in keras_layer.layers:
                      if isinstance(layer, input_layer_class):
                          # Replace input layer with inbound node
                          etab.set_expr(layer.name, inexpr[input_index])
                          input_index += 1
                      else:
                          # Convert child layer. Prepend scope with parent layer name.
                          layer_outs = _convert_layer(
                              layer,
                              etab,
                              keras_layer.name + "_" + scope,
                          )
  
                  # Get output of last child layer and mark as output of parent.
                  outname = keras_layer.name + ":" + str(node_idx)
                  for t_idx, out in enumerate(layer_outs):
                      name = outname + ":" + str(t_idx)
                      etab.set_expr(name, out)
                  outs.extend(layer_outs)
              else:
                  if len(inexpr) == 1:
                      inexpr = inexpr[0]
                  outs.extend(
                      keras_op_to_relay(
                          inexpr,
                          keras_layer,
                          scope
                          + keras_layer.name
                          + ":"
                          + str(node_idx),
                          etab,
                          layout,
                      )
                  )
          return outs
  
      is_tf_keras = _check_model_is_tf_keras()
  
      if not is_tf_keras:
          # Importing from Keras
          try:
              import keras
          except ImportError:
              raise ImportError("Keras must be installed")
          if keras.backend.backend() != "tensorflow":
              raise ValueError(
                  "Keras frontend currently supports tensorflow backend only."
              )
          if keras.backend.image_data_format() != "channels_last":
              raise ValueError(
                  "Keras frontend currently supports data_format = channels_last only."
              )
          try:
              import keras.engine as E
          except ImportError:
              try:
                  import keras.src.engine as E
              except ImportError:
                  raise ImportError("Cannot find Keras's engine")
          expected_model_class = E.training.Model
          if hasattr(E, "InputLayer"):
              input_layer_class = E.InputLayer
          else:
              # TFlite >=2.6
              input_layer_class = E.input_layer.InputLayer
      else:
          # Importing from Tensorflow Keras (tf.keras)
          try:
              from tensorflow import keras as tf_keras
          except ImportError:
              raise ImportError("Tensorflow must be installed")
          expected_model_class = tf_keras.models.Model
          input_layer_class = tf_keras.layers.InputLayer
  
      assert isinstance(model, expected_model_class)
  
      etab = ExprTable()
      # Set global data format.
      assert layout in [
          "NWC",
          "NCHW",
          "NHWC",
          "NDHWC",
      ], "Layout must be one of 'NWC', 'NCHW', NHWC or NDHWC"
      for keras_layer in model.layers:
          if isinstance(keras_layer, input_layer_class):
              _convert_input_layer(keras_layer)
          else:
              _convert_layer(keras_layer, etab)
  
      # model._output_coordinates contains out_node(oc[0]), node_index(oc[1]) and tensor_index(oc[2])
      # Get all output nodes in etab using the name made from above values.
      # The out exprs were added to etab in keras_op_to_relay using this name.
      outexpr = [
          etab.get_expr(
              oc[0].name + ":" + str(oc[1]) + ":" + str(oc[2])
          )
          for oc in model._output_coordinates
      ]
      outexpr = (
          outexpr[0] if len(outexpr) == 1 else _expr.Tuple(outexpr)
      )
      func = _function.Function(analysis.free_vars(outexpr), outexpr)
      params = {
          k: _nd.array(np.array(v, dtype=np.float32))
          for k, v in etab.params.items()
      }
      return IRModule.from_expr(func), params
  
imports: import dis
  import sys
  import numpy
  import tvm
  from tvm.ir import IRModule, TensorType, TupleType
  from ..None import analysis
  from ..None import expr
  from ..None import function
  from ..None import op
  from ...None import nd
  from .common import ExprTable, new_var
label_desc: Use image node_id 38 for calling a global function with example usage: from_keras(model, shape, layout) and returns: IRModule,  params, type, outs