A machine learning system for classifying English text readability levels (Elementary, Intermediate, Advanced) using a fine-tuned BERT model. This project implements a complete MLOps pipeline including training, evaluation, API serving, and cloud deployment.
β οΈ Intel Mac Users: This project uses PyTorch 2.6.0, which doesn't have wheels for Intel Macs withuv. Please see INTEL_MAC_GUIDE.md for Docker-based setup instructions.
Group 63 - DTU Course 02476 Machine Learning Operations
| Student Number |
|---|
| s234869 (Alexander Hougaard) (GitHub: Alexander-bit-boop) |
| s245176 (William Hyldig) (GitHub: Williamhyldig) |
| s244742 (Valdemar Stamm) (GitHub: HrStamm) |
| s245362 (Frederik JΓΈnsson) (GitHub: Trexz14) |
| s246089 (Gustav Christensen) (GitHub: DonConarch) |
This project was developed as part of the 02476 Machine Learning Operations course at DTU. It builds an end-to-end ML pipeline that predicts text readability levels on a 0-2 scale:
- 0: Elementary (simple vocabulary and sentence structure)
- 1: Intermediate (moderate complexity)
- 2: Advanced (complex vocabulary and sentence structure)
- π€ BERT-based model using the lightweight
prajjwal1/bert-mini(11M parameters) - π Experiment tracking with Weights & Biases
- π³ Containerized training and API serving with Docker
- βοΈ Cloud deployment on Google Cloud Platform (Cloud Run)
- π CI/CD pipelines with GitHub Actions
- π¦ Data versioning with DVC and Google Cloud Storage
- π§ͺ Comprehensive testing with pytest and code coverage
- π API monitoring with Prometheus metrics
For detailed setup instructions, see QUICKSTART.md.
# Clone the repository
git clone https://github.com/Trexz14/ml-ops-assignment.git
cd ml-ops-assignment
# Install dependencies (requires uv)
uv sync
# Authenticate with Google Cloud (for data/model access)
gcloud auth application-default login
# Pull data and models from DVC
uv run dvc pull
# Evaluate the trained model
uv run invoke evaluate --checkpoint models/model_final.pt
# Start the API server
uv run invoke serve-apiβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Data Pipeline β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β HuggingFace ββββββΆβ Tokenizer ββββββΆβ Processed β β
β β Dataset β β (BERT) β β Dataset β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββββββββββββββββββββββ β
β β DVC + GCS Storage β β
β ββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Training Pipeline β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Config ββββββΆβ Training ββββββΆβ Model β β
β β (YAML) β β Script β β Checkpoints β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β β
β βΌ βΌ β
β ββββββββββββββ ββββββββββββββ β
β β W&B β β DVC β β
β β Logging β β Storage β β
β ββββββββββββββ ββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Serving Pipeline β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β FastAPI ββββββΆβ Docker ββββββΆβ Cloud Run β β
β β Server β β Container β β Deployment β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β
β βΌ β
β ββββββββββββββββ β
β β Prometheus β β
β β Metrics β β
β ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CI/CD Pipeline β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β GitHub ββββββΆβ GitHub ββββββΆβ Cloud β β
β β Push β β Actions β β Build β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β β
β βΌ βΌ β
β ββββββββββββββ ββββββββββββββ β
β β Tests β β Artifact β β
β β + Lint β β Registry β β
β ββββββββββββββ ββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββ .github/ # GitHub Actions workflows
β βββ workflows/
β βββ tests.yaml # Run tests on push/PR
β βββ linting.yaml # Code linting with ruff
β βββ docker-build.yaml # Build and push Docker images
βββ configs/ # Experiment configuration files
β βββ experiments/
β βββ default.yaml # Default training config
βββ data/ # Data directory (DVC tracked)
β βββ processed/ # Tokenized dataset
βββ dockerfiles/ # Docker configurations
β βββ api.dockerfile # API server image
β βββ train.dockerfile # Training image
β βββ evaluate.dockerfile # Evaluation image
βββ docs/ # MkDocs documentation
β βββ source/
βββ models/ # Trained model checkpoints (DVC tracked)
βββ reports/ # Exam report and figures
βββ src/ml_ops_assignment/ # Source code
β βββ api.py # FastAPI application
β βββ data.py # Data loading and preprocessing
β βββ evaluate.py # Model evaluation script
β βββ model.py # Model definition and training logic
β βββ train.py # Training entry point
β βββ visualize.py # Visualization utilities
βββ tests/ # Unit tests
β βββ test_api.py # API tests
β βββ test_data.py # Data pipeline tests
β βββ test_model.py # Model tests
βββ cloudbuild.yaml # Google Cloud Build configuration
βββ pyproject.toml # Project dependencies (uv)
βββ tasks.py # Invoke tasks for common commands
βββ README.md # This file# Preprocess data (if starting from scratch)
uv run invoke preprocess-data
# Train the model
uv run invoke train
# Train with Docker
uv run invoke docker-train# Evaluate on test set
uv run invoke evaluate --checkpoint models/model_final.pt
# Evaluate on validation set
uv run invoke evaluate --checkpoint models/model_final.pt --split validation# Start the API server locally
uv run invoke serve-api
# Make a prediction
curl -X 'POST' \
'http://127.0.0.1:8000/predict' \
-H 'Content-Type: application/json' \
-d '{"text": "The quick brown fox jumps over the lazy dog."}'# Run all tests
uv run pytest tests/ -v
# Run tests with coverage
uv run pytest tests/ --cov=ml_ops_assignment --cov-report=term-missing# Format code
uv run ruff format .
# Lint code
uv run ruff check . --fix
# Run all pre-commit hooks
uv run pre-commit run --all-files| Category | Tools |
|---|---|
| ML Framework | PyTorch 2.6.0, Transformers |
| Model | BERT-mini (prajjwal1/bert-mini) |
| Data | HuggingFace Datasets, DVC |
| API | FastAPI, Uvicorn, Pydantic |
| Monitoring | Prometheus, Weights & Biases |
| Infrastructure | Docker, Google Cloud Run, Cloud Build |
| CI/CD | GitHub Actions |
| Code Quality | Ruff, Mypy, Pre-commit |
| Testing | Pytest, Coverage |
| Package Management | uv |
The project uses the OneStop English dataset from HuggingFace, which contains English texts at three readability levels. The dataset is automatically split into:
- Training: 80% of the data
- Validation: 10% of the data
- Test: 10% of the data
- Course instructors and TAs at DTU
- MLOps Template by Nicki Skafte
- HuggingFace for the dataset and transformers library
- Astral for uv package manager
This project is licensed under the MIT License - see the LICENSE file for details.