MCPcopy Index your code
hub / github.com/bminixhofer/nlprule

github.com/bminixhofer/nlprule @0.6.4

Chat with this repo
repository ↗ · DeepWiki ↗ · release 0.6.4 ↗ · + Follow
549 symbols 1,470 edges 33 files 131 documented · 24%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

nlprule

<a href="https://pypi.org/project/nlprule">
    <img src="https://img.shields.io/pypi/v/nlprule" alt="PyPI">
</a>
<a href="https://crates.io/crates/nlprule">
    <img src="https://img.shields.io/crates/v/nlprule" alt="Crates.io">
</a>
<a href="https://docs.rs/nlprule">
    <img src="https://docs.rs/nlprule/badge.svg" alt="Docs.rs">
</a>
<a href="https://pepy.tech/project/nlprule">
    <img src="https://pepy.tech/badge/nlprule/month" alt="PyPI Downloads">
</a>
<a href="">
    <img src="https://img.shields.io/crates/l/nlprule" alt="License">
</a>

A fast, low-resource Natural Language Processing and Error Correction library written in Rust. nlprule implements a rule- and lookup-based approach to NLP using resources from LanguageTool.

Python Usage

Install: pip install nlprule

Use:

from nlprule import Tokenizer, Rules

tokenizer = Tokenizer.load("en")
rules = Rules.load("en", tokenizer)
rules.correct("He wants that you send him an email.")
# returns: 'He wants you to send him an email.'

rules.correct("I can due his homework.")
# returns: 'I can do his homework.'

for s in rules.suggest("She was not been here since Monday."):
    print(s.start, s.end, s.replacements, s.source, s.message)
# prints:
# 4 16 ['was not', 'has not been'] WAS_BEEN.1 Did you mean was not or has not been?
for sentence in tokenizer.pipe("A brief example is shown."):
    for token in sentence:
        print(
            repr(token.text).ljust(10),
            repr(token.span).ljust(10),
            repr(token.tags).ljust(24),
            repr(token.lemmas).ljust(24),
            repr(token.chunks).ljust(24),
        )
# prints:
# 'A'        (0, 1)     ['DT']                   ['A', 'a']               ['B-NP-singular']       
# 'brief'    (2, 7)     ['JJ']                   ['brief']                ['I-NP-singular']       
# 'example'  (8, 15)    ['NN:UN']                ['example']              ['E-NP-singular']       
# 'is'       (16, 18)   ['VBZ']                  ['be', 'is']             ['B-VP']                
# 'shown'    (19, 24)   ['VBN']                  ['show', 'shown']        ['I-VP']                
# '.'        (24, 25)   ['.', 'PCT', 'SENT_END'] ['.']                    ['O']

Rust Usage

Recommended setup:

Cargo.toml

[dependencies]
nlprule = "<version>"

[build-dependencies]
nlprule-build = "<version>" # must be the same as the nlprule version!

build.rs

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    nlprule_build::BinaryBuilder::new(
        &["en"],
        std::env::var("OUT_DIR").expect("OUT_DIR is set when build.rs is running"),
    )
    .build()
    .validate();
}

src/main.rs

use nlprule::{Rules, Tokenizer, tokenizer_filename, rules_filename};

fn main() {
    let mut tokenizer_bytes: &'static [u8] = include_bytes!(concat!(
        env!("OUT_DIR"),
        "/",
        tokenizer_filename!("en")
    ));
    let mut rules_bytes: &'static [u8] = include_bytes!(concat!(
        env!("OUT_DIR"),
        "/",
        rules_filename!("en")
    ));

    let tokenizer = Tokenizer::from_reader(&mut tokenizer_bytes).expect("tokenizer binary is valid");
    let rules = Rules::from_reader(&mut rules_bytes).expect("rules binary is valid");

    assert_eq!(
        rules.correct("She was not been here since Monday.", &tokenizer),
        String::from("She was not here since Monday.")
    );
}

nlprule and nlprule-build versions are kept in sync.

