Wisent 发布 Ster 0.14:Rust 原生激活引导与 LoRA 微调工具包
wisent-ai/ster
Wisent 发布 Ster 0.14,这是一个用 Rust 编写的原生工具包,可从指定 Transformer 层读取隐藏状态、用对比样本学习方向并在生成时施加激活引导,同时支持 LoRA 监督微调、DPO/IPO、Bradley-Terry 奖励模型和 GRPO。
Ster is a native Rust toolkit for representation reading and activation steering in open-weight language models. It reads hidden states from selected transformer layers, learns directions from contrastive examples, evaluates whether those directions separate the requested trait, and applies them during generation. It also trains the weights themselves: LoRA adapters under a supervised, a preference, a reward-modelling or a policy-gradient objective, and the tools to merge, score and inspect what comes out. And it reads decisions: typed questions about a state answered from one forward pass, with a probability for every option and no text generated.
The product is Ster. Wisent is the company that builds it.
Current product contract
Ster 0.14 provides one binary and one library crate. Both use the same versioned JSON artifacts and native Candle runtime.
Included now:
- local and Hugging Face checkpoints published as unquantized Safetensors
whose
model_typeisllama,mistral,mixtral,qwen2,qwen2_moe,qwen3,qwen3_moe,phi,phi3,granite,granitemoe,stablelm,starcoder2,cohere,cohere2,nemotron,olmo,olmo2,olmo3,olmoe,exaone4,internlm3,seed_oss,arcee,ernie4_5,minicpm,orion,glm,glm4,gpt_neox,gptj,gpt2,gpt_bigcode,opt,bloom,falcon,mpt,deepseek_v2,deepseek_v3(also insidekimi_k25),minicpm3,mamba,falcon_mamba,glm4_moe,internlm2,exaone,jamba,hunyuan_v1_dense,mamba2,bamba,gpt_oss,lfm2,ernie4_5_moe,dbrx,phimoe,hunyuan_v1_moe,telechat,lfm2_moe,granitemoehybrid,nemotron_h,jais2,bailing_moe,bailing_hybrid,sarvam_moe,sarvam_mla,cohere2_moe,deepseek,ministral3(also insidemistral3),llama4_text(also insidellama4),qwen3_5_textandqwen3_5_moe_text(also insideqwen3_5andqwen3_5_moe),afmoe,nemotron_h_puzzle,chatglm,laguna,longcat_flash_ngram(also a config that names onlyLongcatFlashNgramForCausalLM),muse_glimmer_text(also insidemuse_glimmer),plamo3,hrm_text,inkling_text(also insideinkling_mm_model),deepseek_v4,glm5_next_text(also insideglm5_next),hy_v4(in its release tensor names or Transformers'),dots3_note(sparse-indexed latent attention on itsfull_attentionlayers, its own narrower latent attention throughsliding_window_sizeon itssliding_attentionlayers, both withk_rope_only_layernorm,apply_mla_qkv_lora_rescaleand a headwiseg_projgate; the image and audio towers are never mapped),minimax_m3_vl_text(insideminimax_m3_vlbelowlanguage_model, or a config that names onlyMiniMaxM3SparseForCausalLM: every feed-forward is SwiGLU-OAI clamped byswiglu_limitwith the gate sharpnessswiglu_alpha, every norm is Gemma's, and thesparse_attention_freqlayers run MiniMax Sparse Attention, each key-value group attending only thesparse_topk_blocksblocks ofsparse_block_sizekeys its block indexer ranks highest, its own andsparse_local_blocklocal blocks among them; the vision tower is never mapped),TeleFLM,falcon_h1,qwen3_next,kimi_linear(also insidekimi_k3),minimax_m2,minimax_text_01(orminimax),zamba2,step3_text(also insidestep3_vl),step3p5,k2_horizon,longcat_flash,mimo,mimo_v2_flash,mimo_v2,mellum,flex_olmo,granite_swa,granitemoe_swa,granitemoeshared,glm4_moe_lite,glm_moe_dsa,deepseek_v32,axk1,iquestcoder,iquestloopcoder,hyperclovax(also insidehyperclovax_vision_v2),apertus,exaone_moe,solar,step1,telechat3,param2moe,PanguEmbedded,pangu_ultra_moe,olmo_hybrid,hy_v3,nanbeige,nemotron-nas,smollm3,gemma,gemma2,vaultgemma,gemma3_text,gemma3n_text(also insidegemma3n),gemma4_textorgemma4_unified_text(also insidegemma4andgemma4_unified), with the rotation read fromrope_thetaandrope_scalingor from Transformers 5'srope_parameters. OLMo, OLMoE and DBRX clamp every query, key and value component toclip_qkv; PhiMoE routes two experts per token by SparseMixer. GPT-OSS adds a learned sink logit per head to every attention softmax and routes over biased experts with a clamped gate (swiglu_limit); OpenAI's own checkpoints are MXFP4-quantized and refused, their BF16 exports load. LFM2 replaces attention on most layers with a gated short convolution (conv.in_projtoB,C,x; a causal depthwiseconvoverB·xspanningconv_L_cachepositions;Ctimes its output;conv.out_proj) and keeps attention with per-head norms onfull_attn_idxs; adapter training on it is refused. Coverage is measured against vLLM's list of text-only architectures; every architecture on it that Ster does not load is tracked with what the decoder lacks for it. Mamba and Falcon-Mamba replace attention with a selective state-space mixer (in_proj, a causal depthwiseconv1d,x_proj,dt_proj,A_log,D,out_proj, scanned token by token and carried between decode steps); Jamba interleaves that mixer, with weighted norms on its step and matrices, with position-free attention, and gives every layer a feed-forward, routed on its expert layers. Mamba-2 uses the structured multi-head mixer (in_projto gate, stream,B,Cand a step per head,conv1d,dt_bias,A_log,D, a gated RMSnormper group,out_proj), and Bamba interleaves it with attention onattn_layer_indicesand a feed-forward after every layer. Configs written with Python'sInfinity,-InfinityorNaNare read with those as unstated. These state-space models are steered like any other model, and adapter training on them is refused because their state-space layers have no attention or feed-forward projection. Gemma 3's image-text checkpoints (model_typegemma3) load as theirtext_configlanguage model, read from belowlanguage_model; the vision tower is never mapped. Every other family is a rotary, grouped-query decoder with what its config adds read from the config itself: a statedhead_dim(attention wider or narrower than the residual stream), RMS or LayerNorm norms (with a bias for StableLM, Starcoder2, Phi-2, Nemotron and Orion, without for Cohere, with neither scale nor bias for OLMo 1, offset from one for Gemma and Nemotron), query and key norms per head (Qwen3, Gemma 3, Cohere'suse_qk_norm, StableLM'sqk_layernorm) or over the whole projection (OLMo 2 and 3, OLMoE), projection bias (attention_bias,use_qkv_bias,use_bias,mlp_bias, Phi-2's biased head), a gated feed-forward, a plain one (Starcoder2'sc_fcandc_proj, Phi-2'sfc1andfc2, Nemotron's squared ReLU) or a mixture of experts (Mixtral, Qwen2-MoE with its gated shared expert, Qwen3-MoE, OLMoE, GraniteMoE, DeepSeek with its shared experts, sigmoid scores, group-limited routing ande_score_correction_bias: a router picksnum_experts_per_tokexperts per token, renormalised when the family does, with Qwen'smlp_only_layersanddecoder_sparse_stepand DeepSeek'sfirst_k_dense_replacelayers kept dense), DeepSeek's and MiniCPM3's multi-head latent attention (low-rank query and key-value bottlenecks, a rotated key part shared by every head, values narrower than queries), sequential or parallel blocks (Cohere, Phi-2, StableLM'suse_parallel_residual), sliding-window attention on the layerssliding_window,max_window_layers,sliding_window_patternorlayer_typesname, Phi-3's fusedqkv_projandgate_up_proj, GLM's fusedgate_up_proj, GPT-2's, GPT-BigCode's and MPT's stackedc_attn/Wqkvand GPT-NeoX's, BLOOM's and Falcon'squery_key_valuegrouped by key-value head (split at load, and merged back row by row byster tune merge), GPT-2'sConv1Dweights stored inputs-first, positions as rotation, a learned table (GPT-2, GPT-BigCode, OPT, MPT without ALiBi) or ALiBi (BLOOM, MPT, Falcon'salibi), BLOOM's norm after the embedding, Falcon's new decoder architecture withln_attnandln_mlp, each family's own tensor paths (GPT-NeoX'sgpt_neox.layersandembed_out, GPT-J's and GPT-2'stransformer.h, OPT'smodel.decoder.layers, checkpoints saved without that root), parallel blocks with one norm or two, OLMo 2's and EXAONE 4's norms after each sublayer instead of before it, GLM-4'spost_self_attn_layernormandpost_mlp_layernorm, Granite's and MiniCPM's embedding, residual and logit multipliers, Granite's attention multiplier, Cohere'slogit_scale, interleaved rotation (Cohere, GLM, ERNIE 4.5, GPT-J), unrotated layers (SmolLM3'sno_rope_layers, Cohere 2's global layers), rotation of only part of each head (partial_rotary_factor, GPT-NeoX'srotary_pct, GPT-J'srotary_dim), GPT-style key names (n_embd,n_layer,n_head,n_positions,n_inner,rotary_emb_base),linearrotary scaling and Phi-3'slongrope(short factors within the original context, long ones past it), YaRN (rope_scalingof typeyarn, with DeepSeek'smscale_all_dimsharpening the scores), and Gemma's1 + weightnorms, scaled embedding, tanh GELU gate and tied embeddings, plus Gemma 2's and 3's post-attention and post-feed-forward norms,query_pre_attn_scalarand logit soft-capping, and Gemma 3's separaterope_local_base_freqon sliding-window layers. A quantized checkpoint (one that declaresquantization_config, such as GPTQ) is refused with the sentence that names it, as is a config whosehidden_act(oractivation_function) is not silu, gelu, gelu_pytorch_tanh, gelu_new, gelu_fast, relu or relu2, that rotates an odd or empty share of each head, whoserope_scalingis notllama3,linear, Phi-3'slongrope,yarnor HunYuan'sdynamicwith analpha(a fixed base ofrope_theta * alpha^(d / (d - 2))), or that asks for a variant the decoder does not implement (GPT-2'sscale_attn_by_inverse_layer_idx, OPT's post-normdo_layer_norm_before: falseorword_embed_proj_dim, BLOOM'sapply_residual_connection_post_layernorm). Adapter targets a family has no projection for (the gate of a plain feed-forward, every feed-forward projection of a mixture of experts, the key, value and bottlenecked query of latent attention, anything on a state-space model) are refused before any adapter is built; - CPU execution, with compile-time Metal and CUDA backends;
- pair-set authoring and inspection for duplicates, length balance and diversity, with no model loaded;
- synthetic pair generation from a trait description, written either by the local runtime or by a hosted model reached through Brama, with every answer judged for a refusal by the model that wrote it;
- last-token hidden-state extraction from any selected transformer layer;
- contrastive activation addition (
caa), principal-direction (pca), and logistic-probe training; - holdout selection across method and layer, published as the scored candidate table the choice was made on;
- artifact evaluation by pair-ordering accuracy and projection margin;
- additive residual-stream steering during autoregressive generation;
- LoRA supervised fine-tuning of local checkpoints from prompt and completion examples;
- direct preference optimization, and its IPO variant, over a contrastive pair set, scored against the frozen reference the same weights already carry;
- Bradley-Terry reward models: a scalar head trained with the adapters beneath it and written in the same artifact;
- group-relative policy optimization against a reward model or an offline deterministic reward, with a KL penalty to the frozen base;
- merging an adapter into the base weights as a standalone checkpoint;
- frozen adapter artifacts applied at generation time;
- deterministic JSON pair, activation, steering, and evaluation formats.
- typed decisions — a choice from named options, a score on ordered levels, or a yes/no — read from the next-token distribution over answer letters after one cached pass over the state, every option shown under every letter so the model's letter preference cancels, in TypeSafe's System One request and answer shapes;
- temperature calibration of those decisions on labelled examples, reported with negative log-likelihood, expected calibration error, accuracy, and a shuffled-state control;
Explicit boundaries:
- The native runtime implements the decoder families above and no others.
A config naming any other
model_type— an encoder-decoder such as T5 among them, since every family above is one decoder stack — fails before weights are loaded rather than silently running a wrong decoder. - Ster controls local open-weight models. Hosted model routing belongs to Brama.
- Steering reads hidden states, so it always runs on a local open-weight model.
Writing pair text needs no activations, so
ster pairs synthesizemay take its generator from Brama instead. Ster holds no provider credential and speaks no provider API: it calls the gateway, which owns the routing. - Fine-tuning trains low-rank adapters, and on a reward run the scalar head that reads them. It trains nothing else: the base weights are mapped read-only and 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 and no fleet placement. Ster does not place work on another machine, and nothing places Ster: it trains on the machine you start it on.
- No objective consults a hosted model.
ster tune grpotakes its reward from a reward model you trained or from a deterministic function of the completion; there is no judge model and no LLM-as-critic wired into any gradient. - Ster does not place work on a fleet, and manages no credentials: it has no
credential store, no credential lifecycle, and reads what it needs from the
environment it was started in. Neither responsibility is delegated to another
product. The compute registry declares no Ster placement profile, no Ster OS
unit, and no Ster workload;
stado fleet listplaces Ster nowhere; and Skarbiec has no record of Ster in its source, README or documentation. If you need a run on a bigger machine, you start Ster on that machine yourself. - Release delivery is the one thing another product does do for Ster: Stado
installs the built binary from the
.wisent-release.jsonthis repository ships. See Installing through Stado. - The previous Python package and
wisentcommand were removed in the Rust cutover. Python namespace compatibility is not part of the Ster contract.
Install
Install the current source release from GitHub:
cargo install --git https://github.com/wisent-ai/ster --locked
From this source checkout:
cargo install --path . --lockedMetal and CUDA are build-time choices:
cargo install --git https://github.com/wisent-ai/ster --features metal --locked cargo install --git https://github.com/wisent-ai/ster --features cuda --locked
The crates.io name ster is currently unclaimed and is not Ster's release
surface. pip install ster installs unrelated software from another publisher.
Delivery through Stado and the checkpoint cache are covered in installing and where downloads land.
First steering workflow
From a pair set to a steered generation — importing or writing the set, adding, synthesizing, importing and inspecting pairs, training a direction and generating with it — is walked through in the first steering workflow.
CLI
Every command, what the Python wisent CLI called it, and the guide of each
command family are listed in the CLI overview. Run
ster <command> --help for exact arguments; every answer is one JSON document
on stdout, and the global --text flag prints it as path: value lines.
Architecture
The runtime uses Candle directly. Ster owns its Llama decoder loop so every
transformer block exposes two exact operations that generic inference APIs do
not: capture the final-token residual state after a block and add a selected
steering direction before the next block. The same decoder can also run a
differentiable pass, which is what makes fine-tuning possible at all: Candle's
fused rotary_emb::rope, ops::softmax_last_dim, and ops::rms_norm kernels
have no backward pass, so training selects composed equivalents at exactly those
three call sites while inference keeps the fused ones. The same pass also
chooses whether the attached adapters apply, which is what lets preference
optimization score the frozen reference without a second copy of the weights.
Tokenization, Safetensors loading, attention, KV caching, sampling, and device
kernels remain native Rust.
Documentation and support
- Product documentation: https://ster.wisent.com/docs
- Source and defects: https://github.com/wisent-ai/ster
- Community: https://discord.gg/qRjpkthq54
- Private vulnerabilities: GitHub Security Advisories for this repository
Ster is pre-1.0. Artifact schema changes and supported-model expansion remain subject to the repository's versioned release contract.
License
MIT — see LICENSE.
来源:GitHub · github.com
