ONNX export of
fastino/gliner2-multi-v1 for zero-shot Named Entity Recognition.
This repository contains a single monolithic ONNX file (encoder + span head) that can be run with any ONNX Runtime backend (CPU, CUDA, CoreML, DirectML, etc.).
1import re
2WORD_RE = re.compile(
3 r"(?:https?://[^\s]+|www\.[^\s]+)"
4 r"|[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}"
5 r"|@[a-z0-9_]+"
6 r"|\w+(?:[-_]\w+)*"
7 r"|\S",
8 re.IGNORECASE,
9)
10words = [(m.group(), m.start(), m.end()) for m in WORD_RE.finditer(text)]
See
example.py for a complete runnable script. Summary:
1import numpy as np
2import onnxruntime as ort
3from tokenizers import Tokenizer
4
5tokenizer = Tokenizer.from_file("tokenizer.json")
6session = ort.InferenceSession("model.onnx")
7
8text = "Steve Jobs founded Apple Inc. in Cupertino, California on April 1, 1976."
9labels = ["person", "company", "city", "date"]
10
11# 1. Split text into words
12# 2. Build schema: ( [P] entities ( [E] person [E] company ... ) ) [SEP_TEXT] word1 word2 ...
13# 3. Tokenize with is_pretokenized=True, add_special_tokens=False
14# 4. Build span_idx, text_positions, schema_positions
15# 5. Run inference and threshold span_scores >= 0.5
16# 6. Map word spans back to character offsets
17
18outputs = session.run(None, {
19 "input_ids": input_ids,
20 "attention_mask": attention_mask,
21 "text_positions": text_positions,
22 "schema_positions": schema_positions,
23 "span_idx": span_idx,
24})
See
example.mjs for a complete runnable script. Summary:
1import * as ort from "onnxruntime-node";
2import { Tokenizer } from "tokenizers";
3
4// Load tokenizer (strip pre_tokenizer/decoder/post_processor/normalizer
5// as the npm package doesn't support these custom wrappers)
6const tokenizerJson = JSON.parse(fs.readFileSync("tokenizer.json", "utf-8"));
7delete tokenizerJson.pre_tokenizer;
8delete tokenizerJson.decoder;
9delete tokenizerJson.post_processor;
10delete tokenizerJson.normalizer;
11const tokenizer = Tokenizer.fromString(JSON.stringify(tokenizerJson));
12
13const session = await ort.InferenceSession.create("model.onnx");
14
15// 1. Split text into words (lowercase)
16// 2. Build schema: ( [P] entities ( [E] person [E] company ... ) ) [SEP_TEXT] word1 word2 ...
17// 3. Encode each word individually with ▁ (U+2581) prefix to mimic is_pretokenized
18// 4. Build span_idx, text_positions, schema_positions as BigInt64Arrays
19// 5. Run inference and threshold span_scores >= 0.5
20
21const results = await session.run({
22 input_ids: new ort.Tensor("int64", inputIds, [1, seqLen]),
23 attention_mask: new ort.Tensor("int64", attentionMask, [1, seqLen]),
24 text_positions: new ort.Tensor("int64", textPositions, [numWords]),
25 schema_positions: new ort.Tensor("int64", schemaPositions, [numSchemaPos]),
26 span_idx: new ort.Tensor("int64", spanIdx, [1, numWords * 8, 2]),
27});
See
example.rs for a complete example using the
ort crate. Summary:
1use ort::session::Session;
2use ort::value::Tensor;
3use tokenizers::Tokenizer;
4
5let tokenizer = Tokenizer::from_file("tokenizer.json")?;
6let mut session = Session::builder()?.commit_from_file("model.onnx")?;
7
8// 1. Split text into words (lowercase)
9// 2. Build schema: ( [P] entities ( [E] person [E] company ... ) ) [SEP_TEXT] word1 word2 ...
10// 3. Tokenize with Vec<&str> (pre-tokenized input)
11// 4. Build span_idx, text_positions, schema_positions
12// 5. Run inference and threshold span_scores >= 0.5
13
14let outputs = session.run(ort::inputs![
15 "input_ids" => Tensor::from_array((vec![1, seq_len], token_ids))?,
16 "attention_mask" => Tensor::from_array((vec![1, seq_len], mask))?,
17 "text_positions" => Tensor::from_array((vec![num_words], text_pos))?,
18 "schema_positions" => Tensor::from_array((vec![num_schema], schema_pos))?,
19 "span_idx" => Tensor::from_array((vec![1, num_spans, 2], spans))?,
20])?;
21
22let (shape, scores) = outputs["span_scores"].try_extract_tensor::<f32>()?;
Use the
tokenizer.json file included in this repository. It is identical to the one from the original PyTorch model (
fastino/gliner2-multi-v1).