Skip to main content

SasakNLP: Research-Grade Low-Resource Language NLP Toolkit

Python 3.9+ License: MIT Tests: 69 passed Code Style: Clean Architecture

SasakNLP is an open-source Natural Language Processing (NLP) and morphological processing toolkit specifically engineered for Bahasa Sasak (Basa Sasak), an Austronesian low-resource regional language spoken by approximately 3 million people on the island of Lombok, Indonesia.

Unlike standard rule-based heuristic stemmers, SasakNLP employs a Dictionary-Enhanced Rule-Based Architecture featuring multi-candidate morphological generation, lexicon validation, multi-factor candidate ranking, and a dialect-aware framework designed for scientific reproducibility and academic research.


🔬 Research Focus & Architectural Innovation

Low-resource regional language NLP typically suffers from severe understemming, overstemming, unverified rule assumptions, and dialect conflation. SasakNLP resolves these challenges through a systematic 6-stage pipeline:

               ┌───────────────────────────────┐
               │          INPUT TEXT           │
               └──────────────┬────────────────┘
                              │
                              ▼
               ┌───────────────────────────────┐
               │      TEXT NORMALIZATION       │
               │   (NFC, Glottals, Quotes)     │
               └──────────────┬────────────────┘
                              │
                              ▼
               ┌───────────────────────────────┐
               │         TOKENIZATION          │
               │  (Reduplications, Enclitics)  │
               └──────────────┬────────────────┘
                              │
                              ▼
               ┌───────────────────────────────┐
               │    DIALECT CONTEXTUALIZATION  │
               │ (Markers: Selaparang, Ngeno)  │
               └──────────────┬────────────────┘
                              │
               ┌──────────────┴───────────────┐
               ▼                              ▼
      [Direct Lexicon Lookup]        [Rule Morphological Engine]
       (Is word already root?)                    │
               │                                  ▼
               │                     [Candidate Generation]
               │                      • Prefix rules (te-, pe-, N-)
               │                      • Suffix rules (-an, -ang, -ne)
               │                      • Infix rules (-in-, -um-)
               │                      • Circumfixes (pe-...-an, te-...-ang)
               │                      • Reduplications (kata-kata, kata kata)
               │                                  │
               │                                  ▼
               │                     [Dictionary Validation]
               │                      • EXACT_MATCH
               │                      • PARTIAL_MATCH
               │                      • OOV (Out-Of-Vocabulary)
               │                                  │
               │                                  ▼
               │                     [Candidate Multi-Criteria Ranker]
               │                      Score = w_lex·S_lex + w_morph·S_morph
               │                            + w_conf·S_conf + w_freq·S_freq
               │                            + w_dial·S_dial
               │                                  │
               └──────────────┬───────────────────┘
                              │
                              ▼
               ┌───────────────────────────────┐
               │       STRUCTURED OUTPUT       │
               │ (Lemmas, Affixes, Confidence) │
               └───────────────────────────────┘

✨ Features

  • High-Accuracy Morphological Processing: Supports inflectional prefixes (te-), nominalizers (pe-), nasal morphophonemics (N- $\rightarrow$ m-, n-, ng-, ny-), suffixes (-an, -ang, -in), pronominal enclitics (-ne, -ku, -mu), infixes (-in-, -um-), and circumfixes (ka-...-an, te-...-ang).
  • Comprehensive Reduplication Handling: Resolves full hyphenated reduplications (bareng-bareng), spaced reduplications (bareng bareng), affixed reduplications (bareng-barengan), and partial reduplication (dwipurwa).
  • SasakLex Dictionary: In-memory hash indexing and fast Prefix Trie ($O(L)$) for instant lookup and morphological validation.
  • Dialect-Aware Architecture: Handles dialectal taxonomy including Menu-Meni (Selaparang / East Lombok), Ngeno-Ngene (Central West), Mriak-Mriku (South Central), Ngeto-Ngete (Northeast), and Kuto-Kute (North/Bayan).
  • Declarative Rule Configuration: Affix rules and phonological mappings are defined in transparent JSON configuration files, enabling linguistic adaptation without modifying engine code.
  • Scientific Evaluation Suite: Standardized benchmark evaluator computing Accuracy, Macro/Weighted Precision, Recall, F1, and a 6-tier linguistic error taxonomy (Correct, Overstemming, Understemming, Incorrect Lemma, OOV Error, Dialect Error).
  • Zero Heavy Runtime Dependencies: Pure Python standard library implementation for maximum speed, portability, and instant installation.
  • CLI & Python API: Unified interfaces for interactive command-line usage and programmatic scripts.

