CoolFace
Modelpublic

citan/plgec-herbert-large-v2

sourceHugging Facecc-by-nc-4.0updated 1d agoView on Hugging Face
0likes43downloads
Model Card

plgec-herbert-large-v2 — Polish grammar error correction

plgec-herbert-large-v2 is the second versioned release of a GECToR-style token-edit classifier over HerBERT-large. It reads a Polish sentence and proposes minimal, conservative edits (replace, append, delete), each tagged with an error class (orth, infl, agree, punct, conf, spell) and a raw confidence. It is an advisory WARN-level gate for document pipelines: flag suspected errors for a human, never rewrite on its own.

The v2 checkpoint is a continued fine-tune of the v1 model, trained to stop flagging the domain it kept misfiring on (the numbers are in the domain-adaptation section below). The decode got more permissive and the per-class filter moved to schema version 3; both changes are disclosed in full, next to the calibration and ablation evidence that shaped them. What did not change is the design goal: a low spurious-edit rate you can trust as a linter, per-edit classes you can route, and honest per-class numbers — including the weak classes, which stay weak and are documented as such.

This card is generated from committed measurement manifests; no number on it was typed by hand. The one deliberate gap is the re-benchmark verdict slot in its own section: that number arrives from a once-only measurement on real documents and will be recorded whatever it shows.

Model identity

fieldvalue
PyTorch checkpoint (Stage-IV epoch 1)7735d425ff4b05d4d641606591b6332c76a1c867d5a35d3457b4a3b10ef58dd2
ONNX fp32 graph80d46678b79038a1c2868c86239993ea04abea0eaefe6d24e13e9faff93d3a3b
ONNX export agreement100.0% argmax, max probability delta 2.04e-05
Label vocabulary6,757 tags (extended from the v1 vocabulary; ids are a strict prefix — see Data and training)
thresholds.yaml (schema version 3)a5b5cfb0307722e864192872a5556743ad0c936a8fb3f1b2b035772d7f18689b — the sha256 sidecar ships beside it
Decodekeepconfidencebias 0.25, minerrorprobability 0.20, max_iters 1, identity temperature

What changed from v1

settingv1v2
decode keepconfidencebias0.300.25
decode minerrorprobability0.300.20
decode max_iters11
confidence temperature0.7598 (fitted)1.0 (identity — see below)
thresholds schemaper-class barsversion 3 (+ conf floor key)
conf classdisableddisabled (marginal verdict — see below)
punctuation blocklistenabledcarried verbatim, enabled

The decode pair moved from 0.30/0.30 to 0.25/0.20 on a fresh 135-combination sweep over this checkpoint, selected on validation F0.5 under the inherited spurious gate; the pairing is more permissive, and the per-class bars in thresholds.yaml still filter consumer-side after decoding.

Consumers pin the v2.0.0 tag, not the default branch. The v1 repository stays online and unchanged; its corrigendum points here.

Results

One instrument: the frozen 180-sentence curated test set, token-level detection, attribution-derived per-class precision. The v1 card reported detection and char-span correction side by side; v2 reports the detection instrument with Wilson 95% intervals and refers the correction story to the domain-adaptation and conf sections, where the v2 work actually moved the numbers.

classdetection recalldetection precision
orth0.605 (95% CI [0.447, 0.744], n=38)†0.529 (95% CI [0.310, 0.738], n=17)†
infl0.469 (95% CI [0.309, 0.636], n=32)†0.391 (95% CI [0.222, 0.592], n=23)†
agree0.967 (95% CI [0.833, 0.994], n=30)†0.879 (95% CI [0.727, 0.952], n=33)†
punct0.806 (95% CI [0.637, 0.908], n=31)†0.900 (95% CI [0.596, 0.982], n=10)†
conf0.200 (95% CI [0.095, 0.373], n=30)†0.108 (95% CI [0.043, 0.247], n=37)†
spell0.867 (95% CI [0.703, 0.947], n=30)†0.941 (95% CI [0.730, 0.990], n=17)†
all classes0.649 (95% CI [0.579, 0.713], n=191)0.905 (95% CI [0.844, 0.944], n=137)

