Skip to main content

๐Ÿง™โ€โ™€๏ธ Merlina - Magical Model Training

Train LLMs with ORPO, DPO, SimPO, CPO, IPO, KTO, and SFT using a delightful web interface powered by magic โœจ

Merlina Banner

Tests Quick Tests codecov Python 3.10+ API Coverage

Features

  • ๐ŸŽจ Beautiful Web Interface - Cute wizard-themed UI with animations
  • ๐Ÿงช 7 Training Modes - ORPO, DPO, SimPO, CPO, IPO, KTO, and SFT
  • ๐Ÿ’ฌ Messages Format Support - Automatic detection and conversion of common chat dataset formats
  • ๐Ÿ“š Flexible Datasets - HuggingFace, upload files (JSON/CSV/Parquet), or local paths
  • ๐Ÿ“ Multiple Formats - ChatML, Llama 3, Mistral, custom templates, or automatic tokenizer-based formatting
  • ๐Ÿค– Tokenizer Format - Automatically uses the model's native chat template
  • ๐Ÿ—œ๏ธ 4-bit Quantization - Train large models on consumer GPUs
  • ๐Ÿช„ GGUF Export - Quantize any trained model to GGUF via llama.cpp (Q4_K_M, Q5_K_M, Q8_0, F16, and more)
  • ๐Ÿ”ฎ llama-server Inference - Swap between transformers (base + LoRA) and a llama-server GGUF backend from the UI
  • ๐Ÿ“ฆ Export & Artifacts - Dedicated Export section for post-hoc GGUF, HuggingFace uploads, and per-model artifact browsing / cleanup
  • ๐Ÿ“Š Real-time Monitoring - WebSocket updates with live metrics and GPU stats
  • ๐Ÿ’พ Persistent Job Storage - SQLite database preserves jobs across restarts
  • ๐Ÿ“‹ Job Queue - Priority-based queue with configurable concurrency
  • โœ… Pre-flight Validation - Catch configuration errors before training starts
  • ๐Ÿค— HuggingFace Integration - Push models directly to the Hub (public or private) with upload state tracking
  • ๐Ÿ“ˆ W&B Logging - Detailed experiment tracking

Quick Start

Pick your path โ€” all of them end at the same web UI:

๐Ÿ pip pip install merlina then merlina serve
๐Ÿณ Docker docker compose up with GPU passthrough
โ˜๏ธ RunPod One-line setup script or GHCR image โ€” guide
๐Ÿ““ Colab Open In Colab free GPU, three cells
๐Ÿ› ๏ธ From source git clone + pip install -r requirements.txt (below)

About torch: Merlina deliberately does not install torch/torchvision/torchaudio โ€” GPU environments (RunPod, Colab, Lambda, etc.) ship CUDA-matched builds that pip would silently replace with broken generic ones. If you don't have torch yet, install it first:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128

torchvision is required for VLM training (Qwen-VL, LLaVA, etc.) โ€” without it the model still trains, but the image-processor files are silently skipped and the uploaded checkpoint misses the vision side of the processor.

Option A: pip install

pip install merlina          # add [vlm] / [diffusion] / [all] extras as needed
merlina serve                # then open http://localhost:8000

Option B: Docker

Requires the NVIDIA Container Toolkit for GPU access.

docker run --gpus all -p 8000:8000 \
  -v ./data:/app/data -v ./models:/app/models \
  ghcr.io/schneewolf-labs/merlina:latest

Or clone the repo and docker compose up -d (see docker-compose.yml for volumes and .env wiring).

Option C: From source

git clone https://github.com/Schneewolf-Labs/Merlina.git
cd Merlina

pip install -r requirements.txt

cp .env.example .env   # optional: HF token, W&B key, etc.

python merlina.py

Visit http://localhost:8000 and start training! ๐ŸŽ‰

