Instructions to use aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("image-text-to-text", model="aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO") 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("aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO") model = AutoModelForMultimodalLM.from_pretrained("aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO", device_map="auto") 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 aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO", "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/aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO
- SGLang
How to use aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO 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 "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO" \ --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": "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO", "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 "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO" \ --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": "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO", "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 aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO with Docker Model Runner:
docker model run hf.co/aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO
AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO (research preview / future work)
This is a research-preview checkpoint and is NOT the thesis headline model. It is released for completeness alongside the AnomalyThink family. The reported/headline model of the thesis is the Arm-C SFT checkpoint
aacudad/AnomalyThink-Qwen2.5-VL-7B(DS-MVTec 82.80 / VisA 72.07). The GRPO run below is discussed only as future work.
A reasoning-enhanced vision-language model for explainable industrial anomaly detection. It
starts from Qwen2.5-VL-7B-Instruct, is
supervised-fine-tuned on Gemini-2.5-Flash "AnomalyThink" reasoning traces (the Arm-C teacher-ablation
model), and then trained further with GRPO on top of that Arm-C init, with the RL training prompt
aligned to the evaluation prompt (KL penalty β = 0.1, ~3 epochs, reward = accuracy + consistency).
This is checkpoint-954 of that run.
Why "future work" and not a result
GRPO on the already-strong Arm-C init edges the SFT ceiling on average but the trajectory bounces across epoch 3 rather than climbing monotonically, so the gain is small and not yet clearly stable. The thesis therefore reports the Arm-C SFT model as the headline and holds this run as future work. Do not read these numbers as "GRPO beat SFT".
Balanced accuracy (checkpoint-954)
Balanced accuracy BA = 0.5 * (TP/(TP+FN) + TN/(TN+FP)), recomputed from the raw tp/tn/fp/fn of
each eval JSON (shipped in the code repo).
| Benchmark | BA | tp | tn | fp | fn | n |
|---|---|---|---|---|---|---|
| DS-MVTec | 82.95 | 1004 | 373 | 71 | 222 | 1670 |
| VisA | 72.62 | 719 | 804 | 140 | 478 | 2141 |
Average 77.78, versus the Arm-C init's 77.44 (82.80 / 72.07).
The AnomalyThink family for context
| Model | DS-MVTec | VisA | Note |
|---|---|---|---|
…-7B (Arm-C SFT) |
82.80 | 72.07 | thesis headline |
…-7B-SFT (SFT-6K) |
80.16 | 64.78 | |
…-7B-SFT-GRPO (GRPO on SFT-6K, ckpt-530) |
82.73 | 70.39 | released RL model |
| this model (GRPO on Arm-C, ckpt-954) | 82.95 | 72.62 | research preview / future work |
Usage
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
from qwen_vl_utils import process_vision_info
model_id = "aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO"
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(model_id, torch_dtype="auto", device_map="auto")
processor = AutoProcessor.from_pretrained(model_id)
messages = [{"role": "user", "content": [
{"type": "image", "image": "file:///path/to/part.png"},
{"type": "text", "text": "Is there a defect in this product? Analyze and answer yes or no."},
]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
imgs, vids = process_vision_info(messages)
inputs = processor(text=[text], images=imgs, videos=vids, padding=True, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=512)
print(processor.batch_decode(out[:, inputs.input_ids.shape[1]:], skip_special_tokens=True)[0])
Links
- Code, training/eval scripts, and the exact
checkpoint-954eval JSONs: https://github.com/aacudad/IAD-VLMs - Dataset: https://huggingface.co/datasets/aacudad/AnomalyThink
- MSc thesis (TU Delft, 2026): Reasoning-Enhanced Vision-Language Models for Explainable Industrial Anomaly Detection, Adnane Acudad
Citation / license
Derived from Qwen2.5-VL-7B-Instruct (Apache-2.0). Evaluated on DS-MVTec and VisA (MMAD protocol); trained on AnomalyThink traces distilled from Gemini-2.5-Flash over Real-IAD.
- Downloads last month
- 8
Model tree for aacudad/AnomalyThink-Qwen2.5-VL-7B-ArmC-GRPO
Base model
Qwen/Qwen2.5-VL-7B-Instruct