Log runs¶
The Python library¶
pip install "runyard[images,system]" # extras: images, system, video, tensorboard
export RUNYARD_SERVER=https://my-server RUNYARD_API_KEY=ry_...
import runyard as ry
run = ry.init(project="sft", name="lr3e-4", config=vars(args), tags=["qwen"], notes="first try")
run.log({"loss": loss.item(), "lr": sched.get_last_lr()[0]}, step=step)
run.image("samples", grid, step=step, caption="seed 0") # PIL image, numpy array, torch tensor, path; or a list
run.video("rollout", frames, fps=8) # frames become an H.264 mp4 (`video` extra), else a GIF
run.text("generations", [{"prompt": p, "output": o}], step=step)
run.artifact("out/checkpoint-500", kind="checkpoint", step=500) # where it is; upload=True also sends a copy
run.alert("loss is NaN", level="error") # info, warn or error; also notifies
run.config.update(batch=64)
run.summary["best_eval"] = 0.31
run.finish() # optional
The same calls exist as module functions (ry.log(...)) for the current run.
- Steps: without
step, eachlogis the next step after the last one. - Status: a clean exit marks the run finished; an exception or non-zero exit, failed; five minutes without a heartbeat (sent every 30 seconds), crashed.
- Recorded on its own: stdout and stderr (
capture_output=Falseturns it off), GPU, CPU and RAM usage assys/metrics (systemextra,system=Falseturns it off), the host and the git commit. - Never in the way: calls are queued and sent by a background thread. When the server is unreachable,
what was not sent is saved at exit under
~/.cache/runyard/pending(RUNYARD_CACHE);runyard syncsends it. - Artifacts: by default only the record is kept (this host and the path, size, step).
upload=Truesends a copy, a directory as one.tar.gz, streamed from disk.runyard artifacts RUN --get NAMEdownloads it. - Settings:
RUNYARD_SERVER,RUNYARD_API_KEY,RUNYARD_PROJECTandRUNYARD_RUN_NAMEfill in whatinitis not given.
Frameworks, with one line¶
| Framework | One line |
|---|---|
transformers Trainer, TRL, Unsloth |
callbacks=[runyard.integrations.hf.RunyardCallback(project="sft")] (records each saved checkpoint too) |
| Accelerate | Accelerator(log_with=[runyard.integrations.accelerate.RunyardTracker(project="unet")]) |
| Lightning | Trainer(logger=runyard.integrations.lightning.RunyardLogger(project="mnist")) |
| Keras 3 | model.fit(..., callbacks=[runyard.integrations.keras.RunyardCallback(project="mnist")]) |
| XGBoost | xgb.train(..., callbacks=[runyard.integrations.xgboost.RunyardCallback(project="tabular")]) |
| LightGBM | lgb.train(..., callbacks=[runyard.integrations.lightgbm.runyard_callback(project="tabular")]) |
| scikit-learn | runyard.integrations.sklearn.autolog(project="tabular"): every outer fit() is a run |
| torchtune | metric_logger: {_component_: runyard.integrations.torchtune.RunyardLogger, project: sft} |
Other keyword arguments go to runyard.init. On macOS, xgboost and lightgbm need brew install libomp and must
be imported before torch.
Tools you cannot change¶
Weights & Biases. For tools that only speak W&B (ai-toolkit, diffusers examples, report_to="wandb"): install
runyard into their environment and set RUNYARD_WANDB=1. import wandb then loads a small bridge that writes to
runyard: init, log, config, summary, define_metric, Image, Video, Table, alert, finish.
Anything else prints a warning and is skipped.
TensorBoard. For tools that write event files (kohya sd-scripts, DeepSpeed, SummaryWriter):
pip install "runyard[tensorboard]"
runyard watch ./logs --project lora # new events every 10 s until Ctrl-C
runyard watch ./old-logs --once # import finished trainings and exit
Each directory with event files becomes a run named by its path, with its scalars, images, text and hparams. A restarted watcher continues the same runs.
MLflow. The server speaks enough of MLflow's tracking API for MLflow's own client:
export MLFLOW_TRACKING_URI=https://my-server MLFLOW_TRACKING_TOKEN=ry_...
mlflow.start_run, log_param/log_metric/set_tag, log_artifact, mlflow.autolog() with its logged models
(loadable again through models:/<id>), report_to="mlflow" and Lightning's MLFlowLogger work. Experiments are
projects, params go to the config, artifacts to the run's artifacts. MLflow clients send no heartbeats, so their
runs count as crashed only after an hour without writes. Searches ignore filters and ordering (newest first).