Inference clients depend on stable field names as much as they depend on model weights. A TensorFlow SavedModel can expose several callable signatures so a standard score request and a richer classification request share one deployable artifact without leaking graph tensor names into client code.

TensorFlow's tf.keras.export.ExportArchive registers each endpoint as a concrete function with a declared TensorSpec. The TensorSpec name becomes the request key, while dictionary keys returned by the endpoint become response keys.

The first endpoint registered is also exported as serving_default unless that name is added manually. Treat endpoint and field names as an API contract because changing them can break TensorFlow Serving clients even when the model computation is unchanged.

Steps to export serving signatures for a TensorFlow SavedModel:

  1. Save the model definition in export_signatures.py.
    export_signatures.py
    import os
    from pathlib import Path
     
    os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
     
    import tensorflow as tf
     
    tf.get_logger().setLevel("ERROR")
     
    export_dir = Path("priority_serving")
    features = tf.keras.Input(shape=(4,), name="features")
    scores = tf.keras.layers.Dense(
        1,
        activation="sigmoid",
        kernel_initializer=tf.keras.initializers.Constant([[1.2], [0.8], [-0.6], [1.0]]),
        bias_initializer=tf.keras.initializers.Constant([-0.4]),
        name="scores",
    )(features)
    model = tf.keras.Model(features, scores, name="support_priority")

    The fixed initializers keep the sample output repeatable; production code supplies the trained Keras model at this point.

  2. Append the score endpoint to export_signatures.py with stable request and response keys.
    export_signatures.py
    @tf.function(
        input_signature=[tf.TensorSpec((None, 4), tf.float32, name="features")]
    )
    def score(features):
        return {"scores": model(features, training=False)}
  3. Append the classify endpoint to export_signatures.py to return labels beside scores.
    export_signatures.py
    @tf.function(
        input_signature=[tf.TensorSpec((None, 4), tf.float32, name="features")]
    )
    def classify(features):
        scores = model(features, training=False)
        labels = tf.cast(scores >= 0.5, tf.int32)
        return {"scores": scores, "labels": labels}
  4. Append the archive registration block to export_signatures.py.
    export_signatures.py
    archive = tf.keras.export.ExportArchive()
    archive.track(model)
    archive.add_endpoint("score", score)
    archive.add_endpoint("classify", classify)
    archive.write_out(export_dir, verbose=False)

    The first registered endpoint, score, also receives the serving_default alias required by the default TensorFlow Serving prediction path.

  5. Run export_signatures.py to write the SavedModel.
    $ python3 export_signatures.py
  6. List the SignatureDef keys in the exported SavedModel.
    $ saved_model_cli show --dir priority_serving --tag_set serve
    The given SavedModel MetaGraphDef contains SignatureDefs with the following keys:
    SignatureDef key: "__saved_model_init_op"
    SignatureDef key: "classify"
    SignatureDef key: "score"
    SignatureDef key: "serving_default"
  7. Inspect the serving_default request and response contract.
    $ saved_model_cli show \
      --dir priority_serving \
      --tag_set serve \
      --signature_def serving_default
    The given SavedModel SignatureDef contains the following input(s):
      inputs['features'] tensor_info:
          dtype: DT_FLOAT
          shape: (-1, 4)
          name: serving_default_features:0
    The given SavedModel SignatureDef contains the following output(s):
      outputs['scores'] tensor_info:
          dtype: DT_FLOAT
          shape: (-1, 1)
          name: StatefulPartitionedCall_2:0
    Method name is: tensorflow/serving/predict

    Serving clients continue to depend on the features and scores keys after integration.

  8. Confirm that the classify signature returns labels and scores for a two-row features batch.
    $ saved_model_cli run \
      --dir priority_serving \
      --tag_set serve \
      --signature_def classify \
      --input_exprs 'features=[[0.2,0.9,0.1,0.8],[0.1,0.1,0.9,0.1]]'
    ##### snipped #####
    Result for output key labels:
    [[1]
     [0]]
    Result for output key scores:
    [[0.78583497]
     [0.34524652]]