Skip to content

fix(analyzer): keep Stanza multi-word tokens as surface tokens to preserve text and entity offsets - #2253

Open
ManoharPaturi wants to merge 1 commit into
data-privacy-stack:mainfrom
ManoharPaturi:fix/stanza-mwt-offsets
Open

fix(analyzer): keep Stanza multi-word tokens as surface tokens to preserve text and entity offsets#2253
ManoharPaturi wants to merge 1 commit into
data-privacy-stack:mainfrom
ManoharPaturi:fix/stanza-mwt-offsets

Conversation

@ManoharPaturi

Copy link
Copy Markdown

Fixes #2249.

StanzaTokenizer.__get_tokens_with_heads flattened stanza multi-word-token expansions (im -> in + dem), so token texts no longer matched the source text. _convert_doc then rebuilt the doc text from those tokens, which corrupted the document text (see the issue repro), made Stanza NER spans miss every token boundary so entities were silently dropped, and could raise ValueError from the lemma enhancer on indented text.

Multi-word tokens now stay a single surface token (a small wrapper carrying surface text/lemma plus the first expanded word's annotations), with a word-index to token-index map that remaps dependency heads across the collapsed token. Single-word tokens keep the previous code path byte-for-byte.

Verified with the real German model: doc.text is preserved, PER and IP_ADDRESS entities are detected where pristine drops them. 11 new tests (pure-unit head remap + German model tests over all 8 contractions) fail on main and pass here; existing stanza suites pass unchanged (12 + 13 + 16), ruff clean vs main baseline.

…serve text and entity offsets

Stanza's mwt processor expands German contractions (im/am/zum/zur/beim/
vom/ins/ans) into multiple words. StanzaTokenizer.__get_tokens_with_heads
flattened the expanded words, which broke alignment with the original
text: _convert_doc then replaced the doc text with space-separated
expanded tokens, silently dropped every NER entity (offsets no longer
mapped to tokens), and, on indented text, let tokens_indices end before
pattern matches near the end of the text, raising 'Did not find word ...'
in LemmaContextAwareEnhancer (HTTP 500).

Keep a multi-word token as a single surface token (MultiWordTokenSurface:
text/lemma are the surface form, other annotations come from the first
expanded word) and remap 1-based word heads to the collapsed token list
so dependency heads around the collapsed token stay correct.

Fixes data-privacy-stack#2249
Copilot AI lite review requested due to automatic review settings September 13, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

StanzaNlpEngine: German multi-word tokens (im/am/zum) replace the doc text and drop every NER entity; indented text ends in 500 "Did not find word"

2 participants