vLLM Evaluation¶
CircuitKit supports fast downstream benchmark evaluation via vLLM, accessed through lm-evaluation-harness's native vLLM backend. CircuitKit does not reimplement or wrap vLLM — it writes a standard HuggingFace checkpoint and hands it to lm-eval, which handles the vLLM serving.
When to Use vLLM¶
Use vLLM at the benchmark evaluation stage (after pruning/quantization), not during circuit discovery or faithfulness evaluation.
| Stage | Tool | vLLM? |
|---|---|---|
| Circuit discovery | TransformerLens | No |
| 6-pillar faithfulness | TransformerLens | No |
Downstream benchmarks (boolq, etc.) |
lm-eval | Optional |
vLLM provides a speedup for throughput-bound benchmark evaluation. For GPT-2 scale, it is usually not worth the setup overhead. For Llama-3B / Gemma-4B at large sample counts, it can be 3–5× faster.
Installation¶
vLLM is not part of any CircuitKit extra:
See the vLLM installation guide for CUDA requirements.
Workflow¶
Step 1: Discover a circuit and save a pruned checkpoint¶
from circuitkit.api import discover_circuit
circuit = discover_circuit({
"model": {"name": "meta-llama/Llama-3.2-1B-Instruct"},
"discovery": {"algorithm": "eap-ig", "task": "boolq", "level": "node",
"data_params": {"num_examples": 128}},
"pruning": {"target_sparsity": 0.3, "scope": "heads"},
"output_path": "./circuit.pt",
})
Step 2: Export a pruned HuggingFace checkpoint¶
import circuitkit as ck
model = ck.load_model("meta-llama/Llama-3.2-1B-Instruct", dtype="bfloat16")
circuit = ck.load_scores("./circuit.pt")
pruned = ck.prune(model, circuit, sparsity=0.3, scope="heads")
ck.export_checkpoint(pruned, circuit, "./checkpoints/pruned")
Or, using save_pruned_checkpoint directly:
from circuitkit.evaluation.hf_checkpoint import save_pruned_checkpoint
save_pruned_checkpoint(model, circuit.nodes, "./checkpoints/pruned", overwrite=True)
Step 3: Evaluate with lm-eval + vLLM backend¶
from lm_eval import evaluator
from lm_eval.models.vllm_causallms import VLLM
lm = VLLM(
pretrained="./checkpoints/pruned",
tokenizer="meta-llama/Llama-3.2-1B-Instruct",
)
results = evaluator.simple_evaluate(model=lm, tasks=["boolq", "winogrande"])
print(results["results"])
The vLLM engine is a distinct model class (--model vllm on the CLI), not an HFLM option — HFLM's backend argument selects causal vs. seq2seq, not the inference engine.
CLI equivalent (lm-eval's own CLI):
lm_eval --model vllm \
--model_args pretrained=./checkpoints/pruned,tokenizer=meta-llama/Llama-3.2-1B-Instruct \
--tasks boolq,winogrande \
--num_fewshot 0
Without vLLM (Default HuggingFace Backend)¶
To run the same benchmark without vLLM — useful when vLLM is not available:
from lm_eval.models.huggingface import HFLM
hflm = HFLM(
pretrained="./checkpoints/pruned",
tokenizer="meta-llama/Llama-3.2-1B-Instruct",
)
results = evaluator.simple_evaluate(model=hflm, tasks=["boolq"])
Or via CircuitKit's own benchmark wrapper:
import circuitkit as ck
scores = ck.benchmark("./checkpoints/pruned", tasks=["boolq", "winogrande"], limit=100)
Memory Considerations¶
vLLM and TransformerLens can contend for GPU memory if held simultaneously. The recommended pattern (and what the example scripts do) is:
- Run discovery + export checkpoint → release TransformerLens model
- Start vLLM evaluation using the on-disk checkpoint
- vLLM loads the checkpoint fresh — the two never co-occupy GPU memory
# Safe pattern
model = ck.load_model(...)
circuit = ck.discover(model, ...)
ck.export_checkpoint(pruned, circuit, "./checkpoint")
del model
torch.cuda.empty_cache()
# Now run lm-eval vLLM benchmark — no contention
Reference Scripts¶
The worked examples above (and the ck.benchmark() / circuitkit benchmark calls referenced throughout this page) are the canonical reference; see Flat API: benchmark and Evaluation: Benchmarking.
Next Steps¶
- Evaluation: Downstream Benchmarking —
ck.benchmarkwrapper - Applications — pruning and checkpoint export
- CLI Reference: Applications —
benchmarkCLI command