Mojo · Training

Training

from uform import Modality, Objective, Negatives, … 4.0.0-rc.1 · 3ee5e534

A run joins its processes with Mesh.bootstrap over a device executor, then steps one Trainer per process:

var executor = Executor.for_vram(library, VramOptions.on(devices))
var mesh = Mesh.bootstrap(executor, options)
var config = TrainerInitVramConfig[origin_of(mesh)]()
config.depth = 12
config.hidden = 768
config.mesh = Pointer(to=mesh)
var trainer = Trainer.init_vram(executor, config)
trainer.on(executor).step(modalities, contents, TrainerStepConfig(relations=relations))
trainer.on(executor).save("checkpoint.safetensors")

API

StructModalityWhat the bytes of one training item hold, uform_modality_t.
struct Modality

Fields

codec_intThe raw uform_modality_t value the ABI exchanges.

Values

TEXTModality(Int32(0))UTF-8 text, a byte per token.
IMAGEModality(Int32(1))A JPEG, PNG or WebP file.
VIDEOModality(Int32(2))An MP4 or WebM file.
AUDIOModality(Int32(3))A WAV, FLAC, MP3 or Opus file.

Conforms to

Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
StructObjectiveWhich losses a step relaxes, uform_objective_t.
struct Objective

Fields

codec_intThe raw uform_objective_t value the ABI exchanges.

Values

MASKEDObjective(Int32(0))Masked reconstruction alone.
CONTRASTIVEObjective(Int32(1))The pairwise contrastive loss alone.
JOINTObjective(Int32(2))Both, joined at the final-norm states.

Conforms to

Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
StructNegativesWhich pairs the contrastive loss pushes apart, uform_negatives_t.
struct Negatives

Fields

codec_intThe raw uform_negatives_t value the ABI exchanges.

Values

AMBIENTNegatives(Int32(0))Repel edges, and every pair no edge names at the ambient weight.
NAMEDNegatives(Int32(1))Repel edges alone.

Conforms to

Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
StructPairLossFormHow a contrastive term turns a row of scores into forces, uform_pair_loss_form_t.
struct PairLossForm

Fields

codec_intThe raw uform_pair_loss_form_t value the ABI exchanges.

Values

DERIVEDPairLossForm(Int32(0))The term's own form: sigmoid for pooled vertices, ranked for token vectors.
BALANCEDPairLossForm(Int32(1))The sigmoid cross-entropy of every cell, its attract and repel halves normalized apart.
RANKEDPairLossForm(Int32(2))The sigmoid cross-entropy of every positive's score over every negative's.
SIGMOIDPairLossForm(Int32(3))SigLIP's sigmoid cross-entropy of every cell, each repel weighed like an attract.

Conforms to

Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
StructLateInteractionSideWhich side of a late-interaction score an item takes, uform_late_interaction_side_t.
struct LateInteractionSide

Fields

codec_intThe raw uform_late_interaction_side_t value the ABI exchanges.

Values

NONELateInteractionSide(Int32(0))The item takes no part in late interaction.
QUERYLateInteractionSide(Int32(1))The item's tokens score the documents it attracts and repels.
DOCUMENTLateInteractionSide(Int32(2))The item's tokens are scored by the queries naming it.
QUERY_AND_DOCUMENTLateInteractionSide(Int32(3))The item plays both sides.

Conforms to

Copyable, Deinitable, Equatable, ImplicitlyCopyable, Movable, RegisterPassable, TrivialRegisterPassable
StructImageShapeThe image slice of a batch envelope, uform_image_shape_t; a zero patch_side leaves images out.1
struct ImageShape

Fields

patch_sidec_size_tThe square patch side images tile into, in pixels.
channelsc_size_tChannels every pixel carries; zero derives four.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the fields that differ from the derived ones.
def __init__(out self, *, patch_side: Int = Int(0), channels: Int = Int(0))
StructVideoShapeThe video slice of a batch envelope, uform_video_shape_t; a zero patch_side leaves video out.1
struct VideoShape

Fields

patch_sidec_size_tThe square patch side one tube tiles into, in pixels.
tube_framesc_size_tFrames one tube folds ahead of its patch; zero derives two.
frame_stridec_size_tSource frames between sampled ones; zero derives one.
channelsc_size_tChannels every pixel carries; zero derives three.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the fields that differ from the derived ones.
def __init__(
    out self,
    *,
    patch_side: Int = Int(0),
    tube_frames: Int = Int(0),
    frame_stride: Int = Int(0),
    channels: Int = Int(0)
)
StructAudioShapeThe audio slice of a batch envelope, uform_audio_shape_t; a zero chunk_samples leaves audio out.1
struct AudioShape

