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: Policy-Adaptive Multimodal Safeguarding with Dynamic Reasoning},
3 author={Ant Group},
4 year={2026}
5}