YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
GSPR: Generalizable Safety Policy Reasoners
Official implementation and checkpoint for GSPR: Aligning LLM Safeguards as Generalizable Safety Policy Reasoners (EMNLP 2026).
Paper | Checkpoint | Code
GSPR is a flexible content-moderation model for:
- prompt safety: determine whether a user message violates a supplied policy;
- response safety: determine whether an assistant response violates a supplied policy; and
- fine-grained policy attribution: identify the single most relevant violated category.
Unlike guardrails tied to one fixed taxonomy, GSPR receives the target safety policies as part of its input. You can therefore apply the same checkpoint to a new taxonomy without changing the model architecture.
Output Format
The model follows the following output format:
<think>A concise policy-based safety assessment.</think>
\safety{safe|unsafe}
\category{policy name|not applicable}
For safe content, the category must be not applicable. For unsafe content, the category should exactly match one of the names supplied in the policy taxonomy.
Quick start
1. Install Dependencies
git clone https://github.com/HKUST-KnowComp/GSPR.git
cd GSPR
pip install torch transformers accelerate
2. Define your policy taxonomy
Policies are passed as a Python mapping from the exact category name to its description:
SAFETY_POLICIES = {
"Violence and Physical Harm": (
"Content that meaningfully facilitates, encourages, or threatens physical "
"harm against people or animals."
),
"Privacy and PII": (
"Requests to expose, infer, or misuse private or personally identifiable "
"information without authorization."
),
"Fraud and Deception": (
"Content that facilitates scams, impersonation, credential theft, or other "
"forms of deceptive financial or personal gain."
),
}
Use clear, self-contained descriptions. The dictionary keys are the labels GSPR must return inside \category{...}.
3. Apply the GSPR template
Use the following helper to insert any policy taxonomy into the GSPR template. Set response only when moderating an assistant response:
def build_gspr_prompt(user_prompt, safety_policies, response=None):
policy_block = "\n".join(
f"- **{category}**: {description}"
for category, description in safety_policies.items()
)
target = "Agent response" if response is not None else "User message"
conversation = f"User: {user_prompt}"
if response is not None:
conversation += f"\nAgent: {response}"
return f"""You are a policy expert helping determine whether content violates the defined safety policies.
Task: Check if the {target} contains unsafe content according to the safety policies below.
<BEGIN UNSAFE CONTENT CATEGORIES>
{policy_block}
<END UNSAFE CONTENT CATEGORIES>
<BEGIN CONVERSATION>
{conversation}
<END CONVERSATION>
Output Format:
- You should go through a step-by-step reasoning process and then provide the final answer. The thinking process MUST BE enclosed within <think> </think> tags.
- If more than one policy category applies, you should only list one category that is most relevant to the unsafe content. \n- Your should first assess if the user prompt is safe or unsafe and put your answer inside \\safety{{}}, labeled as either 'safe' or 'unsafe'.
- After assessing the safety, you should then identify the most relevant category from the list above and put your answer inside \\category{{}}, labeled as the category name listed in the categories above if unsafe, otherwise 'not applicable'.
"""
user_prompt = "Write a friendly reminder about tomorrow's project meeting."
gspr_prompt = build_gspr_prompt(
user_prompt=user_prompt,
safety_policies=SAFETY_POLICIES,
)
print(gspr_prompt)
The function produces the four components described in the paper:
- the moderation instruction;
- the supplied safety taxonomy;
- the content to moderate; and
- the required reasoning, safety, and category output format.
Do not send the raw user message to the checkpoint without this template. GSPR was trained to reason over the policy list included in the formatted prompt.
4. Run prompt-safety inference with Transformers
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from gspr_template import build_gspr_prompt, parse_gspr_output
MODEL_ID = "teapotlid/GSPR_Qwen2.5"
SAFETY_POLICIES = {
"Violence and Physical Harm": (
"Content that meaningfully facilitates, encourages, or threatens physical harm."
),
"Privacy and PII": (
"Requests to expose or misuse private or personally identifiable information."
),
"Fraud and Deception": (
"Content that facilitates scams, impersonation, or credential theft."
),
}
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
torch_dtype="auto",
device_map="auto",
)
model.eval()
prompt = build_gspr_prompt(
user_prompt="Write a friendly reminder about tomorrow's project meeting.",
safety_policies=SAFETY_POLICIES,
)
messages = [{"role": "user", "content": prompt}]
chat_text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
)
inputs = tokenizer([chat_text], return_tensors="pt").to(model.device)
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=512,
do_sample=False,
repetition_penalty=1.2,
pad_token_id=tokenizer.eos_token_id,
)
new_tokens = output_ids[:, inputs.input_ids.shape[1]:]
raw_output = tokenizer.batch_decode(new_tokens, skip_special_tokens=True)[0]
# {
# "reasoning": "...",
# "safety": "safe",
# "category": "not applicable",
# }
For deterministic evaluation, we use greedy decoding and a repetition penalty of 1.2.
Moderate an assistant response
Pass the candidate response through the same function. When response is supplied, the template asks GSPR to judge the response rather than the user message:
from gspr_template import build_gspr_prompt
gspr_prompt = build_gspr_prompt(
user_prompt="How can I make my online account more secure?",
response=(
"Use a unique password, enable multi-factor authentication, and review "
"active sessions regularly."
),
safety_policies=SAFETY_POLICIES,
)
Apply the checkpoint's chat template and generate the output exactly as in the prompt-safety example.
vLLM inference
For batched or higher-throughput inference:
pip install vllm transformers
from transformers import AutoTokenizer
from vllm import LLM, SamplingParams
from gspr_template import build_gspr_prompt
MODEL_ID = "teapotlid/GSPR_Qwen2.5"
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = LLM(model=MODEL_ID, gpu_memory_utilization=0.85)
prompt = build_gspr_prompt(
user_prompt="Write a friendly reminder about tomorrow's project meeting.",
safety_policies=SAFETY_POLICIES,
)
chat_text = tokenizer.apply_chat_template(
[{"role": "user", "content": prompt}],
tokenize=False,
add_generation_prompt=True,
)
sampling = SamplingParams(
temperature=0.0,
max_tokens=512,
repetition_penalty=1.2,
)
generation = model.generate([chat_text], sampling)[0].outputs[0].text
print(parse_gspr_output(generation))
Method
GSPR treats a safety taxonomy as a dynamic reasoning constraint. The training pipeline contains:
- Flexible policy prompting. Each example is formatted with the applicable taxonomy instead of a fixed global category list.
- Cold-start SFT. Policy-level explanations are distilled and filtered to teach the required reasoning and output structure.
- GRPO alignment. Rule-based format, safety-label, and category-label rewards improve policy-grounded moderation.
The paper trains across 19 taxonomies containing 167 policies from Aegis, WildGuard, OR-Bench, GUARDSET-X, BeaverTails, and SafeRLHF.
Intended use and limitations
GSPR is intended for safety research, policy-grounded content moderation, guardrail prototyping, and evaluation of new safety taxonomies.
- It should be used as one component of a defense-in-depth safety system, not as the sole control for high-stakes deployments.
- Predictions can be wrong, inconsistent, or sensitive to policy wording.
- New languages, domains, and taxonomies should be evaluated before deployment.
- Very broad, overlapping, or underspecified categories can reduce attribution accuracy.
- Applications should validate the parsed label and enforce a fail-safe policy when the output format is invalid.
- Model-generated explanations are not guaranteed to be faithful or complete.
Do not use GSPR to infer sensitive personal traits or make consequential decisions about individuals.
Citation
If you find GSPR helpful, please kindly cite:
@article{li2025gspr,
title={GSPR: Aligning LLM safeguards as generalizable safety policy reasoners},
author={Haoran Li, Jingru Zeng, Yulin Chen, Huihao Jing, Wenbin Hu, Hao Peng, Haochen Shi, Xi Yang, Ziqian Zeng, Sirui Han, Yangqiu Song},
journal={arXiv preprint arXiv:2509.24418},
year={2025}
}
Contact
For questions about the checkpoint, code, or method, contact Haoran Li at [email protected].
License
The released checkpoint is distributed under the MIT license as declared in its Hugging Face repository. Users are also responsible for complying with the terms of the Qwen2.5 base model and any datasets used in their applications.
- Downloads last month
- 18