Fields

chunk_samplesc_size_tRaw samples per frame, the fan-in of the learned frontend.
sample_ratec_size_tThe mono rate every recording is resampled to; zero derives 16000.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the fields that differ from the derived ones.
def __init__(out self, *, chunk_samples: Int = Int(0), sample_rate: Int = Int(0))
StructBatchShapeWhat one device's step carries at most, whatever the modality mix, uform_batch_shape_t.1
struct BatchShape

Fields

max_rows_per_devicec_size_tRows one device's step packs.
max_segments_per_devicec_size_tItems one device's step carries across all its rows, which is also its pooling axis.
max_columns_per_rowc_size_tPositions one row spans, the sequence length.
max_bags_per_devicec_size_tBags one device's step carries; zero keeps every item its own routing unit.
max_choices_per_itemc_size_tLegal bytes one item offers to choose from at most; zero makes no choices.
imageImageShapeThe image geometry.
videoVideoShapeThe video geometry.
audioAudioShapeThe audio geometry.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the fields that differ from the derived ones.
def __init__(
    out self,
    *,
    max_rows_per_device: Int = Int(0),
    max_segments_per_device: Int = Int(0),
    max_columns_per_row: Int = Int(0),
    max_bags_per_device: Int = Int(0),
    max_choices_per_item: Int = Int(0),
    image: ImageShape = ImageShape(patch_side=Int(0), channels=Int(0)),
    video: VideoShape = VideoShape(patch_side=Int(0), tube_frames=Int(0), frame_stride=Int(0), channels=Int(0)),
    audio: AudioShape = AudioShape(chunk_samples=Int(0), sample_rate=Int(0))
)
StructMaskingHow the masked objective corrupts a batch and weighs its heads, uform_masking_t; every zero derives the default its field names.1
struct Masking

Fields

token_mask_probabilityFloat32Fraction of text positions covered by spans; 0.15.
token_mean_spanFloat32Mean geometric span length in bytes; 16.
replace_fractionFloat32Of covered positions, the share shown as MASK; 0.8.
random_fractionFloat32Of covered positions, the share replaced by a random byte; 0.1.
image_mask_ratioFloat32Fraction of image patches masked; 0.75.
video_mask_ratioFloat32Fraction of video tubes masked; 0.75.
audio_mask_ratioFloat32Fraction of audio frames masked; 0.75.
text_weightFloat32The weight of the text head; 1.
image_weightFloat32The weight of the image head; 1.
video_weightFloat32The weight of the video head; 1.
audio_weightFloat32The weight of the audio head; 1.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Derives every default.
def __init__(out self)
StructLateInteractionHow the late-interaction loss scores per-token vectors, uform_late_interaction_t; every zero derives the default its field names.1
struct LateInteraction

Fields

weightFloat32The loss weight; zero trains no token head.
widthc_size_tThe token vectors' width, a multiple of 8; 128.
inverse_temperatureFloat32The starting inverse temperature of every contrastive group; 1.
biasFloat32The starting logit bias of every contrastive group; zero.
max_query_spanc_size_tTokens one query segment contributes at most; 64.
max_query_tokens_per_devicec_size_tQuery token rows one device's step holds at most.
max_documents_per_devicec_size_tDocument segments one device's step holds at most.
max_document_tokens_per_devicec_size_tDocument token rows one device's step holds at most.
pair_lossPairLossFormThe pair loss over each query's row of hard MaxSim scores; ranked.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Trains no token head.
def __init__(out self)
StructScheduleThe learning-rate schedule, a linear warmup then a cosine decay, uform_schedule_t.1
struct Schedule

Fields

learning_rateFloat32The peak learning rate; zero derives 5e-4.
min_learning_rateFloat32The floor the cosine settles at; zero derives 1e-5.
warmup_stepsc_size_tSteps from zero to the peak; zero derives a tenth of steps, at most 400.
stepsc_size_tSteps the run takes across resumes, which the cosine spans; zero is refused.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Derives every default but steps, which a run must name.
def __init__(out self)
StructTrainerStepStatsWhat a step reports, every loss its world mean, uform_trainer_step_stats_t.1
struct TrainerStepStats

