Rust + Candle port of GLiNER2 entity and relation extraction (not the original GLiNER).
Run inference — the model downloads automatically on first use (no manual
hf download needed):
cargo run --release -- \
--model-id fastino/gliner2.5-small-v1 \
--text "Apple was founded by Steve Jobs in Cupertino." \
--entities "person,organization,location"
--model-id fetches config.json, tokenizer.json,
encoder_config/config.json, and model.safetensors into a model-specific
directory (./models/gliner2.5-small-v1/) and reuses the verified cache on
later runs. Alternatively point --model-dir at a directory with those four
files (it takes precedence and never downloads).
Requests are entity-only, relation-only, or combined (relations need a
boundary checkpoint such as fastino/gliner2.5-small-v1; span checkpoints
like fastino/gliner2-large-v1 fail clearly).
# Entity-only
gliner2-candle --model-id fastino/gliner2.5-small-v1 \
--text "Apple was founded by Steve Jobs in Cupertino." \
--entities "person,organization,location"
# Relation-only (directed head -> tail)
gliner2-candle --model-id fastino/gliner2.5-small-v1 \
--text "Steve Jobs founded Apple." --relations "founder"
# Combined entities + relations
gliner2-candle --model-id fastino/gliner2.5-small-v1 \
--text "Steve Jobs founded Apple in Cupertino." \
--entities "person,organization,location" --relations "founder"
# Machine-readable JSON (stable field names/ordering, agents can diff output)
gliner2-candle --model-id fastino/gliner2.5-small-v1 --json \
--text "Steve Jobs founded Apple." --entities "person,organization"
# Agent verification case file (per-case pass/fail, nonzero exit on failure)
gliner2-candle --model-id fastino/gliner2.5-small-v1 --cases cases/cli-cases.json
Flags:
--model-dirLocal model directory (config.json,model.safetensors,tokenizer.json,encoder_config/config.json). Takes precedence over--model-id; never triggers a download.--model-idHuggingFace model ID to download/reuse (defaultfastino/gliner2-large-v1).--revisionHub revision (commit sha, tag, or branch) for--model-id. Defaults to the pinned revisions documented inDEVELOP.md(fastino/gliner2.5-small-v1→7132dc4561c3…,fastino/gliner2-large-v1→5312584a6fd5…).--models-rootWhere model cache directories live (default./models); each model ID maps to<models-root>/<repo-name>/.--textInput text.--entitiesComma-separated entity types.--relationsComma-separated relation types.--thresholdScore threshold in[0.0, 1.0](default0.5).--casesVersioned JSON case file (see below).--jsonMachine-readable JSON on stdout (one-off results or case report).--list-weights [N]Lists weight keys with dtype and shape (debug).--devicecpu(default) orcuda:N.
Readable output prints the detected architecture and active tasks, then every
entity (type, confidence, exact text, half-open byte offsets) and every
relation (type, confidence, directed head/tail text and offsets), or an
explicit "No … found above threshold" line. All offsets are half-open UTF-8
byte offsets into --text.
--cases FILE runs each case sequentially through the same production
inference path as one-off runs and reports per-case PASS/FAIL with the exact
mismatches; the exit status is nonzero if any case fails. The format is
versioned JSON ("version": 1) — see cases/cli-cases.json for a committed
example covering positive, negative, and near-threshold (ambiguous) cases:
{
"version": 1,
"model_id": "fastino/gliner2.5-small-v1",
"cases": [
{
"name": "readme-entities",
"text": "Apple was founded by Steve Jobs in Cupertino.",
"entities": ["person", "organization", "location"],
"threshold": 0.5,
"expect_entities": [
{"type": "person", "text": "Steve Jobs", "byte_start": 21, "byte_end": 31,
"confidence": {"min": 0.9, "max": 1.0}}
]
}
]
}Each case names its entity/relation types and (optionally) its own threshold;
expectations give the label/type, exact surface, and exact byte offsets.
Optional confidence: {min, max} bounds catch large numerical drift without
bitwise equality. Matching is strict set equality — a missing extraction, an
unexpected extra extraction, or a confidence outside its bounds fails the
case.
- This project targets the
fastino/gliner2-*model family (fastino/gliner2.5-*boundary checkpoints extract entities and relations;fastino/gliner2-*span checkpoints are entity-only). - CPU performance improves significantly with
--release. - GPU/accelerated backends are supported by Candle, but not configured here by default.
src/model.rsArchitecture dispatch (Model::{Span,Boundary}), load, predictsrc/boundary*.rsBoundary architecture (preprocess, encode, pool, decode, relations)src/processor.rsSpan-path tokenization and input buildingsrc/span_rep.rsSpan representation (span path)src/count_lstm.rsCount-aware structure embedding (span path)src/inference.rsSpan-path post-processing and span extractionsrc/hub.rs--model-iddownload & cache contractsrc/cases.rsCase-file schema, validation, matchingsrc/main.rsCLI
MIT