Main features

  • Rule-based Grammatical Error Correction through multiple thousand rules.
  • A text processing pipeline doing sentence segmentation, part-of-speech tagging, lemmatization, chunking and disambiguation.
  • Support for English, German and Spanish.
  • Spellchecking. (in progress)

Goals

  • A single place to apply spellchecking and grammatical error correction for a downstream task.
  • Fast, low-resource NLP suited for running:
    1. as a pre- / postprocessing step for more sophisticated (i. e. ML) approaches.
    2. in the background of another application with low overhead.
    3. client-side in the browser via WebAssembly.
  • 100% Rust code and dependencies.

Comparison to LanguageTool

|Disambiguation rules| |Grammar rules| LT version nlprule time LanguageTool time
English 843 (100%) 3725 (~ 85%) 5.2 1 1.7 - 2.0
German 486 (100%) 2970 (~ 90%) 5.2 1 2.4 - 2.8
Spanish Experimental support. Not fully tested yet.

See the benchmark issue for details.

Projects using nlprule

  • prosemd: a proofreading and linting language server for markdown files with VSCode integration.
  • cargo-spellcheck: a tool to check all your Rust documentation for spelling and grammar mistakes.

Please submit a PR to add your project!

Acknowledgements

All credit for the resources used in nlprule goes to LanguageTool who have made a Herculean effort to create high-quality resources for Grammatical Error Correction and broader NLP.

License

nlprule is licensed under the MIT license or Apache-2.0 license, at your option.

The nlprule binaries (*.bin) are derived from LanguageTool v5.2 and licensed under the LGPLv2.1 license. nlprule statically and dynamically links to these binaries. Under LGPLv2.1 §6(a) this does not have any implications on the license of nlprule itself.

Extension points exported contracts — how you extend this code

Atomable (Interface)
(no doc) [10 implementers]
nlprule/src/rule/engine/composition.rs
MaybeParallelIterator (Interface)
Allows to convert into an iterator that can be executed either parallelly or serially. The choice is made according to [1 …
nlprule/src/utils/parallelism.rs
MaybeParallelRefIterator (Interface)
Shared reference version of MaybeParallelIterator, works the same but returns an iterator over references, does not cons [1 …
nlprule/src/utils/parallelism.rs
MaybeParallelRefMutIterator (Interface)
Exclusive reference version of MaybeParallelIterator, works the same but returns an iterator over mutable references, do [1 …
nlprule/src/utils/parallelism.rs
MaybeParallelBridge (Interface)
Converts any serial iterator into a CondIterator, that can either run parallelly or serially. [1 implementers]
nlprule/src/utils/parallelism.rs

Core symbols most depended-on inside this repo

push
called by 117
nlprule/src/types.rs
clone
called by 77
nlprule/src/utils/regex.rs
into_iter
called by 56
nlprule/src/types.rs
as_ref
called by 53
nlprule/src/types.rs
as_str
called by 47
nlprule/src/utils/regex.rs
iter
called by 47
nlprule/src/rule/engine/composition.rs
iter
called by 40
nlprule/src/utils/regex.rs
iter
called by 33
nlprule/src/tokenizer/tag.rs

Shape

Method 296
Class 134
Function 87
Enum 24
Interface 8

Languages

Rust96%
Python4%

Modules by API surface

nlprule/src/types.rs62 symbols
python/src/lib.rs50 symbols
nlprule/src/compile/structure.rs45 symbols
nlprule/src/rule/engine/composition.rs44 symbols
nlprule/src/tokenizer/tag.rs43 symbols
nlprule/src/tokenizer/chunk.rs31 symbols
nlprule/src/utils/regex.rs27 symbols
nlprule/src/compile/parse_structure.rs24 symbols
nlprule/src/compile/impls.rs24 symbols
nlprule/src/rule/mod.rs23 symbols
nlprule/src/tokenizer.rs20 symbols
nlprule/src/rules.rs19 symbols

For agents

$ claude mcp add nlprule \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page