The measurement decode for this table is the v1-published stack (bias 0.30, min error probability 0.30, v1 temperature), so every v2-versus-v1 delta below compares models, not decode settings. The shipped decode differs and is disclosed in the changes section. Per-class detection precision is attribution-derived: an edit counts toward a class only when the gold edit at that position is of the same class.

Movement against v1, same instrument

classv1 F0.5v2 F0.5Δ F0.5v1 recallv2 recallΔ recall
orth0.3400.543+20.32 pp0.3680.605+23.68 pp
infl0.4070.405-0.23 pp0.4380.469+3.12 pp
agree0.8920.895+0.31 pp0.9670.9670.00 pp
punct0.7630.880+11.62 pp0.6450.806+16.13 pp
conf0.1190.119+0.05 pp0.1330.200+6.67 pp
spell0.8940.925+3.08 pp0.7670.867+10.00 pp

Positive deltas are improvements. Worst absolute per-class F0.5 drop accepted by the release gate: 0.23 points (bar: 3 points per class, F0.5 and recall separately).

orth is the headline: the v1 card's accepted flagship regression is gone, replaced by the largest per-class gain on the card. infl gives back a fraction of a point of F0.5 (within the release bar of 3 points per class); no other class moved against v1 by more than a rounding step in the wrong direction. The gate that judged this table ran lexicographically over both F0.5 and recall drops per class, accepted the worst absolute drop of 0.23 points, and fired no retry.

A caveat carried over from v1: the curated test set has been read end-to-end several times across the project (selection, re-gate, this eval). The v2 numbers were not selected on it, but the v1 baseline they sit beside was. Read the point estimates with that history in mind; the intervals do not undo it.

Confidence calibration

v2 re-fit the confidence temperature on this checkpoint's own logits and shipped identity, T = 1.0. The ship gate has two legs and the fit passed only one:

  • Wilson leg — passed. On the 4,000-sentence clean carve-out (80,371 candidate positions), 3,870 sentences had lower weighted |confidence − accuracy| after the fitted T: improvement proportion 0.968 (95% CI [0.962, 0.973], n=4,000) — the interval excludes 0.5.
  • ECE leg — failed. Carve-out expected calibration error rose from 0.00175 to 0.00195 instead of decreasing.

A temperature that sharpens sentence-level improvement while making the calibration error worse is not a calibration; the gate returned NO-SHIP. The fitted value (T = 0.8360, L-BFGS, 57 iterations) is recorded here and in the evidence manifest, and is not applied. Nothing was inflated to convert the verdict. Because the shipped constant is identity, the confidences on this card and in the decoder output are raw softmax probabilities.

The conf class: a marginal verdict, shipped disabled

The paired gate re-measured the confusable class at the shipped configuration and returned a marginal verdict (CONFGATEMARGINAL). The two gated axes:

  • char-span precision 0.44 (95% CI [0.19, 0.73], n=9) against the pre-registered bar 0.30 — the point estimate clears the bar, the interval's lower bound does not. At this sample size the measurement cannot certify the bar; that is the verdict, not a near-miss to be rounded up.
  • token recall 0.17 (95% CI [0.07, 0.34], n=30), point-identical to its v1 baseline of 0.17 — recall did not move.

The cost side: 16 of 20 clean-text spurious edits were conf-class (80% of the clean false-positive budget).

So conf ships disabled by default — the same consumer contract as v1, now with a schema-v3 floor key so an operator who opts in can demand extra confidence on top of the class bar. The documented path to revisiting the class is a dedicated real-text confusable mining pass for a future release; a threshold tweak is not that pass and was not attempted.

Domain adaptation: what v2 actually fixed

