barb-2-ie-vi

Joint entity and relation extraction for Vietnamese. It no longer needs the relation labels to do good entity extraction - which is what separates it from barb-1.

The problem it fixes

GLiNER encodes the relation labels you pass alongside the entity labels, and the entity head learns to lean on them. On barb-1 that dependence costs you 6.2 F1 if you only want entities and pass a placeholder relation:

entity-only call full call (18 relations) gap
barb-1 68.63 74.80 6.17
barb-2 72.60 74.87 2.27

Paired bootstrap, barb-2 minus barb-1 on 450 sentences:

measurement delta 95% CI resamples positive
entity-only NER +3.96 [+2.66, +5.43] 100%
full-call NER +0.08 [-0.86, +1.02] 57%
relations (strict) -1.32 [-3.93, +1.36] 17%

So: a real, certain gain when you skip the relations, no loss when you do not, and a small relation cost that the data cannot distinguish from zero.

That also buys throughput. Passing 18 relation labels costs 35% of it (71.3 vs 46.0 sentences/s on one A100, fp32, batch 16). With barb-2 you can skip them for 2.3 F1 instead of 6.2.

How it was trained

Same recipe as barb-1 - fine-tuned from knowledgator/gliner-relex-large-v1.0, 8,910 steps, clean sentences kept and degraded copies added alongside - with one change: the relations were stripped from 30% of the training examples, so the model had to learn to find entities without that prompt some of the time.

30% is tuned, not arbitrary. At 50% the entity-only gain is larger (73.97) but relations drop to 60.53, past what we were willing to pay. The trade is continuous and the mix ratio is the dial.

Results

450 sentences / 1,328 spans, hand-audited. Each row at its own best threshold.

barb-1 barb-2
Clean text 74.80 (0.65) 74.87 (0.65)
Entity-only call 68.63 72.60 (0.60)
Diacritics stripped 63.25 62.34 (0.60)
ALL CAPS 56.06 54.65 (0.60)
Relations, strict 63.41 62.14 (0.50/0.60)
Job-title boundaries (55 spans) 16 exact, F1 23.36 17 exact, F1 27.64

barb-2 gives up about a point on degraded text and on relations, and takes 3.96 on the entity-only call. If your pipeline always passes the full relation list and you care most about no-diacritics input, barb-1 is still the better pick.

Per entity type, threshold 0.65

type P R F1
ngay 95.3 97.8 96.6
dia diem 84.2 79.3 81.7
van ban 92.3 70.6 80.0
to chuc 83.7 63.6 72.3
nguoi 69.8 70.0 69.9
tac pham 70.6 37.5 49.0
giai thuong 41.2 25.0 31.1
san pham 46.2 23.1 30.8
chuc vu 71.4 15.2 25.0
su kien 22.2 11.1 14.8

The five rare types are weak on RECALL, not precision, and they are the longest-spanned types in the schema while having the fewest training examples. We tested six cheap fixes for this and all six failed; see Known limitations.

Usage

pip install gliner==0.2.29
import os, sys
from gliner import GLiNER
from huggingface_hub import hf_hub_download

model = GLiNER.from_pretrained("belumind/barb-2-ie-vi").to("cuda")

sys.path.insert(0, os.path.dirname(
    hf_hub_download("belumind/barb-2-ie-vi", "barb_labels.py")))
from barb_labels import extract, ENTITY_LABELS

# entities + relations
ents, rels = extract(model, [text], threshold=0.5, relation_threshold=0.6, json_keys=True)

# entities only - now cheap
ents, _ = extract(model, [text], labels=ENTITY_LABELS, relations=["x"], threshold=0.6)

Operating points, measured

what you want entity threshold relation_threshold
Entities only 0.60 -
Entities + relations 0.50 0.60
Maximum entity precision 0.70 -
Degraded input (no diacritics / ALL CAPS) 0.60 -

Labels must keep their Vietnamese diacritics

GLiNER encodes the label STRING with the same text encoder as the input, so the label you pass is itself a piece of Vietnamese text. Measured on barb-1 at threshold 0.65:

labels passed to the model NER F1 cost
with diacritics, spaces 74.8 -
ASCII, spaces (to chuc) 39.8 -35.0
snake_case ASCII (to_chuc) 29.6 -45.2

Two separate penalties, and both are silent. We also checked whether the gain from real relation labels is just prompt length: 18 meaningless labels score 69.1 and 18 scrambled ones 68.6, against 74.8 for the real list. It is the meaning, not the count.

barb_labels.check_labels() raises on a de-accented known label and warns on underscores. snake_case is fine as an OUTPUT key - extract(..., json_keys=True) maps it for you - it just must never be what you hand the model.

Weights ship as both model.safetensors and pytorch_model.bin, byte-identical.

Known limitations

  • The five rare types are weak: su kien 14.8, chuc vu 25.0, san pham 30.8, giai thuong 31.1, tac pham 49.0. The failure is recall, and the cause is measured: 96% of training spans belong to the four common types, which average 2.2-3.4 tokens, while the weak types are the longest in the schema. The model learned a short-span prior. We tested and rejected six cheap fixes for this - per-type thresholds, two kinds of boundary post-processing, an initialization change, a false-negative hypothesis, and 8x oversampling - none survived a held-out test. What is left is roughly 3,000 new annotated spans or a length-aware loss.
  • Job titles: 17 of 55 on the correctly-bounded benchmark. Better than barb-1 (16) and than the base model (16 at the same threshold), but still low in absolute terms.
  • Slightly behind barb-1 on degraded text (62.34 vs 63.25 stripped, 54.65 vs 56.06 ALL CAPS) and on relations (62.14 vs 63.41).
  • Benchmark gold is still missing entities, so absolute F1 understates every model on it. Comparisons between models are unaffected.
  • Vietnamese Wikipedia-style prose. Legal, medical and conversational text are out of distribution and have not been measured.

Related

Citation

@misc{barb2ievi2026,
  title   = {barb-2-ie-vi: relation-independent joint IE for Vietnamese},
  author  = {Belumind},
  year    = {2026},
  howpublished = {https://huggingface.co/belumind/barb-2-ie-vi}
}
Downloads last month
40
Safetensors
Model size
0.5B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Spaces using belumind/barb-2-ie-vi 2