# Comparing chat models on Paperless suggestions Which local LLM is worth running behind paperless-ngx's AI suggestions, measured against documents a human already filed, in the `paperless-eval` namespace rather than against the live archive. **Applied by hand, not by Flux.** A Job is immutable, so re-running a configuration means deleting and recreating it, and a Flux-managed Job would simply come back. The namespace itself *is* managed (`kubernetes/apps/paperless-eval/`); only the measurement is not. ## Running one Screen first, always: ```sh ./run-candidate.sh qwen3-8b 5 # ~5 min to a rejection, ~10 to a pass kubectl -n paperless-eval logs -f job/eval-qwen3-8b -c eval kubectl -n paperless-eval delete job eval-qwen3-8b ./run-candidate.sh qwen3-8b # the real measurement, 50 documents ``` Three of the first four candidates could not do the task at all, and each was left running for an hour before anyone looked. eval.py now stops after three consecutive failures from the first document, so a screening run rejects a hopeless candidate in about five minutes. Screening uses genuine paperless requests. That matters — `probe-toolcall.sh` is cheaper still and worth a first pass, but it passed two candidates that then failed on document one, because a synthesised request cannot reproduce the RAG neighbours and taxonomy candidate lists that make a real prompt what it is. Never compare numbers across sample sizes. A screen is a gate; the comparison happens at 50. Candidates live in `candidates.tsv`; the runner substitutes the model-specific values into `job-template.yaml` and refreshes the `eval.py` ConfigMap. Adding a candidate is a line in that file, not a copy of the manifest — the sidecar configuration deliberately exists once. Two run at a time: the pod anti-affinity puts one per node, and only two nodes have a free iGPU. A third waits. Re-running after an edit needs the old Job gone first: `kubectl -n paperless-eval delete job eval-