Documentation

ModelForgeLab is an open adapter registry. The core service — metadata, weights, fine-tune queue, and the API — can run entirely on your own hardware or via our managed hosting. No adapter data or user credentials are shared with third parties.

Optional cloud-adjacent components are available for teams that need them but are never required:

  • Artifact CDN — a pull-through cache fronting /download/* for geographically distributed teams. Your instance remains the source of truth; the CDN holds no originals.
  • SMS verification — the default auth flow uses a configurable SMS provider (or can be replaced with TOTP). The core registry works without phone verification if you disable it in config.py.
  • Enterprise tier — dedicated support SLA and a managed hosting option for organisations that cannot self-host. The software and API are identical to the community edition.

Install the CLI

curl -fsSL https://modelforgelab.cloud/install.sh | sh
mfl login https://your-instance.example

The CLI stores credentials in ~/.config/mfl/credentials.json. Pass --token to override for scripted use.

Pull an adapter

Downloads the adapter weights and verifies the sha256 checksum before writing to the local cache.

mfl pull sd15-pixelart-lora
# resolves latest version, verifies sha256, writes to ~/.cache/mfl/

mfl pull sd15-pixelart-lora --version 2.1.0   # pin a specific version
mfl pull sd15-pixelart-lora --format gguf      # prefer GGUF if available

Interrupted downloads resume automatically via HTTP Range requests. You can also pull a specific base-model revision alongside the adapter:

mfl pull sdxl-watercolor-lora --with-base

Serve locally

mfl serve sd15-pixelart-lora --base runwayml/stable-diffusion-v1-5
# starts an OpenAI-compatible HTTP endpoint on localhost:11434

mfl serve qwen25-7b-support-tone --port 9000 --workers 2

The serve command loads the base model, attaches the adapter, and exposes a /v1/completions (text) or /v1/images/generations (image) endpoint compatible with standard clients.

Fine-tune with LoRA

Upload a JSONL dataset, choose a base model and rank, and queue a run. Progress streams over server-sent events; the resulting adapter lands in your private registry automatically.

mfl finetune \
  --base Qwen/Qwen2.5-7B-Instruct \
  --data ./train.jsonl \
  --rank 16 --alpha 32 \
  --epochs 3 --seed 42

Dataset format — one JSON object per line:

{"prompt": "Summarise this ticket:", "completion": "User reports login error on Safari 17."}
{"prompt": "Summarise this ticket:", "completion": "Payment declined after promo code applied."}

Training runs are isolated per-job. You can monitor live loss curves in the UI or stream them via the API:

curl -N -H "Authorization: Bearer $MFL_TOKEN" \
  https://your-instance.example/events/<job_id>

Formats & precision

FormatTypical precisionCompatible runtimes
safetensorsfp16 / bf16transformers, diffusers, vLLM
ggufq4_k_m, q5_k_m, q8_0llama.cpp, Ollama, LM Studio
diffusersfp16ComfyUI, Automatic1111

The registry stores the format and precision in adapter metadata. mfl pull downloads the correct file automatically. To request a specific format:

mfl pull llama3-8b-changelog-writer --format gguf --precision q4_k_m

Authentication

Public adapters can be pulled without credentials. Members-only adapters and all write operations require a valid session token.

Generate a long-lived API token under Account → API tokens. Tokens are scoped:

ScopeAllowed operations
readPull public and members-only adapters, list catalog
writeUpload datasets, queue fine-tune jobs, push adapters
adminManage users, change adapter visibility, delete artifacts
export MFL_TOKEN=mfl_live_xxxxxxxxxxxxxxxxxxxx
mfl pull flux-linework-lora   # members-only, uses token from env

Python SDK

Install alongside the CLI or standalone. The SDK is distributed via the CLI installer and also available as a wheel in each GitHub release:

pip install mfl/modelforge_sdk-*.whl   # from a downloaded release
from modelforge import Client

client = Client("https://your-instance.example", token="mfl_live_xxx")

# List all public adapters
for adapter in client.adapters.list(public=True):
    print(adapter.slug, adapter.version)

# Pull and load with PEFT
adapter_path = client.adapters.pull("qwen25-7b-support-tone")

from transformers import AutoModelForCausalLM
from peft import PeftModel

base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
model = PeftModel.from_pretrained(base, adapter_path)

Configuration

All settings are controlled via environment variables. No config file required.

VariableDefaultDescription
MFL_SECRET_KEYRequired. Random secret for session signing.
MFL_UPLOAD_ENABLEDtrueAllow dataset uploads.
MFL_MAX_UPLOAD_BYTES5368709120Upload size limit (5 GB default).
MFL_STREAM_BLOCK_BYTES1048576Streaming block size for downloads.
MFL_DOWNLOAD_RATE_MBPS0Throttle downloads (0 = unlimited).
MFL_MAX_CONCURRENT_SSE10Max simultaneous SSE streams.

Rate limits

Default limits apply per IP address (requires MFL_TRUST_XFF=true when behind a reverse proxy):

Endpoint groupLimit
Page requests120 / minute
Downloads (/download/*)20 / minute
Uploads (/upload)5 / minute
SSE streams (/events/*)10 concurrent
API (/v1/*)300 / minute

Exceeding a limit returns 429 Too Many Requests. Limits reset on a rolling 60-second window.