This checkpoint requires a per-ideograph word splitter, and serving it without
one loses every Chinese span with no error of any kind.
GLiNER classifies token spans, and its default whitespace splitter treats a
run of Han characters as one token — so 莫斯科 inside 莫斯科新闻 is not a
span the model can even express, let alone predict. This model was trained with
one token per Han ideograph (src/ner/tokenizer.py::CjkAwareSplitter), which
gliner_config.json cannot record: words_splitter_type names only GLiNER's
built-in kinds.
So the requirement is recorded in ner_meta.json, shipped beside the
weights in this repo:
The serving code reads that file and refuses to start when the configured
splitter disagrees with it. If you load this model yourself, re-attach an
equivalent splitter — measured effect of getting it wrong: 56/56 Chinese spans
found versus 0.
Decision threshold
Served at 0.3, below GLiNER's own 0.5, and
that is a property of serving rather than of the model: retrieval is
recall-hungry, because a city span never extracted can never be retrieved,
while a spurious span only adds a candidate the reranker can demote. The value
is derived from the sweep in make ner-eval --sweep, not asserted.
Results
Overall
bucket
precision
recall
F1
gold
predicted
overall
0.759
0.767
0.763
86
87
By label
bucket
precision
recall
F1
gold
predicted
CITY
0.855
0.887
0.870
53
55
REGION
0.800
0.267
0.400
15
5
STATE
0.333
0.833
0.476
6
15
COUNTRY
0.833
0.833
0.833
12
12
By language
bucket
precision
recall
F1
gold
predicted
ru
0.818
0.818
0.818
22
22
en
0.809
0.809
0.809
21
21
tr
0.708
0.708
0.708
24
24
zh
0.700
0.737
0.718
19
20
Versus the zero-shot baseline
Zero-shot urchade/gliner_multi-v2.1, measured with the same word splitter (otherwise the Chinese delta would be an artefact of segmentation rather than of fine-tuning):
bucket
precision
recall
F1
gold
predicted
overall
0.726
0.616
0.667
86
73
Metrics are micro-averaged over spans, not macro over queries: a query
naming three cities feeds three names into retrieval, so each one is a unit of
work the pipeline either gets right or does not.
Training
Selected by validation span F1, not eval_loss — the checkpoint saved is
whichever epoch scored best when called the way the engine calls it
(predict_entities on raw text).