Skip to content

Fix NameError in extract_entities_long; collapse duplicate surfaces when spans are stripped - #137

Open
blockems wants to merge 2 commits into
fastino-ai:mainfrom
blockems:fix/extract-entities-long-overlap-policy
Open

Fix NameError in extract_entities_long; collapse duplicate surfaces when spans are stripped#137
blockems wants to merge 2 commits into
fastino-ai:mainfrom
blockems:fix/extract-entities-long-overlap-policy

Conversation

@blockems

@blockems blockems commented Aug 9, 2026

Copy link
Copy Markdown

Two independent fixes to the long-document path, found while serving GLiNER2 behind an HTTP API. Happy to split into separate PRs if you prefer.

1. extract_entities_long raises NameError on every call

extract_entities_long forwards overlap_policy=overlap_policy to extract_long, but its own signature never declares the parameter:

model = GLiNER2.from_pretrained("fastino/gliner2-base-v1")
model.extract_entities_long("some long document ...", ["person"])
# NameError: name 'overlap_policy' is not defined

extract_long and batch_extract_long both declare overlap_policy: Optional[str] = None, so this looks like one wrapper missed when the parameter was threaded through. batch_extract_entities_long is unaffected because it does not forward the name — which is why the batch path works and the single-text path does not.

Fix adds the missing declaration, matching extract_long's default.

2. Duplicate surfaces once spans are stripped

_dedupe_items deduplicates spans by position, which correctly keeps the same surface text at different offsets. When include_spans and include_confidence are both false, _strip_span_metadata then reduces those spans to bare strings — and the distinct positions become identical strings that no caller can tell apart.

On a long document this is very visible. A report mentioning "PostgreSQL" 300 times returns it 300 times:

{"entities": {"database": ["PostgreSQL", "PostgreSQL", ...x300]}}

At that fidelity the repeats carry no information — no offset to distinguish them, no confidence to rank them — so a caller can only discard them.

The fix collapses them while preserving first-seen document order, scoped to lists that reduce entirely to strings. Anything still carrying confidence, offsets or attribute-group payloads is untouched, so include_spans=True behaviour is unchanged.

Verified against fastino/gliner2-base-v1 on a document repeating one sentence 120 times:

mode before after
formatted strings database: ~200 entries database: 3 unique, location: 1 unique
include_spans=True 49 entries 49 entries, all distinct positions preserved

I read the note in the long-document tutorial about keeping distinct mentions at different document positions — that behaviour is preserved wherever positions are actually visible in the output. If you would rather have this behind an opt-in flag than as a default, say the word and I will rework it.

Testing

tests/inference and tests/processing pass — 71 tests.

extract_entities_long forwards `overlap_policy=overlap_policy` to extract_long
but never declares the parameter, so every call raises

    NameError: name 'overlap_policy' is not defined

The sibling wrappers thread it correctly — extract_long and batch_extract_long
both declare `overlap_policy: Optional[str] = None` — so this looks like one
wrapper missed when the parameter was added. batch_extract_entities_long is
unaffected because it does not forward the name.

Reproduces on any call:

    from gliner2 import GLiNER2
    model = GLiNER2.from_pretrained("fastino/gliner2-base-v1")
    model.extract_entities_long("some long document ...", ["person"])

Fix adds the parameter to the signature, matching extract_long's default.
_dedupe_items deduplicates spans by position, which correctly keeps the same
surface text at different offsets. But when include_spans and include_confidence
are both false, _strip_span_metadata reduces those spans to bare strings — and
distinct positions then become identical strings no caller can tell apart.

On a long document this is very visible. A report mentioning "PostgreSQL" 300
times returns it 300 times:

    {"entities": {"database": ["PostgreSQL", "PostgreSQL", ... x300]}}

The repeats carry no information at that fidelity: there is no offset to
distinguish them and no confidence to rank them, so a caller can only discard
them. Collapse them, preserving first-seen document order.

Scoped to lists that reduce entirely to strings, so anything still carrying
confidence, offsets or attribute-group payloads is untouched. Verified against
fastino/gliner2-base-v1 on a document repeating one sentence 120 times:

    formatted:  database 3 unique, location 1 unique
    include_spans=True: 49 entries, all distinct positions preserved

tests/inference and tests/processing pass (71 tests).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant