Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
SlovNet is a Python library for deep-learning based NLP modeling for Russian language. Library is integrated with other Natasha projects: Nerus — large automatically annotated corpus, Razdel — sentence segmenter, tokenizer and Navec — compact Russian embeddings. Slovnet provides high quality practical models for Russian NER, morphology and syntax, see evaluation section for more:
Model | Size | Description |
---|---|---|
slovnet_ner_news_v1.tar | 2MB | Russian NER, standart PER, LOC, ORG annotation, trained on news articles. |
slovnet_morph_news_v1.tar | 2MB | Russian morphology tagger optimized for news articles. |
slovnet_syntax_news_v1.tar | 3MB | Russian syntax parser optimized for news articles. |
During inference Slovnet depends only on Numpy. Library supports Python 3.5+, PyPy 3.
$ pip install slovnet
Download model weights and vocabs package, use links from downloads section and Navec download section. Optionally install Ipymarkup to visualize NER markup.
Slovnet annotator map
method has list of items as input and same size iterator over markups as output. Internally items are processed in batches of size batch_size
. Default size is 8, larger batch — more RAM, better CPU utilization. __call__
method just calls map
with a list of 1 item.
>>> from navec import Navec
>>> from slovnet import NER
>>> from ipymarkup import show_span_ascii_markup as show_markup
>>> text = 'Европейский союз добавил в санкционный список девять политических деятелей из самопровозглашенных республик Донбасса — Донецкой народной республики (ДНР) и Луганской народной республики (ЛНР) — в связи с прошедшими там выборами. Об этом говорится в документе, опубликованном в официальном журнале Евросоюза. В новом списке фигурирует Леонид Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там присутствуют Владимир Бидевка и Денис Мирошниченко, председатели законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена Кравченко, председатели ЦИК обеих республик. Выборы прошли в непризнанных республиках Донбасса 11 ноября. На них удержали лидерство действующие руководители и партии — Денис Пушилин и «Донецкая республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР. Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после встречи с украинским лидером Петром Порошенко осудили проведение выборов, заявив, что они нелегитимны и «подрывают территориальную целостность и суверенитет Украины». Позже к осуждению присоединились США с обещаниями новых санкций для России.'
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> ner = NER.load('slovnet_ner_news_v1.tar')
>>> ner.navec(navec)
>>> markup = ner(text)
>>> show_markup(markup.text, markup.spans)
Европейский союз добавил в санкционный список девять политических
LOC─────────────
деятелей из самопровозглашенных республик Донбасса — Донецкой народной
LOC───── LOC──────────────
республики (ДНР) и Луганской народной республики (ЛНР) — в связи с
───────────────── LOC────────────────────────────────
прошедшими там выборами. Об этом говорится в документе, опубликованном
в официальном журнале Евросоюза. В новом списке фигурирует Леонид
LOC────── PER────
Пасечник, который по итогам выборов стал главой ЛНР. Помимо него там
──────── LOC
присутствуют Владимир Бидевка и Денис Мирошниченко, председатели
PER───────────── PER───────────────
законодательных органов ДНР и ЛНР, а также Ольга Позднякова и Елена
LOC LOC PER───────────── PER───
Кравченко, председатели ЦИК обеих республик. Выборы прошли в
───────── ORG
непризнанных республиках Донбасса 11 ноября. На них удержали лидерство
LOC─────
действующие руководители и партии — Денис Пушилин и «Донецкая
PER────────── ORG──────
республика» в ДНР и Леонид Пасечник с движением «Мир Луганщине» в ЛНР.
────────── LOC PER──────────── ORG────────── LOC
Президент Франции Эмманюэль Макрон и канцлер ФРГ Ангела Меркель после
LOC──── PER───────────── LOC PER───────────
встречи с украинским лидером Петром Порошенко осудили проведение
PER─────────────
выборов, заявив, что они нелегитимны и «подрывают территориальную
целостность и суверенитет Украины». Позже к осуждению присоединились
LOC────
США с обещаниями новых санкций для России.
LOC LOC───
Morphology annotator processes tokenized text. To split the input into sentencies and tokens use Razdel.
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Morph
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> morph = Morph.load('slovnet_morph_news_v1.tar', batch_size=4)
>>> morph.navec(navec)
>>> markup = next(morph.map(chunk))
>>> for token in markup.tokens:
>>> print(f'{token.text:>20} {token.tag}')
Европейский ADJ|Case=Nom|Degree=Pos|Gender=Masc|Number=Sing
союз NOUN|Animacy=Inan|Case=Nom|Gender=Masc|Number=Sing
добавил VERB|Aspect=Perf|Gender=Masc|Mood=Ind|Number=Sing|Tense=Past|VerbForm=Fin|Voice=Act
в ADP
санкционный ADJ|Animacy=Inan|Case=Acc|Degree=Pos|Gender=Masc|Number=Sing
список NOUN|Animacy=Inan|Case=Acc|Gender=Masc|Number=Sing
девять NUM|Case=Nom
политических ADJ|Case=Gen|Degree=Pos|Number=Plur
деятелей NOUN|Animacy=Anim|Case=Gen|Gender=Masc|Number=Plur
из ADP
самопровозглашенных ADJ|Case=Gen|Degree=Pos|Number=Plur
республик NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Plur
Донбасса PROPN|Animacy=Inan|Case=Gen|Gender=Masc|Number=Sing
— PUNCT
Донецкой ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ДНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
и CCONJ
Луганской ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
народной ADJ|Case=Gen|Degree=Pos|Gender=Fem|Number=Sing
республики NOUN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
( PUNCT
ЛНР PROPN|Animacy=Inan|Case=Gen|Gender=Fem|Number=Sing
) PUNCT
— PUNCT
в ADP
связи NOUN|Animacy=Inan|Case=Loc|Gender=Fem|Number=Sing
с ADP
прошедшими VERB|Aspect=Perf|Case=Ins|Number=Plur|Tense=Past|VerbForm=Part|Voice=Act
там ADV|Degree=Pos
выборами NOUN|Animacy=Inan|Case=Ins|Gender=Masc|Number=Plur
. PUNCT
Syntax parser processes sentencies split into tokens. Use Razdel for segmentation.
>>> from ipymarkup import show_dep_ascii_markup as show_markup
>>> from razdel import sentenize, tokenize
>>> from navec import Navec
>>> from slovnet import Syntax
>>> chunk = []
>>> for sent in sentenize(text):
>>> tokens = [_.text for _ in tokenize(sent.text)]
>>> chunk.append(tokens)
>>> chunk[:1]
[['Европейский', 'союз', 'добавил', 'в', 'санкционный', 'список', 'девять', 'политических', 'деятелей', 'из', 'самопровозглашенных', 'республик', 'Донбасса', '—', 'Донецкой', 'народной', 'республики', '(', 'ДНР', ')', 'и', 'Луганской', 'народной', 'республики', '(', 'ЛНР', ')', '—', 'в', 'связи', 'с', 'прошедшими', 'там', 'выборами', '.']]
>>> navec = Navec.load('navec_news_v1_1B_250K_300d_100q.tar')
>>> syntax = Syntax.load('slovnet_syntax_news_v1.tar')
>>> syntax.navec(navec)
>>> markup = next(syntax.map(chunk))
# Convert CoNLL-style format to source, target indices
>>> words, deps = [], []
>>> for token in markup.tokens:
>>> words.append(token.text)
>>> source = int(token.head_id) - 1
>>> target = int(token.id) - 1
>>> if source > 0 and source != target: # skip root, loops
>>> deps.append([source, target, token.rel])
>>> show_markup(words, deps)
┌► Европейский amod
┌►└─ союз nsubj
┌───────┌─┌─└─── добавил
│ │ │ ┌──► в case
│ │ │ │ ┌► санкционный amod
│ │ └►└─└─ список obl
│ │ ┌──► девять nummod:gov
│ │ │ ┌► политических amod
│ ┌─────└►┌─└─└─ деятелей obj
│ │ │ ┌──► из case
│ │ │ │ ┌► самопровозглашенных amod
│ │ └►└─└─ республик nmod
│ │ └──► Донбасса nmod
│ │ ┌──────────► — punct
│ │ │ ┌──► Донецкой amod
│ │ │ │ ┌► народной amod
│ │ │ ┌─┌─┌─└─└─ республики
│ │ │ │ │ │ ┌► ( punct
│ │ │ │ │ └►┌─└─ ДНР parataxis
│ │ │ │ │ └──► ) punct
│ │ │ │ │ ┌────► и cc
│ │ │ │ │ │ ┌──► Луганской amod
│ │ │ │ │ │ │ ┌► народной amod
│ │ └─│ └►└─└─└─ республики conj
│ │ │ ┌► ( punct
│ │ └────►┌─└─ ЛНР parataxis
│ │ └──► ) punct
│ │ ┌──────► — punct
│ │ │ ┌►┌─┌─ в case
│ │ │ │ │ └► связи fixed
│ │ │ │ └──► с fixed
│ │ │ │ ┌►┌─ прошедшими acl
│ │ │ │ │ └► там advmod
│ └────►└─└─└─── выборами nmod
└──────────────► . punct
Materials are in Russian:
In addition to quality metrics we measure speed and models size, parameters that are important in production:
init
— time between system launch and first response. It is convenient for testing and devops to have model that starts quickly.disk
— file size of artefacts one needs to download before using the system: model weights, embeddings, binaries, vocabs. It is convenient to deploy compact models in production.ram
— average CPU/GPU RAM usage.speed
— number of input items processed per second: news articles, tokenized sentencies.4 datasets are used for evaluation: factru
, gareev
, ne5
and bsnlp
. Slovnet is compared to deeppavlov
, deeppavlov_bert
, deeppavlov_slavic
, pullenti
, spacy
, stanza
, texterra
, tomita
, mitie
.
For every column top 3 results are highlighted:
factru | gareev | ne5 | bsnlp | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
f1 | PER | LOC | ORG | PER | ORG | PER | LOC | ORG | PER | LOC | ORG |
slovnet | 0.959 | 0.915 | 0.825 | 0.977 | 0.899 | 0.984 | 0.973 | 0.951 | 0.944 | 0.834 | 0.718 |
slovnet_bert | 0.973 | 0.928 | 0.831 | 0.991 | 0.911 | 0.996 | 0.989 | 0.976 | 0.960 | 0.838 | 0.733 |
deeppavlov | 0.910 | 0.886 | 0.742 | 0.944 | 0.798 | 0.942 | 0.919 | 0.881 | 0.866 | 0.767 | 0.624 |
deeppavlov_bert | 0.971 | 0.928 | 0.825 | 0.980 | 0.916 | 0.997 | 0.990 | 0.976 | 0.954 | 0.840 | 0.741 |
deeppavlov_slavic | 0.956 | 0.884 | 0.714 | 0.976 | 0.776 | 0.984 | 0.817 | 0.761 | 0.965 | 0.925 | 0.831 |
pullenti | 0.905 | 0.814 | 0.686 | 0.939 | 0.639 | 0.952 | 0.862 | 0.683 | 0.900 | 0.769 | 0.566 |
spacy | 0.901 | 0.886 | 0.765 | 0.970 | 0.883 | 0.967 | 0.928 | 0.918 | 0.919 | 0.823 | 0.693 |
stanza | 0.943 | 0.865 | 0.687 | 0.953 | 0.827 | 0.923 | 0.753 | 0.734 | 0.938 | 0.838 | 0.724 |
texterra | 0.900 | 0.800 | 0.597 | 0.888 | 0.561 | 0.901 | 0.777 | 0.594 | 0.858 | 0.783 | 0.548 |
tomita | 0.929 | 0.921 | 0.945 | 0.881 | |||||||
mitie | 0.888 | 0.861 | 0.532 | 0.849 | 0.452 | 0.753 | 0.642 | 0.432 | 0.736 | 0.801 | 0.524 |
it/s
— news articles per second, 1 article ≈ 1KB.
init, s | disk, mb | ram, mb | speed, it/s | |
---|---|---|---|---|
slovnet | 1.0 | 27 | 205 | 25.3 |
slovnet_bert | 5.0 | 473 | 9500 | 40.0 (gpu) |
deeppavlov | 5.9 | 1024 | 3072 | 24.3 (gpu) |
deeppavlov_bert | 34.5 | 2048 | 6144 | 13.1 (gpu) |
deeppavlov_slavic | 35.0 | 2048 | 4096 | 8.0 (gpu) |
pullenti | 2.9 | 16 | 253 | 6.0 |
spacy | 8.0 | 140 | 625 | 8.0 |
stanza | 3.0 | 591 | 11264 | 3.0 (gpu) |
texterra | 47.6 | 193 | 3379 | 4.0 |
tomita | 2.0 | 64 | 63 | 29.8 |
mitie | 28.3 | 327 | 261 | 32.8 |
Datasets from GramEval2020 are used for evaluation:
news
— sample from Lenta.ru.wiki
— UD GSD.fiction
— SynTagRus + JZ.social
, poetry
— social, poetry subset of Taiga.Slovnet is compated to a number of existing morphology taggers: deeppavlov
, deeppavlov_bert
, rupostagger
, rnnmorph
, maru
, udpipe
, spacy
, stanza
.
For every column top 3 results are highlighted. slovnet
was trained only on news dataset:
news | wiki | fiction | social | poetry | |
---|---|---|---|---|---|
slovnet | 0.961 | 0.815 | 0.905 | 0.807 | 0.664 |
slovnet_bert | 0.982 | 0.884 | 0.990 | 0.890 | 0.856 |
deeppavlov | 0.940 | 0.841 | 0.944 | 0.870 | 0.857 |
deeppavlov_bert | 0.951 | 0.868 | 0.964 | 0.892 | 0.865 |
udpipe | 0.918 | 0.811 | 0.957 | 0.870 | 0.776 |
spacy | 0.964 | 0.849 | 0.942 | 0.857 | 0.784 |
stanza | 0.934 | 0.831 | 0.940 | 0.873 | 0.825 |
rnnmorph | 0.896 | 0.812 | 0.890 | 0.860 | 0.838 |
maru | 0.894 | 0.808 | 0.887 | 0.861 | 0.840 |
rupostagger | 0.673 | 0.645 | 0.661 | 0.641 | 0.636 |
it/s
— sentences per second.
init, s | disk, mb | ram, mb | speed, it/s | |
---|---|---|---|---|
slovnet | 1.0 | 27 | 115 | 532.0 |
slovnet_bert | 5.0 | 475 | 8087 | 285.0 (gpu) |
deeppavlov | 4.0 | 32 | 10240 | 90.0 (gpu) |
deeppavlov_bert | 20.0 | 1393 | 8704 | 85.0 (gpu) |
udpipe | 6.9 | 45 | 242 | 56.2 |
spacy | 8.0 | 140 | 579 | 50.0 |
stanza | 2.0 | 591 | 393 | 92.0 |
rnnmorph | 8.7 | 10 | 289 | 16.6 |
maru | 15.8 | 44 | 370 | 36.4 |
rupostagger | 4.8 | 3 | 118 | 48.0 |
Slovnet is compated to several existing syntax parsers: udpipe
, spacy
, deeppavlov
, stanza
.
news | wiki | fiction | social | poetry | ||||||
---|---|---|---|---|---|---|---|---|---|---|
uas | las | uas | las | uas | las | uas | las | uas | las | |
slovnet | 0.907 | 0.880 | 0.775 | 0.718 | 0.806 | 0.776 | 0.726 | 0.656 | 0.542 | 0.469 |
slovnet_bert | 0.965 | 0.936 | 0.891 | 0.828 | 0.958 | 0.940 | 0.846 | 0.782 | 0.776 | 0.706 |
deeppavlov_bert | 0.962 | 0.910 | 0.882 | 0.786 | 0.963 | 0.929 | 0.844 | 0.761 | 0.784 | 0.691 |
udpipe | 0.873 | 0.823 | 0.622 | 0.531 | 0.910 | 0.876 | 0.700 | 0.624 | 0.625 | 0.534 |
spacy | 0.943 | 0.916 | 0.851 | 0.783 | 0.901 | 0.874 | 0.804 | 0.737 | 0.704 | 0.616 |
stanza | 0.940 | 0.886 | 0.815 | 0.716 | 0.936 | 0.895 | 0.802 | 0.714 | 0.713 | 0.613 |
it/s
— sentences per second.
init, s | disk, mb | ram, mb | speed, it/s | |
---|---|---|---|---|
slovnet | 1.0 | 27 | 125 | 450.0 |
slovnet_bert | 5.0 | 504 | 3427 | 200.0 (gpu) |
deeppavlov_bert | 34.0 | 1427 | 8704 | 75.0 (gpu) |
udpipe | 6.9 | 45 | 242 | 56.2 |
spacy | 9.0 | 140 | 579 | 41.0 |
stanza | 3.0 | 591 | 890 | 12.0 |
Dev env
python -m venv ~/.venvs/natasha-slovnet
source ~/.venvs/natasha-slovnet/bin/activate
pip install -r requirements/dev.txt
pip install -e .
Test
make test
Rent GPU
yc compute instance create \
--name gpu \
--zone ru-central1-a \
--network-interface subnet-name=default,nat-ip-version=ipv4 \
--create-boot-disk image-folder-id=standard-images,image-family=ubuntu-1804-lts-ngc,type=network-ssd,size=20 \
--cores=8 \
--memory=96 \
--gpus=1 \
--ssh-key ~/.ssh/id_rsa.pub \
--folder-name default \
--platform-id gpu-standard-v1 \
--preemptible
yc compute instance delete --name gpu
Setup instance
sudo locale-gen ru_RU.UTF-8
sudo apt-get update
sudo apt-get install -y \
python3-pip
# grpcio long install ~10m, not using prebuilt wheel
# "it is not compatible with this Python"
sudo pip3 install -v \
jupyter \
tensorboard
mkdir runs
nohup tensorboard \
--logdir=runs \
--host=localhost \
--port=6006 \
--reload_interval=1 &
nohup jupyter notebook \
--no-browser \
--allow-root \
--ip=localhost \
--port=8888 \
--NotebookApp.token='' \
--NotebookApp.password='' &
ssh -Nf gpu -L 8888:localhost:8888 -L 6006:localhost:6006
scp ~/.slovnet.json gpu:~
rsync --exclude data -rv . gpu:~/slovnet
rsync -u --exclude data -rv 'gpu:~/slovnet/*' .
Intall dev
pip3 install -r slovnet/requirements/dev.txt -r slovnet/requirements/gpu.txt
pip3 install -e slovnet
Release
# Update setup.py version
git commit -am 'Up version'
git tag v0.6.0
git push
git push --tags
# Github Action builds dist and publishes to PyPi
FAQs
Deep-learning based NLP modeling for Russian language
We found that slovnet demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.