A Unified Framework for High-Performance and Extensible LLM Steering
Python
299
354 commits
updated Sep 23, 2026

[ English | 中文 ]
Documentation — installation, guides, API reference, replications
👋 Join our WeChat user group. If the QR code has expired, please contact me. (๑•̀ㅂ•́)و✧
attention_heads), attention_add steering, and an ITI replication. See the docs for usage.Built on vLLM, EasySteer is a unified framework for high-performance LLM steering: it applies steering vectors — directions in a model's hidden-state space — during inference to shift model behavior without changing model weights, at serving speed. The current release tracks vLLM v0.29.0 on the V2 model runner, with continuous batching, prefix-cache-compatible steering, CUDA-graph support, the declarative v2 steering API (SteeringSpec/ApplySpec), and a redesigned hidden-state capture pipeline (source-side selection, labeled rows, per-request capture).
| Component | What it is | Docs |
|---|---|---|
vllm-steer/ | vLLM fork with the steering engine (vllm.steer_vectors) | Steering guide |
easysteer.capture | Capture hidden states, attention outputs and MoE router logits | Capture guide |
easysteer.extraction | Extract steering vectors from hidden states (analysis-based) | Extraction guide |
easysteer.training | Train native steering adapters on frozen models (learning-based) | Steering training |
frontend/ | Web UI for interactive steering experiments | Web demo |
replications/ | Reproductions of published steering papers | Replications |
Quick install (prebuilt wheel + fork overlay) — installs the official vLLM wheel and applies the fork's Python changes on top, with no compilation and no editable checkouts:
conda create -n easysteer python=3.12 -y
conda activate easysteer
# Clone EasySteer with its pinned vLLM fork
git clone --recurse-submodules https://github.com/ZJU-REAL/EasySteer.git
cd EasySteer
# Official vLLM wheel, then overlay the pinned fork's Python files
pip install vllm==0.29.0
VLLM_DIR=$(python -c "import vllm, os; print(os.path.dirname(vllm.__file__))")
rsync -a vllm-steer/vllm/ "$VLLM_DIR"/
# EasySteer package
pip install .
Note that reinstalling or upgrading vllm reverts the overlay; re-apply the rsync step afterwards.
Development install (editable, recommended for ongoing work):
conda create -n easysteer python=3.12 -y
conda activate easysteer
# Clone the repository (with submodules)
git clone --recurse-submodules https://github.com/ZJU-REAL/EasySteer.git
cd EasySteer
# For an existing checkout, start here from the EasySteer repository root
git submodule update --init --recursive
cd vllm-steer
# Install with pre-compiled version (recommended)
# EasySteer tracks the vLLM v0.29.0 release commit; pin it so the kernels match.
export VLLM_PRECOMPILED_WHEEL_COMMIT=98dff2a81d747d1dba01a47f939f48c3526d4206
VLLM_USE_PRECOMPILED=1 pip install --editable .
# Install EasySteer
cd ..
pip install --editable .
For full details, build-from-source, and Docker, see the installation guide.
Run from the EasySteer repository root so the relative vectors/ path resolves.
from vllm import LLM, SamplingParams
from vllm.steer_vectors import ApplySpec, SteeringSpec, VectorSpec
# enable_steer_vector=True turns on steering; without it, behaves like regular vLLM.
# steer_algorithms declares the algorithms requests will use — the engine picks
# the fastest CUDA-graph integration that serves them.
llm = LLM(model="Qwen/Qwen2.5-1.5B-Instruct", enable_steer_vector=True,
steer_algorithms=["direct"])
def happy_steering(scale):
# Which vector, how strongly, on which layers, and where it applies
return SteeringSpec(vectors=[VectorSpec(
source="vectors/happy_diffmean.gguf",
scale=scale,
layers=list(range(10, 24)),
apply=ApplySpec(prompt="all", generation="all"),
)])
tokenizer = llm.get_tokenizer()
messages = [
{"role": "system", "content": ""},
{"role": "user", "content": "Alice's dog has passed away. Please comfort her."},
]
prompt_ids = tokenizer.apply_chat_template(
messages, tokenize=True, return_dict=False, add_generation_prompt=True,
)
prompt = {"prompt_token_ids": prompt_ids}
sampling_params = SamplingParams(temperature=0.0, max_tokens=128)
baseline = llm.generate(prompt, steering=False, sampling_params=sampling_params)
happy = llm.generate(prompt, steering=happy_steering(2.0), sampling_params=sampling_params)
print(baseline[0].outputs[0].text) # ordinary condolences
print(happy[0].outputs[0].text) # conspicuously upbeat
Full walkthrough (including where the vector comes from): Quickstart.
We welcome paper replications, new steering algorithms, and support for additional models and components. Algorithms extend BaseSteerVectorAlgorithm; model integration uses module discovery and steering controllers. If you have used EasySteer in your research, reach out and we'll feature your work in News. See the contributing guide for an extension example and the module map, and the testing guide for the test suites.
The replications folder implements published steering methods with EasySteer. See the replication gallery for each example's scope:
| Method | Category | Component |
|---|---|---|
| Thinking Speed | Reasoning | hidden_states |
| Fractional Reasoning | Reasoning | hidden_states |
| Improve Reasoning | Reasoning | hidden_states |
| SEAL | Reasoning | hidden_states |
| Refusal Direction | Safety | hidden_states |
| CAST | Safety | hidden_states |
| Creative Writing | Style | hidden_states |
| Steerable Chatbots | Style | hidden_states |
| SAKE | Knowledge | hidden_states |
| SAE Entities | Truthfulness | hidden_states |
| SHARP (VLM) | Truthfulness | hidden_states |
| ITI | Truthfulness | attention_heads |
| LM-Steer | General | hidden_states |
| LoReFT | General | hidden_states |
| BiPO | Personalization | hidden_states |
| SteerMoE | MoE | router_logits |
Component names match the API: hidden_states denotes decoder block output,
attention_heads denotes head outputs before the attention output projection,
and router_logits denotes MoE routing scores.
If you use EasySteer for your research, please cite our paper:
@article{xu2025easysteer,
title={EasySteer: A Unified Framework for High-Performance and Extensible LLM Steering},
author={Xu, Haolei and Mei, Xinyu and Yan, Yuchen and Zhou, Rui and Zhang, Wenqi and Lu, Weiming and Zhuang, Yueting and Shen, Yongliang},
journal={arXiv preprint arXiv:2509.25175},
year={2025}
}
This project is licensed under the Apache License 2.0.
LLM steering is dual-use. EasySteer is developed primarily as a research tool for advancing model safety, not for circumventing safeguards: steering should be restricted to legitimate research and safety-enhancing applications, any behavioral modifications must be explicitly disclosed to end users, and all applications must adhere to relevant ethical guidelines and legal frameworks.
We thank the vLLM project for providing the high-performance inference framework, and projects like pyreft for their contributions to the field of representation learning. Related projects: EasyEdit · pyreft · repeng · vLLM
Python
59.6%
Jupyter Notebook
23.8%
TypeScript
8.6%
Vue
6.6%
A Unified Framework for High-Performance and Extensible LLM Steering
Python
299
354 commits
updated Sep 23, 2026

