CoolFace
Modelpublic

vankey/DocShield-9B

sourceHugging Faceapache-2.0updated 3mo agoView on Hugging Face
2likes50downloads
inference.py261 linesDownload Raw Back to root
1#!/usr/bin/env python32import argparse3import os4import torch5 6from qwen_vl_utils import process_vision_info7from transformers import (8    AutoProcessor,9    AutoTokenizer,10    AutoModelForImageTextToText,11)12 13 14DEFAULT_SYSTEM_PROMPT = (15    "你是一个图像鉴伪专家,擅长结合视觉,文字结合伪造特征分析手段鉴别输入图像的真假。"16    "分析过程中,你会逐步分析,抽丝剥茧,找到图像伪造的蛛丝马迹,"17    "最终给出专业的鉴别结果及分析。"18)19 20DEFAULT_USER_PROMPT = (21    "请分析这张文档图片是否存在伪造或篡改风险,并输出一份专业、精炼、准确的防伪分析报告。"22)23 24 25def build_messages(image_path: str, system_prompt: str, user_prompt: str):26    return [27        {28            "role": "system",29            "content": [30                {31                    "type": "text",32                    "text": system_prompt,33                }34            ],35        },36        {37            "role": "user",38            "content": [39                {40                    "type": "image",41                    "image": image_path,42                },43                {44                    "type": "text",45                    "text": user_prompt,46                },47            ],48        },49    ]50 51 52def parse_args():53    parser = argparse.ArgumentParser()54 55    parser.add_argument(56        "--model-name",57        type=str,58        default="vankey/DocShield-9B",59    )60    parser.add_argument(61        "--image",62        type=str,63        required=True,64        help="Input image path.",65    )66    parser.add_argument(67        "--prompt",68        type=str,69        default=DEFAULT_USER_PROMPT,70    )71    parser.add_argument(72        "--system-prompt",73        type=str,74        default=DEFAULT_SYSTEM_PROMPT,75    )76 77    thinking_group = parser.add_mutually_exclusive_group()78    thinking_group.add_argument(79        "--thinking",80        action="store_true",81        help="Enable Qwen3.5 thinking mode.",82    )83    thinking_group.add_argument(84        "--no-thinking",85        action="store_true",86        help="Disable Qwen3.5 thinking mode.",87    )88 89    parser.add_argument(90        "--max-new-tokens",91        type=int,92        default=1024,93    )94    parser.add_argument(95        "--temperature",96        type=float,97        default=0.0,98    )99    parser.add_argument(100        "--top-p",101        type=float,102        default=0.8,103    )104    parser.add_argument(105        "--top-k",106        type=int,107        default=20,108    )109    parser.add_argument(110        "--do-sample",111        action="store_true",112        help="Use sampling. If not set, greedy decoding is used.",113    )114    parser.add_argument(115        "--device",116        type=str,117        default="cuda",118    )119    parser.add_argument(120        "--dtype",121        type=str,122        default="bf16",123        choices=["bf16", "fp16", "fp32"],124    )125 126    return parser.parse_args()127 128 129def get_torch_dtype(dtype: str):130    if dtype == "bf16":131        return torch.bfloat16132    if dtype == "fp16":133        return torch.float16134    return torch.float32135 136 137def main():138    args = parse_args()139 140    if not os.path.exists(args.image):141        raise FileNotFoundError(f"Image not found: {args.image}")142 143    enable_thinking = False144    if args.thinking:145        enable_thinking = True146    if args.no_thinking:147        enable_thinking = False148 149    torch_dtype = get_torch_dtype(args.dtype)150 151    print("=" * 100)152    print("Model:", args.model_name)153    print("Image:", args.image)154    print("Prompt:", args.prompt)155    print("Enable thinking:", enable_thinking)156    print("Max new tokens:", args.max_new_tokens)157    print("dtype:", args.dtype)158    print("=" * 100)159 160    tokenizer = AutoTokenizer.from_pretrained(161        args.model_name,162        use_fast=True,163        trust_remote_code=True,164    )165 166    processor = AutoProcessor.from_pretrained(167        args.model_name,168        trust_remote_code=True,169    )170 171    model = AutoModelForImageTextToText.from_pretrained(172        args.model_name,173        torch_dtype=torch_dtype,174        trust_remote_code=True,175        device_map="auto",176    )177 178    model.eval()179 180    messages = build_messages(181        image_path=args.image,182        system_prompt=args.system_prompt,183        user_prompt=args.prompt,184    )185 186    text = processor.apply_chat_template(187        messages,188        tokenize=False,189        add_generation_prompt=True,190        enable_thinking=enable_thinking,191    )192 193    print("\n" + "=" * 100)194    print("Rendered prompt preview:")195    print(text[:2000])196    print("=" * 100 + "\n")197 198    image_inputs, video_inputs = process_vision_info(messages)199 200    inputs = processor(201        text=[text],202        images=image_inputs,203        videos=video_inputs,204        padding=True,205        return_tensors="pt",206    )207 208    inputs = inputs.to(model.device)209 210    print("input_ids shape:", inputs["input_ids"].shape)211    if "pixel_values" in inputs:212        print("pixel_values shape:", inputs["pixel_values"].shape)213    if "image_grid_thw" in inputs:214        print("image_grid_thw:", inputs["image_grid_thw"])215 216    generation_kwargs = {217        "max_new_tokens": args.max_new_tokens,218    }219 220    if args.do_sample:221        generation_kwargs.update(222            {223                "do_sample": True,224                "temperature": args.temperature,225                "top_p": args.top_p,226                "top_k": args.top_k,227            }228        )229    else:230        generation_kwargs.update(231            {232                "do_sample": False,233            }234        )235 236    with torch.no_grad():237        generated_ids = model.generate(238            **inputs,239            **generation_kwargs,240        )241 242    generated_ids_trimmed = [243        out_ids[len(in_ids):]244        for in_ids, out_ids in zip(inputs["input_ids"], generated_ids)245    ]246 247    output_text = processor.batch_decode(248        generated_ids_trimmed,249        skip_special_tokens=False,250        clean_up_tokenization_spaces=False,251    )[0]252 253    print("\n" + "=" * 100)254    print("Model output:")255    print(output_text)256    print("=" * 100)257 258 259if __name__ == "__main__":260    main()261