Text Generation
Transformers
Safetensors
English
lfm2
linux
bash
shell
command-generation
conversational
Instructions to use thealper2/lfm2-700m-linux-command with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use thealper2/lfm2-700m-linux-command with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="thealper2/lfm2-700m-linux-command") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# pip install -U transformers accelerate # Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("thealper2/lfm2-700m-linux-command") model = AutoModelForCausalLM.from_pretrained("thealper2/lfm2-700m-linux-command", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=256) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use thealper2/lfm2-700m-linux-command with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "thealper2/lfm2-700m-linux-command" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "thealper2/lfm2-700m-linux-command", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/thealper2/lfm2-700m-linux-command
- SGLang
How to use thealper2/lfm2-700m-linux-command with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "thealper2/lfm2-700m-linux-command" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "thealper2/lfm2-700m-linux-command", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "thealper2/lfm2-700m-linux-command" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "thealper2/lfm2-700m-linux-command", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use thealper2/lfm2-700m-linux-command with Docker Model Runner:
docker model run hf.co/thealper2/lfm2-700m-linux-command
|
Download README.md from thealper2/lfm2-700m-linux-command: direct link, hf CLI and curl.
- Browser
- Download file 8.87 kB
-
https://huggingface.co/thealper2/lfm2-700m-linux-command/resolve/main/README.md
- Command line
-
hf download hf://thealper2/lfm2-700m-linux-command/README.md
-
curl -L -o README.md https://huggingface.co/thealper2/lfm2-700m-linux-command/resolve/main/README.md
8.87 kB
| base_model: LiquidAI/LFM2-700M | |
| library_name: transformers | |
| pipeline_tag: text-generation | |
| license: other | |
| license_name: lfm1.0 | |
| license_link: https://huggingface.co/LiquidAI/LFM2-700M/blob/main/LICENSE | |
| language: | |
| - en | |
| tags: | |
| - lfm2 | |
| - linux | |
| - bash | |
| - shell | |
| - command-generation | |
| - text-generation | |
| datasets: | |
| - jiacheng-ye/nl2bash | |
| - mecha-org/linux-command-dataset | |
| # thealper2/lfm2-700m-linux-command | |
| LiquidAI/LFM2-700M fine-tuned to map a natural-language Linux task to a single shell | |
| command. The target output is the command only; no explanation is produced. | |
| ## Model details | |
| | Field | Value | | |
| | --- | --- | | |
| | Base model | LiquidAI/LFM2-700M | | |
| | Architecture | `Lfm2ForCausalLM` β hybrid, 16 layers: full attention at `[2, 5, 8, 10, 12, 14]`, gated short convolution elsewhere | | |
| | Parameters | 742,489,344 total (641,826,048 non-embedding) | | |
| | Hidden size / heads / KV heads | 1536 / 24 / 8 | | |
| | Vocabulary | 65,536 | | |
| | Context length (base) | 128,000 | | |
| | Training precision | bfloat16 | | |
| | Fine-tuning method | full | | |
| | Task | NL instruction β shell command | | |
| ## Prompt format | |
| The model uses the LFM2 ChatML-style chat template and was trained with no | |
| system prompt. Apply the template rather than constructing the string manually. | |
| ``` | |
| <|startoftext|><|im_start|>user | |
| Find which process is using port 8080.<|im_end|> | |
| <|im_start|>assistant | |
| lsof -i :8080<|im_end|> | |
| ``` | |
| Two LFM2 tokenizer details matter: | |
| - The chat template emits `bos_token` itself and `add_bos_token` is `true` in | |
| `tokenizer_config.json`. Tokenise templated text with | |
| `add_special_tokens=False`, or the sequence gets a duplicated BOS. | |
| - Decode with `clean_up_tokenization_spaces=False`; the BPE cleanup step strips | |
| spaces around punctuation and can corrupt shell commands. | |
| Special tokens: BOS `<|startoftext|>` (1), EOS `<|im_end|>` (7), PAD `<|pad|>` (0). | |
| ## Usage | |
| ```python | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| model_id = "thealper2/lfm2-700m-linux-command" | |
| tokenizer = AutoTokenizer.from_pretrained(model_id, clean_up_tokenization_spaces=False) | |
| model = AutoModelForCausalLM.from_pretrained(model_id, dtype=torch.bfloat16).to("cuda").eval() | |
| messages = [{"role": "user", "content": "Find which process is using port 8080."}] | |
| prompt = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False) | |
| inputs = tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to(model.device) | |
| output = model.generate( | |
| **inputs, | |
| max_new_tokens=128, | |
| do_sample=False, # deterministic decoding | |
| eos_token_id=tokenizer.eos_token_id, | |
| pad_token_id=tokenizer.pad_token_id, | |
| ) | |
| command = tokenizer.decode(output[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True).strip() | |
| print(command) # lsof -i :8080 | |
| ``` | |
| Greedy decoding (`do_sample=False`) is the intended configuration: the task has a | |
| single intended answer and sampling only adds variance. | |
| ## Training data | |
| | Source | Raw rows | Schema | | |
| | --- | --- | --- | | |
| | [`jiacheng-ye/nl2bash`](https://huggingface.co/datasets/jiacheng-ye/nl2bash) | 9,305 | `nl`, `bash` | | |
| | [`mecha-org/linux-command-dataset`](https://huggingface.co/datasets/mecha-org/linux-command-dataset) | 8,669 | `input`, `output` | | |
| Both were normalised to `{instruction, command, source}` and then: | |
| 1. **Cleaned** β markdown fences and `$`/`#` prompt prefixes stripped, whitespace | |
| runs collapsed outside quoted strings, records with unbalanced quotes, prose | |
| instead of a command, or no parseable utility dropped. Commands themselves | |
| were never rewritten. | |
| 2. **Deduplicated** β exact `(instruction, command)` duplicates removed. Rows | |
| sharing a command with a different instruction, or an instruction with a | |
| different valid command, were kept deliberately. | |
| 3. **Balanced** β `find` was 35.2% of the raw corpus. It was capped per-utility | |
| using a diversity-aware ordering that retains every distinct flag signature | |
| before retaining any repeat, lowering its share to ~19%. | |
| 4. **Split** β 90/5/5, grouped by instruction *template* (filenames, paths, | |
| numbers and quoted literals abstracted) so templated paraphrases cannot | |
| straddle the train/test boundary. | |
| Split sizes: 11756 train / 652 validation / 653 test. | |
| Leakage checks report zero overlap across splits at the exact-pair, | |
| instruction and instruction-template level. | |
| ## Training configuration | |
| | Hyper-parameter | Value | | |
| | --- | --- | | |
| | Method | full | | |
| | Epochs | 3 | | |
| | Learning rate | 3e-05 | | |
| | Scheduler | cosine | | |
| | Warmup ratio | 0.03 | | |
| | Weight decay | 0.01 | | |
| | Optimizer | adamw_torch_fused | | |
| | Per-device batch size | 16 | | |
| | Gradient accumulation | 2 | | |
| | Max sequence length | 128 | | |
| | Precision | bfloat16 | | |
| | Seed | 42 | | |
| Loss is computed on the assistant turn only; prompt tokens are masked with | |
| `-100`. | |
| `max_length` was chosen from the tokenised length distribution of the corpus | |
| (mean 37.7, median 34, p90 57, p95 66, p99 87, max 403) β a 128-token budget | |
| covers 99.94% of examples. | |
| ### Run record | |
| | Field | Value | | |
| | --- | --- | | |
| | Final training loss | 0.516 | | |
| | Validation loss | 0.6445 | | |
| | Training time | 425.0 s | | |
| | Peak VRAM | 8.95 GB | | |
| | GPU | NVIDIA GeForce RTX 5060 Ti | | |
| | torch / transformers | 2.11.0+cu128 / 5.17.0 | | |
| ## Evaluation | |
| Measured on the held-out test set with greedy decoding. | |
| | Metric | Base LFM2-700M | Fine-tuned | Delta | | |
| | --- | --- | --- | --- | | |
| | Exact match | 0.0061 | 0.2910 | +0.2849 | | |
| | Normalised exact match | 0.0061 | 0.2910 | +0.2849 | | |
| | Structural match | 0.0107 | 0.3032 | +0.2925 | | |
| | Command validity | 0.4763 | 0.9939 | +0.5176 | | |
| | Token F1 | 0.1195 | 0.6470 | +0.5275 | | |
| | Primary-utility accuracy | 0.1807 | 0.8377 | +0.6570 | | |
| | Prose-output rate | 0.3783 | 0.0000 | -0.3783 | | |
| Metric definitions: | |
| - **Exact match** β string equality after stripping surrounding whitespace. | |
| - **Normalised exact match** β equality after collapsing whitespace runs outside | |
| quotes and removing a trailing `;`. | |
| - **Structural match** β utility, flag multiset (short-flag bundles expanded for | |
| utilities that use them) and operand sequence compared per pipeline segment. | |
| Recognises `ls -la` == `ls -al`. | |
| - **Command validity** β the output parses under a bash grammar parser | |
| (`bashlex`), not membership in a list of known utilities. | |
| - **Token F1** β token-level overlap, as partial credit. | |
| - **Primary-utility accuracy** β the first utility matches the reference. | |
| - **Prose-output rate** β fraction of outputs that read as an explanation rather | |
| than a command. | |
| ## Limitations | |
| - **Structural match is not a semantic oracle.** It compares command *shape*. It | |
| cannot tell that `find . -name '*.py'` and a shell glob achieve the same | |
| result, and it does not reason about flag semantics. It is an upper bound on | |
| exact match, not semantic accuracy. | |
| - **Exact match understates correctness.** Many Linux tasks have several valid | |
| answers; the test set carries one reference each. | |
| - **Source-distribution bias.** `nl2bash` is `find`-heavy and composition-heavy; | |
| `mecha-org/linux-command-dataset` is templated and single-utility-heavy. | |
| Per-source metrics differ and are reported separately in the project reports. | |
| - **Distribution shift.** Commands reference paths, hosts and variables that | |
| appear in the training corpora (`/path/to/...`, `$source`). Outputs may embed | |
| those placeholders instead of the user's real paths. | |
| - **Short outputs only.** Trained at a 128-token budget; long multi-stage scripts | |
| are out of distribution. | |
| - **No verification of correctness or safety at generation time.** The model can | |
| produce syntactically valid but wrong β or destructive β commands. | |
| ## Intended use and safety | |
| Intended for generating candidate shell commands for review, and as the command | |
| generator of a sandboxed terminal agent. | |
| **Do not execute generated commands directly on a host.** The project this model | |
| comes from executes commands only inside a disposable Docker container started | |
| with `--network none`, `--read-only`, `--cap-drop ALL`, | |
| `--security-opt no-new-privileges`, a non-root user, no host bind mounts, | |
| bounded CPU/memory/PIDs and a wall-clock timeout, and screens commands against a | |
| destructive-pattern list and a read-only allowlist before running them. | |
| ## License | |
| Inherits the LFM Open License v1.0 of the base model, LiquidAI/LFM2-700M. Dataset | |
| licenses apply to the training data: `mecha-org/linux-command-dataset` is | |
| Apache-2.0; `nl2bash` derives from the | |
| [TellinaTool/nl2bash](https://github.com/TellinaTool/nl2bash) corpus. | |
| ## Citation | |
| The NL2Bash corpus: | |
| ```bibtex | |
| @inproceedings{LinWZE2018:NL2Bash, | |
| author = {Xi Victoria Lin and Chenglong Wang and Luke Zettlemoyer and Michael D. Ernst}, | |
| title = {NL2Bash: A Corpus and Semantic Parser for Natural Language Interface to the Linux Operating System}, | |
| booktitle = {LREC 2018}, | |
| year = {2018} | |
| } | |
| ``` | |