Instructions to use Lucius-Morningstar/mailroom-modernbert-classifier with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Lucius-Morningstar/mailroom-modernbert-classifier with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Lucius-Morningstar/mailroom-modernbert-classifier")# Load model directly from transformers import AutoTokenizer, AutoModel tokenizer = AutoTokenizer.from_pretrained("Lucius-Morningstar/mailroom-modernbert-classifier") model = AutoModel.from_pretrained("Lucius-Morningstar/mailroom-modernbert-classifier", device_map="auto") - Notebooks
- Google Colab
- Kaggle
mailroom-modernbert-classifier
Hierarchical document classifier for the LLM-Mailroom intake pipeline: a
fine-tuned ModernBERT-base encoder with a doc_type head plus one
subclass head per document class. It is the deterministic pre-check in the
BERT-coupled intake overhaul (mailroom-issues #85).
Architecture
- Backbone:
answerdotai/ModernBERT-base— 22 layers, 768 hidden, 8,192-token context, bf16. - Heads: one head per class —
doc_type(6 classes) plus 5 subclass heads (contract,corporate_record,correspondence,insurance_claim,merger_agreement). MLP heads with dropout 0.1. - Windowing: token-level, 8,192 tokens with 512-token overlap.
doc_typeby plurality vote over windows; subclass by plurality over windows whosedoc_typevote is the winning class. - Calibration: per-head temperature scaling (
temperatures.json).
Files
| file | purpose |
|---|---|
model.safetensors |
ModernBERT backbone weights (bf16, ~298 MB) |
heads.pt |
hierarchical head state dicts |
labels.json |
head vocabularies (labels / label2id / id2label / weights) |
temperatures.json |
per-head calibration temperatures |
train_counts.json |
per-(doc_type, subclass) authentic train-row counts (support gate) |
config.json, tokenizer.json, tokenizer_config.json |
backbone config + tokenizer |
summary.json |
full run summary (hyperparameters, per-epoch metrics, selection, test metrics) |
Labels
doc_type (6): contract, merger_agreement, corporate_record,
correspondence, insurance_claim, unknown (inference-only abstention —
not a trained class)
contract (24): agency, co_branding, collaboration, consulting, development, distributor, endorsement, franchise, hosting, ip, joint_venture, license, maintenance, manufacturing, marketing, other, outsourcing, promotion, reseller, service, sponsorship, strategic_alliance, supply, transportation
corporate_record (10): articles_of_incorporation, board_resolution, bylaws, charter_amendment, indenture, officer_certificate, other, powers_of_attorney, rights_instrument, subsidiary_list
correspondence (7): demand, email, letter, meeting_request, memo, notice, press_release
insurance_claim (6): auto, carrier, inpatient, outpatient, pde, property
merger_agreement (5): all_cash, all_stock, mixed_cash_stock, mixed_cash_stock_election, other
Results
Trained 2 epochs on Lucius-Morningstar/mailroom-modernbert-training
@ 5b72a345cd3c057b736bea4910fdbef6509ad1c3 — 4,497 train / 489 validation
windows; 323 held-out test documents (never used for training, calibration, or
threshold tuning).
Validation
| epoch | val_loss | doc_acc | macro-F1 (observed) | ECE (calibrated) |
|---|---|---|---|---|
| 1 | 1.0041 | 0.8859 | 0.8524 | 0.0201 |
| 2 | 0.9121 | 0.9195 | 0.9051 | 0.0205 |
Selected epoch: 2 — best observed doc_type macro-F1 subject to
calibrated ECE ≤ 0.05 (gate_met: true).
Held-out test (323 docs)
| metric | value |
|---|---|
doc_type accuracy |
0.9319 (301/323) |
subclass accuracy (given correct doc_type) |
0.5449 (164/301) |
Per-head (epoch 2, validation)
| head | window acc | macro-F1 (observed) | ECE (calibrated) |
|---|---|---|---|
doc_type |
0.9141 | 0.9051 | 0.0205 |
insurance_claim |
0.8889 | 0.8085 | 0.0500 |
corporate_record |
0.5405 | 0.2218 | 0.1037 |
merger_agreement |
0.4656 | 0.1988 | 0.0350 |
correspondence |
0.5161 | 0.0980 | 0.1050 |
contract |
0.1630 | 0.0899 | 0.0630 |
Usage
The backbone is a standard ModernBertModel; the hierarchical heads are a
custom bundle. Load it with the mailroom-ml inference layer:
from mailroom_ml.inference import load_bundle, classify_document
bundle = load_bundle("Lucius-Morningstar/mailroom-modernbert-classifier")
result = classify_document(
title="Notice of Default",
text=document_text,
bundle=bundle,
)
# result["doc_type"], result["subclass"], result["confidence"], result["route"]
route == "fast_path" means the calibrated gate passed and the LLM sorter may
be skipped (skip mode + allowlist only); otherwise route the document to the
LLM sorter with the BERT triage as an advisory prior.
Provenance
- Training run:
20260920-173810— 2 epochs, ~3.78 h on a Modal L4. - Hyperparameters: batch 4, grad-accum 8, lr 2e-5, seed 42,
λ_dt0.65, label smoothing 0.05, sqrt-inverse class weights (cap 10), MLP heads (dropout 0.1), weight decay 0.01, subclass support floor 12. - Dataset revision:
5b72a345cd3c057b736bea4910fdbef6509ad1c3. - Calibration temperatures:
doc_type0.484,contract0.705,corporate_record0.596,correspondence0.960,insurance_claim0.122,merger_agreement0.679.
Limitations
- Subclass heads are weak for
contract/correspondence/corporate_record/merger_agreement(macro-F1 0.09–0.22). Use thedoc_typehead for routing; route subclass-ambiguous documents to the LLM sorter (the Tier-1 prior-scoped lane, mailroom-issues #108). Do not trust a skip-mode subclass for these classes yet. - Trained on a curated legal-document corpus; not a substitute for legal review.
unknownis an inference-only abstention label, not a trained class.- Long documents are windowed (8,192 tokens, 512 overlap); the model never truncates silently — oversize documents fall back to the LLM path.
License
Apache-2.0 (inherits answerdotai/ModernBERT-base).
- Downloads last month
- 29
Model tree for Lucius-Morningstar/mailroom-modernbert-classifier
Base model
answerdotai/ModernBERT-base