Skip to content

core

core

Base abstractions shared across DeltaFlow's models, losses, and solvers.

Every user-facing component (velocity field, interpolant, solver, loss) subclasses one of these bases, so new variants are drop-in and not rewrites of the surrounding machinery.

BaseInterpolant

Bases: ABC

Base class for a probability path between noise x0 and data x1.

An interpolant defines, for each t in [0, 1], an intermediate point x_t and its conditional target velocity u_t such that regressing a model onto u_t (in expectation over the path) yields the marginal velocity field of the flow-matching ODE.

Convention used throughout DeltaFlow: t = 0 corresponds to noise (x_t = x_0) and t = 1 corresponds to data (x_t = x_1).

interpolate abstractmethod

interpolate(x1, t, x0=None)

Return (x_t, target_velocity) for the given data/time (and optional noise).

Source code in deltaflow/core/base_interpolant.py
@abstractmethod
def interpolate(
    self, x1: torch.Tensor, t: torch.Tensor, x0: Optional[torch.Tensor] = None
) -> Tuple[torch.Tensor, torch.Tensor]:
    """Return ``(x_t, target_velocity)`` for the given data/time (and optional noise)."""
    raise NotImplementedError

BaseLoss

Bases: ABC

Base class for a callable training loss.

Subclasses must implement __call__ and return a scalar tensor with requires_grad=True (assuming the model has trainable parameters). The signature is intentionally flexible - individual losses define which positional and keyword arguments they consume.

BaseSolver

BaseSolver(model, time_scale=1.0)

Bases: ABC

Base class for numerical integrators of dx/dt = v_theta(x, t).

A solver holds a reference to a velocity model and exposes two methods:

  • step performs a single integration step from (x, t) to (x', t + dt). Subclasses implement the actual stepping rule.
  • sample drives step in a loop from t_start to t_end and returns the final state.

Design note: PosteriorSolver wraps a BaseSolver and hooks the likelihood gradient into every call to step, so the base stepping logic is never duplicated.

Parameters:

Name Type Description Default
model Callable

callable model(x, t, **cond) -> velocity with the same signature as BaseVelocityField.

required
time_scale float

multiplies the continuous t in [0, 1] before it is passed to the model, useful when the backbone was trained with a different numeric time convention (e.g. diffusion timesteps).

1.0
Source code in deltaflow/core/base_solver.py
def __init__(self, model: Callable, time_scale: float = 1.0):
    self.model = model
    self.time_scale = time_scale

step abstractmethod

step(x, t, dt, **cond)

Advance the state x from time t to t + dt.

Source code in deltaflow/core/base_solver.py
@abstractmethod
def step(self, x: torch.Tensor, t: float, dt: float, **cond) -> torch.Tensor:
    """Advance the state ``x`` from time ``t`` to ``t + dt``."""
    raise NotImplementedError

sample

sample(x, n_steps=50, t_start=0.0, t_end=1.0, show_progress=True, progress_desc=None, **cond)

Integrate from t_start to t_end in n_steps uniform steps.

Source code in deltaflow/core/base_solver.py
def sample(
    self,
    x: torch.Tensor,
    n_steps: int = 50,
    t_start: float = 0.0,
    t_end: float = 1.0,
    show_progress: bool = True,
    progress_desc: Optional[str] = None,
    **cond,
) -> torch.Tensor:
    """Integrate from ``t_start`` to ``t_end`` in ``n_steps`` uniform steps."""
    dt = (t_end - t_start) / n_steps
    steps = range(n_steps)
    if show_progress:
        try:
            from tqdm import tqdm

            steps = tqdm(
                steps,
                desc=progress_desc or type(self).__name__,
                total=n_steps,
                leave=False,
            )
        except ImportError:
            pass

    for i in steps:
        t_val = t_start + i * dt
        x = self.step(x, t_val, dt, **cond)
    return x

BaseVelocityField

Bases: Module, ABC

Base class for the time-conditioned velocity field v_theta(x, t).

Subclasses must implement forward and return a tensor with the same shape as x. Any additional conditioning (e.g. a guidance flag, class label, or cross-attention context) can be passed as keyword arguments and is forwarded unchanged by the losses and solvers.