📦 Installation

From Source (Development)

git clone https://github.com/sasaknlp/sasaknlp.git
cd sasaknlp
pip install -e .

With Developer Dependencies

pip install -e ".[dev]"

🚀 Quickstart

1. Python API

from sasaknlp import SasakNLP

# Initialize default pipeline
nlp = SasakNLP()

# Process full sentence
result = nlp.process("Tiyang mangan nasiq bareng-bareng kance baturne.")

print("Normalized Text :", result.normalized_text)
print("Detected Dialect:", result.dialect)
print("Tokens          :", result.tokens)
print("Lemmas          :", result.lemmas)

Output:

Normalized Text : tiyang mangan nasiq bareng-bareng kance baturne.
Detected Dialect: selaparang
Tokens          : ['tiyang', 'mangan', 'nasiq', 'bareng-bareng', 'kance', 'baturne']
Lemmas          : ['tiyang', 'mangan', 'nasiq', 'bareng', 'kance', 'batur']

2. Direct Stemming & Morphological Analysis

from sasaknlp import MorphologicalAnalyzer, SasakStemmer

stemmer = SasakStemmer()
print(stemmer.stem("tepinaq"))      # -> 'pinaq'
print(stemmer.stem("tulungang"))    # -> 'tulung'
print(stemmer.stem("kelororan"))    # -> 'keloror'
print(stemmer.stem("kasolahan"))    # -> 'solah'
print(stemmer.stem("baturne"))      # -> 'batur'

analyzer = MorphologicalAnalyzer()
res = analyzer.analyze("tulungang")
print(res.to_dict())

Structured Analysis:

{
  "surface_form": "tulungang",
  "lemma": "tulung",
  "prefix": null,
  "infix": null,
  "suffix": "ang",
  "rule_applied": "transitive_ang",
  "dialect": "general",
  "confidence": 0.9624,
  "reduplication": null,
  "is_oov": false
}

💻 Command Line Interface (CLI)

The package provides the sasaknlp command:

# 1. Stem a single word
sasaknlp stem "tepinaq"
# Output:
# Input: tepinaq
# Lemma: pinaq
# Rule: passive_te
# Confidence: 0.9654

# 2. Analyze detailed morphology
sasaknlp analyze "kelororan"

# 3. Process a full sentence
sasaknlp process "Tiyang mangan nasiq bareng-bareng"

# 4. Search and look up dictionary entries
sasaknlp lexicon lookup "mangan"
sasaknlp lexicon search "ba"

# 5. Run benchmark evaluation
sasaknlp evaluate --benchmark datasets/benchmark/synthetic_benchmark.csv

📊 Scientific Benchmark Evaluation

SasakNLP includes a built-in evaluator that scores model outputs against standardized 6-column benchmark datasets:

python scripts/run_benchmark.py --file datasets/benchmark/synthetic_benchmark.csv

Evaluation Report Output:

# SasakNLP Benchmark Evaluation Report

## Primary Metrics

| Metric | Value |
| --- | --- |
| Total Test Samples | 20 |
| Accuracy | 95.00% |
| Macro Precision | 93.75% |
| Macro Recall | 93.75% |
| Macro F1 Score | 93.75% |
| Weighted F1 Score | 95.00% |

## Error Taxonomy Distribution

| Error Category | Count | Percentage |
| --- | --- | --- |
| Correct | 19 | 95.00% |
| Overstemming | 0 | 0.00% |
| Understemming | 0 | 0.00% |
| Incorrect Lemma | 1 | 5.00% |
| OOV Error | 0 | 0.00% |
| Dialect Error | 0 | 0.00% |