Fields

stepc_size_tThe optimizer step the call applied, counted from one across resumes.
learning_rateFloat32The learning rate it applied.
lossFloat32The total loss the step minimized.
contrastive_lossFloat32The contrastive term; zero when the objective is masked alone.
masked_text_lossFloat32The text reconstruction term, before its weight.
masked_image_lossFloat32The image reconstruction term, before its weight.
masked_video_lossFloat32The video reconstruction term, before its weight.
masked_audio_lossFloat32The audio reconstruction term, before its weight.
late_interaction_lossFloat32The late-interaction term, weighted.
choices_lossFloat32The choices term over the items that made a choice, before its weight.
truncatedc_size_tItems cut at a row's width.
droppedc_size_tSegments dropped whole for lack of room, since the last step that read its stats.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Zeroes every field, which is what a failed step leaves.
def __init__(out self)
StructContrastiveHow the contrastive loss scores the pooled embeddings, uform_contrastive_t; every zero derives the default its field names.1
struct Contrastive

Fields

matryoshka_dimensionsList[UInt]Matryoshka prefix widths, strictly ascending, each a multiple of 8, at most 8; empty scores the full width alone.
temperature_groupsIntLearnable inverse temperature and bias pairs, one per group a step's items select; one.
inverse_temperatureFloat32The starting inverse temperature of every group; 10 under the sigmoid form, else 1.
biasFloat32The starting logit bias of every group; -10 under the sigmoid form, else zero.
negativesNegativesWhich pairs repel.
ambient_repulsion_weightFloat32The weight of every pair no edge names, under Negatives.AMBIENT; 1.
max_edges_per_deviceIntEdges one device's step names per edge set at most; zero derives it.
pair_lossPairLossFormThe pair loss over each anchor's row; sigmoid.

Conforms to

Copyable, Defaultable, Deinitable, Movable
__init__Derives every default.
def __init__(out self)
StructTrainerInitVramConfigThe geometry, objective and starting point of a run, uform_trainer_init_vram_t.1
struct TrainerInitVramConfig[mesh_origin: ImmOrigin = ImmUntrackedOrigin]

Parameters

mesh_originImmOrigincomptimeThe borrowed mesh's origin, which the trainer then keeps alive.

Fields

resumeStringThe checkpoint path to continue from, at its saved step; empty starts from seed.
depthIntTransformer blocks stacked.
hiddenIntEmbedding width, a multiple of 128.
batchBatchShapeWhat one device's step carries at most.
objectiveObjectiveWhich losses a step relaxes.
maskingMaskingThe masked objective's corruption and weights, read unless the objective is contrastive alone.
contrastiveContrastiveThe contrastive loss's scoring, read unless the objective is masked alone.
late_interactionLateInteractionThe late-interaction loss beside the pooled one, read when its weight is positive.
choicesChoicesThe calibrated choices, read when its weight is positive.
scheduleScheduleThe learning-rate schedule.
meshOptional[Pointer[Mesh, mesh_origin]]The mesh made over the same executor; absent runs this process alone.
seedUInt64The base of every keyed draw: initialization, corruption and the shuffle.
progressProgressReports the tensors placed on a resume, and stops the call where it says to.

Conforms to

Copyable, Defaultable, Deinitable, Movable
__init__Every field zeroed or derived, which a run then overrides by name.
def __init__(out self)
StructEdgesOne edge set over a step's items as compressed sparse rows; empty offsets name no edges.2
struct Edges[origin: ImmOrigin = ImmUntrackedOrigin]

Parameters

originImmOrigincomptimeThe borrowed offsets, IDs and weights, kept alive for as long as the edges are used.

Fields

offsetsSpan[UInt, origin]The step's count plus one non-decreasing offsets into ids.
idsSpan[UInt32, origin]Item i links to items ids[offsets[i]] up to ids[offsets[i + 1]], ascending within each run.
weightsSpan[Float32, origin]The weight of each edge, paired with ids; empty weighs every edge one.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Names no edges.
def __init__(out self)
ofBorrows the three arrays of one edge set; an empty weights weighs every edge one.
def of[offsets_origin: ImmOrigin, ids_origin: ImmOrigin, weights_origin: ImmOrigin, //](
    offsets: Span[UInt, offsets_origin],
    ids: Span[UInt32, ids_origin],
    weights: Span[Float32, weights_origin]
) -> Edges[origin_of(ids_origin, offsets_origin, weights_origin)]
StructRelationsThe contrastive targets of one step, resolved per pair in this order: a pair ignore names is skipped, one attract names pulls together, one repel names pushes apart, and every other pair follows the run's negatives.2
struct Relations[origin: ImmOrigin = ImmUntrackedOrigin]

