Text Generation
PEFT
TensorBoard
Safetensors
GGUF
English
lora
mistral
agent
posix
shell
self-directed
sek
experimental
conversational
Instructions to use tiararodney/Mistral-7B-Teletype with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use tiararodney/Mistral-7B-Teletype with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("mistralai/Mistral-7B-Instruct-v0.2") model = PeftModel.from_pretrained(base_model, "tiararodney/Mistral-7B-Teletype") - Notebooks
- Google Colab
- Kaggle
| base_model: mistralai/Mistral-7B-Instruct-v0.2 | |
| base_model_relation: adapter | |
| library_name: peft | |
| license: apache-2.0 | |
| language: | |
| - en | |
| pipeline_tag: text-generation | |
| datasets: | |
| - tiararodney/posix-sdc | |
| tags: | |
| - peft | |
| - lora | |
| - mistral | |
| - agent | |
| - posix | |
| - shell | |
| - self-directed | |
| - sek | |
| - experimental | |
| # Mistral-7B-Teletype | |
| A LoRA adapter that teaches **Mistral-7B-Instruct-v0.2** to operate a POSIX shell | |
| as a self-directed user. It lands in a session with no task in the prompt, finds | |
| its assignment in the environment, carries it out, and ends with `exit` or | |
| `panic`. The adapter installs an operating mechanism; it adds no world knowledge. | |
| > **This is not a tool-using model.** It is handed no typed API of functions to | |
| > call. It writes plain-text shell commands at a real prompt; its action space is | |
| > the entire system, discovered the way a person discovers it (`--help`, `man`, | |
| > `ls`), not given to it as a schema. | |
| > **Experimental research artifact.** This adapter installs a behavioural | |
| > *mechanism* (operate-and-terminate), not task competence, and the evaluation is | |
| > a small-n (16-scenario, two-archetype) signal, not a benchmark. Expect it to | |
| > operate reliably and terminate less reliably. Use it to study the paradigm, not | |
| > as a production agent. | |
| Trained on [`tiararodney/posix-sdc`](https://huggingface.co/datasets/tiararodney/posix-sdc) | |
| v2.0.0 (the gate-hardened release: 1003 verified, self-terminating shell | |
| trajectories whose labels come from a checker run against real filesystem state), | |
| via the [`sekft`](https://git.code.tiararodney.com/tiara/sekft) pipeline. It | |
| accompanies the experiment [*From seed to | |
| weights*](https://blog.tiararodney.com/projects/2026/semantic-execution-kernel/experiments/from-seed-to-weights/). | |
| This is an **adapter** (53 MB). The base model is referenced, not redistributed. | |
| ## The mechanism | |
| In every session, whatever tools are present, the model runs one routine: expect | |
| an announcement of where directives live (a motd, an env var, a file, a provider | |
| program's `--help`), read that provider's self-documentation, retrieve the | |
| directives, carry them out, and stop. | |
|  | |
| A session ends in one of two ways. `exit` means the work is done. `panic` means | |
| the model is genuinely blocked and says so instead of faking a success. Both are | |
| trained behaviours rather than a stop token or a step cap. | |
| ## The thesis (and how to falsify it) | |
| The claim this adapter is evidence for is that operate-and-terminate is a | |
| mechanism that is archetype-independent. Fine-tuning installs it so that it fires | |
| on task types never seen in training, even where task competence (solving a | |
| specific unseen task correctly) stays archetype-local. The adapter reliably gets a | |
| 7B to operate and stop; it does not by itself make a 7B solve arbitrary unseen | |
| tasks. | |
| One hypothesis for why the mechanism transfers: it builds on the base model's | |
| pretraining disposition that treats `exit` as a flat, ordinary ending and `panic` | |
| as the loaded one (see [*The flatness of | |
| exit*](https://blog.tiararodney.com/projects/2026/semantic-execution-kernel/notes/the-flatness-of-exit/)). | |
| The weight a base model inherits on its terminal tokens is then a measurable | |
| per-model property. | |
| That makes the thesis falsifiable, with concrete predictions: | |
| - operate_rate stays near 1.0 across more held-out archetypes, not just the two | |
| measured here. If it collapses on a new archetype, the mechanism was | |
| archetype-specific after all. | |
| - Reweighting or renaming the terminal token moves the honest-give-up rate. Frame | |
| the good ending as a reward and the model should reach for it prematurely; frame | |
| it as costly and it should refuse to leave. | |
| - Base models differ in how readily they acquire the mechanism, and should be | |
| rankable in advance by their inherited terminal-token weight. | |
| The result below is the first of these predictions holding up on its first test. | |
| ## How it was made | |
| The data is generated rather than scraped or hand-written. A teacher model authors | |
| each scenario world and an operator model works inside it; the verifier is code. A | |
| trajectory is kept only if a checker, run against the container's final filesystem | |
| state, confirms the effect is present and the session ended cleanly. The | |
| transcript and the model's own claims are never used as the label. | |
|  | |
| ## The render contract: train = serve | |
| The serving harness (ccpty) emits no text markers. It speaks the OpenAI | |
| chat-completions protocol and sends structured `{role, content}` messages | |
| (system orientation, environment output as `user`, the model's commands as | |
| `assistant`); the inference endpoint applies the model's own chat template. So | |
| this adapter is rendered with **Mistral-7B-Instruct-v0.2's default chat | |
| template**, and training renders the trajectories the identical way. Get this | |
| wrong and the prompts go out of distribution. | |
|  | |
| Mistral's built-in template covers `user` / `assistant` only and requires strict | |
| alternation, so each session is canonicalised the same way at train and serve | |
| time (`normalize_for_template`): the orientation is folded into the first user | |
| turn, and consecutive environment turns (login banner, prompt, command output) | |
| are merged into one user turn between commands. Only the assistant turns | |
| (commands plus the terminal `exit` / `panic`) carry loss; environment turns are | |
| context. | |
| ## Training | |
|  | |
| | | | | |
| |---|---| | |
| | base | `mistralai/Mistral-7B-Instruct-v0.2` (Apache-2.0) | | |
| | method | LoRA, fp16 (the V100's 32 GB holds the 7B in fp16, so no 4-bit) | | |
| | LoRA | r=16, alpha=32, dropout=0.05, target `q_proj k_proj v_proj o_proj` | | |
| | objective | causal LM, **assistant-only loss mask** (commands + terminal token; environment turns set to -100) | | |
| | schedule | 3 epochs, lr 2e-4, effective batch 8 (bsz 1 x accum 8), warmup 0.03, max len 4096 | | |
| | data | `tiararodney/posix-sdc` v2.0.0 (`--corpus-version latest`), 1003 trajectories, 996 usable (held-out archetypes excluded from the corpus) | | |
| | hardware | single NVIDIA Tesla V100 32 GB (sm_70, fp16 only); ~31 min | | |
| Training loss fell to ~0.19 over the three epochs (16.7% of tokens trained, the | |
| assistant commands and terminal token; the rest is masked context). Computing the | |
| loss only on the assistant turns is standard SFT practice, and here it carries the | |
| whole thing: feed the environment turns into the loss and the model learns to | |
| hallucinate command output instead of producing commands. | |
| ## Evaluation: held-out generalization | |
| The metric that matters is behavioural, and held out by whole archetype. Two task | |
| types (`text_replace`, `permissions`) are excluded from training entirely; the | |
| adapter is then dropped into them with **no scaffold**, and a checker grades the | |
| final filesystem state. | |
|  | |
| Decoding is greedy (temperature 0), the operator sees a bounded context (finite | |
| scrollback, 3072 tokens, so a wide command output cannot run the prompt off the | |
| rails), and each rollout has a 30-step budget. On 16 held-out scenarios (8 per | |
| archetype), base Mistral-7B against this adapter on the identical harness (same | |
| scenarios, only the adapter differing): | |
| | metric | base | adapter | | |
| |---|---|---| | |
| | operate_rate (reaches command-mode and drives the shell) | 0.00 | **1.00** | | |
| | terminate_rate (emits `exit` / `panic`) | 0.00 | **0.94** | | |
| | verified_rate (checker passes) | 0.13 | **0.94** | | |
| | clean (success or correct-panic) | **0 / 16** | **14 / 16** | | |
|  | |
| Reading it. `operate_rate 1.0` is the result that matters: dropped into two task | |
| types it never trained on, with no scaffold, the model discovered its assignment | |
| and drove the shell every time. The mechanism generalised. Task competence is | |
| high (14/16 clean). Of the two misses, one is an `incomplete` that was | |
| `verified=True` (the model did the task but never emitted `exit` and ran to the | |
| step cap), so effect-achieved is really 15/16 while clean-terminated is 14/16; | |
| that single gap is termination detection, not capability. The other is one | |
| `premature_exit`, the opposite failure, leaving before the work verified. | |
| The base control is measured on this exact setup (the same 16 scenarios, same | |
| bounded/greedy harness, no adapter): bare Mistral-7B is **0/16 clean** and | |
| terminates on **0 of 16**, running every scenario to the step cap. The adapter's | |
| 14/16 is therefore attributable to the fine-tune, not to latent base ability. A | |
| tell sits in `verified_rate`: the base satisfies the checker on 2/16 (both | |
| `permissions`, a one-line `chmod` that prose-contaminated output stumbles onto), | |
| so it occasionally does the work, yet it never types `exit` and its clean rate | |
| stays zero. Doing the task and knowing to verify-and-leave are separate skills, and | |
| the adapter installs the second. | |
| ### Where the lift came from (presumed) | |
| This release improves on the prior cut (clean 9/16 to 14/16), but several things | |
| changed at once and it did **not** ablate them, so read the attribution as | |
| presumed, not measured: | |
| - **Corpus.** Training moved from `posix-sdc` v1.2.2 (787) to the gate-hardened | |
| v2.0.0 (1003): more trajectories, and stricter generation gates that keep | |
| cleaner operate-and-terminate demonstrations. Presumed the largest factor. | |
| - **Decoding.** Evaluation is now greedy (temperature 0) where the prior run | |
| sampled at 0.7; greedy removes the sampling losses on an otherwise confident | |
| policy. | |
| - **Step budget + bounded context.** A 30-step budget (was lower) gives a | |
| wandering run more chances to find `exit`, and the finite-scrollback bound keeps | |
| a long transcript in distribution. | |
| - **Render unification (the deployability fix, orthogonal to the number).** Train | |
| and serve now share the base chat template, so the adapter operates in real | |
| deployment (ccpty / Ollama) instead of no-opping there. This is what makes the | |
| model *usable*; it is not the source of the held-out lift, the prior eval was | |
| already train/serve-consistent under its own (placeholder) render. | |
| ## Use with transformers + PEFT | |
| ```python | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| from peft import PeftModel | |
| BASE = "mistralai/Mistral-7B-Instruct-v0.2" | |
| tok = AutoTokenizer.from_pretrained(BASE) | |
| base = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype=torch.float16, | |
| device_map="auto") | |
| model = PeftModel.from_pretrained(base, "tiararodney/Mistral-7B-Teletype") | |
| model.eval() | |
| messages = [ | |
| {"role": "user", | |
| "content": "sek 0.1.0 host: sek user: alice shell: /bin/dash\n" | |
| "Welcome, alice. Your assignments live in ~/ASSIGNMENTS.\n" | |
| "alice@sek:~$ "}, | |
| ] | |
| prompt = tok.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| ids = tok(prompt, return_tensors="pt").to(model.device) | |
| out = model.generate(**ids, max_new_tokens=64, do_sample=False) | |
| print(tok.decode(out[0, ids.input_ids.shape[1]:], skip_special_tokens=True)) | |
| # -> the next command, e.g. `cat ~/ASSIGNMENTS` | |
| ``` | |
| Drive it in a loop: render history with the chat template, generate one command, | |
| run it in a real shell, append the output as a `user` turn, repeat until the | |
| model emits `exit` or `panic`. | |
| ## Use with Ollama | |
| The included `Modelfile` applies this adapter over the base as a GGUF LoRA and | |
| relies on the base's default chat template and EOS. The converted adapter, | |
| `teletype-lora-f16.gguf`, ships in this repo (regenerate it with llama.cpp | |
| `convert_lora_to_gguf.py` if you prefer), so just: | |
| ```sh | |
| ollama create teletype -f Modelfile | |
| ``` | |
| Mistral's registry base carries its `[INST]` template and stop tokens, so no base | |
| setup is needed (unlike EuroLLM-9B-Teletype, whose base GGUF does not). Sanity-check | |
| anyway: `ollama show teletype --modelfile` should list `PARAMETER stop`, and a | |
| one-line prompt should return a handful of tokens, not the full budget (a model | |
| with no stop rambles to the token cap every turn). | |
| ## Reproduction | |
| Everything needed is public. The dataset ships its own generator and the scenario | |
| worlds; this adapter and the config above do the rest. | |
| ```sh | |
| # train (pulls the gate-hardened v2.0.0 corpus from the Hub; held-out archetypes excluded) | |
| sekft-train --hub --corpus-version latest \ | |
| --base mistralai/Mistral-7B-Instruct-v0.2 --out ./ckpt --epochs 3 | |
| # evaluate behaviourally on held-out scenarios (greedy, finite-scrollback bound) | |
| sekft-eval --base mistralai/Mistral-7B-Instruct-v0.2 --adapter ./ckpt \ | |
| --scenarios ./holdout-scenarios --n 16 --temperature 0 \ | |
| --max-steps 30 --ctx-budget 3072 | |
| ``` | |
| The figures in `figures/` regenerate from their committed sources (`*.puml` via | |
| PlantUML, `*.gp` via gnuplot). | |
| ## Limitations | |
| - Small evaluation: n=16 held-out, two archetypes. The numbers are a signal, not | |
| a benchmark. | |
| - The base control is measured first-party on this exact setup (0/16 clean, 0/16 | |
| terminate), but it is still n=16, one greedy run. | |
| - Several variables changed from the prior release at once (corpus, decoding, step | |
| budget, render); the held-out lift is attributed by presumption, not ablation. | |
| - One base, one dataset, one teacher / operator. | |
| - Installs the mechanism, not competence. It reliably operates and terminates; it | |
| does not make a 7B solve arbitrary unseen task types correctly. | |
| - A termination-detection gap: some runs achieve the effect but fail to emit | |
| `exit` and run to the step cap. | |
| - Trained in `dash` on Alpine; command semantics may differ on another target. | |
| - Render must match train and serve. It is served with the base model's default | |
| chat template over the OpenAI protocol (via ccpty), so fine-tune with that same | |
| template (`apply_chat_template`), not a custom one, or behaviour degrades. | |
| - fp16 on a V100 (no bf16). | |
| ## License and citation | |
| The adapter weights are released under Apache-2.0, consistent with the base | |
| model. The training data (`posix-sdc`) is CC-BY-4.0; attribute "posix-sdc by | |
| Tiara Rodney" if you build on it. | |
| ```bibtex | |
| @misc{mistral-teletype, | |
| title = {Mistral-7B-Teletype: a self-directed shell-operation adapter for Mistral-7B}, | |
| author = {Rodney, Tiara}, | |
| year = {2026}, | |
| howpublished = {Hugging Face PEFT adapter, tiararodney/Mistral-7B-Teletype} | |
| } | |
| ``` | |