Image-Text-to-Text
Transformers
Safetensors
Chinese
English
qwen3_5
forgery-detection
document-forensics
image-tampering
vision-language-model
vlm
qwen3.5-vl
conversational
Instructions to use vankey/DocShield-9B with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use vankey/DocShield-9B with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="vankey/DocShield-9B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] pipe(text=messages)# Load model directly from transformers import AutoProcessor, AutoModelForMultimodalLM processor = AutoProcessor.from_pretrained("vankey/DocShield-9B") model = AutoModelForMultimodalLM.from_pretrained("vankey/DocShield-9B") messages = [ { "role": "user", "content": [ {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"}, {"type": "text", "text": "What animal is on the candy?"} ] }, ] inputs = processor.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use vankey/DocShield-9B with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "vankey/DocShield-9B" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vankey/DocShield-9B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker
docker model run hf.co/vankey/DocShield-9B
- SGLang
How to use vankey/DocShield-9B with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "vankey/DocShield-9B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vankey/DocShield-9B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "vankey/DocShield-9B" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "vankey/DocShield-9B", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "Describe this image in one sentence." }, { "type": "image_url", "image_url": { "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg" } } ] } ] }' - Docker Model Runner
How to use vankey/DocShield-9B with Docker Model Runner:
docker model run hf.co/vankey/DocShield-9B
| #!/usr/bin/env python3 | |
| import argparse | |
| import os | |
| import torch | |
| from qwen_vl_utils import process_vision_info | |
| from transformers import ( | |
| AutoProcessor, | |
| AutoTokenizer, | |
| AutoModelForImageTextToText, | |
| ) | |
| DEFAULT_SYSTEM_PROMPT = ( | |
| "你是一个图像鉴伪专家,擅长结合视觉,文字结合伪造特征分析手段鉴别输入图像的真假。" | |
| "分析过程中,你会逐步分析,抽丝剥茧,找到图像伪造的蛛丝马迹," | |
| "最终给出专业的鉴别结果及分析。" | |
| ) | |
| DEFAULT_USER_PROMPT = ( | |
| "请分析这张文档图片是否存在伪造或篡改风险,并输出一份专业、精炼、准确的防伪分析报告。" | |
| ) | |
| def build_messages(image_path: str, system_prompt: str, user_prompt: str): | |
| return [ | |
| { | |
| "role": "system", | |
| "content": [ | |
| { | |
| "type": "text", | |
| "text": system_prompt, | |
| } | |
| ], | |
| }, | |
| { | |
| "role": "user", | |
| "content": [ | |
| { | |
| "type": "image", | |
| "image": image_path, | |
| }, | |
| { | |
| "type": "text", | |
| "text": user_prompt, | |
| }, | |
| ], | |
| }, | |
| ] | |
| def parse_args(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument( | |
| "--model-name", | |
| type=str, | |
| default="vankey/DocShield-9B", | |
| ) | |
| parser.add_argument( | |
| "--image", | |
| type=str, | |
| required=True, | |
| help="Input image path.", | |
| ) | |
| parser.add_argument( | |
| "--prompt", | |
| type=str, | |
| default=DEFAULT_USER_PROMPT, | |
| ) | |
| parser.add_argument( | |
| "--system-prompt", | |
| type=str, | |
| default=DEFAULT_SYSTEM_PROMPT, | |
| ) | |
| thinking_group = parser.add_mutually_exclusive_group() | |
| thinking_group.add_argument( | |
| "--thinking", | |
| action="store_true", | |
| help="Enable Qwen3.5 thinking mode.", | |
| ) | |
| thinking_group.add_argument( | |
| "--no-thinking", | |
| action="store_true", | |
| help="Disable Qwen3.5 thinking mode.", | |
| ) | |
| parser.add_argument( | |
| "--max-new-tokens", | |
| type=int, | |
| default=1024, | |
| ) | |
| parser.add_argument( | |
| "--temperature", | |
| type=float, | |
| default=0.0, | |
| ) | |
| parser.add_argument( | |
| "--top-p", | |
| type=float, | |
| default=0.8, | |
| ) | |
| parser.add_argument( | |
| "--top-k", | |
| type=int, | |
| default=20, | |
| ) | |
| parser.add_argument( | |
| "--do-sample", | |
| action="store_true", | |
| help="Use sampling. If not set, greedy decoding is used.", | |
| ) | |
| parser.add_argument( | |
| "--device", | |
| type=str, | |
| default="cuda", | |
| ) | |
| parser.add_argument( | |
| "--dtype", | |
| type=str, | |
| default="bf16", | |
| choices=["bf16", "fp16", "fp32"], | |
| ) | |
| return parser.parse_args() | |
| def get_torch_dtype(dtype: str): | |
| if dtype == "bf16": | |
| return torch.bfloat16 | |
| if dtype == "fp16": | |
| return torch.float16 | |
| return torch.float32 | |
| def main(): | |
| args = parse_args() | |
| if not os.path.exists(args.image): | |
| raise FileNotFoundError(f"Image not found: {args.image}") | |
| enable_thinking = False | |
| if args.thinking: | |
| enable_thinking = True | |
| if args.no_thinking: | |
| enable_thinking = False | |
| torch_dtype = get_torch_dtype(args.dtype) | |
| print("=" * 100) | |
| print("Model:", args.model_name) | |
| print("Image:", args.image) | |
| print("Prompt:", args.prompt) | |
| print("Enable thinking:", enable_thinking) | |
| print("Max new tokens:", args.max_new_tokens) | |
| print("dtype:", args.dtype) | |
| print("=" * 100) | |
| tokenizer = AutoTokenizer.from_pretrained( | |
| args.model_name, | |
| use_fast=True, | |
| trust_remote_code=True, | |
| ) | |
| processor = AutoProcessor.from_pretrained( | |
| args.model_name, | |
| trust_remote_code=True, | |
| ) | |
| model = AutoModelForImageTextToText.from_pretrained( | |
| args.model_name, | |
| torch_dtype=torch_dtype, | |
| trust_remote_code=True, | |
| device_map="auto", | |
| ) | |
| model.eval() | |
| messages = build_messages( | |
| image_path=args.image, | |
| system_prompt=args.system_prompt, | |
| user_prompt=args.prompt, | |
| ) | |
| text = processor.apply_chat_template( | |
| messages, | |
| tokenize=False, | |
| add_generation_prompt=True, | |
| enable_thinking=enable_thinking, | |
| ) | |
| print("\n" + "=" * 100) | |
| print("Rendered prompt preview:") | |
| print(text[:2000]) | |
| print("=" * 100 + "\n") | |
| image_inputs, video_inputs = process_vision_info(messages) | |
| inputs = processor( | |
| text=[text], | |
| images=image_inputs, | |
| videos=video_inputs, | |
| padding=True, | |
| return_tensors="pt", | |
| ) | |
| inputs = inputs.to(model.device) | |
| print("input_ids shape:", inputs["input_ids"].shape) | |
| if "pixel_values" in inputs: | |
| print("pixel_values shape:", inputs["pixel_values"].shape) | |
| if "image_grid_thw" in inputs: | |
| print("image_grid_thw:", inputs["image_grid_thw"]) | |
| generation_kwargs = { | |
| "max_new_tokens": args.max_new_tokens, | |
| } | |
| if args.do_sample: | |
| generation_kwargs.update( | |
| { | |
| "do_sample": True, | |
| "temperature": args.temperature, | |
| "top_p": args.top_p, | |
| "top_k": args.top_k, | |
| } | |
| ) | |
| else: | |
| generation_kwargs.update( | |
| { | |
| "do_sample": False, | |
| } | |
| ) | |
| with torch.no_grad(): | |
| generated_ids = model.generate( | |
| **inputs, | |
| **generation_kwargs, | |
| ) | |
| generated_ids_trimmed = [ | |
| out_ids[len(in_ids):] | |
| for in_ids, out_ids in zip(inputs["input_ids"], generated_ids) | |
| ] | |
| output_text = processor.batch_decode( | |
| generated_ids_trimmed, | |
| skip_special_tokens=False, | |
| clean_up_tokenization_spaces=False, | |
| )[0] | |
| print("\n" + "=" * 100) | |
| print("Model output:") | |
| print(output_text) | |
| print("=" * 100) | |
| if __name__ == "__main__": | |
| main() | |