Text Classification
Transformers
Safetensors
English
qwen3_5_text
text-generation
system-one
typed-decisions
decision-model
calibrated-probabilities
knowledge-distillation
jev
noul
choice
score
lora
qwen3_5
dual-head
vllm
Eval Results (legacy)
Instructions to use autotrust/JEV with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use autotrust/JEV with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="autotrust/JEV")# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("autotrust/JEV") model = AutoModelForCausalLM.from_pretrained("autotrust/JEV", device_map="auto") - Notebooks
- Google Colab
- Kaggle
| #!/usr/bin/env python3 | |
| """Build a vLLM-servable decision adapter for a dual-head bundle. | |
| The 24-slot fp32 decision head (W, b) is expressed as an lm_head LoRA: | |
| lm_head'[v_i] = lm_head[v_i] + ΔW_i, ΔW_i = W_i - lm_head[v_i] (only the 24 verbalizer rows change) | |
| so ΔW has rank <= 24 and is written as lora_A = ΔW (24 rows, zero-padded), lora_B = one-hot(v_i) / scaling. | |
| With the adapter active, the logit of verbalizer v_i is exactly W_i·h. The bias b and the per-kind temperature are | |
| applied client-side: p = softmax_active((logprob_i + b_i) / T) — the log-softmax normaliser cancels. | |
| The backbone LoRA (r=16) is zero-padded to the common rank (default 32) with alpha scaled so B·A·alpha/r is unchanged. | |
| python3 scripts/build_vllm_adapter.py --bundle exports/jev-judge-qwen35-9b-v0.8 | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import glob | |
| import json | |
| import os | |
| import torch | |
| from safetensors import safe_open | |
| from safetensors.torch import load_file, save_file | |
| def main() -> None: | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--bundle", required=True) | |
| ap.add_argument("--rank", type=int, default=32) | |
| ap.add_argument("--out", default=None, help="default: <bundle>/adapter_vllm") | |
| ap.add_argument("--dtype", choices=["bfloat16", "float32"], default="bfloat16", | |
| help="storage dtype (vLLM computes LoRA in the model dtype, bf16, anyway)") | |
| args = ap.parse_args() | |
| out = args.out or os.path.join(args.bundle, "adapter_vllm") | |
| src = os.path.join(args.bundle, "adapter") | |
| cfg = json.load(open(os.path.join(src, "adapter_config.json"))) | |
| jc = json.load(open(os.path.join(args.bundle, "judge_config.json"))) | |
| r0, a0 = cfg["r"], cfg["lora_alpha"] | |
| R = args.rank | |
| if R < max(r0, jc["slots"]["num_slots"]): | |
| raise SystemExit("rank must be >= max(backbone r, 24)") | |
| scaling = a0 / r0 | |
| alpha = scaling * R # keep alpha/r identical after padding | |
| sd = load_file(os.path.join(src, "adapter_model.safetensors")) | |
| new: dict[str, torch.Tensor] = {} | |
| for k, t in sd.items(): | |
| t = t.to(torch.float32) | |
| if ".lora_A." in k: | |
| new[k] = torch.cat([t, torch.zeros(R - t.shape[0], t.shape[1])], 0) | |
| elif ".lora_B." in k: | |
| new[k] = torch.cat([t, torch.zeros(t.shape[0], R - t.shape[1])], 1) | |
| else: | |
| new[k] = t | |
| # lm_head rows of the pristine base (shipped in the bundle) | |
| lm = None | |
| for sh in sorted(glob.glob(os.path.join(args.bundle, "model-*.safetensors"))): | |
| with safe_open(sh, "pt", "cpu") as f: | |
| if "lm_head.weight" in f.keys(): | |
| lm = f.get_tensor("lm_head.weight") | |
| break | |
| if lm is None: | |
| raise SystemExit("bundle has no lm_head.weight (export with --mode unmerged / --include-lm-head)") | |
| head = load_file(os.path.join(args.bundle, "head.safetensors")) | |
| W = head["proj.weight"].to(torch.float32) | |
| ids = torch.as_tensor(jc["verbalizer_ids"]) | |
| dW = W - lm[ids].to(torch.float32) | |
| V, H = lm.shape | |
| A = torch.zeros(R, H) | |
| A[: len(ids)] = dW | |
| B = torch.zeros(V, R) | |
| B[ids, torch.arange(len(ids))] = 1.0 / scaling | |
| new["base_model.model.lm_head.lora_A.weight"] = A | |
| new["base_model.model.lm_head.lora_B.weight"] = B | |
| os.makedirs(out, exist_ok=True) | |
| dt = torch.bfloat16 if args.dtype == "bfloat16" else torch.float32 | |
| save_file({k: v.to(dt).contiguous() for k, v in new.items()}, os.path.join(out, "adapter_model.safetensors")) | |
| cfg2 = dict(cfg) | |
| cfg2.update({"r": R, "lora_alpha": alpha, "lora_dropout": 0.0, | |
| "target_modules": sorted(set(cfg["target_modules"]) | {"lm_head"}), | |
| "base_model_name_or_path": None}) | |
| json.dump(cfg2, open(os.path.join(out, "adapter_config.json"), "w"), indent=2) | |
| json.dump({"bias": head["proj.bias"].tolist(), "verbalizer_ids": jc["verbalizer_ids"], "slots": jc["slots"], | |
| "note": "decision logits = lm_head-LoRA logprobs of verbalizer ids + bias, then per-kind temperature"}, | |
| open(os.path.join(out, "decision_head.json"), "w"), indent=1) | |
| print(f"-> {out}: {len(new)} tensors, r={R}, alpha={alpha:g} (scaling {scaling:g}); lm_head ΔW rows {len(ids)}, " | |
| f"max|ΔW| {dW.abs().max():.4f}") | |
| if __name__ == "__main__": | |
| main() | |