nicolasembleton's picture
v2 export: pair reranker in graph; verified decode parity
5e55e26 verified
|
Raw
History Blame
4.24 kB
metadata
library_name: onnx
license: apache-2.0
pipeline_tag: token-classification
base_model: fastino/gliner2.5-multi-v1
tags:
  - onnx
  - gliner2
  - gliner2.5
  - boundary
  - webgpu
  - token-classification

gliner2.5-multi-v1-onnx

ONNX export of fastino/gliner2.5-multi-v1 (GLiNER 2.5 BoundaryExtractor) for onnxruntime-web / WebGPU. Revision 2: the graph now contains the full candidate path — sparse proposer, shared candidate pool, and pair reranker — not just the boundary marginals. Host-side decode is a threshold on the reranked pair scores, matching the Python AutoExtractor pipeline (verified to 4 decimals).

What the graph runs

  1. DeBERTa encoder over packed input_ids (schema + [SEP_TEXT] + words)
  2. Gather of word states and query-marker states
  3. Boundary encoder + boundary marginals
  4. Document candidate pool (top-k endpoints, Cartesian pairing, learned compatibility)
  5. Pair reranker (endpoint compatibility + length features + inside evidence + FiLM-conditioned scoring)

Schema packing (entity-type markers) stays on the host; span decode is a host-side threshold.

Inputs

Name Shape Dtype
input_ids [B, T] int64
attention_mask [B, T] int64
text_word_indices [B, L] int64
text_word_mask [B, L] float32
query_marker_indices [B, Q] int64
query_marker_mask [B, Q] float32

Outputs

Name Shape Dtype Meaning
start_logits [B, Q, L+1] float32 boundary start marginals
end_logits [B, Q, L+1] float32 boundary end marginals
pair_indices [B, Q, C, 2] int64 candidate spans, half-open word boundaries (s,e), s<e≤L; C=192
pair_logits [B, Q, C] float32 reranked span logits
pair_valid [B, Q, C] uint8 1 = real candidate (duplicate (s,e) keys can occur; dedupe on the host)

Host decode (any language)

probs = sigmoid(pair_logits / pair_temperature)          # pair_temperature = 1.0
keep candidates where pair_valid == 1 and probs >= threshold   # 0.5 default
dedupe by (start, end) keeping the max prob
resolve overlaps per label (e.g. max-total-score interval scheduling)
char span = words[s].start .. words[e-1].end

Boundary i sits before word i; boundary L sits after the last word. Pair (s, e) covers words s..e-1.

Verified decode parity

JavaScript decode of this graph (ONNX Runtime Web) vs Python AutoExtractor on "Apple CEO Tim Cook announced iPhone 15 in Cupertino yesterday." with labels company/person/product/location:

Entity ONNX-web JS Python AutoExtractor
Apple 0.9966 0.9966
Tim Cook 0.9987 0.9987
iPhone 15 0.9905 0.9905
Cupertino 0.9988 0.9988

Confidences match to 4 decimals. Reference runtime: Pastel-Org/gliner2.5-onnx-webgpu (live demo: gliner25-onnx-webgpu.pages.dev).

Revision 2 changes

  • Graph now ends at the pair reranker instead of the marginals. The previous revision required a min(sigmoid(start), sigmoid(end)) proxy that cost precision at low thresholds (0.45 P at 0.3 on our 26-sample suite); this revision holds ≥0.77 P across the whole 0.3–0.7 range with flat F1.
  • export_mode="vectorized" proposer; sort/scatter_reduce internals replaced with opset-17-safe topk + sentinel padding (constant-k for any input length; duplicate candidates possible and deduped on the host).
  • Decode parity with the Python pipeline added to the export validation.

Python check

import onnxruntime as ort
sess = ort.InferenceSession("onnx/model.onnx")
print([o.name for o in sess.get_outputs()])
# ['start_logits', 'end_logits', 'pair_indices', 'pair_logits', 'pair_valid']

WebGPU: load onnx/model.onnx with onnxruntime-web (webgpu execution provider; WASM fallback where WebGPU is unavailable). Int64 inputs are required.

Credits

  • Base checkpoints and the GLiNER2 reference implementation by Fastino — Apache-2.0.
  • ONNX export + host protocol by Pastel-Cloud OÜ.