Skip to main content

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>/ with config.yaml, manifest.json, pipeline.log and a link per stage;
  • the validation report at output/<name>-<hash>/validate/validation.json and, if it passed, the checkpoint link at validate/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"}'
ConfigWhat it builds
llm/sft.yamlSFT of Qwen3.5-0.8B (hybrid) on conversations
llm/sft_transformer.yamlthe same recipe on Qwen3-0.6B (transformer)
llm/instruction.yamlinstruction tuning of Qwen3.5-0.8B
llm/dpo.yamlDPO of Qwen3.5-0.8B on preference pairs
llm/sft_lora.yamlthe SFT recipe with a LoRA adapter instead of full fine-tuning
llm/grpo.yamlGRPO of Qwen3.5-0.8B with the exact_match reward
llm/grpo_gsm8k.yamlGRPO on GSM8K word problems from the Hub with the last_number reward
llm/decision_readout.yamlone-pass decision model: full fine-tuning, readout head (Jev, jeff)
llm/decision_pointer.yamlreasoning decision model, stage 1: LoRA, pointer head, reasoning chains as context (Jeeves SFT)
llm/decision_cispo.yamlreasoning decision model, stage 2: CISPO from the stage-1 checkpoint
embedding/contrastive.yamlcontrastive learning of Qwen3-Embedding-0.6B
evaluation/custom.yamlthe llm/sft.yaml experiment's validated checkpoint scored on the sample rows
evaluation/benchmark.yamlthe same checkpoint on the small_general preset plus KMMLU, 100 items each (needs uv sync --extra eval)
evaluation/compare.yamlbase model against the trained checkpoint on the preset and the sample rows, with a four-axis chart
evaluation/decision.yamlthe llm/decision_pointer.yaml checkpoint on the JevBench tiers, without and with reasoning
evaluation/embedding.yamlthe embedding/contrastive.yaml checkpoint on three MTEB tasks (needs uv sync --extra eval)
data/synthetic.yamlKorean conversation rows for llm_sft from four topic seeds through a local Ollama model, evolved, judged, deduplicated
data/speech.yamla 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.yamlfine-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.yamlnear misses of the name, the commands said alone, and ordinary lines, read by 40 speakers of the same voice
data/wake_nearmiss.yaml20 near misses of the name ("Travis", "Jars", "Jarrett", ...) by 120 more speakers, kept without a listening check
wakeword/jarvis.yamlthe "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.