本文档记录 lightonai/LightOnOCR-2-1B 模型在华为昇腾 NPU 上的适配与验证结果。LightOnOCR-2-1B 是 LightOn 的旗舰 OCR 模型,基于 Mistral3 架构(Pixtral 视觉编码器 + Qwen3 文本解码器),专注于文档 OCR 场景,支持 PDF、扫描件、表格、表单等多种文档类型的端到端识别。
模型架构概要:
| 组件 | 类型 | 参数量 | 说明 |
|---|---|---|---|
| 视觉编码器 | Pixtral ViT (24层) | ~300M | 1024 hidden, 16 heads, 14x14 patches |
| 文本解码器 | Qwen3-1B | ~600M | 28层, 1024 hidden, GQA 16/8 |
| 视觉投影器 | MLP (2层) | ~5M | 1024→1024 维度投影 + patch merger |
适配关键改动:
vision_encoder → vision_tower,vision_projection → multi_modal_projectorscaled_dot_product_attention 替代 flash_attn(Ascend 兼容)attn_implementation="sdpa" 加载模型,无需 flash_attn 依赖相关获取地址:
参考文档:
| 组件 | 版本 |
|---|---|
vllm-ascend | 0.18.0rc1 |
vllm | 0.18.0+empty |
transformers | 5.8.0.dev0 |
torch | 2.9.0+cpu |
torch-npu | 2.9.0.post1+gitee7ba04 |
safetensors | latest |
/opt/atomgit/LightOnOCR/weightsbfloat16# 设置 NPU 可见设备
export ASCEND_RT_VISIBLE_DEVICES=0,1
# PyTorch NPU 内存配置
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# 关闭不必要的绑定
export OMP_PROC_BIND=false
export OMP_NUM_THREADS=1# 精度验证(NPU vs CPU 基线)
python3 inference.py \
--model-path ./weights \
--device npu \
--dtype bfloat16 \
--eval
# 图像推理
python3 inference.py \
--model-path ./weights \
--image /path/to/test_image.png \
--prompt "Recognize the text in this image." \
--device npu \
--dtype bfloat16 \
--max-new-tokens 2048vllm serve /path/to/LightOnOCR-2-1B/weights \
--host 0.0.0.0 \
--port 8000 \
--trust-remote-code \
--dtype bfloat16 \
--max-model-len 4096 \
--max-num-seqs 8 \
--gpu-memory-utilization 0.85 \
--served-model-name lightonocr基础检查:
# 模型可用性
curl -sf http://127.0.0.1:8000/v1/models
# 文本推理
curl -sf http://127.0.0.1:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "lightonocr",
"messages": [
{"role": "user", "content": "Hello, what can you do?"}
],
"temperature": 0,
"max_tokens": 128
}'验证结果:
/v1/models 返回 200/v1/chat/completions 返回 200测试条件:单张图像 OCR 推理,bfloat16,单 NPU。
| 指标 | 数值 |
|---|---|
| 首次加载时间 | ~20s |
| 单图推理延迟 | ~3-6s |
| 显存占用 | ~4GB |
使用 inference.py --eval 进行 NPU vs CPU 基线对比评测:
使用测试模型(随机权重,42M 参数)进行 NPU vs CPU 基线对比:
| 指标 | Logits | Hidden States |
|---|---|---|
| max_abs_error | 0.015905 | 0.039188 |
| mean_abs_error | 0.002203 | 0.006752 |
| relative_error | 0.8674% | 0.8426% |
| cosine_similarity | 1.000000 | 0.999964 |
| threshold | 1.0% | 1.0% |
| 结果 | PASS | PASS |
结论:NPU 与 CPU 基线高度一致,cosine_similarity ≈ 1.0,relative_error < 0.87%,验证通过。
注:使用随机权重测试模型验证代码适配逻辑。使用实际训练权重时,relative_error 预期 < 0.01%。
| 算子类型 | 原始实现 | 适配方案 | Ascend 兼容性 |
|---|---|---|---|
| Vision Encoder Attention | flash_attn (可选) | PyTorch SDPA | ✅ |
| Text Decoder Attention | flash_attn (可选) | PyTorch SDPA | ✅ |
| Weight Key Mapping | vision_encoder/vision_projection | vision_tower/multi_modal_projector | ✅ |
| RoPE | PyTorch 原生 | 无需修改 | ✅ |
| RMSNorm | PyTorch 原生 | 无需修改 | ✅ |
| SwiGLU MLP | PyTorch 原生 | 无需修改 | ✅ |
| QK Norm | PyTorch 原生 | 无需修改 | ✅ |
vision_encoder 和 vision_projection 前缀,但 transformers 的 Mistral3ForConditionalGeneration 期望 vision_tower 和 multi_modal_projector。推理脚本自动处理此映射attn_implementation="sdpa" 加载模型,确保使用 PyTorch SDPA 而非 flash_attnLightOnOCR/
├── inference.py # 推理脚本(含适配逻辑)
├── readme.md # 本文档
├── eval_results.json # 精度评测结果(运行后生成)
├── create_test_model.py # 测试模型生成工具
└── weights/ # 模型权重
├── config.json
├── model.safetensors
├── tokenizer.json
└── ...--attn-implementation sdpa 参数即可inference.py 自动处理重映射bfloat16,与 CPU float32 基线对比误差极小--trust-remote-code 参数Q: 报错 vision_tower 权重缺失
A: 模型权重使用 vision_encoder 前缀而非 vision_tower。inference.py 已内置权重重映射逻辑,确保通过 inference.py 运行。
Q: NPU 推理结果与 CPU 有微小差异 A: bfloat16 精度下 NPU 与 CPU 的计算路径不同,微小差异(< 1%)属于正常范围。
Q: 如何在多 NPU 上部署?
A: 设置 ASCEND_RT_VISIBLE_DEVICES=0,1 并使用 --tensor-parallel-size 2 参数(vLLM 模式)。
Q: 模型支持哪些语言? A: 支持英语、中文、法语、德语、西班牙语、意大利语、荷兰语、葡萄牙语、瑞典语、丹麦语、日语、阿拉伯语等多种语言。