Skip to main content

Production-ready headless LLM fine-tuning with smart defaults, Windows support, and modular architecture

Project description

Backpropagate Logo

Backpropagate

Headless LLM Fine-Tuning - Making fine-tuning accessible without the complexity

CI Codecov PyPI Python 3.10+ License

Part of MCP Tool Shop

Train LLMs in 3 lines of code. Export to Ollama in one more.

InstallationQuick StartMulti-Run TrainingExport to OllamaContributing


Why Backpropagate?

Problem Solution
Fine-tuning is complex 3 lines: load, train, save
Windows is a nightmare First-class Windows support
VRAM management is hard Auto batch sizing, GPU monitoring
Model export is confusing One-click GGUF + Ollama registration
Long runs cause forgetting Multi-run SLAO training

Quick Start

pip install backpropagate[standard]
from backpropagate import Trainer

trainer = Trainer("unsloth/Qwen2.5-7B-Instruct-bnb-4bit")
trainer.train("my_data.jsonl", steps=100)
trainer.export("gguf", quantization="q4_k_m")  # Ready for Ollama

Philosophy

  • For Users: Upload data, pick a model, click train
  • For Developers: Clean Python API with smart defaults
  • For Everyone: Windows-safe, VRAM-aware, production-ready

Installation

Modular Installation (v0.1.0+)

Install only what you need:

pip install backpropagate              # Core only (minimal)
pip install backpropagate[unsloth]     # + Unsloth 2x faster training
pip install backpropagate[ui]          # + Gradio web UI
pip install backpropagate[standard]    # unsloth + ui (recommended)
pip install backpropagate[full]        # Everything

Available Extras

Extra Description Dependencies
unsloth 2x faster training, 50% less VRAM unsloth
ui Gradio web interface gradio>=5.6.0
validation Pydantic config validation pydantic, pydantic-settings
export GGUF export for Ollama llama-cpp-python
monitoring WandB + system monitoring wandb, psutil

Requirements

  • Python 3.10+
  • CUDA-capable GPU (8GB+ VRAM recommended)
  • PyTorch 2.0+

Usage

Use as Library

from backpropagate import Trainer

# Dead simple
trainer = Trainer("unsloth/Qwen2.5-7B-Instruct-bnb-4bit")
trainer.train("my_data.jsonl", steps=100)
trainer.save("./my-model")

# Export to GGUF for Ollama
trainer.export("gguf", quantization="q4_k_m")

With Options

from backpropagate import Trainer

trainer = Trainer(
    model="unsloth/Llama-3.2-3B-Instruct-bnb-4bit",
    lora_r=32,
    lora_alpha=64,
    learning_rate=1e-4,
    batch_size="auto",  # Auto-detects based on VRAM
)

run = trainer.train(
    dataset="HuggingFaceH4/ultrachat_200k",
    steps=200,
    samples=2000,
)

print(f"Final loss: {run.final_loss:.4f}")
print(f"Duration: {run.duration_seconds:.1f}s")

Launch the Web UI

# CLI
backpropagate --ui

# Or from Python
from backpropagate import launch
launch(port=7862)

Multi-Run Training (SLAO)

Multiple short runs with LoRA merging prevents catastrophic forgetting and improves results:

from backpropagate import Trainer

trainer = Trainer("unsloth/Qwen2.5-7B-Instruct-bnb-4bit")

# Run 5 training runs, each on fresh data
result = trainer.multi_run(
    dataset="HuggingFaceH4/ultrachat_200k",
    num_runs=5,
    steps_per_run=100,
    samples_per_run=1000,
    merge_mode="slao",  # Smart LoRA merging
)

print(f"Final loss: {result.final_loss:.4f}")
print(f"Total time: {result.total_time_seconds:.1f}s")

Or use the dedicated trainer:

from backpropagate import MultiRunTrainer, MultiRunConfig

config = MultiRunConfig(
    num_runs=5,
    steps_per_run=100,
    samples_per_run=1000,
)

trainer = MultiRunTrainer(
    model="unsloth/Qwen2.5-7B-Instruct-bnb-4bit",
    config=config,
)

result = trainer.run("my_data.jsonl")

CLI Usage

# Show system info and features
backprop info

# Show current configuration
backprop config

# Train a model
backprop train \
    --data my_data.jsonl \
    --model unsloth/Qwen2.5-7B-Instruct-bnb-4bit \
    --steps 100 \
    --samples 1000

# Multi-run training (recommended for best results)
backprop multi-run \
    --data HuggingFaceH4/ultrachat_200k \
    --runs 5 \
    --steps 100 \
    --samples 1000

# Export to GGUF for Ollama
backprop export ./output/lora \
    --format gguf \
    --quantization q4_k_m \
    --ollama \
    --ollama-name my-model

# Launch UI
backpropagate --ui --port 7862

Feature Flags

Check which features are installed:

from backpropagate import FEATURES, list_available_features

print(FEATURES)
# {'unsloth': True, 'ui': True, 'validation': False, ...}

for name, desc in list_available_features().items():
    print(f"{name}: {desc}")

Configuration

All settings can be overridden via environment variables:

# Model settings
BACKPROPAGATE_MODEL__NAME=unsloth/Llama-3.2-3B-Instruct-bnb-4bit
BACKPROPAGATE_MODEL__MAX_SEQ_LENGTH=4096

# Training settings
BACKPROPAGATE_TRAINING__LEARNING_RATE=1e-4
BACKPROPAGATE_TRAINING__MAX_STEPS=200
BACKPROPAGATE_TRAINING__BATCH_SIZE=4

# LoRA settings
BACKPROPAGATE_LORA__R=32
BACKPROPAGATE_LORA__ALPHA=64

