Views
No views yet
Extract entities, classify text, parse structured records, score span attributes, and extract relations — all in one boundary architecture.
AutoExtractor: the checkpoint's architecture field selects BoundaryExtractor automatically.Classifier for cross-task label constraints, JointIE for typed entity–relation graphsgliner2[local] — no external API required| Model | Parameters | Encoder | Language | Use case |
|---|---|---|---|---|
fastino/gliner2.5-small-v1 | 74M | DeBERTa-v3-xsmall | English | Fast CPU extraction / classification |
fastino/gliner2.5-base-v1 | 194M | DeBERTa-v3-base | English | Default English multi-task checkpoint |
fastino/gliner2.5-multi-v1 | 287M | mDeBERTa-v3-base | Multilingual | Default multilingual multi-task checkpoint |
fastino/gliner2.5-multi-v1. All three checkpoints share the same public API.pip install "gliner2[local]"[local] extra pulls in PyTorch so you can load Hub checkpoints.AutoExtractor for GLiNER2.5. GLiNER2.from_pretrained(...) is the legacy span loader and will not dispatch this checkpoint.1from gliner2 import AutoExtractor
2
3model = AutoExtractor.from_pretrained("fastino/gliner2.5-multi-v1")
4
5print(type(model).__name__)
6print(model.config.architecture)
7# BoundaryExtractor
8# boundary1model = AutoExtractor.from_pretrained(
2 "fastino/gliner2.5-multi-v1",
3 map_location="cuda", # or "cpu" / "mps"
4 quantize=True, # fp16 weights on GPU
5 compile=True, # torch.compile after the first tracing call
6)
7print(type(model).__name__, next(model.parameters()).device)
8# BoundaryExtractor cuda:01text = "Apple CEO Tim Cook announced iPhone 15 in Cupertino yesterday."
2
3result = model.extract_entities(
4 text,
5 ["company", "person", "product", "location"],
6 include_confidence=True,
7 include_spans=True,
8)
9print(result)
10# {
11# "entities": {
12# "company": [{"text": "Apple", "start": 0, "end": 5, "confidence": 0.98}],
13# "person": [{"text": "Tim Cook", "start": 10, "end": 18, "confidence": 0.97}],
14# "product": [{"text": "iPhone 15", "start": 29, "end": 38, "confidence": 0.96}],
15# "location": [{"text": "Cupertino", "start": 42, "end": 51, "confidence": 0.95}],
16# }
17# }text[start:end] == entity["text"].1result = model.extract_entities(
2 "Patient received 400mg ibuprofen for severe headache at 2 PM.",
3 {
4 "medication": "Names of drugs or pharmaceutical substances",
5 "dosage": "Amounts such as 400mg, 2 tablets, or 5ml",
6 "symptom": "Reported symptoms or conditions",
7 "time": "Clock times or relative times",
8 },
9 include_spans=True,
10)
11print(result)
12# {
13# "entities": {
14# "medication": [{"text": "ibuprofen", "start": 23, "end": 32}],
15# "dosage": [{"text": "400mg", "start": 17, "end": 22}],
16# "symptom": [{"text": "severe headache", "start": 37, "end": 52}],
17# "time": [{"text": "2 PM", "start": 56, "end": 60}],
18# }
19# }classify_text:1result = model.classify_text(
2 "This laptop has amazing performance but terrible battery life!",
3 {"sentiment": ["positive", "negative", "neutral"]},
4)
5print(result)
6# {"sentiment": "negative"}
7
8result = model.classify_text(
9 "Great camera quality, decent performance, but poor battery life.",
10 {
11 "aspects": {
12 "labels": ["camera", "performance", "battery", "display", "price"],
13 "multi_label": True,
14 "cls_threshold": 0.4,
15 }
16 },
17)
18print(result)
19# {"aspects": ["camera", "performance", "battery"]}gliner2.classification.Classifier when labels on one task legally constrain another. classify_text will not enforce those rules.1from gliner2.classification import (
2 Classifier,
3 ClassificationSchema,
4 ClassificationConfig,
5)
6from gliner2.classification import constraints as C
7
8clf = Classifier.from_pretrained("fastino/gliner2.5-multi-v1")
9
10schema = (
11 ClassificationSchema()
12 .single("intent", ["read", "write", "delete"])
13 .multi("effects", ["read_only", "create", "modify", "delete"], min_labels=1)
14 .constrain(
15 C.implies(("intent", "delete"), ("effects", "delete")),
16 C.excludes(("intent", "read"), ("effects", "delete")),
17 )
18)
19
20result = clf.classify("Delete the temporary file from /tmp", schema)
21print(result.value("intent"))
22print(result.value("effects"))
23print(result.feasible)
24print(result.to_dict())
25# delete
26# ['delete']
27# True
28# {
29# "intent": {
30# "value": "delete",
31# "confidence": 0.93,
32# "probabilities": {"read": 0.02, "write": 0.05, "delete": 0.93},
33# },
34# "effects": {
35# "value": ["delete"],
36# "confidence": 0.88,
37# "probabilities": {
38# "read_only": 0.04, "create": 0.03, "modify": 0.05, "delete": 0.88
39# },
40# },
41# "_meta": {"feasible": True, "decoder": "exact"},
42# }ClassificationConfig on the call, not in from_pretrained:1result = clf.classify(
2 "Preview the report",
3 schema,
4 config=ClassificationConfig(decoder="beam", beam_size=16),
5)
6print(result.value("intent"), result.value("effects"), result.feasible)
7# read ['read_only'] Trueenable_relations=True. Independent decoding:1text = "Alice works for Acme in Paris."
2result = model.extract_relations(
3 text,
4 ["works_for", "located_in"],
5 include_spans=True,
6 include_confidence=True,
7)
8print(result)
9# {
10# "relation_extraction": {
11# "works_for": [{
12# "head": {"text": "Alice", "start": 0, "end": 5, "confidence": 0.91},
13# "tail": {"text": "Acme", "start": 16, "end": 20, "confidence": 0.91},
14# }],
15# "located_in": [{
16# "head": {"text": "Acme", "start": 16, "end": 20, "confidence": 0.87},
17# "tail": {"text": "Paris", "start": 24, "end": 29, "confidence": 0.87},
18# }],
19# }
20# }1schema = model.create_schema().relations(
2 {"works_for": {"threshold": 0.6}, "located_in": {"threshold": 0.6}}
3)
4result = model.extract(text, schema, include_spans=True)
5print(result)
6# {
7# "relation_extraction": {
8# "works_for": [{
9# "head": {"text": "Alice", "start": 0, "end": 5},
10# "tail": {"text": "Acme", "start": 16, "end": 20},
11# }],
12# "located_in": [{
13# "head": {"text": "Acme", "start": 16, "end": 20},
14# "tail": {"text": "Paris", "start": 24, "end": 29},
15# }],
16# }
17# }works_for heads are people and tails are organizations.JointIE scores mention and relation candidates, then searches a globally consistent graph with typed endpoints and uniqueness constraints.1from gliner2.joint_ie import JointIE, JointIEConfig
2
3joint = JointIE.from_pretrained("fastino/gliner2.5-multi-v1")
4
5schema = (
6 joint.create_schema()
7 .entities(["person", "organization", "location"])
8 .relation("works_for", "person", "organization", unique_head=True)
9 .relation("located_in", "organization", "location")
10 .no_self_loops()
11)
12
13result = joint.extract(
14 "Alice works for Acme in Paris. Bob joined Acme last year.",
15 schema,
16 config=JointIEConfig(optimizer="beam", beam_size=32),
17)
18
19print(result.feasible)
20print(result.to_dict())
21# True
22# {
23# "entities": [
24# {"id": "e1", "type": "person", "text": "Alice", "start": 0, "end": 5, "confidence": 0.94},
25# {"id": "e2", "type": "organization", "text": "Acme", "start": 16, "end": 20, "confidence": 0.92},
26# {"id": "e3", "type": "location", "text": "Paris", "start": 24, "end": 29, "confidence": 0.90},
27# {"id": "e4", "type": "person", "text": "Bob", "start": 31, "end": 34, "confidence": 0.91},
28# ],
29# "relations": [
30# {"type": "works_for", "head": "e1", "tail": "e2", "confidence": 0.88},
31# {"type": "works_for", "head": "e4", "tail": "e2", "confidence": 0.81},
32# {"type": "located_in", "head": "e2", "tail": "e3", "confidence": 0.86},
33# ],
34# }result.feasible. False means the hard constraints could not be satisfied (distinct from “the text contains no facts”).1for rel in result.relations:
2 head = result.entity(rel.head)
3 tail = result.entity(rel.tail)
4 print(f"{head.text} -{rel.type}-> {tail.text}")
5# Alice -works_for-> Acme
6# Bob -works_for-> Acme
7# Acme -located_in-> Paris1from gliner2 import AutoExtractor, AttributeGroup
2
3model = AutoExtractor.from_pretrained("fastino/gliner2.5-multi-v1")
4
5text = (
6 "Alice was delighted with the promotion, "
7 "but Bob sounded frustrated about the delay."
8)
9
10schema = (
11 model.create_schema()
12 .entities(["person"])
13 .entity_attributes({
14 "sentiment": AttributeGroup(
15 ["positive", "negative", "neutral"],
16 applies_to=["person"],
17 qualify_labels=True,
18 )
19 })
20)
21
22result = model.extract(
23 text,
24 schema,
25 include_spans=True,
26 include_confidence=True,
27)
28print(result)
29# {
30# "entities": {
31# "person": [
32# {
33# "text": "Alice",
34# "start": 0,
35# "end": 5,
36# "confidence": 0.96,
37# "sentiment": {"label": "positive", "confidence": 0.89},
38# },
39# {
40# "text": "Bob",
41# "start": 44,
42# "end": 47,
43# "confidence": 0.95,
44# "sentiment": {"label": "negative", "confidence": 0.84},
45# },
46# ]
47# }
48# }applies_to=["person"] keeps sentiment off other entity types. qualify_labels=True encodes model-facing queries as sentiment: positive while returning the short label positive.1schema = (
2 model.create_schema()
3 .entities(["person", "organization"])
4 .entity_attributes({
5 "sentiment": AttributeGroup(
6 ["positive", "negative", "neutral"],
7 applies_to=["person"],
8 qualify_labels=True,
9 )
10 })
11)
12
13result = model.extract(
14 "Alice praised Microsoft, but Bob criticized OpenAI.",
15 schema,
16 include_spans=True,
17 include_confidence=True,
18)
19print(result)
20# {
21# "entities": {
22# "person": [
23# {
24# "text": "Alice",
25# "start": 0,
26# "end": 5,
27# "confidence": 0.96,
28# "sentiment": {"label": "positive", "confidence": 0.88},
29# },
30# {
31# "text": "Bob",
32# "start": 29,
33# "end": 32,
34# "confidence": 0.95,
35# "sentiment": {"label": "negative", "confidence": 0.86},
36# },
37# ],
38# "organization": [
39# {"text": "Microsoft", "start": 14, "end": 23, "confidence": 0.97},
40# {"text": "OpenAI", "start": 44, "end": 50, "confidence": 0.96},
41# ],
42# }
43# }sentiment field. Person spans do.natural mode with an anchor field:1schema = (
2 model.create_schema()
3 .structure("purchase", mode="natural", anchor="buyer")
4 .field("buyer", dtype="str", cardinality="required_one")
5 .field("item", dtype="str", cardinality="required_one")
6)
7
8result = model.extract(
9 "Alice bought apples and Bob bought oranges.",
10 schema,
11)
12print(result)
13# {
14# "purchase": [
15# {"buyer": "Alice", "item": "apples"},
16# {"buyer": "Bob", "item": "oranges"},
17# ]
18# }enable_records=True.extract call:1from gliner2 import AttributeGroup
2
3schema = (
4 model.create_schema()
5 .entities({
6 "person": "Named people",
7 "organization": "Companies or teams",
8 "product": "Named products or services",
9 })
10 .entity_attributes({
11 "sentiment": AttributeGroup(
12 ["positive", "negative", "neutral"],
13 applies_to=["person"],
14 qualify_labels=True,
15 )
16 })
17 .classification("topic", ["technology", "business", "sports", "politics"])
18 .relations(["works_for", "announced"])
19 .structure("announcement", mode="natural", anchor="product")
20 .field("company", dtype="str")
21 .field("product", dtype="str", cardinality="required_one")
22)
23
24text = "Apple CEO Tim Cook unveiled the iPhone 15 Pro for $999."
25result = model.extract(text, schema, include_spans=True, include_confidence=True)
26print(result)
27# {
28# "entities": {
29# "person": [{
30# "text": "Tim Cook",
31# "start": 10,
32# "end": 18,
33# "confidence": 0.97,
34# "sentiment": {"label": "positive", "confidence": 0.82},
35# }],
36# "organization": [{"text": "Apple", "start": 0, "end": 5, "confidence": 0.98}],
37# "product": [{"text": "iPhone 15 Pro", "start": 32, "end": 45, "confidence": 0.96}],
38# },
39# "topic": {"label": "technology", "confidence": 0.94},
40# "relation_extraction": {
41# "works_for": [{
42# "head": {"text": "Tim Cook", "start": 10, "end": 18, "confidence": 0.86},
43# "tail": {"text": "Apple", "start": 0, "end": 5, "confidence": 0.86},
44# }],
45# "announced": [{
46# "head": {"text": "Tim Cook", "start": 10, "end": 18, "confidence": 0.84},
47# "tail": {"text": "iPhone 15 Pro", "start": 32, "end": 45, "confidence": 0.84},
48# }],
49# },
50# "announcement": [{
51# "company": "Apple",
52# "product": "iPhone 15 Pro",
53# }],
54# }topic is independent of per-person sentiment.1texts = [
2 "Google hired Jane Doe in London.",
3 "Tesla launched the Model 3 in California.",
4]
5results = model.batch_extract_entities(
6 texts,
7 ["company", "person", "product", "location"],
8 batch_size=8,
9 include_spans=True,
10)
11print(results)
12# [
13# {
14# "entities": {
15# "company": [{"text": "Google", "start": 0, "end": 6}],
16# "person": [{"text": "Jane Doe", "start": 13, "end": 21}],
17# "product": [],
18# "location": [{"text": "London", "start": 25, "end": 31}],
19# }
20# },
21# {
22# "entities": {
23# "company": [{"text": "Tesla", "start": 0, "end": 5}],
24# "person": [],
25# "product": [{"text": "Model 3", "start": 19, "end": 26}],
26# "location": [{"text": "California", "start": 30, "end": 40}],
27# }
28# },
29# ]batch_extract accepts one schema or a list of schemas (one per document).extract(...) with max_len truncates. Long-context helpers scan overlapping word chunks and remap spans to document offsets.1long_text = ("Quarterly overview. " * 40) + "Satya Nadella spoke in Redmond about Microsoft."
2
3result = model.extract_entities_long(
4 long_text,
5 ["person", "organization", "location"],
6 chunk_size=384,
7 chunk_overlap=64,
8 include_spans=True,
9)
10print(result)
11# {
12# "entities": {
13# "person": [{"text": "Satya Nadella", "start": 800, "end": 813}],
14# "organization": [{"text": "Microsoft", "start": 837, "end": 846}],
15# "location": [{"text": "Redmond", "start": 823, "end": 830}],
16# }
17# }
18
19result = model.extract_long(long_text, schema, chunk_size=384, chunk_overlap=64)
20print(result["topic"])
21# technologyClassifier.classify_long and JointIE.extract_long.BoundaryExtractor)[L, W] width grid)max_len=4096)microsoft/mdeberta-v3-baseenable_records=True), relations (enable_relations=True)flat (weighted interval scheduling); override per call with overlap_policyGLiNER2 / SpanExtractor. Those classes expect the legacy span architecture.1@misc{zaratiana2025gliner2efficientmultitaskinformation,
2 title={GLiNER2: An Efficient Multi-Task Information Extraction System with Schema-Driven Interface},
3 author={Urchade Zaratiana and Gil Pasternak and Oliver Boyd and George Hurn-Maloney and Ash Lewis},
4 year={2025},
5 eprint={2507.18546},
6 archivePrefix={arXiv},
7 primaryClass={cs.CL},
8 url={https://arxiv.org/abs/2507.18546},
9}