🗂 Repository Structure

library-sasak/
├── pyproject.toml              # Build & packaging configuration
├── README.md                   # Project documentation
├── LICENSE                     # MIT License
├── CONTRIBUTING.md             # Contribution guidelines
├── CODE_OF_CONDUCT.md          # Community code of conduct
├── requirements.txt            # Minimal runtime dependencies
├── requirements-dev.txt        # Development dependencies
│
├── src/
│   └── sasaknlp/
│       ├── core/               # Pipeline orchestrator, config, and data types
│       ├── tokenizer/          # Word & sentence boundary tokenizers
│       ├── normalization/      # Unicode, glottal apostrophe, and casefold normalizer
│       ├── lexicon/            # SasakLex manager, loader, PrefixTrie, and data
│       ├── morphology/         # Rule engine, candidate generator, analyzer
│       │   └── rules/          # Prefix, suffix, infix, circumfix, reduplication
│       ├── stemmer/            # Dictionary validator, ranker, and SasakStemmer
│       ├── dialect/            # Dialect taxonomy manager and marker detector
│       ├── evaluation/         # Metrics, error analyzer, benchmark evaluator
│       └── cli/                # Command-line interface subcommands
│
├── datasets/
│   ├── sasaklex/               # Base lexicon reference files
│   └── benchmark/              # Benchmark evaluation datasets (CSV)
│
├── examples/
│   ├── quickstart.py           # End-to-end pipeline usage
│   ├── morphological_analysis.py # In-depth morphological candidate inspection
│   └── benchmark_evaluation.py # Academic evaluation script
│
├── docs/                       # Technical & linguistic guides
│   ├── installation.md
│   ├── usage.md
│   ├── lexicon_guide.md
│   ├── morphological_rules.md
│   ├── dialect_guide.md
│   └── evaluation_guide.md
│
├── tests/                      # 69 Unit tests covering all core modules
└── scripts/                    # Automation and evaluation scripts

🧪 Running Tests

Execute the test suite using unittest or pytest:

# Using Python's built-in test runner:
python3 -m unittest discover -s tests -v

# Or with pytest:
pytest tests -v

All 69 unit tests execute in under 0.05 seconds with 100% pass rate.


📖 Citation

If you use SasakNLP in your research, computational linguistics publications, or low-resource language benchmarks, please cite:

@software{sasaknlp2026,
  author = {kodetr},
  title = {SasakNLP: Research-Grade Natural Language Processing and Morphological Toolkit for Bahasa Sasak},
  year = {2026},
  publisher = {GitHub},
  url = {https://github.com/kodetr/sasaknlp}
}

👨‍💻 Pembuat / Author


📄 License

This project is licensed under the MIT License — see the LICENSE file for details.

Metadata

Release files for sasaknlp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sasaknlp 0.1.0
File Size Uploaded
sasaknlp-0.1.0.tar.gz 88.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sasaknlp 0.1.0
File Interpreter ABI Platform
sasaknlp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 182.8 kB

Release files / sasaknlp-0.1.0.tar.gz

Download URL sasaknlp-0.1.0.tar.gz
Size 88.3 kB
Tags Source
SHA-256 checksum
How to use checksums
01324ee68d40a56a03e4779039133bc19db95efab913dbd9cdaffccf4007d8cc
BLAKE2b-256 checksum
How to use checksums
ee990ce04975d637fc2ccf70c36865ad2db36c91819772b05d32f03bc50f4d84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release files / sasaknlp-0.1.0-py3-none-any.whl

Download URL sasaknlp-0.1.0-py3-none-any.whl
Size 94.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f7e8110d4d40a3a94730c73e96761eecf0e0e3d1dcbdd0e6beca20a3adf12f1
BLAKE2b-256 checksum
How to use checksums
e0cace273ab6e374965b0ee964e94c909420d985d020fc2930d503122f929e24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.0

Release history Release notifications | RSS feed

0.1.2

2 release files

0.1.1

2 release files

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page