Parameters

originImmOrigincomptimeThe borrowed edge sets, kept alive for as long as the relations are used.

Fields

attractEdges[origin]Pairs pulled together.
repelEdges[origin]Pairs pushed apart.
ignoreEdges[origin]Pairs skipped, like known false negatives; their weights are not read.

Conforms to

Copyable, Defaultable, Deinitable, ImplicitlyCopyable, Movable
__init__Names no pairs.
def __init__(out self)
ofGathers the three edge sets of one step.
def of[attract_origin: ImmOrigin, repel_origin: ImmOrigin, ignore_origin: ImmOrigin, //](
    attract: Edges[attract_origin],
    repel: Edges[repel_origin] = Edges(),
    ignore: Edges[ignore_origin] = Edges()
) -> Relations[origin_of(attract_origin, ignore_origin, repel_origin)]
StructTrainerStepConfigThe routing, targets and report slot of a training step, uform_trainer_step_t; every array is optional and, when given, holds one entry per item.1
struct TrainerStepConfig[bags_origin: ImmOrigin = ImmUntrackedOrigin, groups_origin: ImmOrigin = ImmUntrackedOrigin, sides_origin: ImmOrigin = ImmUntrackedOrigin, choices_origin: ImmOrigin = ImmUntrackedOrigin, targets_origin: ImmOrigin = ImmUntrackedOrigin, relations_origin: ImmOrigin = ImmUntrackedOrigin, stats_origin: MutOrigin = MutUntrackedOrigin]

Fields

bagsSpan[UInt32, bags_origin]The bag of each item, items sharing a bag landing on one device; empty keeps every item its own.
temperature_groupsSpan[UInt32, groups_origin]The temperature group of each item; empty puts every item in group zero.
sidesSpan[LateInteractionSide, sides_origin]The late-interaction side of each item; empty makes every item LateInteractionSide.NONE.
choicesOptional[TapeView[choices_origin]]Each item's legal choices, one byte each, as text_choose reads them; absent makes no choices.
choice_targetsOptional[TapeView[targets_origin]]The target probability of each choice, F32, as text_choose answers them; read with choices.
relationsRelations[relations_origin]The contrastive targets, read unless the objective is masked alone.
outputs_scalarScalarKindThe scalar type the pooled embeddings land as, read only with an arena.
statsOptional[Pointer[TrainerStepStats, stats_origin]]Receives the losses, overwritten by the call; absent skips their readback too.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable
__init__Names only the arrays and knobs a step uses.
def __init__(
    out self,
    *,
    bags: Span[UInt32, bags_origin] = Span(),
    temperature_groups: Span[UInt32, groups_origin] = Span(),
    sides: Span[LateInteractionSide, sides_origin] = Span(),
    choices: Optional[TapeView[choices_origin]] = Optional(),
    choice_targets: Optional[TapeView[targets_origin]] = Optional(),
    relations: Relations[relations_origin] = Relations(),
    outputs_scalar: ScalarKind = ScalarKind.F32,
    stats: Optional[Pointer[TrainerStepStats, stats_origin]] = Optional()
)
StructTrainerA training run on a device executor's devices, released when it goes out of scope.5
struct Trainer[mesh_origin: ImmOrigin = ImmUntrackedOrigin]

Its verbs run only on an executor: trainer.on(executor) blocks there, and trainer.deferred(executor) submits there and answers a Deferred.

Parameters

mesh_originImmOrigincomptimeThe mesh it borrows, kept alive for as long as the trainer is.

Fields

libraryLibraryThe loaded engine, held so its symbol table outlives every call made through the handle.
addressAddressThe opaque uform_trainer_t.
meshOptional[Pointer[Mesh, mesh_origin]]The mesh the run spans, absent for a process running alone.

Conforms to

