Library / SDK
natasha/yargy avatar
natasha/yargy

natasha/yargy: rule-based fact extraction for Russian text

Rule-based facts extraction for Russian language

335 stars44 forksPythonMIT

At a glance

What is it?
Yargy turns Russian sentences into structured facts using grammar rules and dictionaries instead of a trained model. It is a small library with a narrow scope, and its documentation is almost entirely in Russian.
Who is it for?
Adopt yargy when you need to pull named fields such as position and name out of Russian text and you can write the grammar yourself; a rule you can read beats a model you cannot. Skip it if your input is not Russian, if you need open-ended entity types you cannot enumerate, or if nobody on the team reads the Russian notebooks, because the English README stops at one example.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 158 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What yargy solves, and who it is written for

Russian is a heavily inflected language, so the same field value appears in many surface forms. A person's surname in a document might be nominative in one sentence and genitive in the next. Regex over raw strings breaks on that. Yargy works at the level of morphology instead: its predicates such as gram('Surn') and gram('Name') match by grammatical category rather than by literal characters, so one rule covers the inflections. The README describes the library as using "rules and dictionaries to extract structured information from Russian texts" and compares it to the Tomita parser, a Yandex tool with the same philosophy.

The audience is narrow and specific. You are a Python developer with Russian input and a small, known set of fields to pull out: job titles, names, organisations, dates, amounts. You can write the grammar for those fields by hand. If that describes your task, yargy is a reasonable fit. If you are hoping to point a general extractor at arbitrary Russian prose and get entities back, this is not that tool, and the README makes no such promise.

How the parser turns rules into facts

The mechanism is a grammar written in Python expressions, compiled into a parser, and run over text. Predicates are the leaves: gram('Surn') is true for a token whose morphology says it is a surname, not_(gram('Abbr')) excludes abbreviations. and_ combines them into a token-level test. Larger units come from rule, which sequences elements, and from morph_pipeline, which matches multi-word dictionary entries such as 'управляющий директор' while still allowing morphological variation inside them.

Interpretation is the layer that produces data rather than spans. fact('Name', ['first', 'last']) declares a record type, and .interpretation(Name.first) attaches a field to whichever element matched. The top-level rule carries .interpretation(Person), so a successful match yields a Person object with position and name attributes rather than a list of character offsets. The gnc_relation and .match(gnc) calls add an agreement constraint: the first name and surname in the example must agree in gender, number and case, which is what stops the parser from pairing an unrelated name elsewhere in the sentence with the surname it just saw.

That constraint is the interesting design choice and also the sharp edge. Agreement is a strong filter in Russian and it removes a class of false positives, but it also means a rule can fail to match text that a human would read as a correct pair, for example when a name appears in an unusual case or the morphology dictionary does not know the word.

Installing yargy and extracting a first fact

The README gives a single install command and states the runtime requirements: Python 3.7 or newer, or PyPy 3, with Pymorphy2 as the only dependency. That dependency is doing real work, since every gram predicate is a query against the Pymorphy2 morphological dictionary, so the quality of your matches is bounded by that dictionary.

bash
$ pip install yargy

After installation, the smallest useful program is the README example, which extracts a position and a full name from one Russian sentence. The imports cover the parser, rule combinators, the fact factory, predicates, the agreement relation and the dictionary pipeline.

python
from yargy import Parser, rule, and_, not_
from yargy.interpretation import fact
from yargy.predicates import gram
from yargy.relations import gnc_relation
from yargy.pipelines import morph_pipeline

The README example declares a Name fact with two fields and a Person fact holding a position and a name, then builds the parser and matches one sentence.

python
Name = fact(
    'Name',
    ['first', 'last'],
)
Person = fact(
    'Person',
    ['position', 'name']
)

LAST = and_(
    gram('Surn'),
    not_(gram('Abbr')),
)
FIRST = and_(
    gram('Name'),
    not_(gram('Abbr')),
)
python
POSITION = morph_pipeline([
    'управляющий директор',
    'вице-мэр'
])

gnc = gnc_relation()
NAME = rule(
    FIRST.interpretation(
        Name.first
    ).match(gnc),
    LAST.interpretation(
        Name.last
    ).match(gnc)
).interpretation(
    Name
)
python
PERSON = rule(
    POSITION.interpretation(
        Person.position
    ).match(gnc),
    NAME.interpretation(
        Person.name
    )
).interpretation(
    Person
)

