Plain Malay in, shell command out. A LoRA tune of
Qwen2.5-Coder-1.5B-Instruct
for camne, which runs it locally on
CPU — 4 cores, 8 GB, no GPU, nothing leaving the machine.
The point is the register. Machine translation produces
"Bagaimanakah cara untuk mencari fail..."; nobody types that. People type
camne nak cari file — and more often they type rojak, Malay grammar around
English technical nouns, because Malaysians do not translate file, port
or server.
Results
InterCode-ALFA, unmodified
scorer, 300 tasks per set. Temperature 0, n_predict 64, embedding threshold
0.75, repeat_penalty 1.08, single-line GBNF grammar. Seed 42. Full history,
including the runs that failed, in the repo's
RESULTS.md.
Paired exact McNemar against that model, 95% CI on the difference:
register
change
p
BM
+0.187 [+0.122, +0.251]
6e-08
rojak
+0.070 [+0.010, +0.130]
0.031
EN
−0.060 [−0.117, −0.003]
0.050
Read the English row honestly. This revision is worse than the
English-only model on advanced English one-liners, by the same 0.06 as the
previous revision. Someone who only ever types English is better served by
that model. camne exists for the person who types Malay or rojak, and for
the first fifty things a beginner asks.
Why this revision shipped. Against the previous revision the benchmark
cannot tell them apart (BM +0.010, rojak +0.027, EN 0.000, all inside the
95% CI; the same recipe re-run reproduces to ±0.013). What changed is the
shape of the answers on beginner tasks: the previous revision answered
create a new file with touch path/to/file1 path/to/file2 ...,
create a new folder with skicka mkdir path/to/folder, create a new user with kcadm.sh create users; this one says touch newfile.txt,
mkdir newfolder, sudo useradd -m newuser. On the repo's 222-prompt
probe: placeholder answers 29 → 2, beginner tasks 0.90 → 0.94 (p = 0.12),
held-out tools 0.90 → 0.85 (5 lost, 3 gained). It is a better answer for
the person at the prompt, not a higher score.
Training
The pool is 228,357 rows in four registers (formal BM, colloquial, rojak,
English), built from
NL2SH-ALFA (MIT),
tldr-pages (CC-BY-4.0),
commandlinefu via
b-mc2/cli-commands-explained
(CC0) and
0xrushi/git-instruction-dataset
(MIT), plus 2,496 hand-written beginner rows (326 tasks: create, list,
delete, copy, move a file or folder; read, find, disk, processes,
permissions, archives, network, editors, git, packages) with real filenames
in all four registers. Rare tools are floored, long-tail tools are capped at 300 rows outside
the coreutils, find is held to 5%, and rows whose command carries a
path/to placeholder were rewritten to a concrete name on both sides or
dropped; nothing is duplicated. Commands are byte-identical to their sources and were
never translated — that is what keeps the benchmark scorer usable. The
Malay side was machine-translated locally with
Gemma-SEA-LION-v3-9B-IT,
with Malay technical nouns kept outside the rojak register.
LoRA r32 / α64 / dropout 0.05, all linear layers, 2e-4 cosine with 3% warmup,
one epoch, seq 160, effective batch 32, bf16, seed 42, one RTX 3090.
After the SFT stage, one DPO epoch (TRL, β 0.1, lr 5e-6, LoRA r32 on the
merged checkpoint, 3,430 pairs, seed 42): chosen = the beginner-task command,
rejected = what the SFT model actually said when it was wrong, plus the same
command with its names replaced by path/to/... or its tool swapped for an
obscure one from the pool. The benchmark tasks are held out of the pairs.
Previous revisions are the commits before this one in this repository's
history: run 7 (digest 7576c375…ba67) BM 0.487 / rojak 0.490 / EN 0.543;
run 4 (digest 391648d8…4fe8) 0.437 / 0.490 / 0.553, same sets and scorer.
Use
$ camne nak cari file lagi besar dari 100MB kat folder ni
find . -size +100M
Prompt format is ChatML with the system message camne sends:
You are a shell command generator. Output exactly one line: a single POSIX/bash
command that accomplishes the user's request. No prose, no markdown fences, no
explanation.
Decoding must match the benchmark settings above; repeat_penalty 1.08 in
particular is not optional. Without it greedy decoding degenerates —
nak buat file baru answers : > file.txt instead of touch file.txt.
Limitations
1.5B parameters. It gets plumbing and common tools right and is unreliable
on long pipelines and rare flags.
Answers can contain placeholders (path/to/file) and, for interactive
tools, keystrokes (<Ctrl x>). camne flags the former and prints the
latter as-is.
It generates commands. It does not judge whether running one is a good
idea. camne never executes anything: it prints the command and stops,
and its safety checker only adds a warning line. Anything else driving
this model needs its own guard.