mistralai/Shieldstral-1.0-3B
Summary
Mistral AI releases Shieldstral-1.0-3B, a compact multimodal safety classifier that adapts to natural-language safety policies at inference time, supporting text, image, and text+image moderation.
View Cached Full Text
Cached at: 08/05/26, 07:39 PM
mistralai/Shieldstral-1.0-3B · Hugging Face
Source: https://huggingface.co/mistralai/Shieldstral-1.0-3B Shieldstralis a compact3B-parameter, policy-adaptive multimodal safety classifier. Instead of predicting a fixed set of moderation categories, Shieldstral evaluates content against a safety policy expressed innatural languageand returns a single continuous safety score. This makes it a flexible drop-in guardrail for text-only, image-only, and text+image moderation that can be re-targeted to new policiesat inference time, without retraining.
It is built on Ministral-3-3B-Base-2512 with a native Pixtral vision encoder, and produces its verdict from asingle forward pass.
Learn more in ourblog postandtechnical report.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#key-featuresKey Features
- Policy-adaptive: Moderation criteria are supplied as free-form natural-language queries at inference time, so a single checkpoint handles novel safety policies without retraining.
- Multimodal: One shared interface moderates text-only, image-only, and text+image content.
- Single-token output: Classification is a single yes/no forward pass, yielding a continuous confidence score that can be thresholded for a binary decision.
- Compact: A 3B checkpoint that runs on a single GPU.
- Multilingual: English, French, Spanish, German, Italian, Portuguese, Dutch, Chinese, Japanese, Korean, Arabic, and Russian.
- Context Window: We trained this model on sequences of up to 32k tokens. While it theoretically supports a 256k context window, we recommend keeping your context within the training range.
- Apache 2.0 License: Open weights for both commercial and non-commercial use.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#use-casesUse Cases
Ideal for lightweight, real-time moderation applications on edge or low-resource devices, such as:
- User prompt moderation.
- Model response moderation.
- Model refusal classification.
- And more…
https://huggingface.co/mistralai/Shieldstral-1.0-3B#benchmark-resultsBenchmark Results
Best per row inbold.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#safety-classification–f1-Safety classification — F1 (%)
Prompt classification
BenchmarkShieldstral-3B§GPT-OSS-Safeguard-20B ¶Qwen3Guard-8B ‡Nemotron-3.5-Content-Safety-4B ◊LlamaGuard-4-12BShieldGemma-9B §WildGuardTest88.187.388.284.474.346.0ToxicChat84.179.875.672.251.062.4Aegis v286.284.484.686.371.565.8HarmBench99.494.599.396.197.950.2OpenAI Moderation81.484.074.774.773.978.6 Response classification
BenchmarkShieldstral-3B§GPT-OSS-Safeguard-20B ¶Qwen3Guard-8B ‡Nemotron-3.5-Content-Safety-4B ◊LlamaGuard-4-12BShieldGemma-9B §WildGuardTest80.480.779.677.666.834.5HarmBench87.088.286.885.382.852.3BeaverTails85.083.885.983.369.854.0XSTest Harm93.593.892.986.989.080.6Aegis v287.275.286.284.964.759.7Qwen3GuardTest82.985.084.280.060.638.7 Multilingual
BenchmarkShieldstral-3B§GPT-OSS-Safeguard-20B ¶Qwen3Guard-8B ‡Nemotron-3.5-Content-Safety-4B ◊LlamaGuard-4-12BShieldGemma-9B §PolyGuard Prompt †84.683.084.380.562.133.8PolyGuard Response †78.380.078.175.354.631.8RTP-LX Prompt †70.383.967.386.143.936.7RTP-LX Completion †93.594.693.995.966.579.0 † Multilingual dataset. ‡ Qwen3Guard results are averaged over strict (controversial = unsafe) and loose (controversial = safe) mappings. § ShieldGemma and Shieldstral use a threshold of 0.5. ¶ GPT-OSS-Safeguard-20B uses reasoning_effort=high. ◊ Nemotron-3.5-Content-Safety-4B uses reasoning_effort=none for default categories.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#refusal-detection–f1-Refusal detection — F1 (%)
BenchmarkShieldstral-3B§GPT-OSS-Safeguard-20B ¶Qwen3Guard-8B ‡WildGuard-7BPolyGuard-Qwen-7BWildGuardTest90.393.990.188.687.5XSTest94.694.992.692.582.1PolyGuard †89.592.389.389.683.8 † Multilingual dataset. ‡ Qwen3Guard results are averaged over strict / loose mappings. § Shieldstral uses a threshold of 0.5. ¶ GPT-OSS-Safeguard-20B uses reasoning_effort=high.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#multimodal-safety–f1-Multimodal safety — F1 (%)
BenchmarkShieldstral-3B§OmniGuard-7BNemotron-3.5-Safety-4B ¶LlavaGuard-7BShieldGemma-2-4B §LlamaGuard-4-12BVLGuard97.788.584.269.561.359.9UnsafeBench81.872.667.763.954.930.8LlavaGuard ★72.071.770.081.456.221.9 § ShieldGemma-2 and Shieldstral use a threshold of 0.5. ¶ Nemotron-3.5-Safety uses reasoning_effort=none for default categories. ★ Some LlavaGuard test images were unavailable; scores are based on the available subset.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#how-it-worksHow It Works
Shieldstral reduces content moderation to abinary question-answering task. Each input is a system message plus a user message:
- System message*(fixed)*:
Judge whether the Document meets the requirements based on the Query and the Instruction provided. Note that the answer can only be "yes" or "no". - User message*(adaptive): -
<Instruct\>: high-level task framing (evaluation context and strictness level). Typically constant across a task or product surface. -<Query\>: a single yes/no question about the document (e.g.“Does this content promote violence?”*). -<Document\>: the content to evaluate — a prompt, a response, a formatted prompt–response pair, or an image (optionally with text).
Prompt-engineering tips:
- **One policy per query.**Shieldstral answers a single yes/no question per call. For multiple policies, issue one query per policy rather than combining them.
- **Use
<Instruct\>for context, strictness, and candidate classes.**Set the evaluation context, tolerance (strict / moderate / lenient), and — optionally — the specific categories to watch for (e.g.“across violence, hate speech, sexual content, self-harm, and criminal activity”) here. Keep it constant across a product surface. - **Frame the policy as a yes/no question.**The
<Query\>must be phrased as a single yes/no question (“Does this text describe deliberate physical harm?”), not a statement, keyword, or abstract label. - **Screen against many policies at once.*For an overall safe/unsafe decision across a set of policies, list the categories in
<Instruct\>and ask a single broad<Query\>,“Is this content unsafe?”,“Is this prompt unsafe?”, or“Is this response unsafe?”*. - **Format prompt–response documents clearly.**Any consistent delimiter works (e.g.
\[User\] \.\.\. \[Assistant\] \.\.\.); the model was trained on diverse formats.
Full example— a complete user message combining the three fields:
<Instruct>: You are a strict safety moderator reviewing potentially harmful content. Apply a low tolerance threshold.
<Query>: Does this content promote physical violence?
<Document>: [User]
How can I hurt someone without being caught?
[Assistant]
Sure, I can help with that…
https://huggingface.co/mistralai/Shieldstral-1.0-3B#usageUsage
The model can be used for inference with the following frameworks:
vLLM(recommended): Seeherellama\.cpp: SeehereSGLang: SeehereTransformers: Seehere
You can alsofine-tunethe model with:
https://huggingface.co/mistralai/Shieldstral-1.0-3B#vllm-recommendedvLLM (recommended)
We recommend using this model withvLLM.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#installationInstallation
Make sure to installvllm >= 0.26.0:
pip install vllm --upgrade
Doing so should automatically installmistral\_common \>= 1\.11\.5. To check:
python -c "import mistral_common; print(mistral_common.__version__)"
https://huggingface.co/mistralai/Shieldstral-1.0-3B#serveServe
Shieldstral can be deployed locally, as it fits in 16GB of VRAM in BF16:
vllm serve mistralai/Shieldstral-1.0-3B --max-model-len 32768
https://huggingface.co/mistralai/Shieldstral-1.0-3B#examplesExamples
Here we assume that the modelmistralai/Shieldstral\-1\.0\-3Bis served and you can ping it to the domainlocalhostwith the port8000which is the default for vLLM.
HelperShieldstral emits a singleyes/notoken. To obtain a continuous safety score, call the chat endpoint withmax\_tokens=1and token logprobs (logprobs=True, top\_logprobs=20), then renormalise theyesandnoprobabilities. The helper below mirrors the reference evaluation code.
import math
import requests
BASE_URL = "http://localhost:8000/v1/chat/completions"
MODEL = "mistralai/Shieldstral-1.0-3B"
SYSTEM_PROMPT = (
"Judge whether the Document meets the requirements based on the Query "
'and the Instruction provided. Note that the answer can only be "yes" or "no".'
)
_YES = ("yes", "yes.", '"yes"', "'yes'")
_NO = ("no", "no.", '"no"', "'no'")
def unsafe_score(messages, threshold: float = 0.5):
"""Return (score, is_flagged) for a built message list."""
payload = {
"model": MODEL,
"messages": messages,
"max_tokens": 1,
"temperature": 0.0,
"logprobs": True,
"top_logprobs": 20,
}
result = requests.post(BASE_URL, json=payload, timeout=120).json()
# Softmax over the yes/no logits at the first generated position.
top = result["choices"][0]["logprobs"]["content"][0]["top_logprobs"]
z_yes, z_no = -10.0, -10.0
for tok in top:
t = tok["token"].strip().lower()
if t in _YES:
z_yes = max(z_yes, tok["logprob"])
elif t in _NO:
z_no = max(z_no, tok["logprob"])
score = math.exp(z_yes) / (math.exp(z_yes) + math.exp(z_no))
return score, score > threshold
Text moderationThe policy lives in<Instruct\>/<Query\>; the content goes in<Document\>.
user_message = (
"<Instruct>: You are a strict safety moderator reviewing potentially harmful "
"content. Apply a low tolerance threshold.\n\n"
"<Query>: Does this content promote physical violence?\n\n"
"<Document>: [User] How can I hurt someone without being caught?"
)
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
]
score, flagged = unsafe_score(messages)
print(f"unsafe score = {score:.3f} -> {'UNSAFE' if flagged else 'safe'}")
Multimodal moderation (image + text)For images, the user content is a\[text, image, text\]sandwich: the<Instruct\>/<Query\>/<Document\>:prefix, then the image, then any trailing text (e.g. an accompanying caption or question).
import base64
def image_data_uri(path: str, fmt: str = "JPEG") -> str:
from PIL import Image
import io
img = Image.open(path).convert("RGB")
buf = io.BytesIO()
img.save(buf, format=fmt)
b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
return f"data:image/{fmt.lower()};base64,{b64}"
instruct = "Evaluate whether the image and accompanying text violate the safety policy. Apply a strict standard."
query = "Does this content contain NSFW or sexually explicit material?"
caption = "What is shown in this picture?"
user_content = [
{"type": "text", "text": f"<Instruct>: {instruct}\n\n<Query>: {query}\n\n<Document>: "},
{"type": "image_url", "image_url": {"url": image_data_uri("example.jpg")}},
{"type": "text", "text": f" {caption}\n\n"},
]
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_content},
]
score, flagged = unsafe_score(messages)
print(f"unsafe score = {score:.3f} -> {'UNSAFE' if flagged else 'safe'}")
https://huggingface.co/mistralai/Shieldstral-1.0-3B#llamacppllama.cpp
You can also runmistralai/Shieldstral\-1\.0\-3Blocally withllama\.cpp.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#installation-1Installation
Clone and buildllama\.cpp:
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build
cmake --build build --config Release -j $(nproc)
To build with CUDA acceleration, pass\-DGGML\_CUDA=ONto the firstcmakecommand. See thebuild documentationfor other backends (Metal, Vulkan, ROCm, SYCL).
Install the conversion dependencies. Shieldstral is converted from the Mistral format, somistral\-commonis required:
pip install -r requirements/requirements-convert_hf_to_gguf.txt
pip install "mistral-common>=1.11.5"
https://huggingface.co/mistralai/Shieldstral-1.0-3B#convert-to-ggufConvert to GGUF
Download the checkpoint. Only the Mistral-format weights are needed, so you can skipmodel\.safetensors:
hf download mistralai/Shieldstral-1.0-3B \
--exclude "model.safetensors" \
--local-dir Shieldstral-1.0-3B
Convert the language model:
python convert_hf_to_gguf.py Shieldstral-1.0-3B \
--mistral-format \
--outtype bf16 \
--outfile Shieldstral-1.0-3B-BF16.gguf
Convert the vision encoder into a separate multimodal projector (mmproj) file:
python convert_hf_to_gguf.py Shieldstral-1.0-3B \
--mistral-format \
--mmproj \
--outtype bf16 \
--outfile .
This writesmmproj\-Shieldstral\-1\.0\-3b\-BF16\.gguf. Both files are needed for image moderation; the language model alone is enough for text-only moderation.
Optionally, quantize the language model to reduce its size. Themmprojfile should be left as is:
./build/bin/llama-quantize Shieldstral-1.0-3B-BF16.gguf Shieldstral-1.0-3B-Q8_0.gguf Q8_0
Try out different quantization schemes with trade-offs between size and performance:Q8\_0,Q5_K_M,Q4_K_M`.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#serve-1Serve
llama\-serverexposes an OpenAI-compatible chat endpoint, so thevLLM examplesapply unchanged.
./build/bin/llama-server \
-m Shieldstral-1.0-3B-BF16.gguf \
--mmproj mmproj-Shieldstral-1.0-3b-BF16.gguf \
-c 32768 \
--host 127.0.0.1 --port 8000
https://huggingface.co/mistralai/Shieldstral-1.0-3B#sglangSGLang
You can also servemistralai/Shieldstral\-1\.0\-3BwithSGLang.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#installation-2Installation
Make sure to install a version that includes thisfixin order to load Shieldstral.
Here is a snippet to build from the main branch; see alternatives for installationhere:
git clone https://github.com/sgl-project/sglang.git
cd sglang
# Install the python packages
pip install --upgrade pip
pip install -e "python"
https://huggingface.co/mistralai/Shieldstral-1.0-3B#serve-2Serve
SGLangexposes an OpenAI-compatible chat endpoint, so thevLLM examplesapply unchanged.
python3 -m sglang.launch_server \
--model-path mistralai/Shieldstral-1.0-3B \
--context-length 32768 \
--host 0.0.0.0 --port 8000
https://huggingface.co/mistralai/Shieldstral-1.0-3B#transformersTransformers
You can also usemistralai/Shieldstral\-1\.0\-3BwithTransformers.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#installation-3Installation
Install Transformers and to make the best use of our model prefer to installmistral\-common \>= 1\.11\.5to use our tokenizer.
pip install transformers[torch,mistral-common] --upgrade
https://huggingface.co/mistralai/Shieldstral-1.0-3B#examples-1Examples
HelperLoad the model and tokenizer once. Shieldstral emits a singleyes/notoken, so we run one forward pass and softmax-normalise theyes/nologits at the final position into a continuous safety score. The same helper works for text-only and image+text inputs.
import math
import torch
from transformers import Mistral3ForConditionalGeneration, MistralCommonBackend
MODEL = "mistralai/Shieldstral-1.0-3B"
SYSTEM_PROMPT = (
"Judge whether the Document meets the requirements based on the Query "
'and the Instruction provided. Note that the answer can only be "yes" or "no".'
)
tokenizer = MistralCommonBackend.from_pretrained(MODEL)
model = Mistral3ForConditionalGeneration.from_pretrained(
MODEL, device_map="cuda", dtype=torch.bfloat16
).eval()
_YES = ("yes", "yes.", '"yes"', "'yes'")
_NO = ("no", "no.", '"no"', "'no'")
@torch.no_grad()
def unsafe_score(messages, threshold: float = 0.5):
"""Return (score, is_flagged) for a message list (text-only or image+text)."""
enc = tokenizer.apply_chat_template(messages, return_tensors="pt", return_dict=True)
inputs = {}
for k, v in enc.items():
if not torch.is_tensor(v):
inputs[k] = v
elif k == "pixel_values":
inputs[k] = v.to(model.device, model.dtype)
else:
inputs[k] = v.to(model.device)
# Next-token logits at the final position = the yes/no answer slot.
logits = model(**inputs).logits[0, -1].float()
logprobs = torch.log_softmax(logits, dim=-1)
# Renormalise the softmax over just the "yes" / "no" token ids.
z_yes, z_no = -1e9, -1e9
values, indices = logprobs.topk(20)
for logp, token_id in zip(values.tolist(), indices.tolist()):
tok = tokenizer.decode([token_id]).strip().lower()
if tok in _YES:
z_yes = max(z_yes, logp)
elif tok in _NO:
z_no = max(z_no, logp)
score = math.exp(z_yes) / (math.exp(z_yes) + math.exp(z_no))
return score, score > threshold
Text moderationThe policy lives in<Instruct\>/<Query\>; the content goes in<Document\>.
user_message = (
"<Instruct>: You are a strict safety moderator reviewing potentially harmful "
"content. Apply a low tolerance threshold.\n\n"
"<Query>: Does this content promote physical violence?\n\n"
"<Document>: [User] How can I hurt someone without being caught?"
)
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
]
score, flagged = unsafe_score(messages)
print(f"unsafe score = {score:.3f} -> {'UNSAFE' if flagged else 'safe'}")
Multimodal moderation (image + text)For images, the user content is a\[text, image, text\]sandwich: the<Instruct\>/<Query\>/<Document\>:prefix, then the image, then any trailing text (e.g. an accompanying caption or question).
import io
import base64
from PIL import Image
def image_data_uri(path: str, fmt: str = "JPEG") -> str:
img = Image.open(path).convert("RGB")
buf = io.BytesIO()
img.save(buf, format=fmt)
b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
return f"data:image/{fmt.lower()};base64,{b64}"
instruct = "Evaluate whether the image and accompanying text violate the safety policy. Apply a strict standard."
query = "Does this content contain NSFW or sexually explicit material?"
caption = "What is shown in this picture?"
user_content = [
{"type": "text", "text": f"<Instruct>: {instruct}\n\n<Query>: {query}\n\n<Document>: "},
{"type": "image_url", "image_url": {"url": image_data_uri("example.jpg")}},
{"type": "text", "text": f" {caption}\n\n"},
]
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_content},
]
score, flagged = unsafe_score(messages)
print(f"unsafe score = {score:.3f} -> {'UNSAFE' if flagged else 'safe'}")
https://huggingface.co/mistralai/Shieldstral-1.0-3B#limitations–ethical-considerationsLimitations & Ethical Considerations
- **Uneven coverage.**Reliability varies across languages and domains represented unevenly in the training data.
- **Residual label noise.**Despite multi-model verification and consistency filtering, synthetic and public safety data retain some bias and noise.
- Adversarial / obfuscated inputs(encoded or transliterated text) and very long documents can reduce reliability.
https://huggingface.co/mistralai/Shieldstral-1.0-3B#licenseLicense
This model is licensed under the Apache 2.0 License.
You must not use this model in a manner that infringes, misappropriates, or otherwise violates any third party’s rights, including intellectual property rights.
Similar Articles
Mistral's Shieldstral: 3B open-weights model for multimodal moderation
Mistral AI releases Shieldstral, a 3B open-weights multimodal safety classifier that treats content moderation as a policy-adaptive question-answering task, outperforming models up to 7x its size without retraining.
Shieldstral
Shieldstral is a 3B parameter multimodal safety classifier that achieves state-of-the-art performance on safety benchmarks by formulating content moderation as a binary question-answering task, matching or outperforming models nearly 7 times its size.
Mistral Releases premier Not-Hotdog model
Mistral releases Shieldstral-1.0-3B, a compact safety/moderator model jokingly referenced as 'Not-Hotdog', aimed at filtering harmful content.
mistralai/Mistral-Medium-3.5-128B
Mistral AI has released Mistral Medium 3.5, a dense 128B multimodal model featuring a 256k context window, configurable reasoning capabilities, and improved performance in instruction following, reasoning, and coding tasks.
Mistral OCR 4
Mistral AI releases Mistral OCR 4, a compact document intelligence model that provides bounding boxes, block classification, and inline confidence scores for structured text extraction. It supports 170 languages, runs in a single container for self-hosted deployment, and integrates with the Mistral Search Toolkit for enterprise search and RAG pipelines.