Skip to main content

coffeetrain

Lightweight event-driven PyTorch training runtime with composable plugins. Inspired by MosaicML Composer, but with fewer external dependencies and support for recent PyTorch versions.

Features

  • Plugin-based composition: bundle events, systems, and commands into reusable plugins
  • Decorator-driven wiring: hook training logic with @trainer.system('EVENT')
  • Shared context state: systems receive kwargs from context and return dict updates
  • CLI commands: function parameter defaults become hyperparameters for python train.py train --lr 1e-4
  • Interruptible default loop: graceful SIGINT/SIGTERM handling built into the core train plugin
  • Optional batteries: W&B, Comet, EMA, SWA, checkpointing, LR monitoring, and more

Quick Start

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
import torchvision
import torchvision.transforms as transforms

from coffeetrain import Trainer

trainer = Trainer()


class MnistCNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Conv2d(1, 32, 3), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 3), nn.ReLU(), nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(1600, 128), nn.ReLU(),
            nn.Linear(128, 10),
        )

    def forward(self, x):
        return self.net(x)


@trainer.system('DATA_BEFORE')
def load_data():
    transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,)),
    ])
    train_ds = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
    test_ds = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
    return {
        'train_dataloader': DataLoader(train_ds, batch_size=64, shuffle=True),
        'eval_dataloader': DataLoader(test_ds, batch_size=256, shuffle=False),
        'loss_fn': nn.CrossEntropyLoss(),
    }


@trainer.system('MODEL_BEFORE')
def create_model():
    compute_device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    return {'model': MnistCNN().to(compute_device), 'device': None, 'compute_device': compute_device}


@trainer.system('OPTIMIZER_BEFORE')
def create_optimizer(model, lr=5e-4):
    return {'optimizer': torch.optim.Adam(model.parameters(), lr=lr), 'lr': lr}


@trainer.system('FORWARD_BEFORE')
def prepare_forward_batch(batch, compute_device):
    inputs, labels = batch
    return {'inputs': inputs.to(compute_device), 'labels': labels.to(compute_device)}


@trainer.system('FORWARD')
def forward_pass(model, inputs):
    return {'outputs': model(inputs)}


@trainer.system('BACKWARD_AFTER')
def optimizer_step(optimizer):
    optimizer.step()
    optimizer.zero_grad()


if __name__ == '__main__':
    trainer()

Run training:

python train.py train --max_epochs 10 --lr 5e-4

See examples/mnist/main.py for a complete working example.

Core Concepts

Plugin

A plugin bundles related events, systems, and commands. The trainer auto-registers a default plugin set on construction; optional plugins are added with trainer.register_plugin(...).

System

A system is a function registered on one or more events. Its parameters are filled from shared context and hyperparameter defaults. Return a dict to update context:

@trainer.system('BATCH_AFTER')
def log_loss(loss, log):
    log.info(f"loss={loss.item():.4f}")

Command

Commands are top-level entry points dispatched from the CLI. The default train command runs the standard training loop:

python train.py train --max_epochs 20

State

Training state lives in a shared context dict on the trainer. Systems can also use injected helpers: get_state, set_state, run_event, and execution_block.

Key Description
model nn.Module being trained
optimizer PyTorch optimizer
train_dataloader Training DataLoader
eval_dataloader Optional validation DataLoader
batch Current batch from the dataloader
outputs Model outputs from the current forward pass
loss Current scalar loss tensor
epoch Current epoch (0-indexed)
batch_idx Batch index within the epoch
global_step Total training batches processed
eval_loss Mean validation loss after an eval pass
stop_training Set True to stop after the current batch
interrupted Set when SIGINT/SIGTERM is received

Event Lifecycle

The default train plugin defines a block-oriented event model. Each block fires {EVENT}_BEFORE, {EVENT}, and {EVENT}_AFTER hooks.

flowchart LR
    subgraph setup [Setup blocks]
        DATA["DATA"]
        MODEL["MODEL"]
        OPT["OPTIMIZER"]
    end
    setup --> FIT["FIT"]
    FIT --> EPOCH["EPOCH"]
    EPOCH --> BATCH["BATCH"]
    BATCH --> FWD["FORWARD"]
    FWD --> LOSS["LOSS"]
    LOSS --> BWD["BACKWARD"]
    EPOCH --> EVAL["EVAL"]
    EVAL --> EVALBATCH["EVAL_BATCH"]
    EVALBATCH --> EVALFWD["EVAL_FORWARD"]
    EVALFWD --> EVALLOSS["EVAL_LOSS"]
