MLServe.Backend (MLServe v0.1.0)

Copy Markdown View Source

Guarded invocation of MLServe.Model callbacks.

Every call into a backend goes through this module. It exists for three reasons:

  1. Nothing raises out of a backend into MLServe's runtime. A raise, throw or exit is converted to {:error, {:backend_error, %MLServe.BackendError{}}} carrying the original exception and stacktrace. Errors are surfaced, never swallowed — the point of catching is to attach context, not to hide the failure.
  2. Optional callbacks are resolved once. MLServe.Model.batch_predict/2 and friends are detected with function_exported?/3 and given sane fallbacks.
  3. Return values are validated. A backend that returns a bare value instead of an {:ok, term} tuple gets a clear error naming the callback, rather than a confusing mismatch three layers up.

Application code does not normally call this module; it is public because backend authors and the guides refer to its semantics.

Summary

Types

invocation_result()

@type invocation_result() :: {:ok, term()} | {:error, term()}

Functions

batch_predict(spec, state, inputs)

@spec batch_predict(MLServe.ModelSpec.t(), term(), [term()]) ::
  {:ok, [term()]} | {:error, term()}

Calls MLServe.Model.batch_predict/2, falling back to a mapped MLServe.Model.predict/2.

The fallback stops at the first error rather than running the remaining inputs, since a batch result is all-or-nothing. Backends that can vectorise should implement batch_predict/2; the whole point of MLServe.batch_predict/3 is one backend round-trip instead of N.

A backend that exports batch_predict/2 but cannot batch this particular model returns {:error, :not_supported} to opt back into the mapped fallback.

load(spec)

@spec load(MLServe.ModelSpec.t()) :: {:ok, term()} | {:error, term()}

Calls MLServe.Model.load/1.

The spec's :config already carries :version, and :path when one is configured.

metadata(spec, state)

@spec metadata(MLServe.ModelSpec.t(), term()) :: map()

Calls MLServe.Model.metadata/1 when exported, returning %{} otherwise.

predict(spec, state, input)

@spec predict(MLServe.ModelSpec.t(), term(), term()) :: invocation_result()

Calls MLServe.Model.predict/2.

supports_batching?(backend)

@spec supports_batching?(module()) :: boolean()

Returns whether the backend exports MLServe.Model.batch_predict/2.

Surfaced in MLServe.model_status/2 so operators can see whether a batch call is one backend round-trip or N.

Examples

iex> MLServe.Backend.supports_batching?(MLServe.Backend.Static)
true

unload(spec, state)

@spec unload(MLServe.ModelSpec.t(), term()) :: :ok

Calls MLServe.Model.unload/1 when exported. Always returns :ok.

Unload failures are logged, not propagated: the model is going away regardless, and refusing to finish an unload because a backend's cleanup raised would leak the whole model instance.