Skip to main content

Spam classifier

This project demonstrates how to package and train a simple spam/ham classifier with MLOps practices. It is designed for students learning how to structure ML code into modules, build training pipelines, configure via YAML, and add tests and CI.

Project structure

  • spam_classifier/ — package code (pipeline, training, inference)
  • data/ — raw and processed datasets
  • config.yaml — pipeline and training configuration
  • tests/ — pytest suite (unit + quality)
  • .github/workflows/ci.yml — GitHub Actions CI

Setup (uv)

uv venv --seed --python 3.13
uv pip install -e ".[dev]"

Minimum supported Python version is 3.11. If you prefer venv, you can still use it, but the project CI and Makefile expect uv.

Data

Download and prepare the dataset:

make download_data
make process_data

make process_data builds data/processed/train.csv and data/processed/test.csv. The holdout split is controlled by:

  • data.test_size in config.yaml (default 0.1)
  • training.use_holdout (True/False)

Training

Train with cross-validation and optional holdout evaluation:

make train

Training behavior is controlled in config.yaml:

  • training.cv_folds — number of CV folds
  • training.metrics — metrics to log (accuracy/precision/recall/f1/roc_auc)
  • training.use_holdout — evaluate on test.csv if True
  • training.run_validation — run CV if True

Versioned artifacts

Package version is stored in spam_classifier/_VERSION. Model and log filenames include this version:

  • Model: spam_classifier/models/spam_classifier_vX.Y.Z.pkl
  • Logs: spam_classifier/logs/logs_X.Y.Z.log

Inference

Install from PyPI

uv pip install spam-classifier

CLI usage

Single message:

uv run python -m spam_classifier.predict "Free prize! Call now"

Batch inference from file (one message per line):

uv run python -m spam_classifier.predict data/processed/test.csv -o results/preds.csv

Options:

  • -o/--output — output CSV path (default: project root)
  • --no-message — exclude message text from output CSV
  • --model-path — path to a trained .pkl model (overrides default)

If you installed the package from PyPI, you must train a model or pass --model-path because no weights are bundled with the package by default. Pretrained weights are attached to the GitHub Release assets for each version.

Python usage

from spam_classifier.predict import load_model, predict_message

model = load_model("/path/to/model.pkl")
print(predict_message("Free prize! Call now", model))

If you have activated the virtual environment, you can omit uv run and call python directly.

Tests

Run full test suite:

uv run pytest tests

Quality tests (require trained model and holdout data):

uv run pytest -m quality

If you have activated the virtual environment, you can omit uv run for pytest as well.

CI

GitHub Actions runs on PRs to main and develop:

  • black --check
  • flake8
  • mypy
  • pytest tests

Pre-commit

Install and run pre-commit hooks:

pre-commit install
pre-commit run --all-files

Hooks included: black, flake8, mypy.

Publishing

TestPyPI (manual)

  1. Update spam_classifier/_VERSION
  2. Create a GitHub Actions run:
    • Go to Actions → Publish → Run workflow
    • Select testpypi
  3. The package is built and published to TestPyPI

PyPI (release)

  1. Update spam_classifier/_VERSION
  2. Create a GitHub Release (tag should match the version, e.g. v0.1.0)
  3. The Publish workflow will build and upload to PyPI

Trusted publishing

This project uses GitHub Actions OIDC (trusted publishing). You must configure the trusted publisher on PyPI and TestPyPI to allow the Publish workflow from this repository to upload packages.

Metadata

Release files for spam-classifier 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 spam-classifier 0.2.1
File Size Uploaded
spam_classifier-0.2.1.tar.gz 14.5 kB Details

Built distribution (wheel)

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

Total release size: 27.0 kB

Release files / spam_classifier-0.2.1.tar.gz

Download URL spam_classifier-0.2.1.tar.gz
Size 14.5 kB
Tags Source
SHA-256 checksum
How to use checksums
778570d40c79dbd1e2f4870bd8c7818fdf52c39e8738fc9d8a2976fa86d25ab3
BLAKE2b-256 checksum
How to use checksums
a298e4c9aa85786bbed3ab1f941cb151db52a026aeb3d0e43a8e053e5ba54b31
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jan 30, 2026.

Transparency log

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

Download URL spam_classifier-0.2.1-py3-none-any.whl
Size 12.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
19e114f9cbd81659626b46b24d94bc98cb60c5b039814169e3dc6f4d2352a5ce
BLAKE2b-256 checksum
How to use checksums
1cead262165605d880389a1e8ab816942dc7849e09f20b0f2b9d828aa8665d84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

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 Jan 30, 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