Deinitable, Movable
__init__Adopts a handle the engine just created.
def __init__(
    out self,
    *,
    library: Library,
    address: Int,
    mesh: Optional[Pointer[Mesh, mesh_origin]]
)
__deinit__Frees the trainer and leaves the mesh; every call using it must be final. Calls uform_trainer_free.
def __deinit__(deinit self)
init_vramBuilds one replica per device and starts or resumes the run; every process of the run calls it with the same geometry, objective and seed. Calls uform_trainer_init_vram.
def init_vram[config_mesh_origin: ImmOrigin, //](
    executor: Executor,
    config: TrainerInitVramConfig[config_mesh_origin]
) -> Trainer[config_mesh_origin]

Raises

Error with CONFIG_MISMATCH for a checkpoint of another geometry, or UNSUPPORTED in a build without the trainer.
onThe trainer's verbs, blocking on executor, the one it was made over. Binding-only.
def on(ref self, ref executor: Executor) -> TrainerOn[origin_of(executor, self)]
deferredThe trainer's verbs, each submitted to executor and answering a Deferred at once. Binding-only.
def deferred(ref self, ref executor: Executor) -> TrainerDeferredOn[origin_of(executor, self)]
StructTrainerOnA trainer bound to the executor its verbs block on, as trainer.on(executor) answers it. Binding-only.1
struct TrainerOn[origin: ImmOrigin]

Parameters

originImmOrigincomptimeThe trainer and the executor, which this receiver borrows.

Fields

libraryLibraryThe loaded engine every verb crosses into.
trainerAddressThe uform_trainer_t every verb addresses.
executorAddressThe uform_executor_t every verb runs on.

Conforms to

Copyable, Deinitable, ImplicitlyCopyable, Movable, TrainVerbs
__init__Binds a trainer to an executor.
def __init__(out self, library: Library, trainer: Int, executor: Int)
TraitTrainVerbsThe verbs every blocking trainer receiver offers, each written once over the receiver's _route.2
trait TrainVerbs
stepApplies one optimizer step over this process's items and every peer's; every process of the run calls it once per step. Calls uform_trainer_step.
def step[modalities_origin: ImmOrigin, contents_origin: ImmOrigin, bags_origin: ImmOrigin, groups_origin: ImmOrigin, sides_origin: ImmOrigin, choices_origin: ImmOrigin, targets_origin: ImmOrigin, relations_origin: ImmOrigin, stats_origin: MutOrigin, //](
    self,
    modalities: Span[Modality, modalities_origin],
    contents: TapeView[contents_origin],
    config: TrainerStepConfig[bags_origin, groups_origin, sides_origin, choices_origin, targets_origin, relations_origin, stats_origin] = TrainerStepConfig(bags=Span(), temperature_groups=Span(), sides=Span(), choices=Optional(), choice_targets=Optional(), relations=Relations(), outputs_scalar=ScalarKind.F32, stats=Optional())
)
def step[modalities_origin: ImmOrigin, contents_origin: ImmOrigin, bags_origin: ImmOrigin, groups_origin: ImmOrigin, sides_origin: ImmOrigin, choices_origin: ImmOrigin, targets_origin: ImmOrigin, relations_origin: ImmOrigin, stats_origin: MutOrigin, //](
    self,
    modalities: Span[Modality, modalities_origin],
    contents: TapeView[contents_origin],
    mut arena: Arena,
    config: TrainerStepConfig[bags_origin, groups_origin, sides_origin, choices_origin, targets_origin, relations_origin, stats_origin] = TrainerStepConfig(bags=Span(), temperature_groups=Span(), sides=Span(), choices=Optional(), choice_targets=Optional(), relations=Relations(), outputs_scalar=ScalarKind.F32, stats=Optional())
) -> Rows[origin_of(arena)]

The same step, also landing the pooled embedding of every item in arena, as the contrastive loss scored it before the update. Calls uform_trainer_step.

Parameters

modalitiesSpan[Modality, modalities_origin]The modality of each item.
contentsTapeView[contents_origin]Each item's bytes, UTF-8 text or an encoded file as modalities tags it.
configTrainerStepConfig[bags_origin, groups_origin, sides_origin, choices_origin, targets_origin, relations_origin, stats_origin]The routing, the targets and the report slot.

Raises

Error with SHAPE_MISMATCH when the per-item arrays disagree with contents.
saveWrites the weights and the step, which the model loads serve and init_vram resumes; only the process of index zero writes. Calls uform_trainer_save.
def save[path_origin: ImmOrigin, //](
    self,
    path: StringSpan[path_origin],
    progress: Progress = Progress()
)