P1-VL-30B-A3B is the mid-size variant of the P1-VL series, a high-performance open-source vision-language model specialized in physics reasoning. Introduced in
P1-VL: Bridging Visual Perception and Scientific Reasoning in Physics Olympiads, it is built on
Qwen3-VL-30B-A3B-Thinking and refined through multi-stage reinforcement learning on curated physics competition data. P1-VL-30B-A3B achieves impressive results while maintaining reasonable computational requirements, making it accessible for researchers working with physics problems that require visual understanding.
P1-VL-30B-A3B achieves significant gains over its base counterpart across all three scientific domains, demonstrating the effectiveness of multimodal training for scientific reasoning.
Beyond physics reasoning, P1-VL-30B-A3B demonstrates strong generalization across multiple domains, consistently outperforming its base model Qwen3-VL-30B-A3B-Thinking on both text-only and multimodal benchmarks.
1from transformers import Qwen3VLMoeForConditionalGeneration, AutoProcessor
2from PIL import Image
3
4model_name = "PRIME-RL/P1-VL-30B-A3B"
5
6# Load model and processor
7model = Qwen3VLMoeForConditionalGeneration.from_pretrained(
8 model_name, dtype="auto", device_map="auto"
9)
10processor = AutoProcessor.from_pretrained(model_name)
11
12# Load diagram image
13image = Image.open("physics_diagram.png")
14
15# Physics problem with visual input
16messages = [
17 {
18 "role": "user",
19 "content": [
20 {
21 "type": "image",
22 "image": image,
23 },
24 {
25 "type": "text",
26 "text": """Analyze this physics diagram and solve the problem:
27
28A block of mass m is placed on an inclined plane with angle θ.
29The coefficient of kinetic friction is μ.
30Calculate the acceleration of the block down the incline.""",
31 },
32 ],
33 }
34]
35
36# Preparation for inference
37inputs = processor.apply_chat_template(
38 messages,
39 tokenize=True,
40 add_generation_prompt=True,
41 return_dict=True,
42 return_tensors="pt"
43)
44
45# Inference: Generation of the output
46generated_ids = model.generate(**inputs, max_new_tokens=8192)
47generated_ids_trimmed = [
48 out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
49]
50output_text = processor.batch_decode(
51 generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
52)
53print(output_text[0])
We are grateful to the open-source community for their invaluable contributions. Special thanks to:
1@misc{p1vl2025,
2 title={P1-VL: Bridging Visual Perception and Scientific Reasoning in Physics Olympiads},
3 author={Yun Luo and Futing Wang and Qianjia Cheng and Fangchen Yu and Haodi Lei and Jianhao Yan and Chenxi Li and Jiacheng Chen and Yufeng Zhao and Haiyuan Wan and Yuchen Zhang and Shenghe Zheng and Junchi Yao and Qingyang Zhang and Haonan He and Wenxuan Zeng and Li Sheng and Chengxing Xie and Yuxin Zuo and Yizhuo Li and Yulun Wu and Rui Huang and Dongzhan Zhou and Kai Chen and Yu Qiao and Lei Bai and Yu Cheng and Ning Ding and Bowen Zhou and Peng Ye and Ganqu Cui},
4 year={2026},
5 url={https://arxiv.org/abs/2602.09443}
6}