What is Ster
Ster is Wisent's native Rust toolkit for representation reading, activation steering, and post-training of open-weight decoder language models. One binary and one library crate (`ster` 0.13.0, Candle runtime, no Python) do two loops. The steering loop reads hidden states out of a transformer, learns a direction that separates a trait, judges whether the direction actually separates it, and adds that direction back into the residual stream while the model generates. The training loop fits LoRA adapters under four objectives — supervised on completions, preference on contrastive pairs, reward modelling with a scalar head, and a group-relative policy gradient against a reward — then merges, scores, or attaches what comes out (LoRA adapter). Both loops read the checkpoint's own conversation format when it publishes one, so an instruct model is fine-tuned and prompted in the shape it was post-trained in rather than as bare text ([chat template](/docs/concept-chat-template)).
Overview#
Ster is Wisent's native Rust toolkit for representation reading, activation steering, and post-training of open-weight decoder language models — the families it loads are listed on model resolution. One binary and one library crate (ster 0.13.0, Candle runtime, no Python) do two loops. The steering loop reads hidden states out of a transformer, learns a direction that separates a trait, judges whether the direction actually separates it, and adds that direction back into the residual stream while the model generates. The training loop fits LoRA adapters under four objectives — supervised on completions, preference on contrastive pairs, reward modelling with a scalar head, and a group-relative policy gradient against a reward — then merges, scores, or attaches what comes out (LoRA adapter). Both loops read the checkpoint's own conversation format when it publishes one, so an instruct model is fine-tuned and prompted in the shape it was post-trained in rather than as bare text (chat template).
Reading: activations out#
Ster owns its own decoder loop instead of using a generic inference API, because the loop needs one exact read: after each selected transformer block, the final-token residual state is copied out as an f32 vector of hidden_size width. That vector is the activation — the only representation Ster ever trains on. ster extract exposes the read directly, exporting activations for arbitrary prompts as a versioned JSON document; ster vector train, ster vector optimize, and ster vector evaluate use the same read internally, once per prompt per selected layer. All four encode the prompt through the checkpoint's own chat template by default, so a direction is fitted in the space it will be applied in (chat template). Models load from a local directory (config.json, tokenizer.json, Safetensors weights) or from the Hugging Face Hub, at f32 unless --precision says otherwise, on CPU by default. One loop serves every supported family, with what each one adds read from its own config.json; any other model_type is refused before weights are loaded. The families, and what each adds, are on model resolution.
Learning and judging: directions from contrast#
A trait is defined operationally, by a contrastive pair set: matched positive and negative prompts that differ in the trait. For each selected layer, Ster captures both sides' activations and trains a unit-length direction with one of three methods — caa (mean difference), pca (principal component of pairwise differences), or logistic (a linear probe). Every direction is immediately judged by the same two numbers: pair-ordering accuracy (fraction of pairs where the positive projects higher than the negative) and mean projection margin (evaluation). ster vector optimize runs the full grid — every method at every selected layer — on an 80/20 holdout, publishes what each candidate scored on it, and keeps the single best layer refitted on all pairs. The result is a steering artifact: a versioned JSON document that records the model identity, resolved revision, trait, method, hidden width, the precision and chat-template format the direction was fitted in, and the per-layer normalized vectors with their training scores.
Intervening: directions back in#
ster generate runs normal autoregressive generation, or steered generation when given an artifact: at each layer that has a vector, strength × vector is added to the residual stream after that block, on every forward step (intervention). Before anything is added, the artifact is gated: wrong schema, wrong product, wrong model string, wrong vector width, out-of-range layer, or a non-finite value each produce a one-sentence refusal instead of a wrong-model steering run. Desktop apps reach the same engine through ster request: one process per operation that reads a JSON body on stdin and prints each job's progress and result as NDJSON, reusing exactly the CLI's code paths (desktop request reference).
What Ster is not#
Ster steers, trains, and scores local open-weight models only, and hosted model routing belongs to Brama — including the one hosted call Ster itself can make, the optional pair writer behind ster pairs synthesize --generator brama. Ster never trains a full weight. The only tensors any objective creates are the low-rank adapter factors and, on a reward run, the scalar head that reads them — `ster tune merge` does write full weights, but it folds a finished adapter into them rather than training them. Training runs in one process: the base weights are never registered as trainable, one sequence goes through each forward pass with gradient accumulation standing in for a batch, and there is no distributed training. No objective consults a hosted model — ster tune grpo takes its reward from a reward model you trained or from a deterministic function of the completion, so there is no judge model wired into any gradient. The reward and policy loops are as local and as small as the rest of the product: same single process, same read-only base, same one sequence per forward, no training is hosted, and no gradient ever leaves this process. Ster does not place work on a fleet and manages no credentials, and neither responsibility is delegated to another product: the compute registry declares no Ster placement profile, OS unit or workload, and Skarbiec has no record of Ster at all. Release delivery is the one thing a neighbour does do — Stado installs the built binary from the repository's .wisent-release.json (install path). The runtime loads the families on model resolution and refuses other model_type values or unsupported checkpoint settings. That reference also states each family's adapter restrictions; loading or steering a family does not imply that every adapter target is supported. The earlier Python package and wisent command were removed in the Rust cutover; pip install ster installs unrelated software from another publisher. Ster keeps no daemon state, no database, and no configuration file — its only durable outputs are the documents it writes where you point it — JSON, plus the safetensors half of an adapter pair. Boundaries: architecture.
The first three commands#
ster vector train --model meta-llama/Llama-3.2-1B --pairs pairs.json \
--layers 12..20 --method caa --output truthful.ster.jsonOne direction per selected layer, trained from contrastive pairs, saved as a steering artifact; a training-score summary prints on stdout.
ster vector inspect truthful.ster.jsonValidate an artifact and summarize it — schema, product, model, width, precision, chat_template, and per layer the width, norm and training scores — without loading any model. The vectors stay in the file; on a twenty-two-layer checkpoint printing them means forty-five thousand floats down a terminal.
ster generate --model meta-llama/Llama-3.2-1B \
--vector truthful.ster.json --strength <S> \
--max-new-tokens <N> --temperature <T> --seed <SEED> \
--prompt "Explain the result and cite only evidence you can verify."Steered generation. Omit --vector for the unsteered baseline of the same prompt. The end-to-end path on a no-download toy checkpoint is quick-start.
The rest of the corpus#
- Nouns — contrastive pair, synthetic pairs, activation, direction, training method, layer selection, evaluation, steering artifact, intervention, model resolution, LoRA adapter, chat template, precision, reproducibility, differentiable pass, preference optimization, reward model, policy optimization.
- Reference — the full CLI, Rust library API, and the desktop request interface.
- Executed end to end — training and steering, runnable examples.
- When it refuses — every error sentence with meaning and fix: runbook.
- Boundaries and knobs — architecture, configuration.