Skip to main content

SlickML fine-tuning toolkit: composable strategies, objectives, and metrics for LLMs

Project description

build codecov downloads license pypi_version python_version slack_invite twitter_url

slick-tune logo

SlickTune ๐Ÿงฉ: Composable LLM Fine-Tuning by SlickML๐Ÿงž

Explore Releases ๐ŸŸฃ Become a Contributor ๐ŸŸฃ PyPI ๐ŸŸฃ Join our Slack ๐ŸŸฃ Tweet Us

๐Ÿง  Philosophy

SlickTune ๐Ÿงฉ is a small, composable toolkit for teaching LLMs new facts and behaviors with Transformers + PEFT + TRL. LoRA / QLoRA are PEFT adapters; full FT updates every weight. The goal is the same SlickML spirit: prototype fast ๐ŸŽ, keep axes orthogonal, and measure whether the model actually learned your facts ๐Ÿ”Ž.

New to fine-tuning? Start here โ†’ Fine-Tuning LLMs: A Visual Guide โ€” pre-training vs prompting vs FT, Full / LoRA / DoRA / AdaLoRA / QLoRA with diagrams, how to choose a strategy, and how probes & holdout perplexity tell you it worked.

Fine-tuning is an orthogonal stack โ€” swap any axis without rewriting the others:

model  ร—  strategy  ร—  objective  ร—  data  ร—  metrics

๐Ÿงฉ Abstractions

flowchart TB
  subgraph inputs [Inputs]
    modelId[model_id]
    dataJsonl[data JSONL]
  end

  subgraph axes [Composable axes]
    strategyNode["Strategy: LoRA / DoRA / AdaLoRA / QLoRA / Full"]
    objectiveNode["Objective: SFT then DPO / GRPO"]
  end

  subgraph core [Tuner fit]
    tuner[Tuner]
    loadStep[load model and tokenizer]
    applyStep[strategy.apply]
    trainStep[TRL trainer]
    metricsStep[MetricsTracker]
  end

  subgraph outputs [Outputs]
    checkpoint[adapter or checkpoint]
    metricsFile[metrics.json]
    probeRate[probe pass rate]
  end

  modelId --> tuner
  dataJsonl --> tuner
  strategyNode --> tuner
  objectiveNode --> tuner
  tuner --> loadStep --> applyStep --> trainStep --> metricsStep
  trainStep --> checkpoint
  metricsStep --> metricsFile
  checkpoint --> probeRate
Axis Responsibility Phase 3
Strategy How weights change (PEFT vs full) LoRA / DoRA / AdaLoRA / QLoRA / Full
Objective What is optimized / data contract SFT / DPO / ORPO / KTO
Data Examples โ†’ chat or preferences train + holdout + prefs/KTO JSONL (about_amir*.jsonl)
Metrics Comparable run stats MetricsTracker (+ holdout PPL, judge score)
Eval Holdout + judges slicktune eval, SubstringJudge, LLMJudge
Probe Did the model learn your facts? slicktune probe

๐Ÿ“Œ Quick Start

from slicktune import LoRAStrategy, SFTObjective, Tuner

Tuner(
    model_id="HuggingFaceTB/SmolLM2-135M-Instruct",
    strategy=LoRAStrategy(r=8),
    objective=SFTObjective(),
    output_dir="outputs/sft_lora",
    eval_data="examples/data/about_amir.eval.jsonl",
).fit("examples/data/about_amir.jsonl")

๐Ÿ‘ค Personal โ€œabout meโ€ loop (recommended)

  1. Edit examples/data/about_amir.jsonl with facts about you (or keep the SlickML starter facts) โœ๏ธ.
  2. Edit examples/data/about_amir.eval.jsonl with held-out paraphrases (same topics, not copied from train) for perplexity ๐Ÿ“‰.
  3. Edit examples/data/about_amir.probes.jsonl with questions and a must_contain substring that should appear after training ๐ŸŽฏ.
  4. Train a strategy on a tiny instruct model ๐Ÿงช.
  5. Probe the checkpoint โ€” pass rate shows whether fine-tuning stuck โœ….
before FT  โ†’  model guesses / hallucinates about you
after FT   โ†’  probe answers contain your facts

๐Ÿ›  Installation

Install Python >=3.10,<3.14 and uv, then simply run ๐Ÿƒโ€โ™€๏ธ:

uv sync --locked --all-extras --all-groups

QLoRA (CUDA + bitsandbytes only) ๐Ÿ”ฅ:

uv sync --extra qlora

Task runner is Poe the Poet (same idea as slick-ml, with uv instead of Poetry). Install the CLI once ๐Ÿƒโ€โ™€๏ธ:

uv tool install poethepoet
poe greet

Developer workflow (format / check / test) lives in CONTRIBUTING.md ๐Ÿง‘โ€๐Ÿ’ป๐Ÿค.

๐Ÿš‚ Train each strategy

Default demo model: HuggingFaceTB/SmolLM2-135M-Instruct (small enough for laptop smoke tests) ๐Ÿ’ป.

๐ŸŸข LoRA + SFT (default โ€” works on Mac MPS / CPU / CUDA)

uv run slicktune train \
  --strategy lora \
  --data examples/data/about_amir.jsonl \
  --eval-data examples/data/about_amir.eval.jsonl \
  --output outputs/sft_lora \
  --epochs 20

uv run slicktune probe \
  --model-dir outputs/sft_lora \
  --probes examples/data/about_amir.probes.jsonl

Or: poe train-lora / poe probe-lora / poe eval-lora / uv run python examples/run_sft_lora.py

๐ŸŸฃ DoRA + SFT

