File size: 8,967 Bytes
905ca6e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | ---
license: apache-2.0
language: en
library_name: pytorch
base_model: allenai/scibert_scivocab_cased
tags: [information-extraction, relation-extraction, named-entity-recognition, scientific-text, lab-protocols]
---
# Model card: ProtocolLedger span-relation extractor
| | |
|---|---|
| Served model | `scibert-uniform-negatives-s21-7dc7a1893e` |
| Architecture | SpERT-style span and directed-relation classifier over a shared encoder (independent implementation of Eberts and Ulges, arXiv:1909.07755) |
| Encoder | `allenai/scibert_scivocab_cased` at revision `ddf0be025f8e432a1870e34811997ba6725bf04a` (Apache-2.0), fine-tuned |
| Training data | WNUT-2020 Wet Lab Protocols, cleaned **train** split (314 protocols); see the [dataset card](https://github.com/professor3333/ProtocolLedger/blob/main/docs/dataset_card.md) |
| Selection | dev end-to-end relation micro-F1; configuration chosen on a 3-seed mean, then the **median** seed served |
| Status | Evaluated once on the locked test split (2026-10-11) after targets were frozen |
## Intended use
The model extracts actions, materials, quantities, equipment and locations, conditions,
and the directed relations between them, from English wet-lab protocol text. Its output
is a set of **suggested** preparation-sheet entries, each linked to its source
characters, which a reviewer confirms or corrects in the ProtocolLedger interface before
export.
## Not for
- Judging whether a protocol is scientifically complete, correct or safe.
- Executing or automating protocols from unreviewed output.
- Using unreviewed results as final records.
- Filling in implicit arguments, or treating "not explicitly stated" as "not required".
The system never does this; downstream users should not either.
- Entity or relation types outside the 18-entity and 14-relation schema.
- Non-English text, or PDF / OCR input.
- Other domains or protocol sources without local validation.
## Provenance
- **Encoder.** SciBERT cased, pinned by Hugging Face commit. Case preservation is forced
and checked at load time, because the cased checkpoint ships no tokenizer config and
would otherwise lowercase `mM` to `mm`.
- **Encoder view.** Characters the vocabulary cannot represent (for example the micro
sign in `µL`, which SciBERT maps to `[UNK]`) are substituted only in the text handed to
the encoder. Offsets always refer to the original text.
- **Heads.**
- A span is the max-pool of its words plus a width embedding.
- Entity logits come from the span concatenated with the CLS vector.
- Relation logits use both spans, the max-pooled words between them, both entity types
and a signed distance bucket.
- Relations are multilabel (sigmoid).
- **Training.**
- AdamW: encoder learning rate 2e-5, heads 1e-3, 10% warmup with linear decay.
- Batch size 16, at most 10 epochs, patience 3, mixed precision on one Tesla T4 (Kaggle).
- About 100 sampled negative spans and pairs per step, sampled uniformly.
- Seed 21; best epoch 9.
- **Reproducibility.** Code commit, split-manifest hash, encoder revision, checkpoint
hash and the selection-report hash are all recorded in the bundle's `bundle.json`. The
bundle was rebuilt on CPU and reproduces the GPU dev scores exactly (entity F1 0.8003,
relation F1 0.6389).
## Training data and splits
The released WNUT-2020 splits were the starting point, with these changes:
- **Deduplication.** Exact and near-duplicate copies and revisions were removed by
document, always keeping the copy in the most protected split.
- **Correction ledger.** 291 whitespace-trimming corrections were applied identically to
every split.
- **Locked test.** `test_data_2020` is never used for any decision.
Cleaned sizes: train 314, dev 112, test 111 protocols.
## Metrics (dev, 112 protocols)
| Metric | Selected configuration (3 seeds) | Served seed | CRF + logistic regression |
|---|---:|---:|---:|
| Strict entity micro-F1 | 0.800 | 0.800 | 0.756 |
| **End-to-end relation micro-F1** (primary) | **0.640 ± 0.004** | 0.639 [0.614, 0.665] | 0.582 |
| Relation F1 given gold entities | 0.826 | 0.830 | 0.812 |
| Quantity attachment accuracy | 0.758 | 0.757 | 0.708 |
**Proposed targets** (not yet frozen):
- Entity F1 ≥ 0.75: met.
- At least 5 points above the traditional baseline: met (+5.8).
- **End-to-end relation F1 ≥ 0.65: not met** (0.640).
**Confidence** (served seed, joint score P(relation) × P(head) × P(tail)):
- **Precision.** 0.920 at 30% coverage. 95% precision is reachable only at 18.7%
coverage, so the target of 95% precision at ≥ 30% coverage is not met.
- **Calibration.** Isotonic calibration, cross-fitted by document on dev, reduces the
expected calibration error from 0.183 to 0.009.
**Error profile** (served seed):
- **Correct:** 62.7% of gold relations.
- **Endpoint entity wrong:** 27.7%.
- **Missed:** 4.8%.
- **Genuine attachment errors:** 2.9%.
- **Wrong label:** 1.8%.
**Slices:**
| Slice | Served seed | CRF + logistic regression |
|---|---:|---:|
| Reagent recall, names unseen in train | 0.658 | 0.570 |
| Reagent recall, names seen in train | 0.903 | 0.873 |
| Relation recall, documents without a template sibling in train | 0.613 | 0.524 |
| Relation recall, documents with a template sibling in train | 0.740 | 0.719 |
**Reference point.** Duplicate copies of the same protocol in the corpus agree with each
other at entity F1 0.863 and relation F1 0.711.
## Locked test results (evaluated once)
| Metric (cleaned `test_data_2020`, 111 protocols) | SciBERT (served) | CRF + logistic regression |
|---|---:|---:|
| Strict entity micro-F1 | 0.766 [0.748, 0.784] | 0.703 |
| **End-to-end relation micro-F1** | **0.580** [0.552, 0.606] | 0.504 |
| Relation F1 given gold entities | 0.787 | 0.768 |
| Quantity attachment accuracy | 0.699 | 0.629 |
| Reagent recall, names unseen in train | 0.762 | 0.631 |
| Precision at 30% coverage (joint score) | 0.905 | — |
| Coverage at 95% precision | 13.4% | — |
| ECE raw / with the dev-fitted calibrator | 0.172 / 0.021 | — |
Frozen targets on test:
- **Met:** entity F1 ≥ 0.75, at least 5 points above the traditional baseline (+7.6),
and robustness (−0.01).
- **Not met:** end-to-end relation F1 ≥ 0.65, and 95% precision at ≥ 30% coverage.
Test is harder than dev for every system. Full report:
[reports/test/locked-test.md](https://github.com/professor3333/ProtocolLedger/blob/main/reports/test/locked-test.md).
## Inference performance
Measured on an Apple M1 (8 GB) with 4 inference threads: 200 sequential requests of dev
protocols up to 500 words, each runtime in a fresh process
([report](https://github.com/professor3333/ProtocolLedger/blob/main/reports/performance/scibert-uniform-negatives-s21-7dc7a1893e-runtimes.md)).
| Runtime | Relation F1 | p50 | p95 | Peak RSS |
|---|---:|---:|---:|---:|
| **PyTorch FP32 (served)** | 0.6389 | 0.48 s | **2.07 s** | 938 MiB |
| ONNX Runtime FP32 | 0.6389 | 2.29 s | 6.94 s | 1,058 MiB |
| ONNX Runtime INT8 (dynamic) | 0.6361 | 0.93 s | 2.90 s | 918 MiB |
On this ARM machine PyTorch FP32 is the fastest runtime and loses no accuracy, so it is
served. INT8 stays within the 1-point accuracy gate but is slower here. Re-measure on the
deployment host (likely x86) with `scripts/optimize_bundle.py` before changing runtimes.
## Known failure modes
- **Entity errors cascade into relations.** Most relation errors come from a wrong or
missed endpoint entity.
- **Open-vocabulary types are weakest.** Modifier, Method, Device and Generic-Measure
score lowest.
- **Unseen reagent names** are found less often than seen ones.
- **Rare relations** are unreliable: Commands (37 dev instances), Of-Type (26) and
Product.
- **Implicit references** such as "it", and cross-step coreference, are not resolved.
- **Negation, alternatives and conditional instructions** are not modelled.
- **Text glued together by table flattening** (for example `100 µlof`) cannot be
segmented.
- **Template overlap.** Protocols that share a vendor template with training data score
higher than the rest.
## Release process
- **Selection.** Thresholds and the configuration are chosen on dev only, never on test.
- **Bundle.** Weights are stored as safetensors (no pickle). The encoder config and
tokenizer are included, and every file is hash-verified on load, so serving needs no
network access.
- **Release.** A release pins the image digest together with the bundle hash.
`scripts/release.py` smoke-tests each activation and restores the previous image and
bundle together if it fails.
## Loading
This repository is a ProtocolLedger bundle (`bundle.json` lists every file with its SHA-256). Load it with the project's verified loader:
```python
from pathlib import Path
from protocolledger.serve.bundle import load_bundle
bundle = load_bundle(Path('scibert-uniform-negatives-s21-7dc7a1893e'))
entities, relations = bundle.extractor.extract('Add 5 mL of water to the tube.')
```
|