DEV Community

Jebra
Jebra

Posted on

Fine-Tuning with QLoRA for JSON Extraction

We needed to extract structured JSON from unstructured text for a domain-specific use case. We decided to train the Qwen2.5-1.5B-Instruct model with quantization levels of 4-bit, 8-bit and 16-bit separately.

Dataset
Total samples: ~280

Training
Fine-tuned using QLoRA


Evaluation Metrics

We measured two scores per split:

  1. Exact Match: Binary per sample (1 if all fields match exactly, else 0). Aggregated across the split.
  2. Field Match: Partial credit per sample (correct fields / total fields). Aggregated across the split.

Example:

Gold JSON

{
  "first_name": "Jordan",
  "last_name": "Kaur",
  "employment_type": "contractor",
  "employer_name": "Grounded Movement",
  "employer_email": "payroll@goat.com",
  "employer_address_line_1": "41 King Street",
  "employer_address_line_2": "Madison, UK",
  "employer_registration_number": null,
  "employer_tax_number": null,
  "currency": "USD",
  "pay_rate": 45.0,
  "pay_rate_basis": "per_shift",
  "incentive_pay": 5.0,
  "incentive_type": "per_reservation_over_n",
  "n": 15,
  "reservation_types": [
    "check_ins"
  ],
  "exclude_staff_reservations": true,
  "exclude_cancelled_shifts": true,
  "max_pay": null,
  "payment_frequency": "weekly"
}
Enter fullscreen mode Exit fullscreen mode
Predicted JSON (model output)

{
  "first_name": "Jordan",
  "last_name": "Kaur",
  "employment_type": "contractor",
>>"employer_name": "Grounded",<<
  "employer_email": "payroll@goat.com",
  "employer_address_line_1": "41 King Street",
  "employer_address_line_2": "Madison, UK",
  "employer_registration_number": null,
  "employer_tax_number": null,
  "currency": "USD",
  "pay_rate": 45.0,
>>"pay_rate_basis": null,<<
  "incentive_pay": 5.0,
  "incentive_type": "per_reservation_over_n",
  "n": 15,
  "reservation_types": [
    "check_ins"
  ],
  "exclude_staff_reservations": true,
  "exclude_cancelled_shifts": true,
  "max_pay": null,
  "payment_frequency": "weekly"
}
Enter fullscreen mode Exit fullscreen mode
Mismatch 1: "employer_name": "Grounded" (Predicted) vs "Grounded Movement" (Gold)
Mismatch 2: "pay_rate_basis": null (Predicted) vs "per_shift" (Gold)

Total Fields = 20
Correct Fields = 18
Wrong Fields = 2

Exact Match
Score: 0/1

Field Level Match
Score: 18/20 = 0.9  (90%)
Enter fullscreen mode Exit fullscreen mode

Results (for 16-bit)

While we experimented with 4-bit, 8-bit and 16-bit QLoRA, the lower-bit experiments are omitted here for brevity.

-------------------------------------------------------------------
Model                    Exact Accuracy    Field Match
-------------------------------------------------------------------
Baseline                 0.00              0.54
Fine‑tuned               0.62              0.97

Enter fullscreen mode Exit fullscreen mode

Chart


Observations

Field match improved from ~54% to ~97% after fine-tuning.
Exact match, while lower (62%), improved from 0%.

The field-level result indicates that the adapter successfully learned the correct key-to-value mapping for the majority of fields.

Top comments (0)