[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-96398":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":9,"totalLinesOfCode":9,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":9,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":17,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":9,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":9,"createdAt":9,"pushedAt":9,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":16,"starSnapshotCount":16,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},96398,"GLiNER2","fastino-ai\u002FGLiNER2","fastino-ai","Unified Schema-Based Information Extraction",null,"https:\u002F\u002Fgithub.com\u002Ffastino-ai\u002FGLiNER2","Python",1942,179,21,40,0,13,39,79.57,false,"main","2026-09-20 04:01:32","# GLiNER2: Unified Schema-Based Information Extraction and Text Classification\n\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-Apache%202.0-blue.svg)](https:\u002F\u002Fopensource.org\u002Flicenses\u002FApache-2.0)\n[![Python 3.10+](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpython-3.10+-blue.svg)](https:\u002F\u002Fwww.python.org\u002Fdownloads\u002F)\n[![PyPI version](https:\u002F\u002Fbadge.fury.io\u002Fpy\u002Fgliner2.svg)](https:\u002F\u002Fbadge.fury.io\u002Fpy\u002Fgliner2)\n[![Downloads](https:\u002F\u002Fpepy.tech\u002Fbadge\u002Fgliner2)](https:\u002F\u002Fpepy.tech\u002Fproject\u002Fgliner2)\n[![Reddit](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FReddit-r%2FGLiNER-FF4500?logo=reddit&logoColor=white)](https:\u002F\u002Fwww.reddit.com\u002Fr\u002FGLiNER\u002F)\n[![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Community-5865F2?logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002Ffastino)\n\n> *Schema-driven information extraction and classification — entities, labels, records, relations, and span attributes in one local model.*\n\nGLiNER2 is a **schema-conditioned** encoder family for **Named Entity Recognition**, **Text Classification**, **Structured Data Extraction**, **Relation Extraction**, and **span attributes**. Two extraction architectures share one public API:\n\n- **`span`** (`GLiNER2` \u002F `SpanExtractor`) — fixed-width span grid; legacy checkpoints and specialty fine-tunes (GLiGuard, PII).\n- **`boundary`** (`BoundaryExtractor`, **GLiNER2.5**) — sparse start\u002Fend pairing; any span length within the encoded window.\n\nLoad any Hub checkpoint with `AutoExtractor.from_pretrained(...)`. It dispatches by the saved `architecture` field. `GLiNER2.from_pretrained(...)` remains span-only and will **not** load GLiNER2.5 boundary checkpoints.\n\nFine-tune via [Fastino](https:\u002F\u002Ffastino.ai). Join discussions on [Discord](https:\u002F\u002Fdiscord.gg\u002Ffastino) and [Reddit](https:\u002F\u002Fwww.reddit.com\u002Fr\u002FGLiNER\u002F).\n\n## ✨ Why GLiNER2?\n\n- **🎯 One schema, many tasks**: entities, classification, structured records, relations, and span attributes in a single forward pass\n- **📐 Two architectures**: span (GLiNER2) and boundary (GLiNER2.5) behind `AutoExtractor`\n- **🔗 Constrained decoding**: `Classifier` for cross-task label rules; `JointIE` for typed entity–relation graphs\n- **💻 CPU first**: fast local inference on standard hardware — no GPU required\n- **🛡️ Privacy**: 100% local processing, zero external dependencies\n\n## 🚀 Installation & Quick Start\n\nGLiNER2 requires Python 3.10 or newer. Choose the smallest install profile that\nmatches your use case:\n\n```bash\n# Schema validation, API client, training-data utilities — no torch required\npip install gliner2\n\n# Local model inference and LoRA support\npip install gliner2[local]\n\n# Model training and recipe configuration\npip install gliner2[train]\n\n# Reproducible tests, contributor tooling, or benchmarks\npip install gliner2[test]\npip install gliner2[dev]\npip install gliner2[benchmark]\n```\n\nThe base install gives you `Schema`, `SchemaInput`, `RegexValidator`, `GLiNER2API`,\n`InputExample`, `TrainingDataset`, and all JSONL validation tooling — everything\nneeded to build schemas, validate data, and call the cloud API without pulling in\nPyTorch. `API` is a concise alias for `GLiNER2API`:\n\n```python\nfrom gliner2 import API, InputExample, Schema, TrainingDataset\n```\n\nThe torch-free API client partitions batch requests locally and can scan long\ndocuments without changing the server protocol:\n\n```python\nclient = API()  # reads PIONEER_API_KEY\nresults = client.batch_extract_entities(\n    documents,\n    [\"company\", \"person\"],\n    batch_size=8,\n)\nlong_result = client.extract_entities_long(\n    annual_report,\n    [\"company\", \"person\"],\n    chunk_size=384,\n    chunk_overlap=64,\n    include_spans=True,\n)\n```\n\nTo load and run models locally, install the `[local]` extra and use\n`AutoExtractor` — it loads span, boundary, GLiGuard, and PII checkpoints:\n\n```python\nfrom gliner2 import AutoExtractor  # requires gliner2[local]\n\n# Default English GLiNER2.5 boundary checkpoint\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\n\ntext = \"Apple CEO Tim Cook announced iPhone 15 in Cupertino yesterday.\"\nresult = model.extract_entities(text, [\"company\", \"person\", \"product\", \"location\"])\n\nprint(result)\n# {'entities': {'company': ['Apple'], 'person': ['Tim Cook'], 'product': ['iPhone 15'], 'location': ['Cupertino']}}\n```\n\nFor legacy span checkpoints or explicit span-only loading, `GLiNER2.from_pretrained(\"fastino\u002Fgliner2-base-v1\")` still works (`GLiNER2 = SpanExtractor`).\n\n### Quantization and Compilation\n\nEnable fp16 and\u002For `torch.compile` for faster inference — no extra dependencies required.\n\n```python\n# fp16\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\", map_location=\"cuda\", quantize=True)\n\n# torch.compile (fused GPU kernels, first call triggers tracing)\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\", map_location=\"cuda\", compile=True)\n\n# Both\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\", map_location=\"cuda\", quantize=True, compile=True)\n\n# Or after loading\nmodel.quantize()\nmodel.compile()\n```\n\n### Custom word splitters\n\nGLiNER2 first splits text into **word tokens**, then encodes those tokens with the model's subword tokenizer. The default `\"whitespace\"` splitter is the one used to train public checkpoints.\n\nFor languages without whitespace-delimited words, such as Chinese, use the character-level splitter:\n\n```python\nmodel = AutoExtractor.from_pretrained(\n    \"fastino\u002Fgliner2.5-base-v1\",\n    word_splitter=\"char\",\n)\n\n# Or after loading\nmodel.set_word_splitter(\"char\")\n```\n\nBuilt-in names:\n\n| Name | Class | Use when |\n|------|-------|----------|\n| `\"whitespace\"` (default) | `WhitespaceTokenSplitter` | Space-delimited languages; matches public checkpoints |\n| `\"char\"` | `CharLevelSplitter` | Languages such as Chinese; keeps Latin words\u002Femails intact and splits other non-space characters |\n\nYou can also pass a custom callable that yields `(token, start, end)` with exclusive-end offsets into the **original** text:\n\n```python\nfrom gliner2.processor import CharLevelSplitter\n\nmodel.set_word_splitter(CharLevelSplitter())\n```\n\nChanging a pretrained model's word boundaries can affect quality unless the model was trained with the same splitter. The choice is runtime-only: saved checkpoints reload with `\"whitespace\"` unless you pass `word_splitter` again.\n\n### Architecture guide\n\nThe boundary architecture (**GLiNER2.5**) uses sparse start\u002Fend pairing instead of a fixed span-width grid, so spans of any length that fit in the encoded window are representable. It supports entities, classification, structured record\u002Fevent decoding, sparse relations, and span attributes when enabled by the checkpoint.\n\nSee the full guide — loading, creating\u002Ftraining a boundary model, record and relation decoding, save\u002Fload, LoRA aliases, export mode, loss\u002Fimbalance controls, and gold-capacity policy — in [`docs\u002Fboundary_architecture.md`](docs\u002Fboundary_architecture.md) and the design notes in [`docs\u002Fgliner2_5_boundary_architecture.md`](docs\u002Fgliner2_5_boundary_architecture.md).\n\n## 📦 Available Models\n\nAll models are on the [GLiNER2 family collection](https:\u002F\u002Fhuggingface.co\u002Fcollections\u002Ffastino\u002Fgliner2-family). Load with `AutoExtractor.from_pretrained(...)` unless noted.\n\n### GLiNER2 (span architecture)\n\n| Model | Parameters | Encoder | Language | Use case |\n|-------|------------|---------|----------|----------|\n| [`fastino\u002Fgliner2-base-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2-base-v1) | 205M | DeBERTa-v3-base | English | Default span checkpoint |\n| [`fastino\u002Fgliner2-large-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2-large-v1) | 340M | DeBERTa-v3-large | English | Higher-accuracy span |\n| [`fastino\u002Fgliner2-multi-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2-multi-v1) | ~205M | mDeBERTa-v3-base | Multilingual | Multilingual span |\n\n### GLiNER2.5 (boundary architecture)\n\n| Model | Parameters | Encoder | Language | Use case |\n|-------|------------|---------|----------|----------|\n| [`fastino\u002Fgliner2.5-small-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2.5-small-v1) | 74M | DeBERTa-v3-xsmall | English | Fast CPU \u002F edge |\n| [`fastino\u002Fgliner2.5-base-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2.5-base-v1) | 194M | DeBERTa-v3-base | English | Default English multi-task |\n| [`fastino\u002Fgliner2.5-multi-v1`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2.5-multi-v1) | 287M | mDeBERTa-v3-base | Multilingual | Default multilingual multi-task |\n\nBoundary checkpoints include classification, records, and relations when those heads are enabled. Prefer **`gliner2.5-base-v1`** for English and **`gliner2.5-multi-v1`** for multilingual.\n\n### Safety and PII (span fine-tunes)\n\n| Model | Parameters | Use case |\n|-------|------------|----------|\n| [`fastino\u002Fgliguard-LLMGuardrails-300M`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliguard-LLMGuardrails-300M) | ~300M | LLM prompt\u002Fresponse guardrails (safety, toxicity, jailbreak, refusal) |\n| [`fastino\u002Fgliner2-privacy-filter-PII-multi`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002Fgliner2-privacy-filter-PII-multi) | 205M | Multilingual PII detection (42 entity types) |\n| [`fastino\u002FGLiNER2-Guardrails-PII-Multi`](https:\u002F\u002Fhuggingface.co\u002Ffastino\u002FGLiNER2-Guardrails-PII-Multi) | 205M | Combined guardrails + PII in one checkpoint |\n\nSee [Safety, PII, and GLiGuard](tutorial\u002F16-safety_pii.md) for usage. GLiGuard and PII models are span checkpoints; `AutoExtractor` and `GLiNER2` both load them.\n\n**Loader cheat-sheet**\n\n| Goal | Checkpoint |\n|------|------------|\n| English IE (recommended) | `fastino\u002Fgliner2.5-base-v1` |\n| Multilingual IE | `fastino\u002Fgliner2.5-multi-v1` |\n| Small \u002F fast English | `fastino\u002Fgliner2.5-small-v1` |\n| Legacy span | `fastino\u002Fgliner2-{base,large,multi}-v1` |\n| LLM guardrails | `fastino\u002Fgliguard-LLMGuardrails-300M` |\n| PII redaction | `fastino\u002Fgliner2-privacy-filter-PII-multi` |\n| Guardrails + PII | `fastino\u002FGLiNER2-Guardrails-PII-Multi` |\n\n## 📚 Documentation & Tutorials\n\n### Core extraction (tutorials 1–7)\n- **[Text Classification](tutorial\u002F1-classification.md)** — Single and multi-label classification\n- **[Entity Extraction](tutorial\u002F2-ner.md)** — NER with descriptions and spans\n- **[Structured Data Extraction](tutorial\u002F3-json_extraction.md)** — JSON \u002F record structures\n- **[Combined Schemas](tutorial\u002F4-combined.md)** — Multi-task extraction in one pass\n- **[Regex Validators](tutorial\u002F5-validator.md)** — Filter and validate spans\n- **[Relation Extraction](tutorial\u002F6-relation_extraction.md)** — Independent relation tuples\n- **[API Access](tutorial\u002F7-api.md)** — Cloud API via `GLiNER2API`\n\n### Advanced decoding (GLiNER2.5)\n- **[Long-Context Extraction](tutorial\u002F12-long_context.md)** — Chunked long-document APIs\n- **[Span Attributes](tutorial\u002F13-span_attributes.md)** — Sentiment and labels on entity spans\n- **[Constrained Classification](tutorial\u002F14-constrained_classification.md)** — Hard cross-task label constraints\n- **[Joint Information Extraction](tutorial\u002F15-joint_ie.md)** — Typed entity–relation graphs\n\n### Safety, PII, and GLiGuard\n- **[Safety, PII, and GLiGuard](tutorial\u002F16-safety_pii.md)** — Guardrails and PII checkpoints\n\n### Training & customization\n- **[Training Data Format](tutorial\u002F8-train_data.md)** — JSONL formats\n- **[Model Training](tutorial\u002F9-training.md)** — Span and boundary training\n- **[LoRA Adapters](tutorial\u002F10-lora_adapters.md)** — Parameter-efficient fine-tuning\n- **[Adapter Switching](tutorial\u002F11-adapter_switching.md)** — Runtime adapter routing\n\n### Architecture\n- **[Boundary architecture guide](docs\u002Fboundary_architecture.md)** — Loading, training, records, relations\n- **[GLiNER2.5 design notes](docs\u002Fgliner2_5_boundary_architecture.md)** — Propose-then-rerank internals\n\n## 🎯 Core Capabilities\n\n### 1. Entity Extraction\nExtract named entities with optional descriptions for precision:\n\n```python\n# Basic entity extraction\nentities = model.extract_entities(\n    \"Patient received 400mg ibuprofen for severe headache at 2 PM.\",\n    [\"medication\", \"dosage\", \"symptom\", \"time\"]\n)\n# Output: {'entities': {'medication': ['ibuprofen'], 'dosage': ['400mg'], 'symptom': ['severe headache'], 'time': ['2 PM']}}\n\n# Enhanced with descriptions for medical accuracy\nentities = model.extract_entities(\n    \"Patient received 400mg ibuprofen for severe headache at 2 PM.\",\n    {\n        \"medication\": \"Names of drugs, medications, or pharmaceutical substances\",\n        \"dosage\": \"Specific amounts like '400mg', '2 tablets', or '5ml'\",\n        \"symptom\": \"Medical symptoms, conditions, or patient complaints\",\n        \"time\": \"Time references like '2 PM', 'morning', or 'after lunch'\"\n    }\n)\n# Same output but with higher accuracy due to context descriptions\n\n# With confidence scores\nentities = model.extract_entities(\n    \"Apple Inc. CEO Tim Cook announced iPhone 15 in Cupertino.\",\n    [\"company\", \"person\", \"product\", \"location\"],\n    include_confidence=True\n)\n# Output: {\n#     'entities': {\n#         'company': [{'text': 'Apple Inc.', 'confidence': 0.95}],\n#         'person': [{'text': 'Tim Cook', 'confidence': 0.92}],\n#         'product': [{'text': 'iPhone 15', 'confidence': 0.88}],\n#         'location': [{'text': 'Cupertino', 'confidence': 0.90}]\n#     }\n# }\n\n# With character positions (spans)\nentities = model.extract_entities(\n    \"Apple Inc. CEO Tim Cook announced iPhone 15 in Cupertino.\",\n    [\"company\", \"person\", \"product\"],\n    include_spans=True\n)\n# Output: {\n#     'entities': {\n#         'company': [{'text': 'Apple Inc.', 'start': 0, 'end': 9}],\n#         'person': [{'text': 'Tim Cook', 'start': 15, 'end': 23}],\n#         'product': [{'text': 'iPhone 15', 'start': 35, 'end': 44}]\n#     }\n# }\n\n# With both confidence and spans\nentities = model.extract_entities(\n    \"Apple Inc. CEO Tim Cook announced iPhone 15 in Cupertino.\",\n    [\"company\", \"person\", \"product\"],\n    include_confidence=True,\n    include_spans=True\n)\n# Output: {\n#     'entities': {\n#         'company': [{'text': 'Apple Inc.', 'confidence': 0.95, 'start': 0, 'end': 9}],\n#         'person': [{'text': 'Tim Cook', 'confidence': 0.92, 'start': 15, 'end': 23}],\n#         'product': [{'text': 'iPhone 15', 'confidence': 0.88, 'start': 35, 'end': 44}]\n#     }\n# }\n```\n\n### Long-Document Extraction\nUse the explicit long-document APIs when input text is longer than the model's\nnormal context window. GLiNER2 scans overlapping word chunks, remaps chunk-local\nspans back to the original document, and merges duplicate detections from the\noverlap.\n\n```python\nlong_text = open(\"annual_report.txt\").read()\n\nresult = model.extract_entities_long(\n    long_text,\n    [\"company\", \"person\", \"product\", \"location\"],\n    chunk_size=384,\n    chunk_overlap=64,\n    include_spans=True,\n    include_confidence=True,\n)\n\n# Spans are global offsets into long_text.\nfor company in result[\"entities\"].get(\"company\", []):\n    assert long_text[company[\"start\"]:company[\"end\"]] == company[\"text\"]\n```\n\nFor multiple documents, use `batch_extract_entities_long(...)` or the generic\n`batch_extract_long(...)` with a schema. Increase `chunk_overlap` when important\nentities or relations may appear near chunk boundaries.\n\nAll extraction methods accept the same explicit `overlap_policy`: `allow`\nkeeps every distinct span, `nested` permits containment but rejects crossing\nspans, `flat`\u002F`disallow` selects a deterministic non-overlapping set, and\n`longest` removes strictly contained spans. Leaving it as `None` preserves the\nloaded architecture's checkpoint-compatible default.\n\n### 2. Text Classification\nSingle or multi-label classification with configurable confidence:\n\n```python\n# Sentiment analysis\nresult = model.classify_text(\n    \"This laptop has amazing performance but terrible battery life!\",\n    {\"sentiment\": [\"positive\", \"negative\", \"neutral\"]}\n)\n# Output: {'sentiment': 'negative'}\n\n# Multi-aspect classification\nresult = model.classify_text(\n    \"Great camera quality, decent performance, but poor battery life.\",\n    {\n        \"aspects\": {\n            \"labels\": [\"camera\", \"performance\", \"battery\", \"display\", \"price\"],\n            \"multi_label\": True,\n            \"cls_threshold\": 0.4\n        }\n    }\n)\n# Output: {'aspects': ['camera', 'performance', 'battery']}\n\n# With confidence scores\nresult = model.classify_text(\n    \"This laptop has amazing performance but terrible battery life!\",\n    {\"sentiment\": [\"positive\", \"negative\", \"neutral\"]},\n    include_confidence=True\n)\n# Output: {'sentiment': {'label': 'negative', 'confidence': 0.82}}\n\n# Multi-label with confidence\nschema = model.create_schema().classification(\n    \"topics\",\n    [\"technology\", \"business\", \"health\", \"politics\", \"sports\"],\n    multi_label=True,\n    cls_threshold=0.3\n)\ntext = \"Apple announced new health monitoring features in their latest smartwatch, boosting their stock price.\"\nresults = model.extract(text, schema, include_confidence=True)\n# Output: {\n#     'topics': [\n#         {'label': 'technology', 'confidence': 0.92},\n#         {'label': 'business', 'confidence': 0.78},\n#         {'label': 'health', 'confidence': 0.65}\n#     ]\n# }\n```\n\n### 3. Structured Data Extraction\nParse complex structured information with field-level control:\n\n```python\n# Product information extraction\ntext = \"iPhone 15 Pro Max with 256GB storage, A17 Pro chip, priced at $1199. Available in titanium and black colors.\"\n\nresult = model.extract_json(\n    text,\n    {\n        \"product\": [\n            \"name::str::Full product name and model\",\n            \"storage::str::Storage capacity like 256GB or 1TB\", \n            \"processor::str::Chip or processor information\",\n            \"price::str::Product price with currency\",\n            \"colors::list::Available color options\"\n        ]\n    }\n)\n# Output: {\n#     'product': [{\n#         'name': 'iPhone 15 Pro Max',\n#         'storage': '256GB', \n#         'processor': 'A17 Pro chip',\n#         'price': '$1199',\n#         'colors': ['titanium', 'black']\n#     }]\n# }\n\n# Multiple structured entities\ntext = \"Apple Inc. headquarters in Cupertino launched iPhone 15 for $999 and MacBook Air for $1299.\"\n\nresult = model.extract_json(\n    text,\n    {\n        \"company\": [\n            \"name::str::Company name\",\n            \"location::str::Company headquarters or office location\"\n        ],\n        \"products\": [\n            \"name::str::Product name and model\",\n            \"price::str::Product retail price\"\n        ]\n    }\n)\n# Output: {\n#     'company': [{'name': 'Apple Inc.', 'location': 'Cupertino'}],\n#     'products': [\n#         {'name': 'iPhone 15', 'price': '$999'},\n#         {'name': 'MacBook Air', 'price': '$1299'}\n#     ]\n# }\n\n# With confidence scores\nresult = model.extract_json(\n    \"The MacBook Pro costs $1999 and features M3 chip, 16GB RAM, and 512GB storage.\",\n    {\n        \"product\": [\n            \"name::str\",\n            \"price\",\n            \"features\"\n        ]\n    },\n    include_confidence=True\n)\n# Output: {\n#     'product': [{\n#         'name': {'text': 'MacBook Pro', 'confidence': 0.95},\n#         'price': [{'text': '$1999', 'confidence': 0.92}],\n#         'features': [\n#             {'text': 'M3 chip', 'confidence': 0.88},\n#             {'text': '16GB RAM', 'confidence': 0.90},\n#             {'text': '512GB storage', 'confidence': 0.87}\n#         ]\n#     }]\n# }\n\n# With character positions (spans)\nresult = model.extract_json(\n    \"The MacBook Pro costs $1999 and features M3 chip.\",\n    {\n        \"product\": [\n            \"name::str\",\n            \"price\"\n        ]\n    },\n    include_spans=True\n)\n# Output: {\n#     'product': [{\n#         'name': {'text': 'MacBook Pro', 'start': 4, 'end': 15},\n#         'price': [{'text': '$1999', 'start': 22, 'end': 27}]\n#     }]\n# }\n\n# With both confidence and spans\nresult = model.extract_json(\n    \"The MacBook Pro costs $1999 and features M3 chip, 16GB RAM, and 512GB storage.\",\n    {\n        \"product\": [\n            \"name::str\",\n            \"price\",\n            \"features\"\n        ]\n    },\n    include_confidence=True,\n    include_spans=True\n)\n# Output: {\n#     'product': [{\n#         'name': {'text': 'MacBook Pro', 'confidence': 0.95, 'start': 4, 'end': 15},\n#         'price': [{'text': '$1999', 'confidence': 0.92, 'start': 22, 'end': 27}],\n#         'features': [\n#             {'text': 'M3 chip', 'confidence': 0.88, 'start': 32, 'end': 39},\n#             {'text': '16GB RAM', 'confidence': 0.90, 'start': 41, 'end': 49},\n#             {'text': '512GB storage', 'confidence': 0.87, 'start': 55, 'end': 68}\n#         ]\n#     }]\n# }\n```\n\n### 4. Relation Extraction\nExtract relationships between entities as directional tuples:\n\n```python\n# Basic relation extraction\ntext = \"John works for Apple Inc. and lives in San Francisco. Apple Inc. is located in Cupertino.\"\n\nresult = model.extract_relations(\n    text,\n    [\"works_for\", \"lives_in\", \"located_in\"]\n)\n# Output: {\n#     'relation_extraction': {\n#         'works_for': [('John', 'Apple Inc.')],\n#         'lives_in': [('John', 'San Francisco')],\n#         'located_in': [('Apple Inc.', 'Cupertino')]\n#     }\n# }\n\n# With descriptions for better accuracy\nschema = model.create_schema().relations({\n    \"works_for\": \"Employment relationship where person works at organization\",\n    \"founded\": \"Founding relationship where person created organization\",\n    \"acquired\": \"Acquisition relationship where company bought another company\",\n    \"located_in\": \"Geographic relationship where entity is in a location\"\n})\n\ntext = \"Elon Musk founded SpaceX in 2002. SpaceX is located in Hawthorne, California.\"\nresults = model.extract(text, schema)\n# Output: {\n#     'relation_extraction': {\n#         'founded': [('Elon Musk', 'SpaceX')],\n#         'located_in': [('SpaceX', 'Hawthorne, California')]\n#     }\n# }\n\n# With confidence scores\nresults = model.extract_relations(\n    \"John works for Apple Inc. and lives in San Francisco.\",\n    [\"works_for\", \"lives_in\"],\n    include_confidence=True\n)\n# Output: {\n#     'relation_extraction': {\n#         'works_for': [{\n#             'head': {'text': 'John', 'confidence': 0.95},\n#             'tail': {'text': 'Apple Inc.', 'confidence': 0.92}\n#         }],\n#         'lives_in': [{\n#             'head': {'text': 'John', 'confidence': 0.94},\n#             'tail': {'text': 'San Francisco', 'confidence': 0.91}\n#         }]\n#     }\n# }\n\n# With character positions (spans)\nresults = model.extract_relations(\n    \"John works for Apple Inc. and lives in San Francisco.\",\n    [\"works_for\", \"lives_in\"],\n    include_spans=True\n)\n# Output: {\n#     'relation_extraction': {\n#         'works_for': [{\n#             'head': {'text': 'John', 'start': 0, 'end': 4},\n#             'tail': {'text': 'Apple Inc.', 'start': 15, 'end': 25}\n#         }],\n#         'lives_in': [{\n#             'head': {'text': 'John', 'start': 0, 'end': 4},\n#             'tail': {'text': 'San Francisco', 'start': 33, 'end': 46}\n#         }]\n#     }\n# }\n\n# With both confidence and spans\nresults = model.extract_relations(\n    \"John works for Apple Inc. and lives in San Francisco.\",\n    [\"works_for\", \"lives_in\"],\n    include_confidence=True,\n    include_spans=True\n)\n# Output: {\n#     'relation_extraction': {\n#         'works_for': [{\n#             'head': {'text': 'John', 'confidence': 0.95, 'start': 0, 'end': 4},\n#             'tail': {'text': 'Apple Inc.', 'confidence': 0.92, 'start': 15, 'end': 25}\n#         }],\n#         'lives_in': [{\n#             'head': {'text': 'John', 'confidence': 0.94, 'start': 0, 'end': 4},\n#             'tail': {'text': 'San Francisco', 'confidence': 0.91, 'start': 33, 'end': 46}\n#         }]\n#     }\n# }\n```\n\n### 5. Span attributes (GLiNER2.5)\n\nAttach labels such as **sentiment** to extracted entity spans. Attributes are scored at decoded spans, not as document-level classification.\n\n```python\nfrom gliner2 import AutoExtractor, AttributeGroup\n\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\n\nschema = (\n    model.create_schema()\n    .entities([\"person\"])\n    .entity_attributes({\n        \"sentiment\": AttributeGroup(\n            [\"positive\", \"negative\", \"neutral\"],\n            applies_to=[\"person\"],\n            qualify_labels=True,\n        )\n    })\n)\n\nresult = model.extract(\n    \"Alice was delighted, but Bob sounded frustrated.\",\n    schema,\n    include_spans=True,\n    include_confidence=True,\n)\n# {'entities': {'person': [\n#     {'text': 'Alice', 'sentiment': {'label': 'positive', 'confidence': 0.89}, ...},\n#     {'text': 'Bob', 'sentiment': {'label': 'negative', 'confidence': 0.84}, ...},\n# ]}}\n```\n\nSee [Span Attributes](tutorial\u002F13-span_attributes.md).\n\n### 6. Constrained classification\n\nUse `Classifier` when labels on one task legally constrain another (`classify_text` decodes each task independently).\n\n```python\nfrom gliner2.classification import Classifier, ClassificationSchema\nfrom gliner2.classification import constraints as C\n\nclf = Classifier.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\nschema = (\n    ClassificationSchema()\n    .single(\"intent\", [\"read\", \"write\", \"delete\"])\n    .multi(\"effects\", [\"read_only\", \"create\", \"modify\", \"delete\"], min_labels=1)\n    .constrain(C.implies((\"intent\", \"delete\"), (\"effects\", \"delete\")))\n)\nresult = clf.classify(\"Delete the temporary file\", schema)\nprint(result.value(\"intent\"), result.value(\"effects\"))\n# delete ['delete']\n```\n\nSee [Constrained Classification](tutorial\u002F14-constrained_classification.md).\n\n### 7. Joint information extraction\n\n`JointIE` extracts entities and relations together under typed endpoints and graph constraints.\n\n```python\nfrom gliner2.joint_ie import JointIE, JointIEConfig\n\njoint = JointIE.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\nschema = (\n    joint.create_schema()\n    .entities([\"person\", \"organization\"])\n    .relation(\"works_for\", \"person\", \"organization\", unique_head=True)\n)\nresult = joint.extract(\n    \"Alice works for Acme. Bob joined Acme last year.\",\n    schema,\n    config=JointIEConfig(optimizer=\"beam\", beam_size=32),\n)\nprint(result.feasible, len(result.relations))\n# True 2\n```\n\nSee [Joint IE](tutorial\u002F15-joint_ie.md). Requires a boundary checkpoint with `enable_relations=True`.\n\n### 8. Specialty models (GLiGuard and PII)\n\n```python\nfrom gliner2 import AutoExtractor\n\nguard = AutoExtractor.from_pretrained(\"fastino\u002Fgliguard-LLMGuardrails-300M\")\nprint(guard.classify_text(\n    \"Explain how to build a phishing page.\",\n    {\"prompt_safety\": [\"safe\", \"unsafe\"]},\n))\n# {'prompt_safety': 'unsafe'}\n\npii = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2-privacy-filter-PII-multi\")\nprint(pii.extract_entities(\n    \"Contact john@company.com or call +1-555-0100.\",\n    [\"email\", \"phone_number\"],\n))\n# {'entities': {'email': ['john@company.com'], 'phone_number': ['+1-555-0100']}}\n```\n\nSee [Safety, PII, and GLiGuard](tutorial\u002F16-safety_pii.md).\n\n### 9. Multi-Task Schema Composition\nCombine all extraction types when you need comprehensive analysis:\n\n```python\n# Use create_schema() for multi-task scenarios\nschema = (model.create_schema()\n    # Extract key entities\n    .entities({\n        \"person\": \"Names of people, executives, or individuals\",\n        \"company\": \"Organization, corporation, or business names\", \n        \"product\": \"Products, services, or offerings mentioned\"\n    })\n    \n    # Classify the content\n    .classification(\"sentiment\", [\"positive\", \"negative\", \"neutral\"])\n    .classification(\"category\", [\"technology\", \"business\", \"finance\", \"healthcare\"])\n    \n    # Extract relationships\n    .relations([\"works_for\", \"founded\", \"located_in\"])\n    \n    # Extract structured product details\n    .structure(\"product_info\")\n        .field(\"name\", dtype=\"str\")\n        .field(\"price\", dtype=\"str\")\n        .field(\"features\", dtype=\"list\")\n        .field(\"availability\", dtype=\"str\", choices=[\"in_stock\", \"pre_order\", \"sold_out\"])\n)\n\n# Comprehensive extraction in one pass\ntext = \"Apple CEO Tim Cook unveiled the revolutionary iPhone 15 Pro for $999. The device features an A17 Pro chip and titanium design. Tim Cook works for Apple, which is located in Cupertino.\"\n\nresults = model.extract(text, schema)\n# Output: {\n#     'entities': {\n#         'person': ['Tim Cook'], \n#         'company': ['Apple'], \n#         'product': ['iPhone 15 Pro']\n#     },\n#     'sentiment': 'positive',\n#     'category': 'technology',\n#     'relation_extraction': {\n#         'works_for': [('Tim Cook', 'Apple')],\n#         'located_in': [('Apple', 'Cupertino')]\n#     },\n#     'product_info': [{\n#         'name': 'iPhone 15 Pro',\n#         'price': '$999',\n#         'features': ['A17 Pro chip', 'titanium design'],\n#         'availability': 'in_stock'\n#     }]\n# }\n```\n\n## 🏭 Example Usage Scenarios\n\n### Financial Document Processing\n\n```python\nfinancial_text = \"\"\"\nTransaction Report: Goldman Sachs processed a $2.5M equity trade for Tesla Inc. \non March 15, 2024. Commission: $1,250. Status: Completed.\n\"\"\"\n\n# Extract structured financial data\nresult = model.extract_json(\n    financial_text,\n    {\n        \"transaction\": [\n            \"broker::str::Financial institution or brokerage firm\",\n            \"amount::str::Transaction amount with currency\",\n            \"security::str::Stock, bond, or financial instrument\",\n            \"date::str::Transaction date\",\n            \"commission::str::Fees or commission charged\", \n            \"status::str::Transaction status\",\n            \"type::[equity|bond|option|future|forex]::str::Type of financial instrument\"\n        ]\n    }\n)\n# Output: {\n#     'transaction': [{\n#         'broker': 'Goldman Sachs',\n#         'amount': '$2.5M', \n#         'security': 'Tesla Inc.',\n#         'date': 'March 15, 2024',\n#         'commission': '$1,250',\n#         'status': 'Completed',\n#         'type': 'equity'\n#     }]\n# }\n```\n\n### Healthcare Information Extraction\n\n```python\nmedical_record = \"\"\"\nPatient: Sarah Johnson, 34, presented with acute chest pain and shortness of breath.\nPrescribed: Lisinopril 10mg daily, Metoprolol 25mg twice daily.\nFollow-up scheduled for next Tuesday.\n\"\"\"\n\nresult = model.extract_json(\n    medical_record,\n    {\n        \"patient_info\": [\n            \"name::str::Patient full name\",\n            \"age::str::Patient age\",\n            \"symptoms::list::Reported symptoms or complaints\"\n        ],\n        \"prescriptions\": [\n            \"medication::str::Drug or medication name\",\n            \"dosage::str::Dosage amount and frequency\",\n            \"frequency::str::How often to take the medication\"\n        ]\n    }\n)\n# Output: {\n#     'patient_info': [{\n#         'name': 'Sarah Johnson',\n#         'age': '34',\n#         'symptoms': ['acute chest pain', 'shortness of breath']\n#     }],\n#     'prescriptions': [\n#         {'medication': 'Lisinopril', 'dosage': '10mg', 'frequency': 'daily'},\n#         {'medication': 'Metoprolol', 'dosage': '25mg', 'frequency': 'twice daily'}\n#     ]\n# }\n```\n\n### Legal Contract Analysis\n\n```python\ncontract_text = \"\"\"\nService Agreement between TechCorp LLC and DataSystems Inc., effective January 1, 2024.\nMonthly fee: $15,000. Contract term: 24 months with automatic renewal.\nTermination clause: 30-day written notice required.\n\"\"\"\n\n# Multi-task extraction for comprehensive analysis\nschema = (model.create_schema()\n    .entities([\"company\", \"date\", \"duration\", \"fee\"])\n    .classification(\"contract_type\", [\"service\", \"employment\", \"nda\", \"partnership\"])\n    .relations([\"signed_by\", \"involves\", \"dated\"])\n    .structure(\"contract_terms\")\n        .field(\"parties\", dtype=\"list\")\n        .field(\"effective_date\", dtype=\"str\")\n        .field(\"monthly_fee\", dtype=\"str\")\n        .field(\"term_length\", dtype=\"str\")\n        .field(\"renewal\", dtype=\"str\", choices=[\"automatic\", \"manual\", \"none\"])\n        .field(\"termination_notice\", dtype=\"str\")\n)\n\nresults = model.extract(contract_text, schema)\n# Output: {\n#     'entities': {\n#         'company': ['TechCorp LLC', 'DataSystems Inc.'],\n#         'date': ['January 1, 2024'],\n#         'duration': ['24 months'],\n#         'fee': ['$15,000']\n#     },\n#     'contract_type': 'service',\n#     'relation_extraction': {\n#         'involves': [('TechCorp LLC', 'DataSystems Inc.')],\n#         'dated': [('Service Agreement', 'January 1, 2024')]\n#     },\n#     'contract_terms': [{\n#         'parties': ['TechCorp LLC', 'DataSystems Inc.'],\n#         'effective_date': 'January 1, 2024',\n#         'monthly_fee': '$15,000',\n#         'term_length': '24 months', \n#         'renewal': 'automatic',\n#         'termination_notice': '30-day written notice'\n#     }]\n# }\n```\n\n### Knowledge Graph Construction\n\n```python\n# Extract entities and relations for knowledge graph building\ntext = \"\"\"\nElon Musk founded SpaceX in 2002. SpaceX is located in Hawthorne, California.\nSpaceX acquired Swarm Technologies in 2021. Many engineers work for SpaceX.\n\"\"\"\n\nschema = (model.create_schema()\n    .entities([\"person\", \"organization\", \"location\", \"date\"])\n    .relations({\n        \"founded\": \"Founding relationship where person created organization\",\n        \"acquired\": \"Acquisition relationship where company bought another company\",\n        \"located_in\": \"Geographic relationship where entity is in a location\",\n        \"works_for\": \"Employment relationship where person works at organization\"\n    })\n)\n\nresults = model.extract(text, schema)\n# Output: {\n#     'entities': {\n#         'person': ['Elon Musk', 'engineers'],\n#         'organization': ['SpaceX', 'Swarm Technologies'],\n#         'location': ['Hawthorne, California'],\n#         'date': ['2002', '2021']\n#     },\n#     'relation_extraction': {\n#         'founded': [('Elon Musk', 'SpaceX')],\n#         'acquired': [('SpaceX', 'Swarm Technologies')],\n#         'located_in': [('SpaceX', 'Hawthorne, California')],\n#         'works_for': [('engineers', 'SpaceX')]\n#     }\n# }\n```\n\n## ⚙️ Advanced Configuration\n\n### Custom Confidence Thresholds\n\n```python\n# High-precision extraction for critical fields\nresult = model.extract_json(\n    text,\n    {\n        \"financial_data\": [\n            \"account_number::str::Bank account number\",  # default threshold\n            \"amount::str::Transaction amount\",           # default threshold  \n            \"routing_number::str::Bank routing number\"   # default threshold\n        ]\n    },\n    threshold=0.9  # High confidence for all fields\n)\n\n# Per-field thresholds using schema builder (for multi-task scenarios)\nschema = (model.create_schema()\n    .structure(\"sensitive_data\")\n        .field(\"ssn\", dtype=\"str\", threshold=0.95)         # Highest precision\n        .field(\"email\", dtype=\"str\", threshold=0.8)        # Medium precision  \n        .field(\"phone\", dtype=\"str\", threshold=0.7)        # Lower precision\n)\n```\n\n### Field Types and Constraints\n\n```python\n# Structured extraction with choices and types\nresult = model.extract_json(\n    \"Premium subscription at $99\u002Fmonth with mobile and web access.\",\n    {\n        \"subscription\": [\n            \"tier::[basic|premium|enterprise]::str::Subscription level\",\n            \"price::str::Monthly or annual cost\",\n            \"billing::[monthly|annual]::str::Billing frequency\", \n            \"features::[mobile|web|api|analytics]::list::Included features\"\n        ]\n    }\n)\n# Output: {\n#     'subscription': [{\n#         'tier': 'premium',\n#         'price': '$99\u002Fmonth', \n#         'billing': 'monthly',\n#         'features': ['mobile', 'web']\n#     }]\n# }\n```\n\n## 🔍 Regex Validators\n\nFilter extracted spans to ensure they match expected patterns, improving extraction quality and reducing false positives.\n\n```python\nfrom gliner2 import AutoExtractor, RegexValidator\n\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\n\n# Email validation\nemail_validator = RegexValidator(r\"^[\\w\\.-]+@[\\w\\.-]+\\.\\w+$\")\nschema = (model.create_schema()\n    .structure(\"contact\")\n        .field(\"email\", dtype=\"str\", validators=[email_validator])\n)\n\ntext = \"Contact: john@company.com, not-an-email, jane@domain.org\"\nresults = model.extract(text, schema)\n# Output: {'contact': [{'email': 'john@company.com'}]}  # Only valid emails\n\n# Phone number validation (US format)\nphone_validator = RegexValidator(r\"\\(\\d{3}\\)\\s\\d{3}-\\d{4}\", mode=\"partial\")\nschema = (model.create_schema()\n    .structure(\"contact\")\n        .field(\"phone\", dtype=\"str\", validators=[phone_validator])\n)\n\ntext = \"Call (555) 123-4567 or 5551234567\"\nresults = model.extract(text, schema)\n# Output: {'contact': [{'phone': '(555) 123-4567'}]}  # Second number filtered out\n\n# URL validation\nurl_validator = RegexValidator(r\"^https?:\u002F\u002F\", mode=\"partial\")\nschema = (model.create_schema()\n    .structure(\"links\")\n        .field(\"url\", dtype=\"list\", validators=[url_validator])\n)\n\ntext = \"Visit https:\u002F\u002Fexample.com or www.site.com\"\nresults = model.extract(text, schema)\n# Output: {'links': [{'url': ['https:\u002F\u002Fexample.com']}]}  # www.site.com filtered out\n\n# Exclude test data\nimport re\nno_test_validator = RegexValidator(r\"^(test|demo|sample)\", exclude=True, flags=re.IGNORECASE)\nschema = (model.create_schema()\n    .structure(\"products\")\n        .field(\"name\", dtype=\"list\", validators=[no_test_validator])\n)\n\ntext = \"Products: iPhone, Test Phone, Samsung Galaxy\"\nresults = model.extract(text, schema)\n# Output: {'products': [{'name': ['iPhone', 'Samsung Galaxy']}]}  # Test Phone excluded\n\n# Multiple validators (all must pass)\nusername_validators = [\n    RegexValidator(r\"^[a-zA-Z0-9_]+$\"),  # Alphanumeric + underscore\n    RegexValidator(r\"^.{3,20}$\"),        # 3-20 characters\n    RegexValidator(r\"^(?!admin)\", exclude=True, flags=re.IGNORECASE)  # No \"admin\"\n]\n\nschema = (model.create_schema()\n    .structure(\"user\")\n        .field(\"username\", dtype=\"str\", validators=username_validators)\n)\n\ntext = \"Users: ab, john_doe, user@domain, admin, valid_user123\"\nresults = model.extract(text, schema)\n# Output: {'user': [{'username': 'john_doe'}]}  # Only valid usernames\n```\n\n## FlashDeBERTa (Optional GPU Acceleration)\n\nFor DeBERTaV2-based models, you can use [FlashDeBERTa](https:\u002F\u002Fgithub.com\u002Ffastino-ai\u002Fflashdeberta) to accelerate inference on NVIDIA GPUs via flash attention kernels.\n\n**Install:**\n\n```bash\npip install flashdeberta\n```\n\n**Use:**\n\n```python\nfrom gliner2 import AutoExtractor\n\nmodel = AutoExtractor.from_pretrained(\n    \"fastino\u002Fgliner2-base-v1\",\n    use_flashdeberta=True,\n    map_location=\"cuda\",\n)\nmodel.half().eval()\n\nresult = model.extract_entities(\n    \"Apple CEO Tim Cook announced iPhone 15 in Cupertino.\",\n    [\"company\", \"person\", \"product\", \"location\"]\n)\n```\n\nThe option works for both span and boundary checkpoints. It is only effective when the model uses a DeBERTaV2 encoder and the `flashdeberta` package is installed; otherwise the standard Hugging Face encoder is used. For backward compatibility, setting `USE_FLASHDEBERTA=1` still enables it when `use_flashdeberta` is omitted. Passing `use_flashdeberta=False` explicitly overrides the environment variable.\n\nUse FP16 or BF16 on CUDA to realize the flash-kernel speedup. The benchmark compares both backends in separate processes, verifies that FlashDeBERTa actually activated, and reports latency, statistical significance, and peak memory:\n\n```bash\n# End-to-end extraction (FP16 is the CUDA default)\npython benchmarks\u002Fbenchmark_flashdeberta.py --dtype fp16 --architecture auto\n\n# Encoder-only comparison, excluding preprocessing and decoding\npython benchmarks\u002Fbenchmark_flashdeberta.py --dtype fp16 --encoder-only\n\n# Boundary checkpoint (the model config must declare boundary architecture)\npython benchmarks\u002Fbenchmark_flashdeberta.py \\\n  --model \u002Fpath\u002Fto\u002Fboundary-checkpoint \\\n  --architecture boundary \\\n  --dtype bf16\n```\n\n## 📦 Batch Processing\n\nProcess multiple texts efficiently in a single call:\n\n```python\n# Batch entity extraction\ntexts = [\n    \"Google's Sundar Pichai unveiled Gemini AI in Mountain View.\",\n    \"Microsoft CEO Satya Nadella announced Copilot at Build 2023.\",\n    \"Amazon's Andy Jassy revealed new AWS services in Seattle.\"\n]\n\nresults = model.batch_extract_entities(\n    texts,\n    [\"company\", \"person\", \"product\", \"location\"],\n    batch_size=8\n)\n# Returns list of results, one per input text\n\n# Batch relation extraction\ntexts = [\n    \"John works for Microsoft and lives in Seattle.\",\n    \"Sarah founded TechStartup in 2020.\",\n    \"Bob reports to Alice at Google.\"\n]\n\nresults = model.batch_extract_relations(\n    texts,\n    [\"works_for\", \"founded\", \"reports_to\", \"lives_in\"],\n    batch_size=8\n)\n# Returns list of relation extraction results for each text\n# All requested relation types appear in each result, even if empty\n\n# Batch with confidence and spans\nresults = model.batch_extract_entities(\n    texts,\n    [\"company\", \"person\"],\n    include_confidence=True,\n    include_spans=True,\n    batch_size=8\n)\n```\n\n## 🎓 Training Custom Models\n\nTrain GLiNER2 on your own data to specialize for your domain or use case.\n\n### Quick Start Training\n\n```python\nfrom gliner2 import AutoExtractor\nfrom gliner2.training.data import InputExample\nfrom gliner2.training.trainer import ExtractorTrainer, TrainingConfig\n\n# GLiNER2Trainer is a backward-compatible alias for ExtractorTrainer\n\n# 1. Prepare training data\nexamples = [\n    InputExample(\n        text=\"John works at Google in California.\",\n        entities={\"person\": [\"John\"], \"company\": [\"Google\"], \"location\": [\"California\"]}\n    ),\n    InputExample(\n        text=\"Apple released iPhone 15.\",\n        entities={\"company\": [\"Apple\"], \"product\": [\"iPhone 15\"]}\n    ),\n    # Add more examples...\n]\n\n# 2. Configure training (span or boundary base checkpoint)\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2.5-base-v1\")\nconfig = TrainingConfig(\n    output_dir=\".\u002Foutput\",\n    num_epochs=10,\n    batch_size=8,\n    encoder_lr=1e-5,\n    task_lr=5e-4\n)\n\n# 3. Train\ntrainer = ExtractorTrainer(model, config)\ntrainer.train(train_data=examples)\n```\n\n### Training Data Format (JSONL)\n\nGLiNER2 uses JSONL format where each line contains an `input` and `output` field:\n\n```jsonl\n{\"input\": \"Tim Cook is the CEO of Apple Inc., based in Cupertino, California.\", \"output\": {\"entities\": {\"person\": [\"Tim Cook\"], \"company\": [\"Apple Inc.\"], \"location\": [\"Cupertino\", \"California\"]}, \"entity_descriptions\": {\"person\": \"Full name of a person\", \"company\": \"Business organization name\", \"location\": \"Geographic location or place\"}}}\n{\"input\": \"OpenAI released GPT-4 in March 2023.\", \"output\": {\"entities\": {\"company\": [\"OpenAI\"], \"model\": [\"GPT-4\"], \"date\": [\"March 2023\"]}}}\n```\n\n**Classification Example:**\n```jsonl\n{\"input\": \"This movie is absolutely fantastic! I loved every minute of it.\", \"output\": {\"classifications\": [{\"task\": \"sentiment\", \"labels\": [\"positive\", \"negative\", \"neutral\"], \"true_label\": [\"positive\"]}]}}\n{\"input\": \"The service was terrible and the food was cold.\", \"output\": {\"classifications\": [{\"task\": \"sentiment\", \"labels\": [\"positive\", \"negative\", \"neutral\"], \"true_label\": [\"negative\"]}]}}\n```\n\n**Structured Extraction Example:**\n```jsonl\n{\"input\": \"iPhone 15 Pro Max with 256GB storage, priced at $1199.\", \"output\": {\"json_structures\": [{\"product\": {\"name\": \"iPhone 15 Pro Max\", \"storage\": \"256GB\", \"price\": \"$1199\"}}]}}\n```\n\n**Relation Extraction Example:**\n```jsonl\n{\"input\": \"John works for Apple Inc. and lives in San Francisco.\", \"output\": {\"relations\": [{\"works_for\": {\"head\": \"John\", \"tail\": \"Apple Inc.\"}}, {\"lives_in\": {\"head\": \"John\", \"tail\": \"San Francisco\"}}]}}\n```\n\n### Training from JSONL File\n\n```python\nfrom gliner2 import AutoExtractor\nfrom gliner2.training.trainer import ExtractorTrainer, TrainingConfig\n\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2-base-v1\")\nconfig = TrainingConfig(output_dir=\".\u002Foutput\", num_epochs=10)\n\ntrainer = ExtractorTrainer(model, config)\ntrainer.train(train_data=\"train.jsonl\")\n```\n\n### LoRA Training (Parameter-Efficient Fine-Tuning)\n\nTrain lightweight adapters for domain-specific tasks:\n\n```python\nfrom gliner2 import AutoExtractor\nfrom gliner2.training.data import InputExample\nfrom gliner2.training.trainer import ExtractorTrainer, TrainingConfig\n\nlegal_examples = [\n    InputExample(\n        text=\"Apple Inc. filed a lawsuit against Samsung Electronics.\",\n        entities={\"company\": [\"Apple Inc.\", \"Samsung Electronics\"]}\n    ),\n]\n\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2-base-v1\")\nconfig = TrainingConfig(\n    output_dir=\".\u002Flegal_adapter\",\n    num_epochs=10,\n    batch_size=8,\n    encoder_lr=1e-5,\n    task_lr=5e-4,\n    use_lora=True,\n    lora_r=8,\n    lora_alpha=16.0,\n    lora_dropout=0.0,\n    save_adapter_only=True,\n    lora_targets=[\"encoder\", \"all_task_heads\"],\n)\n\ntrainer = ExtractorTrainer(model, config)\ntrainer.train(train_data=legal_examples)\n\nmodel.load_adapter(\".\u002Flegal_adapter\u002Ffinal\")\nresults = model.extract_entities(legal_text, [\"company\", \"law\"])\n```\n\n**Benefits of LoRA:**\n- **Smaller size**: Adapters are ~2-10 MB vs ~450 MB for full models\n- **Faster training**: 2-3x faster than full fine-tuning\n- **Easy switching**: Swap adapters in milliseconds for different domains\n\n### Complete Training Example\n\n```python\nfrom gliner2 import AutoExtractor\nfrom gliner2.training.data import InputExample, TrainingDataset\nfrom gliner2.training.trainer import ExtractorTrainer, TrainingConfig\n\n# Prepare training data\ntrain_examples = [\n    InputExample(\n        text=\"Tim Cook is the CEO of Apple Inc., based in Cupertino, California.\",\n        entities={\n            \"person\": [\"Tim Cook\"],\n            \"company\": [\"Apple Inc.\"],\n            \"location\": [\"Cupertino\", \"California\"]\n        },\n        entity_descriptions={\n            \"person\": \"Full name of a person\",\n            \"company\": \"Business organization name\",\n            \"location\": \"Geographic location or place\"\n        }\n    ),\n    # Add more examples...\n]\n\n# Create and validate dataset\ntrain_dataset = TrainingDataset(train_examples)\ntrain_dataset.validate(strict=True, raise_on_error=True)\ntrain_dataset.print_stats()\n\n# Split into train\u002Fvalidation\ntrain_data, val_data, _ = train_dataset.split(\n    train_ratio=0.8,\n    val_ratio=0.2,\n    test_ratio=0.0,\n    shuffle=True,\n    seed=42\n)\n\n# Configure training\nmodel = AutoExtractor.from_pretrained(\"fastino\u002Fgliner2-base-v1\")\nconfig = TrainingConfig(\n    output_dir=\".\u002Fner_model\",\n    experiment_name=\"ner_training\",\n    num_epochs=15,\n    batch_size=16,\n    encoder_lr=1e-5,\n    task_lr=5e-4,\n    warmup_ratio=0.1,\n    scheduler_type=\"cosine\",\n    fp16=True,\n    eval_strategy=\"epoch\",\n    save_best=True,\n    early_stopping=True,\n    early_stopping_patience=3\n)\n\ntrainer = ExtractorTrainer(model, config)\ntrainer.train(train_data=train_data, val_data=val_data)\n\nmodel = AutoExtractor.from_pretrained(\".\u002Fner_model\u002Fbest\")\n```\n\nFor more details, see the [Training Tutorial](tutorial\u002F9-training.md) and [Data Format Guide](tutorial\u002F8-train_data.md).\n\n## 🚢 Release process\n\nEvery release must pass Python 3.10–3.12 CI, offline and checkpoint quality\ngates, CUDA hardware checks, and fresh wheel\u002Fsdist installation smoke tests.\nVersion tags build artifacts automatically, but PyPI publishing stays disabled\nuntil the protected trusted-publishing environment and repository opt-in\nvariable are configured. Maintainers should follow the complete\n[release checklist](RELEASE.md); local token uploads are not supported.\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n\n## 📚 Citation\n\nIf you use GLiNER2 in your research, please cite:\n\n```bibtex\n@inproceedings{zaratiana-etal-2025-gliner2,\n    title = \"{GL}i{NER}2: Schema-Driven Multi-Task Learning for Structured Information Extraction\",\n    author = \"Zaratiana, Urchade  and\n      Pasternak, Gil  and\n      Boyd, Oliver  and\n      Hurn-Maloney, George  and\n      Lewis, Ash\",\n    editor = {Habernal, Ivan  and\n      Schulam, Peter  and\n      Tiedemann, J{\\\"o}rg},\n    booktitle = \"Proceedings of the 2025 Conference on Empirical Methods in Natural Language Processing: System Demonstrations\",\n    month = nov,\n    year = \"2025\",\n    address = \"Suzhou, China\",\n    publisher = \"Association for Computational Linguistics\",\n    url = \"https:\u002F\u002Faclanthology.org\u002F2025.emnlp-demos.10\u002F\",\n    pages = \"130--140\",\n    ISBN = \"979-8-89176-334-0\",\n    abstract = \"Information extraction (IE) is fundamental to numerous NLP applications, yet existing solutions often require specialized models for different tasks or rely on computationally expensive large language models. We present GLiNER2, a unified framework that enhances the original GLiNER architecture to support named entity recognition, text classification, and hierarchical structured data extraction within a single efficient model. Built on a fine-tuned encoder architecture, GLiNER2 maintains CPU efficiency and compact size while introducing multi-task composition through an intuitive schema-based interface. Our experiments demonstrate competitive performance across diverse IE tasks with substantial improvements in deployment accessibility compared to LLM-based alternatives. We release GLiNER2 as an open-source library available through pip, complete with pre-trained models and comprehensive documentation.\"\n}\n```\n\n## 🙏 Acknowledgments\n\nBuilt upon the original [GLiNER](https:\u002F\u002Fgithub.com\u002Furchade\u002FGLiNER) architecture by the team at [Fastino AI](https:\u002F\u002Ffastino.ai).\n\n---\n\n\u003Cdiv align=\"center\">\n    \u003Cstrong>Ready to extract insights from your data?\u003C\u002Fstrong>\u003Cbr>\n    \u003Ccode>pip install \"gliner2[local]\"\u003C\u002Fcode>\n\u003C\u002Fdiv>\n","GLiNER2 是一个基于统一模式（schema）的轻量级信息抽取与文本分类框架，支持命名实体识别、关系抽取、结构化记录提取、跨度属性标注等多任务联合推理。其核心采用 schema-conditioned 编码器设计，提供 span 和 boundary 两种抽取架构，通过统一 API（AutoExtractor）自动适配；支持本地 CPU 推理、零外部依赖、隐私敏感场景部署，并内置模式验证、规则约束解码与 LoRA 微调能力。适用于金融、医疗、法律等需定制化抽取规则、强调数据本地化与低资源部署的行业文档解析与知识结构化任务。",2,"2026-09-19 02:30:05","trending"]