Downloads · 30 days
11
11% of all-time downloads
nadirclaw/cascade-verifier-v1
cascade-verifier-v1 is a text classification model from nadirclaw. Use it when you need a label for a piece of text. It is set up for transformers. The card lists the license as mit.
A fine-tuned DeBERTa-v3-small that scores whether a cheap LLM's answer to a prompt is good enough to ship. Used as the gating signal in Nadir's verifier-gated 2-tier cascade router.
Downloads · 30 days
11
11% of all-time downloads
All-time downloads
103
Public
Parameters
142M
1 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors568 MB · 56%
From the Hugging Face model README
A fine-tuned DeBERTa-v3-small that scores whether a cheap LLM's answer to a prompt is good enough to ship. Used as the gating signal in Nadir's verifier-gated 2-tier cascade router.
This is the frozen snapshot used to produce Nadir's RouterArena submission:
| Metric | Value |
|---|---|
| arena_F | 0.7358 |
| Accuracy | 0.7518 |
| Cost / 1k queries | $0.2986 |
| Rank | #1 (main split) |
| File | Size | Precision | Used for |
|---|---|---|---|
model.safetensors | ~541 MB | FP32 | Reference, fine-tuning |
verifier_int8.pt | ~418 MB | INT8 quantized | Production inference (CPU) |
The INT8 variant runs on CPU at ~10ms per (prompt, answer) pair on a modern laptop. That's what our production cascade at api.getnadir.com uses.
pip install nadirclaw[trained]
export NADIRCLAW_TIERS_PROFILE=n2_trained
NadirClaw wires the verifier into the full 2-tier cascade automatically. The default threshold is tau = 0.80 (escalate if the verifier scores the cheap answer below 0.80).
This is a sequence-pair classifier, not a single-text scorer. Pass the prompt as text and a structured cheap/expensive block as text_pair. The output is a softmax over 2 classes; the score is P(class=1) = "cheap answer is acceptable."
from transformers import AutoModelForSequenceClassification, AutoTokenizer
import torch
model = AutoModelForSequenceClassification.from_pretrained("nadirclaw/cascade-verifier-v1")
tokenizer = AutoTokenizer.from_pretrained("nadirclaw/cascade-verifier-v1")
model.eval()
prompt = "What is the capital of France?"
cheap_answer = "Paris is the capital of France."
reference_answer = "" # optional; empty string when running cheap-only
inputs = tokenizer(
text=prompt,
text_pair=f"CHEAP:\n{cheap_answer}\n\nEXPENSIVE:\n{reference_answer}",
truncation=True,
max_length=512,
return_tensors="pt",
)
with torch.no_grad():
logits = model(**inputs).logits[0]
probs = torch.softmax(logits, dim=-1)
score = float(probs[1]) # in [0, 1]; class 1 = "cheap is acceptable"
print(f"verifier_score = {score:.3f}")
Higher score means "this cheap answer is good enough." In our production cascade, scores below 0.80 trigger escalation to a stronger model.
For an INT8-quantized CPU build that matches production latency (~60 ms per call), apply dynamic quantization after loading:
torch.backends.quantized.engine = "qnnpack" # or "fbgemm" on x86
model = torch.quantization.quantize_dynamic(
model, {torch.nn.Linear}, dtype=torch.qint8
)
import torch
state = torch.load("verifier_int8.pt", map_location="cpu")
# state is a quantized DebertaV2ForSequenceClassification; load into the
# matching architecture per torch.ao.quantization conventions.
For the full INT8 loading flow including the dynamic quantization wrapper, see nadirclaw/trained_verifier.py in the NadirClaw repository.
This is a sequence-pair classifier. Two segments:
prompt.Segment B template:
CHEAP:
{cheap_answer}
EXPENSIVE:
{reference_answer}
When no reference answer is available (the default in our production cascade because the strong-tier model hasn't been called yet), pass an empty string for {reference_answer}. The verifier still produces a calibrated score; it's just more conservative without a reference.
Truncate the joined input to 512 tokens.
Output: softmax over 2 classes. Use P(class=1) as the acceptance score in [0, 1]. Threshold at tau = 0.80 to match the production deployment.
Production wrapper signature (in NadirClaw and the Pro backend):
verifier.score(prompt: str, cheap_answer: str, reference_answer: str | None = None) -> float
When reference_answer is None, the wrapper substitutes an empty string before tokenization.
microsoft/deberta-v3-small (6 layers, 768 hidden, 128k SentencePiece vocab){reject, accept})P(accept) = softmax probability of class 1torch.ao.quantization.quantize_dynamic on Linear layers onlytau = 0.80 (escalate if score < 0.80)(prompt, cheap, reference) call after first-call compileThe reproducible inference path is open. The build pipeline behind it is not:
These are the active value of Nadir Pro, which runs the same architecture but with a verifier that improves every week.
# 1. Clone the open-source router
pip install nadirclaw[trained]
# 2. Use the n2_trained profile (matches the submission)
export NADIRCLAW_TIERS_PROFILE=n2_trained
# 3. The router's wide_deep_asym_v3 classifier (bundled) + this verifier
# reproduces the routing decisions in the RouterArena prediction file.
Expect a reproducibility error bar of roughly ±0.005 vs the published 0.7358. The drift comes from local cache state (which cached model wins the cheapest-pick) and from verifier scoring against actual cheap responses vs the snapshot's proxy. Rank does not change inside that band.
model.safetensors) and INT8 (verifier_int8.pt) variants.training_args.bin deliberately excluded to avoid leaking training-environment paths and hyperparameters.Future updates will be released as cascade-verifier-v2, v3, ... rather than overwriting these weights. The v1 snapshot is permanent for reproducibility.
If you use this verifier in research, please cite:
@misc{nadir2026cascade,
title = {Verifier-Gated Cascade Routing for LLMs},
author = {Nadir Team},
year = {2026},
url = {https://github.com/NadirRouter/NadirClaw},
}
MIT. See the LICENSE file in the NadirClaw repository.