Quick start
A pilot run takes a few minutes on a laptop: the shipped configs train a few steps on the sample rows so you can see
every stage end to end before pointing them at real data. You need Python 3.12 and uv; a GPU is optional (Apple
silicon trains on MPS).
What you will see after llmclick run:
- a progress bar per stage and one for the steps inside the running stage;
- an experiment directory
output/<name>-<hash>/withconfig.yaml,manifest.json,pipeline.logand a link per stage; - the validation report at
output/<name>-<hash>/validate/validation.jsonand, if it passed, the checkpoint link atvalidate/checkpoint.
Run the same command again and every stage reports cached. Edit training.lr and only train and validate run
again; the data stage is shared.
uv sync # Python 3.12
cp environment/.env.sample environment/.env # HF_TOKEN for gated models; API_TOKEN, API_PATHS for a shared server
uv run llmclick recipes # recipes, their stages and registry keys
uv run llmclick validate configs/llm/sft.yaml # experiment key and stage plan
uv run llmclick run configs/llm/sft.yaml # the stages the config asks for
uv run llmclick serve --host 0.0.0.0 --port 8000 # API + Swagger at /docs (or: uvicorn core.api.app:app)
curl -X POST localhost:8000/api/jobs -H 'content-type: application/json' \
-d '{"config_path": "configs/llm/sft.yaml"}'
| Config | What it builds |
|---|---|
llm/sft.yaml | SFT of Qwen3.5-0.8B (hybrid) on conversations |
llm/sft_transformer.yaml | the same recipe on Qwen3-0.6B (transformer) |
llm/instruction.yaml | instruction tuning of Qwen3.5-0.8B |
llm/dpo.yaml | DPO of Qwen3.5-0.8B on preference pairs |
llm/sft_lora.yaml | the SFT recipe with a LoRA adapter instead of full fine-tuning |
llm/grpo.yaml | GRPO of Qwen3.5-0.8B with the exact_match reward |
llm/grpo_gsm8k.yaml | GRPO on GSM8K word problems from the Hub with the last_number reward |
llm/decision_readout.yaml | one-pass decision model: full fine-tuning, readout head (Jev, jeff) |
llm/decision_pointer.yaml | reasoning decision model, stage 1: LoRA, pointer head, reasoning chains as context (Jeeves SFT) |
llm/decision_cispo.yaml | reasoning decision model, stage 2: CISPO from the stage-1 checkpoint |
embedding/contrastive.yaml | contrastive learning of Qwen3-Embedding-0.6B |
evaluation/custom.yaml | the llm/sft.yaml experiment's validated checkpoint scored on the sample rows |
evaluation/benchmark.yaml | the same checkpoint on the small_general preset plus KMMLU, 100 items each (needs uv sync --extra eval) |
evaluation/compare.yaml | base model against the trained checkpoint on the preset and the sample rows, with a four-axis chart |
evaluation/decision.yaml | the llm/decision_pointer.yaml checkpoint on the JevBench tiers, without and with reasoning |
evaluation/embedding.yaml | the embedding/contrastive.yaml checkpoint on three MTEB tasks (needs uv sync --extra eval) |
data/synthetic.yaml | Korean conversation rows for llm_sft from four topic seeds through a local Ollama model, evolved, judged, deduplicated |
data/speech.yaml | a Piper training set: assistant lines written by a local Ollama model, read by the jgkawell/jarvis voice, checked by Whisper (needs environment/piper/setup.sh) |
tts/piper_jarvis.yaml | fine-tuning from the jgkawell/jarvis medium checkpoint on that set, with the agent's nine read-backs; replace <hash> with the data/speech.yaml experiment's |
data/wake_phrase.yaml | "Jarvis." (statement, question, call) read by 300 speakers of the libritts_r Piper voice, kept if Whisper hears it exactly |
data/wake_negatives.yaml | near misses of the name, the commands said alone, and ordinary lines, read by 40 speakers of the same voice |
data/wake_nearmiss.yaml | 20 near misses of the name ("Travis", "Jars", "Jarrett", ...) by 120 more speakers, kept without a listening check |
wakeword/jarvis.yaml | the "Jarvis" wake word detector from those three sets; replace each <hash> |
The llm/ and embedding/ configs ship as pilots: sample rows from samples/ and max_steps: 4. Point
data.sources at your rows and remove max_steps for a real run.
Docker: IMAGE_TAG=$(git rev-parse --short HEAD) docker compose -f environment/docker-compose.yml up -d --build.
Installed as a package (uv build, then pip install dist/llmclick-*.whl), llmclick runs from any directory:
config paths, output_dir and environment/.env are relative to the working directory, and LLMCLICK_ENV names a
different settings file.
Apple silicon
Training and validation run on MPS; device in the config (or auto-detection: cuda, then mps, then cpu) decides.
Weights are trained in FP32: fully fine-tuning Qwen3.5-0.8B needs roughly 13 GB of unified memory at the shipped
batch sizes, and training.adapter (LoRA) cuts that to little more than the weights themselves.
Source: README.md. This page is generated; edit the source and run npm run sync.