Downloads · 30 days
16
26% of all-time downloads
belumind/barb-2-ie-vi
barb-2-ie-vi is a token classification model from belumind. Use it when you need labels on individual words, such as names. It is set up for gliner. The card lists the license as apache-2.0.
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.
Downloads · 30 days
16
26% of all-time downloads
All-time downloads
62
Public
Parameters
467M
3.7 GB on disk
Likes
0
Public
Click a slice to open those files.
.bin1.9 GB · 50%
From the Hugging Face model README
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.
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.
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.
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.
| 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.
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)
| 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 | - |
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.
@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}
}