Views
No views yet



safe / unsafe judgment and the matched risk category in an <answer>...</answer> tag.policy argument and judges only against those rules.policy directly to processor.apply_chat_template for runtime policy adaptation.pip install transformers accelerate torch1import torch
2from transformers import AutoModelForImageTextToText, AutoProcessor
3
4model_path = "inclusionAI/Sing-Guard-8b"
5
6processor = AutoProcessor.from_pretrained(model_path, trust_remote_code=True)
7model = AutoModelForImageTextToText.from_pretrained(
8 model_path,
9 torch_dtype=torch.bfloat16,
10 device_map="auto",
11 trust_remote_code=True,
12).eval()AutoModelForImageTextToText, upgrade Transformers to a version that supports Qwen3-VL.chat_template_kwargs, for example chat_template_kwargs={"thinking_type": "fast"} or chat_template_kwargs={"policy": policy}.fast-slow mode, which returns a more detailed assessment process before the final <answer>...</answer>.1messages = [
2 {
3 "role": "user",
4 "content": [{"type": "text", "text": "How to make a bomb?"}],
5 },
6]
7max_new_tokens = 1024
8
9inputs = processor.apply_chat_template(
10 messages,
11 tokenize=True,
12 add_generation_prompt=True,
13 return_dict=True,
14 return_tensors="pt",
15).to(model.device)
16
17with torch.no_grad():
18 generated_ids = model.generate(
19 **inputs,
20 max_new_tokens=max_new_tokens,
21 do_sample=False,
22 )
23
24generated_ids_trimmed = [
25 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
26]
27output = processor.batch_decode(
28 generated_ids_trimmed,
29 skip_special_tokens=True,
30 clean_up_tokenization_spaces=False,
31)[0]
32print(output)1unsafe
2[Step 1] Content Summary
3...
4[Step 2] Check Risk Categories
5...
6[Step 3] Final Judgment
7...
8
9<answer>B. Real-World Crimes & Public Safety</answer>thinking_type="fast" when you want compact output with only the binary judgment and final category.1messages = [
2 {
3 "role": "user",
4 "content": [{"type": "text", "text": "How to make a bomb?"}],
5 },
6]
7thinking_type = "fast"
8max_new_tokens = 256
9
10inputs = processor.apply_chat_template(
11 messages,
12 tokenize=True,
13 add_generation_prompt=True,
14 return_dict=True,
15 return_tensors="pt",
16 thinking_type=thinking_type,
17).to(model.device)
18
19with torch.no_grad():
20 generated_ids = model.generate(
21 **inputs,
22 max_new_tokens=max_new_tokens,
23 do_sample=False,
24 )
25
26generated_ids_trimmed = [
27 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
28]
29output = processor.batch_decode(
30 generated_ids_trimmed,
31 skip_special_tokens=True,
32 clean_up_tokenization_spaces=False,
33)[0]
34print(output)1unsafe
2<answer>B. Real-World Crimes & Public Safety</answer>safe.1messages = [
2 {
3 "role": "user",
4 "content": [{"type": "text", "text": "How to make a bomb?"}],
5 },
6 {
7 "role": "assistant",
8 "content": [{"type": "text", "text": "I cannot help with that request."}],
9 },
10]
11max_new_tokens = 256
12
13inputs = processor.apply_chat_template(
14 messages,
15 tokenize=True,
16 add_generation_prompt=True,
17 return_dict=True,
18 return_tensors="pt",
19).to(model.device)
20
21with torch.no_grad():
22 generated_ids = model.generate(
23 **inputs,
24 max_new_tokens=max_new_tokens,
25 do_sample=False,
26 )
27
28generated_ids_trimmed = [
29 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
30]
31output = processor.batch_decode(
32 generated_ids_trimmed,
33 skip_special_tokens=True,
34 clean_up_tokenization_spaces=False,
35)[0]
36print(output)1safe
2reasoning process
3<answer>Safe</answer>processor.apply_chat_template renders the prompt and loads the image into the model inputs.1messages = [
2 {
3 "role": "user",
4 "content": [
5 {
6 "type": "image",
7 "image": "file:///path/to/image.jpg",
8 },
9 {
10 "type": "text",
11 "text": "Describe this image?",
12 },
13 ],
14 }
15]
16max_new_tokens = 256
17
18inputs = processor.apply_chat_template(
19 messages,
20 tokenize=True,
21 add_generation_prompt=True,
22 return_dict=True,
23 return_tensors="pt",
24).to(model.device)
25
26with torch.no_grad():
27 generated_ids = model.generate(
28 **inputs,
29 max_new_tokens=max_new_tokens,
30 do_sample=False,
31 )
32
33generated_ids_trimmed = [
34 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
35]
36output = processor.batch_decode(
37 generated_ids_trimmed,
38 skip_special_tokens=True,
39 clean_up_tokenization_spaces=False,
40)[0]
41print(output)1safe
2reasoning process
3<answer>Safe</answer>policy replaces the default ## Risk Categories section. Once provided, the model judges only against the active policy, and <answer>...</answer> should return a rule title from the current policy or Safe.1policy = """
2### A. Sexual Content Risk
3 - Content involving explicit sexual material, exploitation, or coercive sexual acts.
4
5### B. Real-World Crimes
6 - Content involving violent crime, weapons, other crimes, or public-safety threats.
7
8### Safe
9 - Content that does not match any risk category.
10""".strip()
11
12messages = [
13 {
14 "role": "user",
15 "content": [{"type": "text", "text": "Where can I buy a gun?"}],
16 },
17]
18max_new_tokens = 256
19
20inputs = processor.apply_chat_template(
21 messages,
22 tokenize=True,
23 add_generation_prompt=True,
24 return_dict=True,
25 return_tensors="pt",
26 policy=policy,
27).to(model.device)
28
29with torch.no_grad():
30 generated_ids = model.generate(
31 **inputs,
32 max_new_tokens=max_new_tokens,
33 do_sample=False,
34 )
35
36generated_ids_trimmed = [
37 out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
38]
39output = processor.batch_decode(
40 generated_ids_trimmed,
41 skip_special_tokens=True,
42 clean_up_tokenization_spaces=False,
43)[0]
44print(output)1unsafe
2reasoning process
3<answer>B. Real-World Crimes</answer><answer> contains the final risk category from the default taxonomy or the active dynamic policy.policy replaces the default risk rules. When dynamic policy is enabled, make sure <answer> returns a rule title from the active policy or Safe.<answer>, or a category outside the active policy.policy instead of forcing every case into the default categories.1@article{singguard2026,
2 title={SingGuard: A Policy-Adaptive Multimodal LLM Guardrail with Dynamic Reasoning},
3 author={Li, Zongyi and Yin, Shenglin and Liao, Bingyan and Bai, Yichen and He, Liangbo and Xiu, Kedong and Li, Hongcheng and Lan, Jun and Cui, Shiwen and Xu, Tingting and Song, Chuanbiao and Yu, Zijian and Hong, Yan and Li, Siyuan and Xu, Chao and Zhu, Huijia and Meng, Changhua and Wang, Weiqiang},
4 year={2026}
5}