Imp.Training.FastSlow.Backend behaviour (Imp v0.5.0)

Copy Markdown View Source

Provider-neutral effects required by the Fast-Slow Algorithm 1 runner.

Every callback receives the persisted operation intent. Backends should use intent.id as their idempotency key when an effect can be retried.

Summary

Callbacks

Generates and verifies one rollout for a planned slot not satisfied by the reuse cache.

Runs one fast GEPA phase and returns exactly K Pareto-selected candidates.

Prefetches exactly count ordered, data-only minibatches and their resulting cursor.

Certifies that replaying an existing unreconciled or retryable intent cannot duplicate an external effect.

Hands one ordered minibatch and its question groups to the slow-weight backend.

Validates the provider-owned dataset transition produced by prefetch/4.

Types

backend_context()

@type backend_context() :: Imp.Training.FastSlow.Config.json_value()

data_minibatch()

@type data_minibatch() :: map()

error_reason()

@type error_reason() :: term()

gepa_result()

@type gepa_result() :: %{
  :candidates => [term()],
  :candidate_ids => [String.t()],
  :instance_scores => map(),
  :instance_frontier => map(),
  optional(:anchor_digest) => String.t(),
  optional(:cached_trajectories) => [Imp.Training.FastSlow.CachedTrajectory.t()]
}

live_rollout_result()

@type live_rollout_result() :: %{
  :output => term(),
  :score => number(),
  :behavior_logprobs => [number()],
  :response_token_ids => [non_neg_integer()],
  :response_mask => [0 | 1],
  optional(:metrics) => term()
}

rollout_slot()

@type rollout_slot() :: %{
  cycle: non_neg_integer(),
  slow_step: non_neg_integer(),
  batch_id: String.t(),
  group_id: String.t(),
  problem: map(),
  problem_id: String.t(),
  dataset_indices: [non_neg_integer()],
  input_digest: String.t(),
  prompt: term(),
  prompt_digest: String.t(),
  prompt_index: non_neg_integer(),
  member_index: non_neg_integer(),
  group_size: pos_integer(),
  theta_id: String.t(),
  prompt_revision: non_neg_integer(),
  sampling_config_digest: String.t()
}

Callbacks

generate_rollout(t, rollout_slot, t, backend_context)

Generates and verifies one rollout for a planned slot not satisfied by the reuse cache.

optimize_fast(t, list, t, backend_context)

Runs one fast GEPA phase and returns exactly K Pareto-selected candidates.

prefetch(t, pos_integer, t, backend_context)

Prefetches exactly count ordered, data-only minibatches and their resulting cursor.

replay_safe?(t, backend_context)

Certifies that replaying an existing unreconciled or retryable intent cannot duplicate an external effect.

Return true only when the provider uses intent.id idempotently or has established that the prior attempt was not applied.

update_slow(t, data_minibatch, list, t, backend_context)

Hands one ordered minibatch and its question groups to the slow-weight backend.

This callback is the provider boundary: the runner does not implement or verify a CISPO loss, gradient update, optimizer step, or model artifact. A backend claiming CISPO must enforce those semantics itself and return a content-bound identity for the resulting policy in theta_payload.

validate_prefetch_progression(t, list, t, backend_context)

@callback validate_prefetch_progression(
  Imp.Training.FastSlow.State.t(),
  [data_minibatch()],
  Imp.Training.FastSlow.DatasetState.t(),
  backend_context()
) :: :ok | {:error, error_reason()}

Validates the provider-owned dataset transition produced by prefetch/4.

The runner validates count, order, identities, and content digests itself. The backend owns cursor, epoch, shuffle, and sampler semantics, so it must reject a resulting dataset state that does not follow from the returned minibatches.