Interactive API docs (Swagger UI) are available at http://localhost:8000/docs, with ReDoc at http://localhost:8000/redoc and the raw OpenAPI spec at http://localhost:8000/openapi.json.

Training Modes

Merlina supports 7 training modes โ€” pick the one that fits your data and goals:

Mode Description Requires Rejected?
ORPO Odds Ratio Preference Optimization โ€” single-pass preference + SFT Yes
DPO Direct Preference Optimization โ€” log-ratio preference learning Yes
SimPO Simple Preference Optimization โ€” reference-free with length normalization Yes
CPO Contrastive Preference Optimization โ€” reference-free contrastive learning Yes
IPO Identity Preference Optimization โ€” squared-loss DPO, robust to noise Yes
KTO Kahneman-Tversky Optimization โ€” binary feedback, works with unpaired data Optional
SFT Supervised Fine-Tuning โ€” train on good examples only No

How to choose:

  • Have paired chosen/rejected responses? โ†’ ORPO, DPO, SimPO, CPO, or IPO
  • Have binary feedback (thumbs up/down)? โ†’ KTO
  • Only have good examples? โ†’ SFT

Dataset Configuration

Merlina supports flexible dataset sources and formats.

Sources:

  • HuggingFace Hub โ€” Load any dataset from the Hub
  • Upload Files โ€” JSON, JSONL, CSV, or Parquet files
  • Local Path โ€” Use datasets from your filesystem

Formats:

  • Tokenizer (Recommended) โ€” Automatically uses the model's chat template
  • ChatML, Llama 3, Mistral โ€” Manual format selection
  • Custom templates โ€” Define your own format

Messages Format (New in v1.3): Merlina automatically detects and converts datasets in the common "messages" format used by many chat datasets. Multi-turn conversations are supported. Toggle this on/off via the UI or the convert_messages_format API parameter.

See the Dataset Guide for detailed instructions.

Training Configuration

The interface lets you configure:

  • Base Model โ€” HuggingFace model IDs or local directory paths
  • Training Mode โ€” ORPO, DPO, SimPO, CPO, IPO, KTO, or SFT
  • LoRA Settings โ€” Rank, alpha, dropout, target modules
  • Training Parameters โ€” Learning rate, epochs, batch size
  • Mode-specific Hyperparameters โ€” Beta, gamma (SimPO), label smoothing (DPO/CPO)
  • Options โ€” 4-bit quantization, W&B logging, HF Hub upload (public/private)

The UI dynamically adapts based on the selected training mode, showing only the relevant parameters.

Export & Quantization

After training, the Export section (step 6 in the nav) lets you work on any model under ./models/ without re-training. Three sub-panels:

  • ๐Ÿช„ GGUF Export โ€” Merge LoRA (if any) and produce one GGUF per selected quant (F16, Q8_0, Q6_K, Q5_K_M, Q5_K_S, Q4_K_M, Q4_K_S, Q3_K_M, Q2_K). Progress streams live over WebSocket. Artifacts land in ./models/{name}/gguf/ with a manifest.json sidecar that the Inference picker reads.
  • ๐Ÿค— HuggingFace Upload โ€” Repo ID override, visibility, commit message, license/tags/description, and include-what checkboxes (LoRA adapter, merged full model, GGUF files, README). A "last uploaded" banner shows whether local files have been modified since your last push, plus full history of every upload attempt (success + failure).
  • ๐Ÿ—‚๏ธ Artifacts โ€” Categorized file browser (adapter, merged, GGUF, tokenizer, processor, config, readme) with sizes and per-file delete. Core files (config.json, adapter_config.json, tokenizer) are ๐Ÿ”’-protected from the API.

llama.cpp integration

GGUF export and the llama-server inference backend are both powered by a local llama.cpp install. Merlina finds the binaries in this order:

  1. LLAMA_CPP_DIR โ€” path to a llama.cpp checkout (must contain convert_hf_to_gguf.py and build/bin/)
  2. LLAMA_CPP_BIN_DIR โ€” path to just the built binaries
  3. System $PATH โ€” if llama-quantize, llama-server, etc. are installed globally
  4. ./vendor/llama.cpp โ€” conventional local clone

