Training
Distilled from kimi-k2.6: the teacher extracted layout JSON for 10,000 PDFs sampled from FinePDFs (Common Crawl), rendered with pdfboss at about 1224 px. The student trained on 60,284 page/JSON pairs with a doc-disjoint eval split.
Table | |
|---|
| Base | Qwen/Qwen3-VL-4B-Instruct, ViT and aligner frozen |
| Method | LoRA r=8, alpha=32, all-linear, lr 1e-4, bf16 |
| Schedule | 1 epoch, 3,768 steps, effective batch 16 (2x RTX 4090, DDP) |
| Context | max_length 6144, IMAGE_MAX_TOKEN_NUM 1024 |
| Framework | ms-swift 4.5.2 |
| Final losses | train 0.115, eval 0.134 |
Evaluation
Generation eval on 1,652 held-out pages (greedy, max_new_tokens 4096):
Table with columns: Metric, Value| Metric | Value |
|---|
| Valid JSON | 98.0% (all failures are max-token truncations on dense pages) |
| Element count | 13,558 predicted vs 13,532 reference; exact per-page match 65.8% |
| Detection P / R / F1 at IoU >= 0.5 | 0.614 / 0.616 / 0.615 |
| Mean IoU of matched boxes | 0.675 |
| Type accuracy on matched boxes | 93.0% |
| Out-of-range bboxes | 0.21% |
Reference labels come from the teacher model.
Usage
Tested with ms-swift:
IMAGE_MAX_TOKEN_NUM=1024 swift infer \
--adapters 4thel00z/kaktus-bbox-lora-v1 \
--infer_backend pt --max_new_tokens 8192 --temperature 0
With transformers + peft:
from transformers import AutoModelForImageTextToText, AutoProcessor
from peft import PeftModel
base = "Qwen/Qwen3-VL-4B-Instruct"
model = AutoModelForImageTextToText.from_pretrained(base, torch_dtype="bfloat16", device_map="auto")
model = PeftModel.from_pretrained(model, "4thel00z/kaktus-bbox-lora-v1")
processor = AutoProcessor.from_pretrained(base)
Prompt with the page as the image and the instruction "Extract this page. Respond with only the JSON object." The system prompt is in args.json. Use max_new_tokens >= 8192 for dense pages and clip bbox values to [0, 1000].
Limitations
- Training labels are model-generated (kimi-k2.6), not human annotations. form_field (0.23 recall) and equation (0.45) are the weakest classes.
- On very dense pages the model can continue a repeating element pattern slightly past the 1000 grid edge. Clip coordinates after parsing.
- Pages that need more than about 4k output tokens truncate mid-JSON unless you raise the generation budget.
- The corpus is English-heavy (FinePDFs eng_Latn).
Training history
TRAINING_HISTORY.md records hardware moves, config changes mid-run, and the exact data snapshot. Training arguments are in args.json.