v1's worst live behavior was register mismatch: on a frozen 2,000-sentence carve of in-domain production Polish it flagged 114 sentences (0.057). The v2 checkpoint is a continued fine-tune of v1 over mined false-positive sites from that same domain. Two instruments measure what it bought, and they are not equal witnesses:

  • Held-out carve (the honest number): flag rate fell to 0.007 (14 of 2,000 sentences) — an 87.7% relative reduction (114 → 14). The carve was frozen before Stage-IV training began, and the training never saw it.
  • Mined false-positive sites (an upper bound by construction): 10,061 sites flagged by v1 fell to 387 under v2 — 96.15% suppressed. These sites are the training source, so this number says the lesson was learned, not generalized.

Both are domain-side instruments on one production domain; the re-benchmark section below is the in-the-wild verdict on documents the model has no relationship with.

RoBERTa encoder ablation

Before freezing v2, a Polish RoBERTa-large encoder was trained through the same pipeline as an ablation, to answer the v1 regression question directly. The answer is mixed and the candidate is not shipped:

  • orth improves under RoBERTa at both comparability surfaces: F0.5 +0.80 pp and recall +5.26 pp (stage-3 leg); F0.5 +0.80 pp and recall +5.26 pp (stage-4 leg).
  • infl regresses at both surfaces: F0.5 -6.61 pp and recall -6.25 pp (stage-3 leg); F0.5 -7.16 pp and recall -9.38 pp (stage-4 leg).
  • The per-class gate verdicts were cliffs at both legs (agree and punct fell beyond the 8-point bound), and strict detection precision fell 18.91 pp (stage-3 leg) and 22.32 pp (stage-4 leg) against the shipping model.

The recommendation recorded in the ablation evidence was to keep HerBERT-large and not extend the re-benchmark to the RoBERTa candidate; that reading stands. The full four-column comparison lives in the project's ablation evidence manifest, which is not redistributed with this model.

INT8 position

No INT8 quantization of this checkpoint exists. The v1 repository documents a gate-rejected INT8 attempt for the v1 graph — nothing quantized was published there either, and that evidence stays with v1. This release ships the fp32 ONNX graph and the schema-v3 thresholds file; there is no quantized sibling to download and none is claimed.

Re-benchmark on real documents

Measured once, read-only, on real production documents (3 docs, 1,962 sentences after extraction): 35 flagged sentences (0.0178 overall).

documentsentencesflaggedflag rateedits
belchatow-report1,723280.016328
immersion-cooling-d215350.03275
pismo-018620.02332

Spot check (class-balanced, n=32 flags): strict precision 0.250 (95% CI [0.133, 0.421]); precision counting debatables 0.375. Under-powered classes are listed inside the spot-check artifact, never padded.

Parity: the in-container fp32 ONNX decode agreed with the live service on 100.0% of sentences (0 disagreements recorded). Latency at report scale: 102.5 ms per sentence amortized.

No URL false-edit occurrences were observed.

The punctuation blocklist

Carried verbatim from v1 and still enabled: an exact-token rule that drops a ;, replacement (class punct, reason punct_style_swap) after decoding, in the same filter stage as the per-class bars — it never re-decodes. A context guard keeps the rule from firing near a clause start (min_tokens_before: 3), so short enumerations keep their gold semicolons. Literary-register consumers who want the swaps back flip one line of yaml (enabled: false).

Limitations

  • The confusable class is disabled by default on a marginal verdict; the full Wilson disclosure is above. Enabling it opts into the class that produced 80% of the clean-text false positives measured at the shipped configuration.
  • The curated evaluation set was machine-verified against the generator and LanguageTool but never reviewed by a human linguist, and it has been read end-to-end several times across the project's history (the v1 baseline numbers it is compared against were themselves selected on it).
  • The per-class table is the token-detection instrument; v2 did not re-measure char-span correction on the curated set. The domain-adaptation section is the correction-side evidence for v2.
  • Domain adaptation tuned against one production domain's false positives; the re-benchmark verdict above covers three real documents, and registers beyond them remain unmeasured.
  • The decode is deliberately single-pass (max_iters 1): multi-error sentences get at most one edit per pass.
  • Polish only; the decoder emits nothing useful for other languages.