If none are found, the GGUF and llama-server features stay disabled in the UI and pre-flight emits an advisory warning (never a blocking error). Check GET /llama-cpp/status to see what the resolver found.

Inference backends

The Inference section exposes two backends:

  • transformers โ€” base model + LoRA adapter, runs on GPU with optional 4-bit quantization. The default.
  • llama_cpp โ€” GGUF served by llama-server as a subprocess. Picked automatically when you select a GGUF entry from the model dropdown (they appear as indented sub-options per model).

Directory Structure

merlina/
โ”œโ”€โ”€ merlina.py                    # Backend server (main entry point)
โ”œโ”€โ”€ config.py                     # Configuration management
โ”œโ”€โ”€ version.py                    # Version information
โ”œโ”€โ”€ bump_version.py               # Version bumping tool
โ”œโ”€โ”€ requirements.txt              # Python dependencies
โ”œโ”€โ”€ Makefile                      # Build/run shortcuts
โ”œโ”€โ”€ .env.example                  # Configuration template
โ”‚
โ”œโ”€โ”€ src/                          # Source modules
โ”‚   โ”œโ”€โ”€ job_manager.py            # SQLite job persistence
โ”‚   โ”œโ”€โ”€ job_queue.py              # Priority-based job queue
โ”‚   โ”œโ”€โ”€ websocket_manager.py      # Real-time updates
โ”‚   โ”œโ”€โ”€ preflight_checks.py       # Configuration validation
โ”‚   โ”œโ”€โ”€ training_runner.py        # Training logic + sync merge orchestration
โ”‚   โ”œโ”€โ”€ merge_artifact.py         # Ref-counted shared merged-model dir
โ”‚   โ”œโ”€โ”€ gguf_exporter.py          # LoRA merge + GGUF convert/quantize pipeline
โ”‚   โ”œโ”€โ”€ llama_cpp_resolver.py     # llama.cpp binary discovery
โ”‚   โ”œโ”€โ”€ llama_server.py           # llama-server subprocess inference backend
โ”‚   โ”œโ”€โ”€ upload_state.py           # Per-model HF upload history sidecar
โ”‚   โ”œโ”€โ”€ model_artifacts.py        # Artifact inventory + safe deletion
โ”‚   โ”œโ”€โ”€ config_manager.py         # Configuration management
โ”‚   โ”œโ”€โ”€ gpu_utils.py              # GPU detection and monitoring
โ”‚   โ”œโ”€โ”€ model_card.py             # Model card generation
โ”‚   โ”œโ”€โ”€ constants.py              # Shared constants
โ”‚   โ”œโ”€โ”€ exceptions.py             # Custom exceptions
โ”‚   โ””โ”€โ”€ utils.py                  # Utilities
โ”‚
โ”œโ”€โ”€ dataset_handlers/             # Dataset pipeline
โ”‚   โ”œโ”€โ”€ base.py                   # Abstract interfaces
โ”‚   โ”œโ”€โ”€ loaders.py                # Dataset loaders (HF, local, upload)
โ”‚   โ”œโ”€โ”€ formatters.py             # Format strategies (ChatML, Llama3, etc.)
โ”‚   โ”œโ”€โ”€ messages_converter.py     # Messages format auto-conversion
โ”‚   โ”œโ”€โ”€ factory.py                # Formatter factory
โ”‚   โ””โ”€โ”€ validators.py             # Validation logic
โ”‚
โ”œโ”€โ”€ frontend/                     # Web interface (no build step)
โ”‚   โ”œโ”€โ”€ index.html
โ”‚   โ”œโ”€โ”€ css/
โ”‚   โ””โ”€โ”€ js/
โ”‚
โ”œโ”€โ”€ docs/                         # Documentation
โ”‚   โ”œโ”€โ”€ user/                     # User guides
โ”‚   โ””โ”€โ”€ dev/                      # Developer docs
โ”‚
โ”œโ”€โ”€ examples/                     # Example scripts and configs
โ”œโ”€โ”€ tests/                        # Test suite
โ””โ”€โ”€ data/                         # Runtime data (created automatically)
    โ””โ”€โ”€ jobs.db                   # SQLite database