Or use a .env file in your project root.

Dataset Formats

JSONL (Recommended)

{"text": "<|im_start|>user\nWhat is Python?<|im_end|>\n<|im_start|>assistant\nPython is a programming language.<|im_end|>"}

HuggingFace Datasets

Any dataset with a text column works:

trainer.train(dataset="HuggingFaceH4/ultrachat_200k", samples=1000)

Export & Ollama Integration

Export trained models to various formats:

from backpropagate import (
    export_lora,
    export_merged,
    export_gguf,
    create_modelfile,
    register_with_ollama,
)

# Export to GGUF for Ollama/llama.cpp
result = export_gguf(
    model,
    tokenizer,
    output_dir="./gguf",
    quantization="q4_k_m",  # f16, q8_0, q5_k_m, q4_k_m, q4_0, q2_k
)

print(result.summary())

# Register with Ollama
register_with_ollama("./gguf/model-q4_k_m.gguf", "my-model")
# Now run: ollama run my-model

GPU Safety Monitoring

Monitor GPU health during training:

from backpropagate import check_gpu_safe, get_gpu_status, GPUMonitor

# Quick safety check
if check_gpu_safe():
    print("GPU is ready for training")

# Get detailed status
status = get_gpu_status()
print(f"GPU: {status.device_name}")
print(f"Temperature: {status.temperature_c}C")
print(f"VRAM: {status.vram_used_gb:.1f}/{status.vram_total_gb:.1f} GB")
print(f"Condition: {status.condition}")  # SAFE, WARNING, CRITICAL

# Continuous monitoring during training
with GPUMonitor(check_interval=30) as monitor:
    trainer.train(dataset, steps=1000)

Windows Support

Backpropagate is designed to work on Windows out of the box:

  • Pre-tokenization to avoid multiprocessing crashes
  • Automatic xformers disable for RTX 40/50 series
  • Safe dataloader settings
  • Tested on RTX 5080 (16GB VRAM)

Windows fixes are applied automatically when os.name == "nt".

Model Presets

Preset VRAM Speed Quality
Qwen 2.5 7B ~12GB Medium Best
Qwen 2.5 3B ~8GB Fast Good
Llama 3.2 3B ~8GB Fast Good
Llama 3.2 1B ~6GB Fastest Basic
Mistral 7B ~12GB Medium Good

Architecture

backpropagate/
├── __init__.py          # Package exports, lazy loading
├── __main__.py          # CLI entry point
├── cli.py               # Command-line interface
├── trainer.py           # Core Trainer class
├── multi_run.py         # Multi-run SLAO training
├── slao.py              # SLAO LoRA merging algorithm
├── datasets.py          # Dataset loading & filtering
├── export.py            # GGUF/Ollama export
├── config.py            # Pydantic settings
├── feature_flags.py     # Optional dependency detection
├── gpu_safety.py        # GPU monitoring & safety
├── theme.py             # Ocean Mist Gradio theme
└── ui.py                # Gradio interface

API Reference

Trainer

class Trainer:
    def __init__(
        self,
        model: str = None,           # Model name/path
        lora_r: int = 16,            # LoRA rank
        lora_alpha: int = 32,        # LoRA alpha
        learning_rate: float = 2e-4, # Learning rate
        batch_size: int | str = "auto",  # Batch size or "auto"
        output_dir: str = "./output",    # Output directory
    )

    def train(
        self,
        dataset: str | Dataset,  # Dataset path or HF name
        steps: int = 100,        # Training steps
        samples: int = 1000,     # Max samples
    ) -> TrainingRun

    def save(self, path: str = None) -> str
    def export(self, format: str, quantization: str = "q4_k_m") -> str

TrainingRun

@dataclass
class TrainingRun:
    run_id: str
    steps: int
    final_loss: float
    loss_history: List[float]
    duration_seconds: float
    samples_seen: int

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

# Development setup
git clone https://github.com/mcp-tool-shop-org/backpropagate
cd backpropagate
pip install -e ".[dev]"

# Run tests
pytest

# Type checking
mypy backpropagate

# Linting
ruff check backpropagate

Related Projects

Part of MCP Tool Shop — AI-powered development tools:

Support

License

MIT License - see LICENSE for details.

Acknowledgments

  • Unsloth for the amazing training optimizations
  • HuggingFace for transformers, datasets, and PEFT
  • Gradio for the beautiful UI framework

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

backpropagate-0.1.2.tar.gz (310.3 kB view details)

Uploaded Source

Built Distribution

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

backpropagate-0.1.2-py3-none-any.whl (135.3 kB view details)

Uploaded Python 3

File details

Details for the file backpropagate-0.1.2.tar.gz.

File metadata

  • Download URL: backpropagate-0.1.2.tar.gz
  • Upload date:
  • Size: 310.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for backpropagate-0.1.2.tar.gz
Algorithm Hash digest
SHA256 cb0ca13f97e27316d206ba2c5bb1c34c1686f910a8feb6d1ec7b31dc577a20aa
MD5 a47a75253c189d6fc194bee07a9f2a79
BLAKE2b-256 c07266d05c412b11f24d3331b1a9a80afde1e3965b2498b2b113cd0530c0cd05

See more details on using hashes here.

File details

Details for the file backpropagate-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: backpropagate-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 135.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for backpropagate-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f60c6600351cf6bc97cdca6e01480e19603d163b2332ca3ccee78ae4734d75c6
MD5 cac5ac9ff7d726acd34657a7d0e9c37e
BLAKE2b-256 1d347a6cfce89a181a3f373694ed5d755420dc9e04f767d3ac03baee19bc1a32

See more details on using hashes here.

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