Skip to main content

One logger, every destination — send ML training events to Discord, Slack, Telegram, W&B, MLflow, Comet, Neptune, TensorBoard, Aim, and Console simultaneously

Project description

ASHi

PyPI version Python CI License: MIT

One logger. Every destination.

ASHi fans out ML training events to every platform you care about — notification channels and experiment trackers alike — from a single, uniform API. Stop wiring up each platform separately; call on_epoch_end() once and every backend receives it simultaneously.

Features

  • Notification channels — Discord, Slack, Telegram, Console
  • Experiment tracking — Weights & Biases, MLflow, Comet ML, Neptune, TensorBoard, Aim
  • Framework callbacks — HuggingFace Transformers, PyTorch Lightning (zero extra dependencies)
  • AI summaries — GPT-powered one-sentence training summaries posted directly to all backends
  • Fan-out by default — every event goes to every backend in one call
  • Resilient — a failing backend never crashes training; each returns bool success
  • Composable — mix and match any backends; add more at runtime with add_backend()

Installation

pip install ahsi

Note: The PyPI package is ahsi but the Python import name is ashi — so you always write from ashi import ... in your code.

Install optional experiment-tracking backends:

pip install ahsi[wandb]       # Weights & Biases
pip install ahsi[mlflow]      # MLflow
pip install ahsi[comet]       # Comet ML
pip install ahsi[neptune]     # Neptune.ai
pip install ahsi[tensorboard] # TensorBoard
pip install ahsi[aim]         # Aim

pip install ahsi[all]         # everything at once

Quick Start

from ashi import TrainLogger, DiscordBackend, WandbBackend, ConsoleBackend

logger = TrainLogger(
    DiscordBackend(webhook_url="https://discord.com/api/webhooks/..."),
    WandbBackend(project="my-project"),
    ConsoleBackend(),
)

logger.on_train_start("my-experiment", config={"epochs": 100, "lr": 3e-4})

for epoch in range(1, 101):
    # ... train ...
    logger.on_epoch_end(epoch, {"loss": 0.42, "val_loss": 0.38}, total_epochs=100, step=epoch * 500)

    if new_best:
        logger.on_best_metric("val_loss", best_val_loss, step=global_step)

logger.on_train_end(total_steps=50000, best_val_loss=0.31)

Every call fans out to Discord, W&B, and the console simultaneously.

Backends

Notification Channels

Backend Setup
DiscordBackend(webhook_url) Server Settings → Integrations → Webhooks
SlackBackend(webhook_url) Slack Incoming Webhooks
TelegramBackend(token, chat_id) Create a bot via @BotFather, get chat_id from @userinfobot
ConsoleBackend() No setup — prints to stdout with ANSI colors

Experiment Tracking Platforms

Backend Install What gets logged
WandbBackend(project) ahsi[wandb] metrics, config, run summary, alerts
MLflowBackend(experiment_name) ahsi[mlflow] metrics, params, tags
CometBackend(project_name) ahsi[comet] metrics, parameters
NeptuneBackend(project) ahsi[neptune] metrics, metadata
TensorBoardBackend(log_dir) ahsi[tensorboard] scalars, text
AimBackend(experiment) ahsi[aim] metrics, metadata

Mix backends freely:

logger = TrainLogger(
    DiscordBackend(webhook_url="..."),
    WandbBackend(project="..."),
    MLflowBackend(experiment_name="..."),
    ConsoleBackend(),
)

Or add them after construction:

logger = TrainLogger()
logger.add_backend(DiscordBackend(webhook_url="..."))
logger.add_backend(WandbBackend(project="..."))

API Reference

TrainLogger(*backends, summarizer=None)

Method Description
on_train_start(experiment, config) Training started — logs config to trackers, posts to notification channels
on_epoch_end(epoch, metrics, total_epochs, step) Metrics + Unicode progress bar
on_step_end(step, metrics, total_steps) Step-level metrics + progress bar
on_best_metric(metric_name, value, step) New best metric alert
on_checkpoint_saved(step, path) Checkpoint saved notification
on_train_end(total_steps, best_val_loss) Training complete summary
on_error(error, context) Exception with context — sends alert to all backends
send(message, color) Custom one-line message
send_file(file_path, message, filename) File attachment (images, plots, model weights, etc.)
catch_errors(context) Context manager — auto-calls on_error on exception, then re-raises
summarize() Call the AI summarizer and post the result to all backends

Available colors for send(): green, red, yellow, blue, gray, orange

catch_errors context manager

with logger.catch_errors("eval_loop"):
    metrics = model.evaluate(val_dataloader)
# Any exception → on_error posted to all backends, exception re-raised

Experiment Tracking Details

Weights & Biases

from ashi import TrainLogger, WandbBackend

logger = TrainLogger(WandbBackend(project="my-project"))
# wandb.init() is called automatically on on_train_start

Reuse an existing run:

import wandb
wandb.init(project="my-project", name="run-1")
logger = TrainLogger(WandbBackend(run=wandb.run))
Event wandb action
on_train_start wandb.init() with config, or updates existing run config
on_epoch_end / on_step_end wandb.log(metrics, step=step)
on_best_metric wandb.log({"best/<name>": value}) + run.summary update
on_checkpoint_saved run.summary — last checkpoint path and step
on_train_end run.summary update, then wandb.finish()
on_error wandb.alert(level=ERROR)
send / summarize wandb.alert(level=INFO)