Intended use

A WARN-level advisory gate for Polish prose in document pipelines: each sentence gets zero or more flagged edits with class, span, and confidence; a human accepts or dismisses. Conservative by construction — the decoder only emits an edit when its raw probability clears a high bar. Not suitable for unattended rewriting, for literary editing, or for languages other than Polish. Self-hosted LanguageTool remains the deterministic first gate; this model is the neural second opinion on the error classes rules structurally miss.

License

The model weights are published under CC BY-NC 4.0 (non-commercial, attribution). The base encoder, allegro/herbert-large-cased, is CC BY 4.0. Training included a licensed corpus that is not redistributed here; no datasets ship with this model.

Citation

bibtex
@software{plgec_herbert_large_v2_2026,
  title  = {plgec-herbert-large-v2: a Polish GECToR grammar-error
            corrector over HerBERT-large (second release)},
  author = {Krystian Lewandowski},
  year   = {2026},
  url    = {https://huggingface.co/citan/plgec-herbert-large-v2},
  note   = {Per-class detection results with 95% CIs on a 180-sentence
            curated Polish set; conservative decode, per-class
            thresholds, domain-adapted continued fine-tune}
}

Usage

Minimal standalone inference — public dependencies only (onnxruntime, tokenizers; no deep-learning framework, no serving stack):

bash
pip install onnxruntime tokenizers
hf download citan/plgec-herbert-large-v2 --revision v2.0.0 --local-dir plgec-herbert-large-v2
cd plgec-herbert-large-v2
python inference_example.py "Mieszkam w Warszawa od pięciu lat."

inference_example.py ships in this repository, next to this card. It loads the ONNX model, tokenizer, label vocabulary and thresholds.yaml from its own directory and prints one JSON object per sentence — per edit: token index, character span on the source text, original → replacement, tag, class, and confidence (the chosen tag's probability under the published decode settings and identity temperature).

thresholds.yaml is the consumer-side filter, applied after decoding. Schema version 3 carries: per-class min_error_probability and enabled keys (conf off by default), an optional per-class confidence floor inside the conf block, a calibration block with the shipped temperature, and a blocklist section with the ; to , rule. Edit the shipped file (or pass --thresholds with your own, or --thresholds none) — the model decode itself never changes:

yaml
schema_version: 3
default:
  min_error_probability: 0.30
  enabled: true
conf:
  min_error_probability: 0.30
  enabled: false   # opt in to confusable-class edits
  floor: 0.30      # additive second bar (schema v3)
# calibration + blocklist sections follow in the shipped file

Runtimes that read this file must support schema version 3; a v1-era runtime refuses the file rather than misreading it. Consumers coming from v1: pin this repository's tag, load the thresholds.yaml that ships with it, and expect the conf class to stay off unless you switch it on.

Note the corrected-text field joins edit-applied tokens with single spaces; consumers that care about typography should apply the per-edit char_spans to the source text instead.

Training lineage

Fourteen runs, in order: seven that built v1, seven that produced and judged this checkpoint. IDs are internal experiment-registry run identifiers; each row was verified finished at release time. The released checkpoint is the Stage-IV epoch-1 model, continued from the v1 (Stage-III) checkpoint, and exported to ONNX with 100% argmax agreement.

runrole
f776e7eab7ad48bf9488339a8ba3bb3dStage-I corpus LM-adaptation on HerBERT-large
cb3c89250de94758a6d12747bb738fe3Stage-II synthetic fine-tune
ee3101243ae848c6bd4e5edca87f4890Stage-III real-error fine-tune + gated epoch selection (the published checkpoint's producing run — dir key)
bc35d532f3724bb3971efe76b695c98ethe committed 135-combo decode grid (threshold_sweep.json)
2816dd834a9647a790622d41c0412cccthe v1 final measurement at the argmax-F0.5 triple (0.30/0.60/1); superseded (delta_05.json provenance)
57952735b055462ea6bd96c037050921n-gram re-ranker LM build + theta calibration + combined selection (the adopted measurement; superseded run d3758ca6 was the pre-OOV-fix calibration)
ae553941ea654e6eb6b96464f29c0edaThe final measurement — the exact final-gate re-run at the combined-selection winner (trust gate GREEN, ONNX 100%/1.135e-05, owner-accepted)
0b91b5909d7b4d689f1e2546a83a42a0domain-val carve + the pre-training v1 baseline (flag rate 0.057, measured before Stage-IV existed)
ef3efb3f35ad41f8bdf090dad76c3dddStage-IV per-class eval on the frozen curated set — the candidate leg
f2b0d68d181240aa99f6f5f974acaf7ffinal evidence pass — FP-site suppression 0.96153 + domain-val flag rate 0.007 vs v1 0.057
72da9d7c6ee8423bb2e8a40245df89c7FP-site mining — v1 inference over the gated legal corpus (10,061 flagged sites, the suppression denominator)
34df97d063204eaab8393a7a9acfdca6fresh curated-surface threshold sweep — 135 combos, chosen 0.25/0.20/1
4ffbc78ccf4b4fb5a22d04ea70f6647fWilson-gate T re-fit on Stage-IV logits — NO-SHIP resolved, identity T=1.0 ships
79b373157f654fd1b54a183950297f2dThe Stage-IV continued fine-tune — lexicographic epoch-1 selection (the artifact dir key; parent-linked onto ee310124…)

Two early smoke attempts failed before the successful Stage-IV train run; they are recorded as exceptions in the evidence chain, not hidden.

Data and training

Training pairs (~1.2M) were generated by injecting synthetic errors into clean Polish sentences (CC100-pl and Polish Wikipedia sources, plus a licensed corpus staged internally; no dataset is redistributed with this model). Errors come from a Morfeusz2-driven generator: inflection and agreement corruptions derived from morphological analysis, curated confusable-pair swaps, single-character orthography swaps (ż/rz, ó/u, ch/h, ą/ę), punctuation, and spelling. The evaluation set is the frozen 180-sentence curated set inherited from v1, machine-verified against the generator and LanguageTool but never reviewed by a human linguist. On top of the v1 mixture, v2 adds a continued fine-tune over mined false-positive sites from in-domain text — the suppression evidence in the domain-adaptation section is what that pass was trained to produce.

The GECToR label vocabulary grew from 6,680 to 6,757 tags — an append-only extension that keeps every v1 id in place, so the two vocabularies load side by side without aliasing (a v2 checkpoint must not load the v1 vocabulary) — and covers 0.9002 of distinct real-error edit forms over its training pool; the ceiling is measured, not assumed.

v3 milestone close (2026-09-21)

The v3 program attempted two enrichment legs beyond this release, and both were dropped by their pre-registered fail-closed gates: the LLM-corruption generator was non-viable at its entry probe (it would not corrupt grammatical Polish on demand), and the mined wiki revision corpus measured 0.47 label purity (n=200; Wilson 95% CI [0.402, 0.539]) under the pre-registered 0.75 drop floor, so the leg was dropped rather than shipped diluted. Nothing about the published artifact changed as a result: no weights, decode parameters, or thresholds were touched, and release tag v2.0.0 remains the canonical pin. No data from either dropped leg (no mined wiki-revision pairs, no LLM-generated rows) entered any published artifact; the license dispositions for both legs were evaluated, and the legs then dropped (evaluated-not-consumed), so the license posture is unchanged (CC BY-NC 4.0).