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
@type backend_context() :: Imp.Training.FastSlow.Config.json_value()
@type data_minibatch() :: map()
@type error_reason() :: term()
@type live_rollout_result() :: %{ :output => term(), :score => number(), :behavior_logprobs => [number()], :response_token_ids => [non_neg_integer()], :response_mask => [0 | 1], optional(:metrics) => term() }
@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
@callback generate_rollout( Imp.Training.FastSlow.State.t(), rollout_slot(), Imp.Training.FastSlow.OperationIntent.t(), backend_context() ) :: {:ok, live_rollout_result(), backend_context()} | {:error, error_reason(), backend_context()}
Generates and verifies one rollout for a planned slot not satisfied by the reuse cache.
@callback optimize_fast( Imp.Training.FastSlow.State.t(), [data_minibatch()], Imp.Training.FastSlow.OperationIntent.t(), backend_context() ) :: {:ok, gepa_result(), backend_context()} | {:error, error_reason(), backend_context()}
Runs one fast GEPA phase and returns exactly K Pareto-selected candidates.
@callback prefetch( Imp.Training.FastSlow.State.t(), pos_integer(), Imp.Training.FastSlow.OperationIntent.t(), backend_context() ) :: {:ok, [data_minibatch()], Imp.Training.FastSlow.DatasetState.t(), backend_context()} | {:error, error_reason(), backend_context()}
Prefetches exactly count ordered, data-only minibatches and their resulting cursor.
@callback replay_safe?(Imp.Training.FastSlow.OperationIntent.t(), backend_context()) :: boolean()
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.
@callback update_slow( Imp.Training.FastSlow.State.t(), data_minibatch(), [Imp.Training.FastSlow.AdvantageGroup.t()], Imp.Training.FastSlow.OperationIntent.t(), backend_context() ) :: {:ok, theta_payload :: term(), backend_context()} | {:error, error_reason(), 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.
@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.