Pass finish_on_end=False to keep the run open after on_train_end.

MLflow

pip install ahsi[mlflow]
from ashi import TrainLogger, MLflowBackend

# Local ./mlruns directory
logger = TrainLogger(MLflowBackend())

# Remote tracking server
logger = TrainLogger(
    MLflowBackend(experiment_name="my-project", tracking_uri="http://localhost:5000")
)

on_train_start starts a new run and logs config as params. on_train_end calls mlflow.end_run().

Comet ML

pip install ahsi[comet]
from ashi import TrainLogger, CometBackend

logger = TrainLogger(
    CometBackend(api_key="...", project_name="my-project", workspace="my-workspace")
)

# Reuse an existing experiment
import comet_ml
exp = comet_ml.Experiment(api_key="...", project_name="...")
logger = TrainLogger(CometBackend(experiment=exp))

Neptune

pip install ahsi[neptune]
from ashi import TrainLogger, NeptuneBackend

logger = TrainLogger(
    NeptuneBackend(project="workspace/project", api_token="...")
)

# Reuse an existing run
import neptune
run = neptune.init_run(project="workspace/project")
logger = TrainLogger(NeptuneBackend(run=run))

Metrics are logged via run["metrics/<name>"].append(value, step=step).

TensorBoard

pip install ahsi[tensorboard]
from ashi import TrainLogger, TensorBoardBackend

logger = TrainLogger(TensorBoardBackend(log_dir="runs/my-experiment"))

# Reuse an existing SummaryWriter
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter("runs/my-experiment")
logger = TrainLogger(TensorBoardBackend(writer=writer))

Works with torch.utils.tensorboard (no extra install if PyTorch is already present) or tensorboardX.

Aim

pip install ahsi[aim]
from ashi import TrainLogger, AimBackend

logger = TrainLogger(AimBackend(experiment="my-experiment", repo="."))

# Reuse an existing run
from aim import Run
run = Run(experiment="my-experiment")
logger = TrainLogger(AimBackend(run=run))

Framework Callbacks

HuggingFace Transformers

No extra dependencies — pass the callback to Trainer.

from transformers import Trainer
from ashi import TrainLogger, DiscordBackend, HuggingFaceCallback

logger = TrainLogger(DiscordBackend(webhook_url="..."))
trainer = Trainer(
    model=model,
    args=training_args,
    callbacks=[HuggingFaceCallback(logger, experiment="my-run")],
)
trainer.train()

Hooks: on_train_beginon_log (each loss log) → on_saveon_train_end

PyTorch Lightning

import pytorch_lightning as pl
from ashi import TrainLogger, DiscordBackend, LightningCallback

logger = TrainLogger(DiscordBackend(webhook_url="..."))
trainer = pl.Trainer(
    max_epochs=100,
    callbacks=[LightningCallback(logger, experiment="my-run")],
)
trainer.fit(model)

Hooks: on_train_starton_train_epoch_endon_save_checkpointon_train_endon_exception


AI Summary (OpenAI)

Pass an AISummarizer to get a 1–2 sentence natural-language analysis of your training run, posted to all backends automatically.

from ashi import TrainLogger, DiscordBackend, AISummarizer

logger = TrainLogger(
    DiscordBackend(webhook_url="..."),
    summarizer=AISummarizer(api_key="sk-...", model="gpt-4o-mini"),
)

logger.on_train_start("my-exp", config={"lr": 3e-4, "epochs": 100})
for epoch in range(1, 101):
    logger.on_epoch_end(epoch, {"loss": 0.42, "val_loss": 0.38}, total_epochs=100)

# Posts an orange message like:
# "Training is converging steadily — val_loss dropped from 0.89 to 0.38
#  over 100 epochs with no signs of overfitting."
logger.summarize()

Call summarize() at any point — mid-training, on checkpoint, or at the end. No extra packages required beyond requests.


License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ahsi-0.1.3.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ahsi-0.1.3-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file ahsi-0.1.3.tar.gz.

File metadata

  • Download URL: ahsi-0.1.3.tar.gz
  • Upload date:
  • Size: 18.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ahsi-0.1.3.tar.gz
Algorithm Hash digest
SHA256 b1b9f33a9b2e473241b6b26e7f0e5d2e7e668543821cfd464ec18b2361eaa64a
MD5 f265e5cfa915ee5b2ebdb154af691de1
BLAKE2b-256 309a7cc063ec9903f53e8eaf684654266da14ee6edd44594d6bd4c246f8878fb

See more details on using hashes here.

Provenance

The following attestation bundles were made for ahsi-0.1.3.tar.gz:

Publisher: publish.yml on byeolki/ASHi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ahsi-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: ahsi-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 23.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ahsi-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 ae3fed63c99b2cf9dad0dd72cdd459652b889804d6cdfe4212e2a73a9455e804
MD5 eeb5d62bdf3efe90fdd8a2f4889cbb4a
BLAKE2b-256 eb7bc63982e699592ff412567304edc184e596a38b778d3be2d3fa3b2dfe870e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ahsi-0.1.3-py3-none-any.whl:

Publisher: publish.yml on byeolki/ASHi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page