Instructions to use betty0/vlm-receipt-extractor with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use betty0/vlm-receipt-extractor with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("unsloth/Qwen3-VL-8B-Instruct-unsloth-bnb-4bit") model = PeftModel.from_pretrained(base_model, "betty0/vlm-receipt-extractor") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Unsloth Studio
How to use betty0/vlm-receipt-extractor with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for betty0/vlm-receipt-extractor to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for betty0/vlm-receipt-extractor to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for betty0/vlm-receipt-extractor to start chatting
Load model with FastModel
pip install unsloth from unsloth import FastModel model, tokenizer = FastModel.from_pretrained( model_name="betty0/vlm-receipt-extractor", max_seq_length=2048, )
vlm-receipt-extractor:Qwen3-VL-8B QLoRA(收據影像 → 結構化 JSON)
對 Qwen3-VL-8B-Instruct 做 QLoRA 微調的 LoRA adapter,任務是把收據照片直接轉成固定 schema 的結構化 JSON(品項、單價、數量、小計、折扣、服務費、稅金、總額)。
任務說明
輸入一張收據照片,輸出:
{
"items": [
{"name": "Nasi Goreng", "count": 2, "unit_price": 25000, "price": 50000}
],
"subtotal": 50000,
"discount": null,
"service": null,
"tax": 5000,
"total": 55000
}
Schema 完整對齊 CORD-v2 的 gt_parse 標註(不含店名/日期,因為原始標註沒有這兩欄);收據上沒有印的欄位一律輸出 null,金額為純數值(已去除千分位符號)。
Foundation Model 與訓練設定
- Foundation Model:
unsloth/Qwen3-VL-8B-Instruct-unsloth-bnb-4bit(Unsloth 預量化的 4-bit 版本,vision tower 維持 bf16) - 方法:Unsloth QLoRA,
finetune_vision_layers=True、finetune_language_layers=True、finetune_attention_modules=True、finetune_mlp_modules=True - LoRA:r=16、alpha=16、dropout=0、bias=none
- 訓練:2 epochs、batch size 2 × gradient accumulation 4(有效 batch size 8)、lr=2e-4(linear schedule)、seed=3407
- 資料:CORD-v2 官方 train split(800 筆),影像最長邊縮至 1280px
- 硬體:單張 RTX 4090(24GB),實際訓練耗時 19.2 分鐘、200 steps,峰值 VRAM 10.27GB
- 驗證:epoch 1 eval_loss=0.0086 → epoch 2 eval_loss=0.0078(持續下降,無過擬合跡象)
微調前後對照(CORD-v2 test split,100 筆,greedy decoding、相同 prompt)
| 指標 | 微調前(zero-shot) | 微調後 |
|---|---|---|
| 合法 JSON 率 | 100.0% | 100.0% |
| total exact match | 75.0% | 90.0% |
| 欄位級 micro F1 | 0.744 | 0.930 |
各欄位 F1 進步最多的:items.unit_price(0.32→0.91)、discount(0.27→0.86)、service(0.57→0.92)。
微調前的 zero-shot 模型有兩個系統性問題:(1) 把收據上印尼盾金額的千分位句點(如 25.000 = 兩萬五千)誤讀成小數點,輸出成 25.0;(2) 會自行「腦補」收據上沒印的 unit_price,或把品項名稱合併/截斷。微調後這兩類錯誤大幅減少。完整對照表與案例展示見 repo 內的 results/comparison.md。
使用方式
import unsloth # 必須放在最前面:修正 transformers/bitsandbytes 對 Qwen3-VL vision tower 的一個載入 bug,即使下面完全不用 FastVisionModel 也需要
from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
from peft import PeftModel
from PIL import Image
import torch
BASE = "unsloth/Qwen3-VL-8B-Instruct-unsloth-bnb-4bit"
model = Qwen3VLForConditionalGeneration.from_pretrained(BASE, device_map="cuda") # 不要額外傳 quantization_config,checkpoint 自帶
model = PeftModel.from_pretrained(model, "betty0/vlm-receipt-extractor")
processor = AutoProcessor.from_pretrained(BASE)
image = Image.open("receipt.jpg").convert("RGB")
prompt = (
'Extract all information from this receipt image and return it as a JSON object with exactly this structure:\n'
'{"items": [{"name": <string>, "count": <integer or null>, "unit_price": <number or null>, "price": <number or null>}], '
'"subtotal": <number or null>, "discount": <number or null>, "service": <number or null>, "tax": <number or null>, "total": <number or null>}\n'
'Rules: amounts must be plain numbers without currency symbols or thousands separators; use null for values not present on the receipt; '
'output only the JSON object with no explanation and no markdown.'
)
messages = [{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": prompt}]}]
text = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
inputs = processor(text=[text], images=[image], return_tensors="pt").to("cuda")
with torch.inference_mode():
out = model.generate(**inputs, max_new_tokens=768, do_sample=False)
print(processor.batch_decode(out[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)[0])
資料集出處與授權
訓練與評估資料為 naver-clova-ix/cord-v2(CORD: A Consolidated Receipt Dataset for Post-OCR Parsing,Park et al., NeurIPS 2019 Workshop),授權為 CC-BY-4.0。收據皆來自印尼零售/餐飲場景,語言以印尼文為主、金額為印尼盾。
已知限制
- 訓練與評估資料集中在印尼零售/餐飲收據,換成其他國家/語言/版面的收據時準確率預期會下降。
- Schema 不含店名與日期,因為 CORD-v2 的
gt_parse標註本身沒有這兩欄。 - 訓練集僅 800 筆、2 epochs,未涵蓋所有收據版面變化(例如手寫收據、極長品項清單)。
discount/service在資料中出現率較低(訓練集分別 7.6%/12.2%),對應的 F1 雖有大幅提升但樣本數仍偏少,實際部署時建議針對目標場景另外驗證。
LoRA 設定細節
r=16、lora_alpha=16、lora_dropout=0、bias=none。target_modules 是 Unsloth 產生的正規表示式,涵蓋 vision tower 與language model 兩側的 attention(q/k/v/o_proj)與 MLP(gate/up/down_proj、linear_fc1/fc2)投影層,完整內容見本 repo 的 adapter_config.json。
- Downloads last month
- 32
Model tree for betty0/vlm-receipt-extractor
Base model
Qwen/Qwen3-VL-8B-Instruct