Event Phase Description
DATA Setup Load datasets and loss function
MODEL Setup Build and place model on device
OPTIMIZER Setup Create optimizer(s)
FIT Training Start/end of full training run
TRAINING_INTERRUPTED Training Fired on graceful interrupt
EPOCH Epoch One training epoch
BATCH Batch One training batch
FORWARD Batch Model forward pass
LOSS Batch Loss computation
BACKWARD Batch loss.backward()
EVAL Eval Full validation pass
EVAL_BATCH Eval One validation batch
EVAL_FORWARD Eval Forward pass during eval
EVAL_LOSS Eval Loss computation during eval

Plugins

Default (bundled)

Registered automatically when you create a Trainer().

Plugin Description
train_plugin Interruptible training loop and train command
tqdm_progress tqdm progress bars for train/eval
cuda_accelerate Move batches to CUDA when a device is set
torch_compile Optional torch.compile on the model
early_stopping Stop when the monitored metric plateaus

Optional

Register these when you need them:

from coffeetrain import Trainer, ema_plugin, save_best_model_plugin, wandb_plugin

trainer = Trainer()
trainer.register_plugin([ema_plugin, save_best_model_plugin, wandb_plugin])
Plugin Description
wandb_plugin Weights & Biases logging
comet_plugin Comet.ml logging
ema_plugin Exponential moving average of weights
swa_plugin Stochastic weight averaging
save_best_model_plugin Save checkpoint when a metric improves
lr_monitor_plugin Log learning rates
parameter_counter_plugin Print parameter counts at fit start
batch_size_scheduler Gradual batch size warmup
gradient_accumulator Gradient accumulation via override_block
hf_accelerator HuggingFace Accelerate integration (install the accelerate extra)
text_progress Plain-text epoch summaries (alternative to tqdm)

Writing a Custom Plugin

from coffeetrain import Plugin, Trainer

my_plugin = Plugin(name="my_plugin", description="Example plugin")

@my_plugin.system('FIT_BEFORE')
def on_fit_start(log):
    log.info("Starting training")

@my_plugin.system('BATCH_AFTER')
def track_step(global_step):
    return {'my_step': global_step}

trainer = Trainer()
trainer.register_plugin(my_plugin)

Plugin parameter defaults (e.g. lr=1e-4 on a system or command) are collected as hyperparameters and can be overridden at the CLI.

Agent Skill

An agent skill lives in skill/coffeetrain/. It teaches AI coding agents how to use coffeetrain — writing training scripts, wiring systems to events, registering plugins, and building custom plugins. To install it for your agent, copy or link the skill/coffeetrain/ directory into your agent's skills directory (e.g. ~/.agents/skills/).

Installation

pip install coffeetrain

Optional extras:

pip install coffeetrain[accelerate,wandb,comet,optimi]

Examples

Tests

From the repository root:

uv run pytest tests -q

License

Apache-2.0

Release files for coffeetrain 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for coffeetrain 0.2.1
File Size Uploaded
coffeetrain-0.2.1.tar.gz 200.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for coffeetrain 0.2.1
File Interpreter ABI Platform
coffeetrain-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 245.9 kB

Release files / coffeetrain-0.2.1.tar.gz

Download URL coffeetrain-0.2.1.tar.gz
Size 200.4 kB
Tags Source
SHA-256 checksum
How to use checksums
1226ca438af134d087141dad230cd5f2d824e20432befa9535c65ded2b062012
BLAKE2b-256 checksum
How to use checksums
b72a5f68cce4d0e8cd669a873673b6c54efc3ea4896f22d1d4a1f5ee684b5627
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release files / coffeetrain-0.2.1-py3-none-any.whl

Download URL coffeetrain-0.2.1-py3-none-any.whl
Size 45.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
500b79a0088f85529f8021140d768e67c837c45b188d556eea843bdd23414e5b
BLAKE2b-256 checksum
How to use checksums
1c817dc84e06ded60e532686c077dc8bf1822ad45d8889a782afdd0059805332
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page