File size: 5,509 Bytes
055ec09
95ea2c2
055ec09
95ea2c2
 
 
 
 
 
 
 
 
 
 
 
 
055ec09
95ea2c2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
---
library_name: transformers
license: apache-2.0
language:
  - zh
  - en
base_model:
  - Qwen/Qwen2.5-VL-7B-Instruct
pipeline_tag: image-text-to-text
tags:
  - forgery-detection
  - document-forensics
  - image-tampering
  - vision-language-model
  - vlm
  - qwen2.5-vl
---

<p align="center">
  <img src="docshield_showcase.png" alt="DocShield-7B showcase" width="90%">
</p>

# DocShield-7B

**DocShield-7B** is a forensic-grade vision-language model for **document / image forgery analysis**. It inspects an input image, reasons step-by-step over visual tampering traces and logical consistency, and produces a professional forgery-analysis report with localized tampered regions and a forgery score.

It is fine-tuned from [Qwen2.5-VL-7B-Instruct](https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct) with supervised chain-of-thought (CoT) reasoning on document-forgery data.

📄 **Paper:** [arxiv.org/abs/2604.02694](https://arxiv.org/abs/2604.02694)

## Capabilities

- **Visual forgery trace analysis** — font / glyph / kerning / baseline inconsistency, copy-paste artifacts, edge halos, compression mismatches, noise-pattern breaks.
- **Logical & fact-checking** — impossible dates, failed calculations, contradictory metadata, domain-commonsense violations.
- **Localization** — bounding boxes of tampered regions with per-region reasoning.
- **Structured CoT report** — forensic-style report with a final conclusion and forgery score.

## Model details

| | |
|---|---|
| Base model | Qwen2.5-VL-7B-Instruct |
| Architecture | Qwen2_5_VLForConditionalGeneration |
| Inference resolution | 1344 × 896 (W × H) |
| Precision (weights) | bfloat16 |
| Precision (compute) | float32 (load with `torch_dtype=torch.float32`) |
| Max new tokens | 8192 |

> The weights are stored in **bfloat16** (~16 GB). Always load them with
> `torch_dtype=torch.float32` so computation runs in float32 (the bf16 weights are
> upcast on load). The base model is **not** bundled here — download it from
> [Qwen/Qwen2.5-VL-7B-Instruct](https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct) if needed.
> This repository only releases the fine-tuned DocShield-7B weights.

## Quick start

Install dependencies:

```bash
pip install transformers torch torchvision pillow opencv-python qwen-vl-utils
```

Run inference (see `inference.py` in this repo):

```bash
python inference.py --image path/to/image.jpg
```

### Minimal example

```python
import cv2, torch
from PIL import Image
from transformers import AutoProcessor, Qwen2_5_VLForConditionalGeneration
from qwen_vl_utils import process_vision_info

MODEL_PATH = "vankey/DocShield-7B"

model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
    MODEL_PATH,
    torch_dtype=torch.float32,
    attn_implementation="eager",
    device_map="auto",
)
model.eval()
processor = AutoProcessor.from_pretrained(MODEL_PATH)

SYSTEM_PROMPT = (
    "你是一个图像鉴伪专家,擅长结合视觉,文字结合伪造特征分析手段鉴别输入图像的真假。"
    "分析过程中,你会逐步分析,抽丝剥茧,找到图像伪造的蛛丝马迹,最终给出专业的鉴别结果及分析。"
)
USER_PROMPT = "请帮我分析这张图片是否是伪造的,并给出分析报告."

image = cv2.cvtColor(cv2.resize(cv2.imread("image.jpg"), (1344, 896)), cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)

messages = [
    {"role": "system", "content": SYSTEM_PROMPT},
    {"role": "user", "content": [
        {"type": "image", "image": image},
        {"type": "text", "text": USER_PROMPT},
    ]},
]

text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs,
                   padding=True, return_tensors="pt").to(model.device)

with torch.no_grad():
    out = model.generate(**inputs,
                         do_sample=True, temperature=1.0, top_p=1.0,
                         top_k=0, repetition_penalty=1.0,
                         max_new_tokens=8192)

generated = out[:, inputs["input_ids"].shape[1]:]
print(processor.batch_decode(generated, skip_special_tokens=True)[0])
```

## Inference notes (important)

These choices are required to reproduce the reported results:

1. **Image resize** — resize the input to `1344 × 896` (W × H) before processing:
   `cv2.resize(image, (1344, 896))`.
2. **Precision — load with `float32`, never compute in `bfloat16`.** The weights are
   stored as bfloat16; load them with `torch_dtype=torch.float32` so they are upcast
   and computation runs in float32. Computing in bfloat16 accumulates rounding error
   over the long CoT and degrades output into gibberish on harder images.
   `float16 + eager` attention also overflows (NaN) for long contexts.
   `float32 (compute) + eager` is the verified configuration.
3. **Sampling — `temperature=1.0, top_p=1.0, top_k=0, repetition_penalty=1.0`**
   (full multinomial sampling). Do **not** use the values in the bundled
   `generation_config.json` (`temperature=0.1, top_k=1, top_p=0.001,
   repetition_penalty=1.05`) — that near-greedy config triggers repetition loops.
4. **No flash-attention** — `attn_implementation="eager"`.

## Citation

```bibtex
@article{docshield2026,
  title={DocShield: A Forensic Vision-Language Model for Document Forgery Analysis},
  author={DocShield},
  year={2026},
  url={https://arxiv.org/abs/2604.02694}
}
```

## License

Apache-2.0.