Course outline

MLOps / Prediction and evidence foundations / Lesson 6

Model packages and inference contracts

Package the complete prediction function and verify compatible inputs before interpreting its output.

About 4 min readContent reviewed
On this page

Lesson goals

  • Include preprocessing, schema, label or score semantics, and runtime assumptions.
  • Validate input names, types, units, and unsupported cases.
  • Separate content identity, trusted loading, and behavioral equivalence.

A weight file is not the complete function

Predictions can depend on feature order, units, learned imputation, scaling, vocabularies, label mappings, thresholds, and inference mode. Package or reference these dependencies through an explicit versioned contract. A coefficient vector without its input interpretation cannot tell a consumer whether a value means centimeters, seconds, or a category. State the output shape, units or class meaning, confidence interpretation, and any decision threshold. A service wrapper that returns a number successfully has not established that the number is compatible with the task. The model package must describe the input-to-output function that evaluation actually assessed.

Preserve learned transformation state

The first fixture serializes a self-created JSON package in memory and applies its stored mean, scale, feature order, weights, and bias. The same raw row becomes two normalized ones and a score of one. The mean and scale are fixed package state; recomputing them from each request or deployment batch would change the function. Validate that scales are nonzero and lengths align in a real loader, and define behavior for missing or unknown fields. This tiny package is an inspectable teaching format for a linear calculation, not an implementation of any framework serialization standard.

python Deterministic offline standard-library fixture
import json
package = {"features":["length", "width"], "units":["cm", "cm"],
           "mean":[10.0,20.0], "scale":[2.0,4.0], "weights":[2.0,-1.0], "bias":0.0}
restored = json.loads(json.dumps(package, allow_nan=False))
row = {"length":12.0, "width":24.0}
values = [row[name] for name in restored["features"]]
z = [(value-mean)/scale for value,mean,scale in zip(values,restored["mean"],restored["scale"])]
score = sum(w*x for w,x in zip(restored["weights"],z)) + restored["bias"]
print("transformed", z)
print("score", score)
Expected output
transformed [1.0, 1.0]
score 1.0

The self-created JSON package carries preprocessing and ordered feature semantics with a fixed linear score; it is not a framework model format.

Validate the request at its semantic boundary

The second fixture accepts a mapping with the required names and finite numeric values, rejecting Booleans explicitly because Python otherwise treats them as integers in some checks. Named mapping order can vary when extraction follows the package’s declared feature order. Units still require an external or explicit request contract; numeric validation alone cannot infer them. Choose a clear policy for unsupported inputs: reject, defer, or use a specified fallback. Do not silently replace invalid measurements with plausible zeros. Keep a stable reason code or message so callers can distinguish unsupported input from a prediction.

python Deterministic offline standard-library fixture
from math import isfinite
def validate(row):
    if set(row) != {"length", "width"}:
        raise ValueError("expected length and width")
    if any(isinstance(x,bool) or not isinstance(x,(int,float)) or not isfinite(x) for x in row.values()):
        raise ValueError("expected finite numeric measurements")
    return True
print("valid", validate({"width":24.0,"length":12.0}))
try:
    validate({"length":True,"width":24.0})
except ValueError as error:
    print(str(error))
Expected output
valid True
expected finite numeric measurements

Named input order can vary because feature extraction follows the package contract; Boolean values are explicitly rejected despite Python numeric inheritance.

Loading and identity need separate evidence

A content hash can identify a package without proving that it came from a trusted source or contains the right function. Some object-loading formats can execute code, and environment compatibility varies by framework and format. Use a reviewed loading policy and the documented dependency boundary rather than testing unknown artifacts in a production process. This course loads only JSON it created itself. Framework-specific tracks explain their own serialization APIs; MLOps preserves the contract, provenance, compatibility evidence, and the distinction between an immutable package version and a mutable selection alias.

Verify the packaged behavior before delivery

Compare known raw inputs through the full packaged function with the evaluated reference, including preprocessing, final scores, labels, and threshold-near decisions. Test singleton and batch behavior, missingness, invalid types, feature swaps, and supported category boundaries. A numerically close score can still change an action near a threshold, so choose tolerances from the actual decision contract. Record the runtime assumptions and tests actually performed. These examples execute local JSON and scalar arithmetic only; no service, model registry, framework loader, external artifact, cloud resource, or deployment is created or exercised.

Common errors and fixes

Inference recomputes training scaling from request values

Why it happens
Learned preprocessing was not preserved as model state.
How to fix it
Use the fitted transform parameters from the evaluated package.
Prevent it next time
Compare raw-input fixtures through training and inference paths.

A Boolean is accepted as a physical measurement

Why it happens
A broad numeric type check ignored language-specific inheritance.
How to fix it
Reject unsupported types explicitly under the input contract.
Prevent it next time
Test Booleans, nonfinite values, missing fields, and extra fields.

A valid package hash is treated as trusted correct inference

Why it happens
Identity was confused with origin, compatibility, and behavior.
How to fix it
Verify each property with its own evidence.
Prevent it next time
Keep provenance and known-input tests beside content identity.

Check your understanding

1. What score would the first package produce for length ten and width twenty?

Show worked solution

Both features equal their stored training means, so normalization yields zero and zero. The weighted sum and zero bias therefore produce zero. This tests the stored transformation boundary; it does not establish a real-world meaning for zero without the output contract.

2. Why should an unknown input field not be ignored automatically?

Show worked solution

It may signal a schema mismatch, unit change, or caller misunderstanding. A contract can intentionally allow extras, but that choice must be stated and tested. Under the narrow fixture contract, exact field names are required so an unexpected request is rejected before a plausible score hides the mismatch.

Key takeaways

  • Package preprocessing and meaning with model parameters.
  • Validate unsupported input before returning a score.
  • Identity, loading trust, compatibility, and behavior are separate checks.

Official references