Skip to main content

valjson

Diagnostics for structured JSON output from LLMs: extract, validate, fix, score per-field accuracy, and gate on confidence. Most commands need no model.

Fine-tuning your LLM for JSON? Your aggregate metrics might be hiding per-field regressions.

pip install valjson

What it does

valjson is the observability layer for structured JSON output. It meets you wherever you are:

You have Command Needs model?
Messy text with JSON valjson --extract --data output.txt No
JSON + schema valjson --validate --schema s.json --data output.jsonl No
Broken JSON + schema valjson --fix --schema s.json --data output.jsonl No
JSON + schema valjson --anatomy --schema s.json --data output.jsonl No
JSON + schema + gold valjson --compare --schema s.json --data output.jsonl --gold truth.jsonl No
Two output sets valjson --diff --schema s.json --data a.jsonl --data2 b.jsonl No
Per-field probabilities valjson --gate --data probs.jsonl No
Model + checkpoint valjson --checkpoint lora/ --schema s.json --data test.jsonl Yes

The problem

Standard fine-tuning + grammar-constrained decoding produces valid JSON. Aggregate loss improves. But:

STRUCTURAL         5.33 -> 0.00     -100%   OK
KEY                0.47 -> 0.00     -100%   OK
BOOLEAN            0.46 -> 1.05     +130%   !! REGRESSION
TOTAL              0.55 -> 0.17      -69%

Aggregate loss improved 69%. Boolean prediction got 130% worse. valjson catches this.

Per-field accuracy vs gold

When you have human-labeled gold JSONs, --compare gives you per-field accuracy without needing a model — role-aware, so a blown free-text field does not drown the signal on the constrained fields you actually care about:

valjson --compare \
    --schema schema.json \
    --data generated.jsonl \
    --gold gold.jsonl \
    --ignore-role STRING,ARRAY
  • --match-by <key> — pair records by ID (wrapper-first lookup), not line order.
  • --ignore-role STRING,ARRAY — focus on BOOLEAN / ENUM / NUMBER fields where exact equality is meaningful. Unmatched IDs are reported separately.

Evidential gating: abstain when the model is unsure

When the model returns a probability distribution over allowed values for each constrained field, --gate decides per record whether to commit, abstain, or reject based on the margin between the top two values:

valjson --gate \
    --data probs.jsonl \
    --margin-threshold 0.30

Input format (one record per line):

{"id": "rec-001",
 "probs": {
   "refundable": {"True": 0.553, "False": 0.447},
   "status":     {"submitted": 0.9, "pending": 0.1, "draft": 0.0}
 }}

A field's margin = top_prob − second_prob. If margin ≥ threshold, the field is committed; otherwise it abstains. Per-field abstention rates are reported — fields with persistently high abstention are diagnostic of underspecified training targets (the regression pattern this paper documents).

Quick start

See QUICK_START.md for a hands-on walkthrough from messy output to full analysis.

Python API

from valjson import analyze

report = analyze(
    model_name="Qwen/Qwen2.5-0.5B-Instruct",
    checkpoint="my_lora/",
    schema="schema.json",
    data="test.jsonl",
)
print(report)

if report.regressions:
    print(f"REGRESSIONS: {[r.role for r in report.regressions]}")

Exit code is 1 if regressions are detected. Use in CI/CD.

Grammar Roles

Role Description Examples
STRUCTURAL JSON syntax { } [ ] : ,
QUOTE String delimiters "
KEY Object key characters city, cuisine
ENUM_VALUE Categorical values Italian, Economy
BOOLEAN Boolean strings True, False
NUMBER Numeric characters 42, 3.14
FREE_TEXT Non-categorical content names, addresses
WHITESPACE Formatting spaces, newlines

License

MIT

Metadata

Release files for valjson 2.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for valjson 2.0.1
File Size Uploaded Provenance Actions
valjson-2.0.1.tar.gz 56.2 kB Without provenance Details for valjson-2.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for valjson 2.0.1
File Interpreter ABI Platform Actions
valjson-2.0.1-py3-none-any.whl Python 3 none any Details for valjson-2.0.1-py3-none-any.whl

Total release size: 121.1 kB

Release files / valjson-2.0.1.tar.gz

Download URL valjson-2.0.1.tar.gz
Size 56.2 kB
Tags Source
SHA-256 checksum
How to use checksums
dfea541992447c142a69e2811fc622fd58a5e70df3892a9314d372b6e266468d
BLAKE2b-256 checksum
How to use checksums
2ce6e146f6a1c2b6c0e99a8f80378dd3b3a8073c6a7d6da6a12f9027eb3cfb55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / valjson-2.0.1-py3-none-any.whl

Download URL valjson-2.0.1-py3-none-any.whl
Size 64.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c7909930d645917bda375c576c4103baa3e2f5850c602521d204b25483158c34
BLAKE2b-256 checksum
How to use checksums
ce445c578c212449b8bfa23ef6ed097afb539cb5a4cce3e486756906abce52b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Security for valjson 2.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page