parser = Parser(PERSON)

match = parser.match('управляющий директор Иван Ульянов')
print(match)

Running this should print a Person object with position set to 'управляющий директор' and a nested Name holding 'Иван' and 'Ульянов', exactly as the README shows. If it prints None instead, the first thing to check is whether the tokens in your own sentence carry the grammatical tags your predicates ask for.

Where yargy stops being the right tool

The documentation is the first limitation, and it is not a small one. The README states plainly that all materials are in Russian: the overview article, the workshop video, the getting started notebook, the reference and the cookbook. Only the README itself is in English, and it contains one worked example. A team without Russian readers is working from a single sample and the source code.

The second limitation is scope. Yargy extracts what you wrote a rule for. There is no model to generalise from examples, no confidence score to threshold, and no way to discover a field you did not anticipate. If your field list changes weekly, you will be editing grammar weekly, and each edit can break a previously working rule in a way that only shows up when you rerun your test set.

Third, the agreement relation is a filter, not a guarantee. It reduces false pairings but it cannot rescue a match when Pymorphy2 mis-tags a token, and unusual proper nouns, transliterations and typos are exactly where a dictionary-driven approach is weakest. The README does not document any fallback for out-of-vocabulary tokens, so plan for those cases to be missed rather than handled.

Finally, the only version reference in the repository files is 0.16.0 in setup.py. Treat the API as pre-1.0 and pin the version you install.

Yargy against a trained NER model

The obvious alternative for the same job is a statistical or neural named entity recogniser, and the difference is not quality but control. A trained model gives you recall on entity types it was trained for, handles unseen wording, and needs no grammar. It also gives you probabilities you cannot inspect, and when it is wrong you can only add training data and retrain.

Yargy inverts that. Every match is traceable to a rule you can read and edit, and a miss is usually a rule you have not written yet. For a fixed schema in a narrow domain, such as parsing job titles out of Russian press releases, that traceability is worth more than generalisation. For open-ended extraction over varied text, the rule-writing cost grows faster than the accuracy does, and a model is the better starting point. The README names Tomita parser as the closest relative, which places yargy in the same family of hand-written grammars rather than in the machine-learning family.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-04-13. The licence is MIT, declared both in setup.py and in the LICENSE file at the top level, which permits commercial use and modification provided the copyright notice and permission notice are kept; that is a summary of the licence text, not legal advice, and your own counsel should confirm how it applies to your distribution.

The upgrade surface is small because the dependency list is small: Pymorphy2 is the only install requirement. That also concentrates the risk, since a change in the morphological dictionary or in Pymorphy2 itself changes what every gram predicate matches, so a version bump can silently alter your extraction results. The repository's own release process, described in the README, is manual: update the version in setup.py, commit, tag, push, and a GitHub Action builds the distribution and publishes it to PyPI. Tests and lint run through make test, which invokes flake8 and pytest with doctest collection over the yargy and tests packages. Documentation is regenerated with make exec-docs, which executes the notebooks in docs/ in place, and the README notes that the diff should be checked manually before committing.

Editorial conclusion

Adopt yargy when you need to pull named fields such as position and name out of Russian text and you can write the grammar yourself; a rule you can read beats a model you cannot. Skip it if your input is not Russian, if you need open-ended entity types you cannot enumerate, or if nobody on the team reads the Russian notebooks, because the English README stops at one example. Before committing, verify three things: that your Python version satisfies the 3.7+ requirement, that the fact fields you need can be expressed with gram, morph_pipeline and rule, and that the gnc_relation agreement constraint actually holds on your own sample of sentences, since that is the part most likely to reject valid matches.

Frequently asked questions

What is yargy used for?

It extracts structured facts from Russian text using rules and dictionaries, in the style of the Tomita parser. The README's example pulls a job position and a person's first and last name out of one sentence.

How do I install yargy?

Run pip install yargy. The README states it supports Python 3.7 or newer and PyPy 3, and that Pymorphy2 is its only dependency.

Does yargy work for languages other than Russian?

The README describes it as extracting information from Russian texts, and its predicates query a Russian morphological dictionary through Pymorphy2. The README documents no support for other languages.

Official sources

  1. Issues
  2. License: MIT
  3. natasha/yargy on GitHub
  4. README
Community notes

Community notes