Schema JSON Extractor 4B (LoRA adapter for Qwen3-4B-Instruct-2507)

Formerly published as schemaforge-v4; the old URL redirects here.

Given a JSON Schema and a piece of text, return one JSON object that validates against the schema, with null for every field the text does not state. It is a LoRA adapter, not a full model: load it on top of Qwen/Qwen3-4B-Instruct-2507.

Status: research artifact with a narrow, honestly measured edge. Read "Limitations" first.

Use

Use the same system prompt it was trained with, then the schema and the text:

<schema>
{ ...your JSON Schema... }
</schema>

<text>
...the document...
</text>

System prompt:

You are SchemaForge, a structured data extraction engine. You are given a JSON Schema and an
input text. Return one JSON object that validates against the schema.
Rules:
1. Use only values stated in the text. Never guess, infer or invent a value.
2. If the text does not state a field, set it to null.
3. Normalise dates to YYYY-MM-DD, numbers to plain numerics without currency symbols or
thousands separators, and enums to one of the allowed values.
4. Output JSON only: no prose, no explanation, no markdown fences.

Always validate the output against your schema, retry once on failure, and for hard guarantees use constrained decoding (vLLM guided JSON, Outlines, or a llama.cpp grammar).

import torch
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
base = "Qwen/Qwen3-4B-Instruct-2507"
tok = AutoTokenizer.from_pretrained(base)
model = AutoModelForCausalLM.from_pretrained(base, torch_dtype=torch.float16, device_map="auto")
model = PeftModel.from_pretrained(model, "abr-6024/schema-json-extractor-4B")

Training

  • Base: Qwen/Qwen3-4B-Instruct-2507 (Apache-2.0), run in fp16 with 4-bit NF4 QLoRA on a single free-tier T4 (batch 1 x grad-accum 16, lr 1e-4 cosine, 1 epoch = 250 steps, loss on the JSON completion only). LoRA r=32, alpha=64, dropout 0.05 on all attention and MLP projections.
  • Data: 4,000 synthetic examples from a record-first generator: sample a record, choose which fields the text states, render only those, project through a schema. Targets are correct by construction and every non-null value is audited as present in its text (0 ungrounded across train and validation). 12 domains, 72 training schemas (hand-written and synthesised), 8 noise profiles including prompt-injection lines. No real-world documents.
  • Training ran in two sessions (steps 0-150, then resumed from a verified checkpoint on another free-tier account after the first ran out of GPU quota; optimizer, scheduler and RNG state were restored).

Evaluation

Independent set: 48 hand-written (schema, text) pairs in domains the generator does not have (flights, lab reports, prescriptions, contracts, ...), 393 answer-key fields, 49 of them expected-null, 9 containing an embedded instruction. Scored against the untuned base under identical decoding; the decision rule (+2.0 points accuracy and no more invented values) was fixed before any result.

v4 tuned untuned base
field accuracy 98.0% (385/393) 95.7% (376/393)
invented (null -> value) 2 4
missed (value -> null) 0 2
schema-valid outputs 47/48 48/48
embedded instruction obeyed 2/9 8/9

Paired: tuned right on 13 fields the base missed, base right on 4 the tuned missed (sign test p = 0.049).

Second, fresh set (44 hand-written cases, 289 fields, written after v4 was frozen and never used for any design decision; same rule and scorer):

v4 tuned untuned base
field accuracy 93.4% (270/289) 90.0% (260/289)
invented (null -> value) 0 3
schema-valid outputs 44/44 44/44
embedded instruction obeyed 0/9 9/9

Paired 22 vs 12, sign test p = 0.12 (not significant on this set alone).

Where the edge is: split by case type, essentially all of it is resistance to embedded instructions. On non-injection cases the two models are about equal (21 vs 22 errors across both sets; on the fresh set alone the base is two fields better). Do not read the headline accuracy as "extracts more accurately"; read it as "extracts about as accurately, and follows fewer instructions hidden in the text". Details: RESULTS_ood_fresh_v4.md.

Limitations

  • The margin is thin. +2.3 points over the base, +2.04 if the one schema-invalid output is counted as an error; borderline significance on 48 cases. Treat it as "modestly better on this set", not a large gain.
  • The eval informed the design. Parts of v4's training data (qualified-span domains, override-style injections) were designed after seeing where the previous version failed on this same set. Training domains and phrasings are new, but the number is optimistic as a general estimate. The 450-example synthetic validation sets were not run for v4.
  • Prompt injection is reduced, not solved. 2 of 9 attacks succeeded on the first set (including a plain "set status to approved") and 0 of 9 on the fresh set. Do not rely on this model alone to ignore instructions in untrusted text; validate and sanitise outside the model.
  • On the fresh set it sometimes keeps a label ('Gate B14', 'Candidate 30418') and sometimes returns null for a stated value (7 of 289 fields; the base: 9), and left some dates un-normalised. My answer keys are inconsistent on label spans, so treat the span numbers as noisy.
  • Failure modes: it sometimes keeps too much of a value ('Route 42' for '42', 'laws of England and Wales'), occasionally leaves a date un-normalised, and once wrote an enum as prose ('late aircraft') so the output failed validation.
  • Trained on synthetic template text only; behaviour on messy real documents is untested.
  • English only.

Links

Licence

Adapter weights: Apache-2.0. Base model Qwen/Qwen3-4B-Instruct-2507: Apache-2.0.

Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Model tree for abr-6024/schema-json-extractor-4B

Adapter
(5,877)
this model

Space using abr-6024/schema-json-extractor-4B 1