def add_embedding_nd(
        self,
        name,
        input_name,
        output_name,
        vocab_size,
        embedding_size,
        W,
        b=None,
        is_quantized_weight=False,
        quantization_type="linear",
        nbits=8,
        quant_scale=None,
        quant_bias=None,
        quant_lut=None,
    ):
        """
        Add an embedding layer to the model that performs a matrix lookup and
        optionally adds a bias.
        Refer to the ``EmbeddingNDLayerParams`` message in the specification
        (NeuralNetwork.proto) for more details.

        Parameters
        ----------
        name: str
            The name of this layer.
        input_name: str
            The input blob name of this layer.
        output_name: str
            The output blob name of this layer.
        vocab_size: int
            Size of the vocabulary (1 + maximum integer index of the words).
        embedding_size: int
            Size of the embedded vector.
        W: float32 numpy.array or bytes()
            Weight matrix of shape (embedding_size, vocab_size).
            If W is of type bytes(), i.e. quantized to 1-8 bits, other quantization
            related arguments must be provided as well (see below).
        b: numpy.array , optional
            Bias vector of shape (embedding_size, ).
        Quantization arguments expected, when W is of type bytes():
        is_quantized_weight: bool
            Set it to true when W is of type bytes(), representing quantized weights
        quantization_type: str
            When weights are quantized (i.e. W is of type bytes()), this should be either "linear" or "lut".
        nbits: int
            Should be between 1 and 8 (inclusive). Number of bits per weight value.
        quant_scale: numpy.array(dtype=numpy.float32)
            scale vector to be used with linear quantization. Must be of length either 1 or embedding_size.
        quant_bias: numpy.array(dtype=numpy.float32)
            bias vector to be used with linear quantization. Must be of length either 1 or embedding_size.
        quant_lut: numpy.array(dtype=numpy.float32)
            the LUT (look up table) to be used with LUT quantization. Must be of length 2^nbits.

        See Also
        --------
        add_inner_product, add_embedding
        """

        spec_layer = self._add_generic_layer(name, [input_name], [output_name])

        # Fill in the parameters
        spec_layer_params = spec_layer.embeddingND

        spec_layer_params.vocabSize = vocab_size
        spec_layer_params.embeddingSize = embedding_size
        spec_layer_params.hasBias = b is not None

        weights = spec_layer_params.weights
        if not is_quantized_weight:
            weights.floatValue.extend(W.flatten())
        else:
            _verify_quantization_arguments(
                weight=W,
                output_channels=embedding_size,
                quantization_type=quantization_type,
                nbits=nbits,
                quant_scale=quant_scale,
                quant_bias=quant_bias,
                quant_lut=quant_lut,
            )

            _fill_quantized_weights(
                weights_message=weights,
                W=W,
                quantization_type=quantization_type,
                nbits=nbits,
                quant_scale=quant_scale,
                quant_bias=quant_bias,
                quant_lut=quant_lut,
            )

        if b is not None:
            bias = spec_layer_params.bias
            bias.floatValue.extend(b.flatten())
        return spec_layer

        Add an embedding layer to the model that performs a matrix lookup and
        optionally adds a bias.
        Refer to the ``EmbeddingNDLayerParams`` message in the specification
        (NeuralNetwork.proto) for more details.

        Parameters
        ----------
        name: str
            The name of this layer.
        input_name: str
            The input blob name of this layer.
        output_name: str
            The output blob name of this layer.
        vocab_size: int
            Size of the vocabulary (1 + maximum integer index of the words).
        embedding_size: int
            Size of the embedded vector.
        W: float32 numpy.array or bytes()
            Weight matrix of shape (embedding_size, vocab_size).
            If W is of type bytes(), i.e. quantized to 1-8 bits, other quantization
            related arguments must be provided as well (see below).
        b: numpy.array , optional
            Bias vector of shape (embedding_size, ).
        Quantization arguments expected, when W is of type bytes():
        is_quantized_weight: bool
            Set it to true when W is of type bytes(), representing quantized weights
        quantization_type: str
            When weights are quantized (i.e. W is of type bytes()), this should be either "linear" or "lut".
        nbits: int
            Should be between 1 and 8 (inclusive). Number of bits per weight value.
        quant_scale: numpy.array(dtype=numpy.float32)
            scale vector to be used with linear quantization. Must be of length either 1 or embedding_size.
        quant_bias: numpy.array(dtype=numpy.float32)
            bias vector to be used with linear quantization. Must be of length either 1 or embedding_size.
        quant_lut: numpy.array(dtype=numpy.float32)
            the LUT (look up table) to be used with LUT quantization. Must be of length 2^nbits.

        See Also
        --------
        add_inner_product, add_embedding
        
coremltools/models/neural_network/builder.py