spaCy¶
The tokenizer and the sentence starts of anySeg in a spaCy pipeline, and the conversion between a spaCy Doc and a document.
pip install "anyseg[spacy]"
The tokenizer and the component register with spaCy when the package is installed and are used by name, without importing anyseg. spaCy has no prebuilt wheels for the free-threaded Python 3.14t and 3.15t.
import spacy
tokenizer = {"@tokenizers": "anyseg.Tokenizer.v1"}
nlp = spacy.blank("ru", config={"nlp": {"tokenizer": tokenizer}})
nlp.add_pipe("anyseg_sentencizer")
doc = nlp("В 1914 г. цена была 3 000 руб. Затем выросла")
[token.text for token in doc]
[sentence.text for sentence in doc.sents]
Sentencizer('ru')
['В', '1914', 'г.', 'цена', 'была', '3 000', 'руб', '.', 'Затем', 'выросла']
['В 1914 г. цена была 3 000 руб.', 'Затем выросла']
Tokenizer¶
anyseg.Tokenizer.v1 is the tokenizer of the section [nlp.tokenizer] of a configuration. The text of a Doc is the text given, and the whitespace is kept as spaCy keeps it: one space after a token is its whitespace_, and the rest of the text between tokens - line breaks, more spaces, invisible separators - is a token of its own. nlp.tokenizer.pipe(texts, batch_size=1000) gives the documents of many texts, segmented in batches without the GIL as Segmenter.pipe does.
| Parameter | Type | Default | Description |
|---|---|---|---|
lang |
str |
None |
ISO 639-1 code of the language; by default the language of the pipeline |
abbreviations |
list[str] |
None |
More abbreviations |
tokens |
list[str] |
None |
Strings that are one token each |
custom = {"@tokenizers": "anyseg.Tokenizer.v1", "tokens": ["C++"]}
nlp = spacy.blank("ru", config={"nlp": {"tokenizer": custom}})
[(token.text, token.whitespace_) for token in nlp("Язык C++\n\nКот спит")]
[('Язык', ' '), ('C++', ''), ('\n\n', ''), ('Кот', ' '), (' ', ''), ('спит', '')]
The settings are in the configuration, so a saved pipeline loads with the tokenizer. A trained pipeline takes it when it is loaded:
nlp = spacy.load("ru_core_news_sm", config={"nlp": {"tokenizer": tokenizer}})
Sentences¶
The component anyseg_sentencizer sets the sentence starts (is_sent_start) of a document as anySeg splits its text; before the parser it fixes the sentences, and the parser keeps them. It works with any tokenizer: a sentence starts at the token where its first character is, and the whitespace after a sentence stays in it.
nlp = spacy.load("ru_core_news_sm", config={"nlp": {"tokenizer": tokenizer}})
nlp.add_pipe("anyseg_sentencizer", before="parser")
| Parameter | Type | Default | Description |
|---|---|---|---|
lang |
str |
None |
ISO 639-1 code of the language; by default the language of the pipeline |
abbreviations |
list[str] |
None |
More abbreviations |
tokens |
list[str] |
None |
Strings that are one token each |
overwrite |
bool |
False |
Replace the sentence starts set before; False - set only the tokens whose start is unknown, as the sentencizer of spaCy does |
scorer |
Callable |
spacy.senter_scorer.v1 |
Scores of the sentences in an evaluation: sents_p, sents_r and sents_f, as for the sentencizer of spaCy |
nlp = spacy.blank("ru")
nlp.add_pipe("anyseg_sentencizer")
[sentence.text for sentence in nlp("Кот спит в 1914 г. Затем\n\nУтро").sents]
Sentencizer('ru')
['Кот спит в 1914 г.', 'Затем\n\n', 'Утро']
With the tokenizer and the component, ru_core_news_sm 3.8.0 finds sentences and parses better. F1 of sentences and LAS on the test parts of the Russian treebanks of UD 2.18, from their raw text, every paragraph a document, scored with the evaluation script of CoNLL 2018. Comparison segments every test file as one text, so its F1 of sentences of the same pipeline is lower on Taiga, whose paragraphs often end without a final mark:
| Test set | Sentences, spaCy | Sentences, anySeg | LAS, spaCy | LAS, anySeg |
|---|---|---|---|---|
| SynTagRus | 95.39 | 98.53 | 81.83 | 82.96 |
| Taiga | 80.42 | 89.92 | 71.55 | 73.39 |
| GSD | 85.85 | 96.32 | 75.80 | 79.34 |
| PUD | 96.45 | 99.25 | 86.14 | 87.26 |
The tokenizer gives 2.7 M tokens per second, nearly ten times as many as the tokenizer of spaCy; with the component, 1.5 M against 0.26 M with the sentencizer of spaCy (SynTagRus test, one thread, Apple M3 Pro).
Documents¶
spaCy document of a document¶
to_doc(document, vocab)
The Doc of a document: its text, its tokens with the whitespace between them as the tokenizer makes it, and its sentences. The columns lemma, upos, xpos and feats become lemma_, pos_, tag_ and morph where set. Heads and relations are set when every word has a head, and the heads of every sentence must form a tree with one root: the relation root becomes ROOT, a word without a relation gets dep (a root - ROOT), and a whitespace token depends on the token before it with dep. A whitespace token has its text for a lemma and SPACE for a part of speech.
| Parameter | Type | Default | Description |
|---|---|---|---|
document |
Document |
- | Document |
vocab |
Vocab |
- | Vocabulary of the pipeline |
Exceptions:
ValueError- the document has a multiword token or a part of speech that spaCy does not know, or the heads of a sentence do not form a tree with one root.
from anyseg import Segmenter
from anyseg.spacy import from_doc, to_doc
document = Segmenter("ru").segment("Ёж идёт. Кот спит")
document.set_columns(upos=["NOUN", "VERB", "PUNCT", "NOUN", "VERB"])
doc = to_doc(document, nlp.vocab)
[(token.text, token.pos_) for token in doc]
[('Ёж', 'NOUN'), ('идёт', 'VERB'), ('.', 'PUNCT'), (' ', 'SPACE'), ('Кот', 'NOUN'), ('спит', 'VERB')]
Document of a spaCy document¶
from_doc(doc)
The document of a Doc, one word per token. Tokens lose the whitespace and the invisible separators at their edges, and tokens of nothing else are dropped. A sentence of the Doc starts at its first token left, a Doc without sentences is a sentence per paragraph, and every paragraph starts a sentence. lemma_, pos_, tag_, morph, the heads and dep_ become the columns lemma, upos, xpos, feats, head and deprel, empty values None, the features in the order of UD; a token without a head has neither. The relation ROOT becomes root, and a word whose head is a dropped token depends on the head of that token. A sentence has one root: the root of the parse or, if the sentence lacks it, the first word whose head is in another sentence; the other such words depend on the root with the relation dep.
| Parameter | Type | Default | Description |
|---|---|---|---|
doc |
Doc |
- | spaCy document |
Exceptions:
ValueError- a token runs over a blank line, or a value cannot be in its column, as forset_columns.
document = from_doc(doc)
document, document.words[3]
(Document(tokens=5, words=5, sentences=2, paragraphs=1), Word(id=1, form='Кот', upos='NOUN'))