Downloads · 30 days
101
26% of all-time downloads
ratlinghitman/qwen3vl-4b-receipt-extraction-gguf
qwen3vl-4b-receipt-extraction-gguf is a image-text-to-text model from ratlinghitman. Use it for the image-text-to-text task on the model card, and read the license before you ship it in a product. It is set up for gguf. The card lists the license as apache-2.0.
Reads a receipt image and returns it as structured JSON. GGUF build for llama.cpp, Ollama and LM Studio.
Downloads · 30 days
101
26% of all-time downloads
All-time downloads
391
Public
Repo size
3.3 GB
Likes
1
Trending 1
Click a slice to open those files.
.gguf3.3 GB · 100%
From the Hugging Face model README
Reads a receipt image and returns it as structured JSON. GGUF build for llama.cpp, Ollama and LM Studio.
| Base model | Qwen/Qwen3-VL-4B-Instruct |
| Fine-tuning | LoRA r=16, language tower only |
| Dataset | naver-clova-ix/cord-v2 |
| Format | Q4_K_M language model + f16 mmproj vision tower |
| Files | *-Q4_K_M.gguf (2.50 GB), mmproj-*-f16.gguf (0.84 GB) |
| Size on disk | 3.3 GB |
| Runtime | llama.cpp, Ollama, LM Studio |
Turning a photo or scan of a retail receipt into structured JSON, for bookkeeping and expense pipelines, or as a starting point for research on document understanding.
Invoices, handwritten notes, and non-receipt images. The model was never trained on them. It also should not be trusted to make financial decisions on its own; treat the output as an extraction to be reviewed.
The model expects one image and this exact prompt, which is the prompt it was trained with:
Extract the receipt from the image into a structured JSON. Your output should contain ONLY correct JSON!
Two files: the quantized language model and its mmproj vision tower. You need both.
huggingface-cli download <your-hf-username>/qwen3vl-4b-receipt-extraction-gguf --local-dir gguf
llama-server -m gguf/*-Q4_K_M.gguf --mmproj gguf/mmproj-*-f16.gguf -ngl 99 -c 8192
Then query the OpenAI-compatible endpoint with an image and the prompt:
Extract the receipt from the image into a structured JSON. Your output should contain ONLY correct JSON!
Your llama.cpp build must support the Qwen3-VL qwen3vl_merger projector. LM Studio and
Ollama load the same pair.
A single JSON object with three top-level keys: menu (the line items), sub_total and
total. Every value is a string, copied from the receipt.
{"menu": [{"nm": "Es Teh Manis", "cnt": "2", "price": "8,000"}],
"sub_total": {"subtotal_price": "8,000"},
"total": {"total_price": "8,000", "cashprice": "10,000", "changeprice": "2,000"}}
CORD-v2 test split, 100 receipts, greedy decoding, images capped at 1600 patches.
| field_f1 | nTED | json_validity | exact_match |
|---|---|---|---|
| 0.8737 | 0.9051 | 0.9700 | 0.4000 |
Measured in section 8.2b of finetune_qwen3vl.ipynb.
Neither subsumes the other, which is why both are here.
Fine-tuned from Qwen/Qwen3-VL-4B-Instruct with LoRA on naver-clova-ix/cord-v2
(800 train / 100 validation / 100 test receipts). Labels were losslessly normalized before
training.
| LoRA rank / alpha / dropout | 16 / 32 / 0.05 |
| Adapted modules | language tower only (q,k,v,o,gate,up,down_proj); vision tower frozen |
| Precision | bf16 |
| Learning rate | 1e-4 |
| Batch size | 2 per device x 4 gradient accumulation |
| Epochs | 20 |
| Image budget | 1600 patches of 28x28 |
Training ran well past convergence on purpose, so there was a wide range of adapters to pick from. Validation loss and the task metrics peak at different times here: loss starts rising around epoch 3, while the best field_f1 and nTED land at epoch 9 or later. The adapter published here is the one that scored best on the validation split by field_f1, and it was then scored once on the held-out test split. Early-stopping on loss would have picked a noticeably worse one.
The language model is quantized to Q4_K_M by llama.cpp's llama-quantize. This is
data-free: no calibration set, no receipts involved. The vision tower is exported separately
as an f16 mmproj file and is left unquantized.
It converts from the bf16 master rather than the GPTQ build, because llama.cpp cannot ingest GPTQ-packed weights. Being data-free, it gives up more than the calibrated GPTQ build does: field_f1 0.8737 here against 0.8840 for GPTQ, on the same test split.
nm, cnt, unitprice), not friendly names.apache-2.0, inherited from the base model. The CORD-v2 dataset carries its own terms; see
its dataset card.