uv run slicktune train \
  --strategy dora \
  --data examples/data/about_amir.jsonl \
  --eval-data examples/data/about_amir.eval.jsonl \
  --output outputs/sft_dora
# or: uv run python examples/run_sft_dora.py

๐ŸŸค AdaLoRA + SFT

uv run slicktune train \
  --strategy adalora \
  --data examples/data/about_amir.jsonl \
  --eval-data examples/data/about_amir.eval.jsonl \
  --output outputs/sft_adalora
# or: uv run python examples/run_sft_adalora.py

๐ŸŸก LoRA + DPO (preference pairs)

uv run slicktune train \
  --strategy lora \
  --objective dpo \
  --data examples/data/about_amir.prefs.jsonl \
  --output outputs/dpo_lora \
  --epochs 3

# or: poe train-dpo / uv run python examples/run_dpo_lora.py

๐ŸŸข LoRA + KTO (unpaired labels)

uv run slicktune train \
  --strategy lora \
  --objective kto \
  --data examples/data/about_amir.kto.jsonl \
  --output outputs/kto_lora \
  --epochs 3

# or: poe train-kto / uv run python examples/run_kto_lora.py

ORPO: --objective orpo with the same prefs JSONL as DPO (TRL experimental).

๐Ÿ”Ž Eval harness (holdout PPL + judges)

uv run slicktune eval \
  --model-dir outputs/sft_lora \
  --eval-data examples/data/about_amir.eval.jsonl \
  --probes examples/data/about_amir.probes.jsonl \
  --judge substring

--eval-data should be a holdout SFT JSONL (not the training file). The shipped about_amir.eval.jsonl paraphrases the same topics for holdout perplexity.

Use --judge llm to score generations with an LLM rubric (0โ€“10 โ†’ normalized). On the tiny demo model, prefer --judge substring: the same 135M checkpoint is a weak judge and will under-score even when answers are correct.

๐Ÿ”ต QLoRA + SFT (CUDA required)

uv sync --extra qlora
uv run python examples/run_sft_qlora.py

On Apple Silicon, use LoRA instead โ€” bitsandbytes 4-bit needs CUDA ๐ŸŽ.

๐ŸŸ  Full fine-tuning + SFT

uv run python examples/run_sft_full.py

Heavier on memory; prefer LoRA for iteration ๐Ÿ’พ.

๐Ÿ“ฆ Data formats

SFT JSONL (any of these per line) ๐Ÿ“:

{"messages":[{"role":"user","content":"..."},{"role":"assistant","content":"..."}]}
{"prompt":"...","response":"..."}
{"instruction":"...","input":"...","output":"..."}

Probe JSONL ๐Ÿ•ต๏ธ:

{"prompt":"Who is Amirhessam Tahmassebi?","must_contain":"SlickML"}

Holdout eval JSONL (same SFT shapes as train; keep examples out of the train file) ๐Ÿ“‰:

{"messages":[{"role":"user","content":"..."},{"role":"assistant","content":"..."}]}

Ship example: examples/data/about_amir.eval.jsonl.

Preference JSONL (DPO / ORPO) โš–๏ธ:

{"prompt":"...","chosen":"...","rejected":"..."}

KTO JSONL (unpaired labels) โœ…โŒ:

{"prompt":"...","completion":"...","label":true}

๐Ÿ—บ Roadmap

Phase Scope
0โ€“1 Skeleton, SFT + LoRA/QLoRA/full, metrics, personal probe loop
2 (done) DoRA / AdaLoRA, holdout PPL + substring/LLM judges
3 (now) DPO / ORPO / KTO
4 GRPO / verifiable RL
5 Merge (TIES/DARE), multi-adapter
6 Optional PPO / multimodal

๐Ÿง‘โ€๐Ÿ’ป๐Ÿค Contributing to SlickTune ๐Ÿงฉ

You can find the details of the development process in our Contributing guidelines. We strongly believe that reading and following these guidelines will help us make the contribution process easy and effective for everyone involved ๐Ÿš€๐ŸŒ™.

Special thanks to all of our amazing contributors ๐Ÿ‘‡

Repobeats analytics image

โ“ ๐Ÿ†˜ ๐Ÿ“ฒ Need Help?

Please join our Slack Channel to interact directly with the core team and our small community. This is a good place to discuss your questions and ideas or in general ask for help ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง ๐Ÿ‘ซ ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ.

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

slicktune-0.3.0.tar.gz (364.0 kB view details)

Uploaded Source

Built Distribution

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

slicktune-0.3.0-py3-none-any.whl (31.9 kB view details)

Uploaded Python 3

File details

Details for the file slicktune-0.3.0.tar.gz.

File metadata

  • Download URL: slicktune-0.3.0.tar.gz
  • Upload date:
  • Size: 364.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for slicktune-0.3.0.tar.gz
Algorithm Hash digest
SHA256 fb7c5dc5a236989b85050d4976e9e1a4edff619d0db3220cab97c43d2645193a
MD5 07ca11aa15884a8cf1ec1be7b00c911d
BLAKE2b-256 3a43311d4d9faa1fd369771bcbc5053c61e0e00e611d62bc7a827a0d7ccfbd5b

See more details on using hashes here.

File details

Details for the file slicktune-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: slicktune-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 31.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for slicktune-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 399752b4ca90379cdab97b1946fad2e2d5d219fc7dddecaf5deffe5940d5227a
MD5 4a8e4de32332772d80facb1d26fcdd82
BLAKE2b-256 0ad22a1190fb917e622ae20dee4f442f9a1ede541d61b9eb206051f839bcc211

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