API Endpoints

Training & Jobs:

  • POST /train?priority=normal โ€” Submit training job (priority: low/normal/high)
  • GET /status/{job_id} โ€” Get job progress and queue status
  • GET /jobs โ€” List all jobs
  • GET /jobs/history โ€” Paginated job history
  • GET /jobs/{job_id}/metrics โ€” Detailed training metrics
  • POST /jobs/{job_id}/stop โ€” Cancel queued or stop running job

Queue Management:

  • GET /queue/status โ€” Queue statistics and job lists
  • GET /queue/jobs โ€” List queued and running jobs

Dataset Management:

  • POST /dataset/preview โ€” Preview raw dataset (10 samples)
  • POST /dataset/preview-formatted โ€” Preview with formatting applied
  • POST /dataset/upload-file โ€” Upload dataset file
  • GET /dataset/uploads โ€” List uploaded datasets

Export & Artifacts:

  • GET /models/{name}/artifacts โ€” Categorized file inventory (adapter, merged, GGUF, tokenizer, etc.)
  • DELETE /models/{name}/artifacts?path=โ€ฆ โ€” Delete a file (protected core files refused)
  • GET /models/{name}/upload-state โ€” Upload history + "local is newer" freshness hint
  • POST /models/{name}/upload โ€” Post-hoc HuggingFace upload with advanced options
  • POST /models/{name}/export-gguf โ€” Post-hoc GGUF export (merges LoRA + runs llama-quantize)
  • GET /llama-cpp/status โ€” Resolver status (available binaries, supported quant types)

Inference:

  • GET /inference/models โ€” List local models (plus discovered GGUF artifacts per model)
  • POST /inference/load โ€” Load a model (backend: "transformers" | "llama_cpp")
  • POST /inference/chat โ€” Send a chat completion to the loaded backend
  • POST /inference/unload โ€” Free VRAM / stop llama-server
  • GET /inference/status โ€” Current backend + model

Validation & Info:

  • POST /validate โ€” Validate configuration before training
  • GET /version โ€” Current version info
  • GET /stats โ€” Database and system statistics
  • GET /docs โ€” Interactive API documentation (Swagger UI)
  • GET /redoc โ€” API documentation (ReDoc)
  • GET /openapi.json โ€” OpenAPI specification

WebSocket:

  • WS /ws/{job_id} โ€” Real-time training and export updates (status, metrics, gguf_progress)

Full API documentation: API.md

MCP Server

Merlina ships an MCP server so an LLM agent (Claude Desktop, Claude Code, Cursor, โ€ฆ) can drive the workshop conversationally โ€” queue training jobs, watch progress, preview datasets, and manage the GPU queue. It's a thin HTTP client to a running Merlina server, so it pulls in no torch.

# 1. Start Merlina as usual
merlina serve            # or: python merlina.py

# 2. In another shell (or wired into your MCP client), run the MCP server
pip install 'merlina[mcp]'
MERLINA_API_URL=http://localhost:8000 merlina-mcp