[ English | 中文 ]
Documentation — installation, guides, API reference, replications
👋 Join our WeChat user group. If the QR code has expired, please contact me. (๑•̀ㅂ•́)و✧
attention_heads), attention_add steering, and an ITI replication. See the docs for usage.Built on vLLM, EasySteer is a unified framework for high-performance LLM steering: it applies steering vectors — directions in a model's hidden-state space — during inference to shift model behavior without changing model weights, at serving speed. The current release tracks vLLM v0.29.0 on the V2 model runner, with continuous batching, prefix-cache-compatible steering, CUDA-graph support, the declarative v2 steering API (SteeringSpec/ApplySpec), and a redesigned hidden-state capture pipeline (source-side selection, labeled rows, per-request capture).
| Component | What it is | Docs |
|---|---|---|
vllm-steer/ | vLLM fork with the steering engine (vllm.steer_vectors) | Steering guide |
easysteer.capture | Capture hidden states, attention outputs and MoE router logits | Capture guide |
easysteer.extraction | Extract steering vectors from hidden states (analysis-based) | Extraction guide |
easysteer.training | Train native steering adapters on frozen models (learning-based) | Steering training |
frontend/ | Web UI for interactive steering experiments | Web demo |
replications/ | Reproductions of published steering papers | Replications |
Quick install (prebuilt wheel + fork overlay) — installs the official vLLM wheel and applies the fork's Python changes on top, with no compilation and no editable checkouts:
conda create -n easysteer python=3.12 -y
conda activate easysteer
# Clone EasySteer with its pinned vLLM fork
git clone --recurse-submodules https://github.com/ZJU-REAL/EasySteer.git
cd EasySteer
# Official vLLM wheel, then overlay the pinned fork's Python files
pip install vllm==0.29.0
VLLM_DIR=$(python -c "import vllm, os; print(os.path.dirname(vllm.__file__))")
rsync -a vllm-steer/vllm/ "$VLLM_DIR"/
# EasySteer package
pip install .
Note that reinstalling or upgrading vllm reverts the overlay; re-apply the rsync step afterwards.
Development install (editable, recommended for ongoing work):
conda create -n easysteer python=3.12 -y
conda activate easysteer
# Clone the repository (with submodules)
git clone --recurse-submodules https://github.com/ZJU-REAL/EasySteer.git
cd EasySteer
# For an existing checkout, start here from the EasySteer repository root
git submodule update --init --recursive
cd vllm-steer
# Install with pre-compiled version (recommended)
# EasySteer tracks the vLLM v0.29.0 release commit; pin it so the kernels match.
export VLLM_PRECOMPILED_WHEEL_COMMIT=98dff2a81d747d1dba01a47f939f48c3526d4206
VLLM_USE_PRECOMPILED=1 pip install --editable .
# Install EasySteer
cd ..
pip install --editable .
For full details, build-from-source, and Docker, see the installation guide.
Run from the EasySteer repository root so the relative vectors/ path resolves.
from vllm import LLM, SamplingParams
from vllm.steer_vectors import ApplySpec, SteeringSpec, VectorSpec
# enable_steer_vector=True turns on steering; without it, behaves like regular vLLM.
# steer_algorithms declares the algorithms requests will use — the engine picks
# the fastest CUDA-graph integration that serves them.
llm = LLM(model="Qwen/Qwen2.5-1.5B-Instruct", enable_steer_vector=True,
steer_algorithms=["direct"])
def happy_steering(scale):
# Which vector, how strongly, on which layers, and where it applies
return SteeringSpec(vectors=[VectorSpec(
source="vectors/happy_diffmean.gguf",
scale=scale,
layers=list(range(10, 24)),
apply=ApplySpec(prompt="all", generation="all"),
)])
tokenizer = llm.get_tokenizer()
messages = [
{"role": "system", "content": ""},
{"role": "user", "content": "Alice's dog has passed away. Please comfort her."},
]
prompt_ids = tokenizer.apply_chat_template(
messages, tokenize=True, return_dict=False, add_generation_prompt=True,
)
prompt = {"prompt_token_ids": prompt_ids}
sampling_params = SamplingParams(temperature=0.0, max_tokens=128)
baseline = llm.generate(prompt, steering=False, sampling_params=sampling_params)
happy = llm.generate(prompt, steering=happy_steering(2.0), sampling_params=sampling_params)
print(baseline[0].outputs[0].text) # ordinary condolences
print(happy[0].outputs[0].text) # conspicuously upbeat
Full walkthrough (including where the vector comes from): Quickstart.
We welcome paper replications, new steering algorithms, and support for additional models and components. Algorithms extend BaseSteerVectorAlgorithm; model integration uses module discovery and steering controllers. If you have used EasySteer in your research, reach out and we'll feature your work in News. See the contributing guide for an extension example and the module map, and the testing guide for the test suites.
The replications folder implements published steering methods with EasySteer. See the replication gallery for each example's scope:
| Method | Category | Component |
|---|---|---|
| Thinking Speed | Reasoning | hidden_states |
| Fractional Reasoning | Reasoning | hidden_states |
| Improve Reasoning | Reasoning | hidden_states |
| SEAL | Reasoning | hidden_states |
| Refusal Direction | Safety | hidden_states |
| CAST | Safety | hidden_states |
| Creative Writing | Style | hidden_states |
| Steerable Chatbots | Style | hidden_states |
| SAKE | Knowledge | hidden_states |
| SAE Entities | Truthfulness | hidden_states |
| SHARP (VLM) | Truthfulness | hidden_states |
| ITI | Truthfulness | attention_heads |
| LM-Steer | General | hidden_states |
| LoReFT | General | hidden_states |
| BiPO | Personalization | hidden_states |
| SteerMoE | MoE | router_logits |
Component names match the API: hidden_states denotes decoder block output,
attention_heads denotes head outputs before the attention output projection,
and router_logits denotes MoE routing scores.
If you use EasySteer for your research, please cite our paper:
@article{xu2025easysteer,
title={EasySteer: A Unified Framework for High-Performance and Extensible LLM Steering},
author={Xu, Haolei and Mei, Xinyu and Yan, Yuchen and Zhou, Rui and Zhang, Wenqi and Lu, Weiming and Zhuang, Yueting and Shen, Yongliang},
journal={arXiv preprint arXiv:2509.25175},
year={2025}
}
This project is licensed under the Apache License 2.0.
LLM steering is dual-use. EasySteer is developed primarily as a research tool for advancing model safety, not for circumventing safeguards: steering should be restricted to legitimate research and safety-enhancing applications, any behavioral modifications must be explicitly disclosed to end users, and all applications must adhere to relevant ethical guidelines and legal frameworks.
We thank the vLLM project for providing the high-performance inference framework, and projects like pyreft for their contributions to the field of representation learning. Related projects: EasyEdit · pyreft · repeng · vLLM
Python
59.6%
Jupyter Notebook
23.8%
TypeScript
8.6%
Vue
6.6%