Views
No views yet
openbmb/MiniCPM-V-2_6
that extracts line items from trade / contractor invoices as structured JSON
({"menu": [{"nm", "cnt", "price"}], "total": ...}) — HVAC, electrical, plumbing,
carpentry, roofing. Built for the Quillwright
project (a small-model agent that drafts trade estimates).naver-clova-ix/cord-v2, is Indonesian restaurant receipts). So we
built a grounded-synthetic corpus: a curated catalog of ~381 real trade
parts/services with real price bands (sourced from public retail listings, contractor
flat-rate templates, and cost guides), assembled into coherent jobs with code-owned
arithmetic and rendered through 8 distinct invoice templates. The generator and catalog
live in the Quillwright repo (finetune/synth/).| Metric | Baseline (un-tuned) | Tuned (this LoRA) | Δ |
|---|---|---|---|
| Item F1 | 0.703 | 0.933 | +0.230 |
| Quantity accuracy | 0.840 | 1.000 | +0.160 |
| Price accuracy | 0.643 | 1.000 | +0.357 |
| Precision | 0.700 | 0.933 | +0.233 |
| Recall | 0.707 | 0.933 | +0.226 |
openbmb/MiniCPM-V-2_6 (8B vision-language model)finetune/synth/.finetune.py + CPMTrainer, single GPU (L40S), no DeepSpeed,
bf16 LoRA. LoRA on the LLM self-attention projections (q/k/v/o) only; vision tower +
resampler frozen. r=64, α=64, dropout=0.05, lr=1e-5, model_max_length=2048, 3 epochs.1from peft import PeftModel
2from transformers import AutoModel, AutoTokenizer
3from PIL import Image
4
5PROMPT = ('Extract the line items from this receipt as JSON with this exact shape: '
6 '{"menu": [{"nm": <item name>, "cnt": <quantity>, "price": <price>}], '
7 '"total": <grand total>}. Output only the JSON.')
8
9base = AutoModel.from_pretrained("openbmb/MiniCPM-V-2_6", trust_remote_code=True,
10 attn_implementation="sdpa")
11model = PeftModel.from_pretrained(base, "Aarya2004/minicpmv-trade-lora",
12 trust_remote_code=True).eval().cuda()
13tok = AutoTokenizer.from_pretrained("openbmb/MiniCPM-V-2_6", trust_remote_code=True)
14
15img = Image.open("invoice.jpg").convert("RGB")
16msgs = [{"role": "user", "content": [img, PROMPT]}]
17print(model.chat(image=None, msgs=msgs, tokenizer=tok, sampling=False))MiniCPM-V-2_6's remote code hard-importsflash_attneven with SDPA; if you hit that ImportError, stripflash_attnfromtransformers.dynamic_module_utils.get_imports(seefinetune/flash_patch.pyin the Quillwright repo) — flash-attn is not required.