Wire it into an MCP client (e.g. Claude Desktop's claude_desktop_config.json):

{
  "mcpServers": {
    "merlina": {
      "command": "merlina-mcp",
      "env": { "MERLINA_API_URL": "http://localhost:8000" }
    }
  }
}

Exposed tools include start_training, get_job_status, get_job_history, get_job_metrics, stop_job, queue_status, validate_training_config, preview_dataset, list_local_models, list_gpus, and get_stats. See docs/user/mcp.md for the full reference.

GPU Memory Requirements

With 4-bit quantization enabled (default):

Model Size VRAM Required
3B params ~6 GB
7B params ~10 GB
13B params ~16 GB

Environment Variables

Configure via .env file or environment variables:

# External services โ€” setting these here means clients don't need to send
# tokens in HTTP request bodies. Tokens in requests still override env.
WANDB_API_KEY=your_wandb_key       # Weights & Biases logging
HF_TOKEN=your_huggingface_token    # HuggingFace Hub access (gated models, uploads)

# Server
HOST=0.0.0.0                       # Server bind address
PORT=8000                           # Server port

# System
CUDA_VISIBLE_DEVICES=0              # GPU selection
MAX_CONCURRENT_JOBS=1               # Queue concurrency (increase for multi-GPU)
LOG_LEVEL=INFO                      # Logging verbosity

# llama.cpp (optional โ€” enables GGUF export and llama-server inference)
LLAMA_CPP_DIR=/opt/llama.cpp        # Path to a llama.cpp checkout (preferred)
LLAMA_CPP_BIN_DIR=                  # Or just the binary directory

See .env.example for all available options.

Docker Support

FROM nvidia/cuda:11.8.0-cudnn8-runtime-ubuntu22.04

WORKDIR /app

RUN apt-get update && apt-get install -y python3.10 python3-pip
COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 8000
CMD ["python3", "merlina.py"]

Build and run:

docker build -t merlina .
docker run --gpus all -p 8000:8000 merlina

Documentation

For Developers:

  • ๐Ÿ—๏ธ Developer Docs โ€” Implementation details and architecture
  • ๐Ÿงช Tests โ€” Test suite and fixtures

Tips

  • ๐ŸŽฏ Start with 1-2 epochs for testing
  • ๐Ÿ’พ Models are saved to ./models/{output_name}
  • ๐Ÿ“Š Enable W&B for detailed metrics
  • ๐Ÿ”ง Adjust LoRA rank based on your GPU memory
  • โœจ Try the Konami code in the UI for a surprise!

Credits

Created with ๐Ÿ’œ by Schneewolf Labs

License

MIT License โ€” feel free to use for your magical model training!

Download files

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

Source Distribution

merlina-2.2.0.tar.gz (685.4 kB view details)

Uploaded Source

Built Distribution

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

merlina-2.2.0-py3-none-any.whl (492.0 kB view details)

Uploaded Python 3

File details

Details for the file merlina-2.2.0.tar.gz.

File metadata

  • Download URL: merlina-2.2.0.tar.gz
  • Upload date:
  • Size: 685.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for merlina-2.2.0.tar.gz
Algorithm Hash digest
SHA256 b02df03ea3939fe559f314788aefbeecbf2fbe44d6c49e80fe8e7f21aadafd47
MD5 b93e3c404b17b6a4c0a3633e7a895db1
BLAKE2b-256 a34410ec1d44a3568f1865d6c80122f0574389aad5438543944bc06510c2c15a

See more details on using hashes here.

Provenance

The following attestation bundles were made for merlina-2.2.0.tar.gz:

Publisher: publish.yml on Schneewolf-Labs/Merlina

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

File details

Details for the file merlina-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: merlina-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 492.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for merlina-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 85480b041c027009dbbefba444970121524254d1c30a18c6c5c5a31a25380325
MD5 aaf31067c7e294780f1d0389ad6f6918
BLAKE2b-256 03ff6c44e89c212c16961979cd8ae75f3f90661aa280db259fb207ae6f33a914

See more details on using hashes here.

Provenance

The following attestation bundles were made for merlina-2.2.0-py3-none-any.whl:

Publisher: publish.yml on Schneewolf-Labs/Merlina

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 Sentry Error logging StatusPage Status page