amharic-segmenter 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- amharic_segmenter-0.1.0/.gitignore +15 -0
- amharic_segmenter-0.1.0/CHANGELOG.md +25 -0
- amharic_segmenter-0.1.0/LICENSE +21 -0
- amharic_segmenter-0.1.0/PKG-INFO +340 -0
- amharic_segmenter-0.1.0/README.md +305 -0
- amharic_segmenter-0.1.0/docs/BOOK_COVERAGE.md +64 -0
- amharic_segmenter-0.1.0/docs/GRAMMAR_RULES.md +49 -0
- amharic_segmenter-0.1.0/pyproject.toml +67 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/__init__.py +40 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/__main__.py +3 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/_version.py +1 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/charset.py +69 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/cli.py +71 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/data/irregular_plurals.tsv +43 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/data/lexicon.txt +110 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/morphology.py +182 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/normalize.py +29 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/py.typed +0 -0
- amharic_segmenter-0.1.0/src/amharic_segmenter/tokenizer.py +309 -0
- amharic_segmenter-0.1.0/tests/test_morphology.py +224 -0
- amharic_segmenter-0.1.0/tests/test_normalize_and_cli.py +56 -0
- amharic_segmenter-0.1.0/tests/test_stemming.py +84 -0
- amharic_segmenter-0.1.0/tests/test_tokenizer.py +68 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
|
+
project uses [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - Unreleased
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- NLTK-style API: `sent_tokenize`, `word_tokenize`, `stem`, `stem_words`, `AmharicStemmer`,
|
|
11
|
+
and `amharic-segmenter --stem`. Stemming also works on words outside the lexicon.
|
|
12
|
+
- Function words (`ነው`, `ናቸው`, `ውስጥ` …) are never split.
|
|
13
|
+
- Word tokenizer for Ethiopic script: letters, Ethiopic punctuation (`፡ ። ፣ ፤ ፧` …), Ethiopic
|
|
14
|
+
and Arabic numerals, Latin text. No character is ever dropped.
|
|
15
|
+
- Sentence splitter for `።`, `፧`, `፨`, `!`, `?` and the old-style `፡፡`.
|
|
16
|
+
- Optional morpheme segmentation for nouns and noun phrases: prepositions (`በ ከ ለ የ ስለ`),
|
|
17
|
+
plural, definite article, possessive suffixes, object marker `ን`, conjunctions `ና`/`ም`.
|
|
18
|
+
- Three splitting strategies: `lexicon` (default), `rules`, `none`.
|
|
19
|
+
- Optional homophone normalisation (`ሐ→ሀ`, `ሠ→ሰ`, `ዐ→አ`, `ፀ→ጸ`).
|
|
20
|
+
- Token offsets (`tokenize_spans`), command line interface, typed package (`py.typed`).
|
|
21
|
+
- Pronoun contractions (`በኔ`, `ከኛ`, `እንዳንተ`), fused feminine `ዋ` (`ሐኪሟ`), irregular and
|
|
22
|
+
reduplicated-adjective plurals, and `lemma()`.
|
|
23
|
+
- Tests from chapter 4 examples (`ጓዳውንና`, `ባለቤቶቹን`, `ሴትዮዋ`).
|
|
24
|
+
- `docs/BOOK_COVERAGE.md`: section-by-section record of what the source book covers.
|
|
25
|
+
- Seed lexicon built from the examples of *አማርኛ ሠዋሰው* (1963 E.C.).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ali Kibret Muhamed
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: amharic-segmenter
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Sentence/word tokenization, morpheme splitting and stemming for Amharic (አማርኛ), NLTK-style and dependency-free.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Alki45/amharic-segmenter
|
|
6
|
+
Project-URL: Documentation, https://github.com/Alki45/amharic-segmenter#readme
|
|
7
|
+
Project-URL: Issues, https://github.com/Alki45/amharic-segmenter/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Alki45/amharic-segmenter/blob/main/CHANGELOG.md
|
|
9
|
+
Author-email: Ali Kibret Muhamed <alikibretmuhamed@gmail.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: amharic,ethiopic,ge'ez,low-resource,morphology,nlp,stemmer,stemming,tokenizer,አማርኛ
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
25
|
+
Classifier: Typing :: Typed
|
|
26
|
+
Requires-Python: >=3.9
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: build; extra == 'dev'
|
|
29
|
+
Requires-Dist: mypy; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
33
|
+
Requires-Dist: twine; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
|
|
38
|
+
# amharic-segmenter
|
|
39
|
+
|
|
40
|
+
**Sentence and word tokenization, morpheme splitting and stemming for Amharic (አማርኛ)**
|
|
41
|
+
as easy as English NLP, built on real grammar rules, with zero dependencies.
|
|
42
|
+
|
|
43
|
+
[](https://pypi.org/project/amharic-segmenter/)
|
|
44
|
+
[](https://pypi.org/project/amharic-segmenter/)
|
|
45
|
+
[](https://github.com/Alki45/amharic-segmenter/actions/workflows/ci.yml)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
[](https://github.com/astral-sh/ruff)
|
|
48
|
+
|
|
49
|
+
[Install](#installation) · [Quickstart](#quickstart) · [Features](#features) · [API](#api-reference) · [CLI](#command-line) · [How it works](#how-it-works) · [Contributing](#contributing)
|
|
50
|
+
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
> **በአማርኛ:** አማርኛ ጽሑፍን ወደ ዓረፍተ ነገሮችና ቃላት የሚከፋፍል፣ እንዲሁም ቃላትን ወደ ሞርፊሞች
|
|
54
|
+
> (`በ`፣ `ከ`፣ `ለ`፣ `ን`፣ `ና`፣ `ዎች`…) የሚሰብር ቀላል የፓይቶን ጥቅል። ለማንኛውም የአማርኛ ቋንቋ ፕሮጀክት ነጻ ነው።
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Why this exists
|
|
59
|
+
|
|
60
|
+
General-purpose tokenizers split on whitespace or learn subwords from data. For Amharic that
|
|
61
|
+
leaves two problems:
|
|
62
|
+
|
|
63
|
+
1. **Ethiopic punctuation is not ASCII.** `።` (full stop), `፣` (comma), `፧` (question mark) and
|
|
64
|
+
the old word separator `፡` are missed or glued to words by generic tools.
|
|
65
|
+
2. **Amharic is morphologically rich.** Prepositions, plural, possessives, the object marker
|
|
66
|
+
`ን` and conjunctions are written *attached* to the word, so `ለተማሪዎቻችን` ("for our
|
|
67
|
+
students") is one whitespace token but five units of meaning.
|
|
68
|
+
|
|
69
|
+
`amharic-segmenter` handles both with transparent, documented rules taken from an Amharic
|
|
70
|
+
grammar book, so results are explainable and easy to improve.
|
|
71
|
+
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
- **NLTK-style API**: `sent_tokenize`, `word_tokenize`, `stem`, `AmharicStemmer`. Works right
|
|
75
|
+
after `pip install`: no model downloads, no setup
|
|
76
|
+
- **Stemming** that strips prefixes and suffixes, also for words it has never seen
|
|
77
|
+
- **Sentence splitting** on `።`, `፧`, `፨`, `!`, `?` and the old-style `፡፡`
|
|
78
|
+
- **Word tokenization** that understands Ethiopic letters, punctuation and numerals
|
|
79
|
+
(`፩፻`), plus Latin text and decimals, and **never drops a character**
|
|
80
|
+
- **Morpheme segmentation** of nouns and noun phrases: prepositions `በ ከ ለ የ ስለ`, plural
|
|
81
|
+
(`ች`, `ዎች`), definite article, possessive suffixes, object marker `ን`, conjunctions `ና`/`ም`
|
|
82
|
+
- **Precision-first design:** words are only split when the stem is known, so names like
|
|
83
|
+
`ከበደ` and words like `ወንድም` stay intact. An opt-in `rules` mode trades precision for recall
|
|
84
|
+
- Handles **pronoun contractions** (`በኔ → በ + እኔ`), **fused feminine forms** (`ሐኪሟ → ሐኪም + ዋ`)
|
|
85
|
+
and **irregular plurals** (`መጻሕፍትን`, `ቃላቶች`), with `lemma()` to get the dictionary form
|
|
86
|
+
- **Token offsets** for aligning tokens with the original text
|
|
87
|
+
- **Optional normalization** of homophone letters (`ሐ→ሀ`, `ሠ→ሰ`, `ዐ→አ`, `ፀ→ጸ`)
|
|
88
|
+
- **Extensible lexicon**: bring your own words, no retraining needed
|
|
89
|
+
- **Command line tool**, fully typed (`py.typed`), pure Python, **no dependencies**,
|
|
90
|
+
Python 3.9+
|
|
91
|
+
|
|
92
|
+
## Installation
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pip install amharic-segmenter
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Quickstart
|
|
99
|
+
|
|
100
|
+
If you have used NLTK on English text, you already know how to use it. Install, import, call:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
from amharic_segmenter import word_tokenize, sent_tokenize, stem
|
|
104
|
+
|
|
105
|
+
text = "ተማሪዎቹ መጻሕፍትን አነበቡ። ከበደና አበበ ለተማሪዎቻቸው ሰጡ።"
|
|
106
|
+
|
|
107
|
+
sent_tokenize(text)
|
|
108
|
+
# ['ተማሪዎቹ መጻሕፍትን አነበቡ።', 'ከበደና አበበ ለተማሪዎቻቸው ሰጡ።']
|
|
109
|
+
|
|
110
|
+
word_tokenize(text)
|
|
111
|
+
# ['ተማሪዎቹ', 'መጻሕፍትን', 'አነበቡ', '።', 'ከበደና', 'አበበ', 'ለተማሪዎቻቸው', 'ሰጡ', '።']
|
|
112
|
+
|
|
113
|
+
[stem(w) for w in word_tokenize(text)]
|
|
114
|
+
# ['ተማሪ', 'መጻሕፍት', 'አነበቡ', '።', 'ከበደ', 'አበበ', 'ተማሪ', 'ሰጡ', '።']
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Or with a stemmer object, the way you would use `PorterStemmer`:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from amharic_segmenter import AmharicStemmer
|
|
121
|
+
|
|
122
|
+
stemmer = AmharicStemmer()
|
|
123
|
+
stemmer.stem("ተማሪዎችን") # 'ተማሪ'
|
|
124
|
+
stemmer.stem_words(["ተማሪዎች", "ላሞች"]) # ['ተማሪ', 'ላም']
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| English (NLTK) | Amharic (this package) |
|
|
128
|
+
|----------------|------------------------|
|
|
129
|
+
| `nltk.sent_tokenize(text)` | `sent_tokenize(text)` |
|
|
130
|
+
| `nltk.word_tokenize(text)` | `word_tokenize(text)` |
|
|
131
|
+
| `PorterStemmer().stem(word)` | `AmharicStemmer().stem(word)` or `stem(word)` |
|
|
132
|
+
| `nltk.download("punkt")` | **nothing to download**: rules and data ship inside the package |
|
|
133
|
+
|
|
134
|
+
### More examples
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from amharic_segmenter import tokenize, sentence_tokenize
|
|
138
|
+
|
|
139
|
+
text = "ተማሪዎቹ በከተማ ውስጥ ይኖራሉ። ከበደና አበበ ለተማሪዎቻችን መጽሐፎችን ሰጡ።"
|
|
140
|
+
|
|
141
|
+
sentence_tokenize(text)
|
|
142
|
+
# ['ተማሪዎቹ በከተማ ውስጥ ይኖራሉ።', 'ከበደና አበበ ለተማሪዎቻችን መጽሐፎችን ሰጡ።']
|
|
143
|
+
|
|
144
|
+
tokenize(text)
|
|
145
|
+
# ['ተማሪዎቹ', 'በከተማ', 'ውስጥ', 'ይኖራሉ', '።', 'ከበደና', 'አበበ', 'ለተማሪዎቻችን', 'መጽሐፎችን', 'ሰጡ', '።']
|
|
146
|
+
|
|
147
|
+
tokenize(text, morphemes=True)
|
|
148
|
+
# ['ተማሪ', 'ዎች', 'ው', 'በ', 'ከተማ', 'ውስጥ', 'ይኖራሉ', '።', 'ከበደ', 'ና', 'አበበ',
|
|
149
|
+
# 'ለ', 'ተማሪ', 'ዎች', 'ችን', 'መጽሐፍ', 'ች', 'ን', 'ሰጡ', '።']
|
|
150
|
+
|
|
151
|
+
tokenize(text, morphemes=True, mark_affixes=True)
|
|
152
|
+
# ['ተማሪ', '+ዎች', '+ው', 'በ+', 'ከተማ', 'ውስጥ', 'ይኖራሉ', '።', 'ከበደ', '+ና', 'አበበ',
|
|
153
|
+
# 'ለ+', 'ተማሪ', '+ዎች', '+ችን', 'መጽሐፍ', '+ች', '+ን', 'ሰጡ', '።']
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Analyse a single word:
|
|
157
|
+
|
|
158
|
+
```python
|
|
159
|
+
from amharic_segmenter import analyze
|
|
160
|
+
|
|
161
|
+
analyze("ለተማሪዎቻችን")
|
|
162
|
+
# Analysis(word='ለተማሪዎቻችን', prefixes=('ለ',), stem='ተማሪ', suffixes=('ዎች', 'ችን'))
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Token offsets:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from amharic_segmenter import tokenize_spans
|
|
169
|
+
|
|
170
|
+
tokenize_spans("ከበደን አየ።")
|
|
171
|
+
# [Token(text='ከበደን', start=0, end=4, kind='word'),
|
|
172
|
+
# Token(text='አየ', start=5, end=7, kind='word'),
|
|
173
|
+
# Token(text='።', start=7, end=8, kind='punct')]
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Command line
|
|
177
|
+
|
|
178
|
+
```console
|
|
179
|
+
$ amharic-segmenter -m "ለተማሪዎቻችን መጽሐፎችን ሰጡ።"
|
|
180
|
+
ለ ተማሪ ዎች ችን መጽሐፍ ች ን ሰጡ ።
|
|
181
|
+
|
|
182
|
+
$ amharic-segmenter --sentences --json "አበበ መጣ። ከበደ ሄደ።"
|
|
183
|
+
["አበበ መጣ።", "ከበደ ሄደ።"]
|
|
184
|
+
|
|
185
|
+
$ amharic-segmenter --stem "ተማሪዎቹ መጻሕፍትን አነበቡ።"
|
|
186
|
+
ተማሪ መጻሕፍት አነበቡ ።
|
|
187
|
+
|
|
188
|
+
$ echo "ተማሪውንም አየሁ።" | amharic-segmenter -m --mark-affixes
|
|
189
|
+
ተማሪ +ው +ን +ም አየሁ ።
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Run `amharic-segmenter --help` for all options (`--strategy`, `--lexicon`, `--normalize`,
|
|
193
|
+
`--no-punct`, `--json`). `python -m amharic_segmenter` works too.
|
|
194
|
+
|
|
195
|
+
## API reference
|
|
196
|
+
|
|
197
|
+
### Module-level functions
|
|
198
|
+
|
|
199
|
+
| Function | Returns | Description |
|
|
200
|
+
|----------|---------|-------------|
|
|
201
|
+
| `sent_tokenize(text)` | `list[str]` | Sentences (NLTK-style name for `sentence_tokenize`) |
|
|
202
|
+
| `word_tokenize(text)` | `list[str]` | Words and punctuation (NLTK-style, same as `tokenize(text)`) |
|
|
203
|
+
| `stem(word, *, aggressive=True)` | `str` | Stem of one word. `aggressive=False` leaves words outside the lexicon alone |
|
|
204
|
+
| `stem_words(words)` | `list[str]` | Stems of many words |
|
|
205
|
+
| `AmharicStemmer().stem(word)` | `str` | Stemmer object, `.stem()` and `.stem_words()` |
|
|
206
|
+
| `tokenize(text, *, morphemes=False, include_punct=True, mark_affixes=False)` | `list[str]` | Split text into tokens, optionally down to morphemes |
|
|
207
|
+
| `tokenize_spans(text, *, include_punct=True)` | `list[Token]` | Word-level tokens with `start`/`end` offsets and `kind` |
|
|
208
|
+
| `sentence_tokenize(text)` | `list[str]` | Split text into sentences |
|
|
209
|
+
| `analyze(word)` | `Analysis` | Prefixes, stem and suffixes of one word |
|
|
210
|
+
| `split_morphemes(word)` | `list[str]` | Morphemes of one word |
|
|
211
|
+
| `lemma(word)` | `str` | Dictionary form of the stem (`መጻሕፍትን → መጽሐፍ`) |
|
|
212
|
+
| `normalize_homophones(text)` | `str` | Collapse `ሐ ኀ → ሀ`, `ሠ → ሰ`, `ዐ → አ`, `ፀ → ጸ` (length-preserving) |
|
|
213
|
+
|
|
214
|
+
### `AmharicTokenizer`
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from amharic_segmenter import AmharicTokenizer
|
|
218
|
+
|
|
219
|
+
tok = AmharicTokenizer(
|
|
220
|
+
lexicon=["መምህር", "ጓደኛ"], # extra stems that may be split off
|
|
221
|
+
default_lexicon=True, # include the built-in seed lexicon
|
|
222
|
+
strategy="lexicon", # "lexicon" | "rules" | "none"
|
|
223
|
+
normalize=False, # collapse homophone letters first
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
tok.tokenize("መምህራችንን አየሁ።", morphemes=True)
|
|
227
|
+
tok.add_words(["ጋዜጣ"])
|
|
228
|
+
tok = AmharicTokenizer.from_file("my_words.txt") # one word per line, '#' comments
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| `strategy` | Behaviour |
|
|
232
|
+
|------------|-----------|
|
|
233
|
+
| `"lexicon"` *(default)* | Accept a split only if the stem is in the lexicon. High precision. |
|
|
234
|
+
| `"rules"` | Also accept unknown stems of at least `min_stem` letters. Higher recall, more false splits. |
|
|
235
|
+
| `"none"` | Never split words into morphemes. |
|
|
236
|
+
|
|
237
|
+
### `Analysis` and `Token`
|
|
238
|
+
|
|
239
|
+
- `Analysis(word, prefixes, stem, suffixes)` with `.morphemes` and `.is_split`
|
|
240
|
+
- `Token(text, start, end, kind)` where `kind` is `word`, `latin`, `number`, `punct` or `other`
|
|
241
|
+
|
|
242
|
+
> **Note:** morphemes are *underlying forms*. `ልጆች` becomes `ልጅ + ች` because the plural rule
|
|
243
|
+
> changes the stem's last letter, so joining the morphemes does not always give back the
|
|
244
|
+
> surface word. Use `tokenize_spans` when you need exact offsets.
|
|
245
|
+
|
|
246
|
+
## How it works
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
raw text
|
|
250
|
+
│
|
|
251
|
+
▼
|
|
252
|
+
┌──────────────────────────┐ Layer 1: rule-based, always on
|
|
253
|
+
│ sentences and word tokens │ Ethiopic punctuation, numerals, Latin, no loss
|
|
254
|
+
└─────────────┬────────────┘
|
|
255
|
+
│ (optional, morphemes=True)
|
|
256
|
+
▼
|
|
257
|
+
┌──────────────────────────┐ Layer 2: morphology
|
|
258
|
+
│ generate candidate splits │ prefixes ← stem → plural → possessive → ን → ና/ም
|
|
259
|
+
│ accept if stem is known │ lexicon check keeps precision high
|
|
260
|
+
└──────────────────────────┘
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The morphology layer works on the structure of the Ethiopic script itself: every letter has
|
|
264
|
+
seven vowel *orders*, and the plural and possessive rules are defined in terms of them
|
|
265
|
+
(`ሰው → ሰዎች`, `አገር → አገራችሁ`). The rules are listed with book references in
|
|
266
|
+
[`docs/GRAMMAR_RULES.md`](docs/GRAMMAR_RULES.md).
|
|
267
|
+
|
|
268
|
+
The rules are based on the grammar book *አማርኛ ሠዋሰው* (1963 E.C.).
|
|
269
|
+
|
|
270
|
+
## How it relates to other Amharic tools
|
|
271
|
+
|
|
272
|
+
| Project (PyPI) | Approach | Good for |
|
|
273
|
+
|----------------|----------|----------|
|
|
274
|
+
| **`amharic-segmenter`** (this package) | Grammar rules from a printed grammar book, NLTK-style API | Sentence and word splitting, morpheme splitting, stemming, explainable output |
|
|
275
|
+
| `amharic-tokenizer` | BPE-like merges learned from a corpus | Subword vocabularies for training language models |
|
|
276
|
+
| `amseg` | Rule-based sentence and word splitter, with normalizer and romanizer | Sentence/word splitting and transliteration |
|
|
277
|
+
|
|
278
|
+
They solve different problems and can be used together, for example `amharic-segmenter` for
|
|
279
|
+
sentences and stems and a trained BPE model for model vocabularies.
|
|
280
|
+
|
|
281
|
+
## Current scope and limitations
|
|
282
|
+
|
|
283
|
+
This is an early release (`0.1`, alpha). Please read this before using it in production:
|
|
284
|
+
|
|
285
|
+
- Only **printed pages 7-110** of the source book have been used so far (chapters 1-5 and the
|
|
286
|
+
start of chapter 6; the punctuation chapter is still missing). See [`docs/BOOK_COVERAGE.md`](docs/BOOK_COVERAGE.md) for exactly what is
|
|
287
|
+
and is not covered, e.g. the book's chapter on punctuation.
|
|
288
|
+
- Stemming is a **noun-oriented** suffix stripper, like a light English stemmer. Verbs are
|
|
289
|
+
left alone rather than guessed. Prefixes (`በ ከ ለ የ`) are only stripped when the rest is a
|
|
290
|
+
known word, so unknown words lose suffixes only. For unknown nouns it can pick the wrong stem when the
|
|
291
|
+
last letter is ambiguous (`ጋዜጦች` could come from `ጋዜጣ` or `ጋዜጥ`).
|
|
292
|
+
- Morphology covers **nouns and noun phrases**. **Verb morphology is not implemented yet.**
|
|
293
|
+
- The built-in lexicon is a small seed. Unknown stems are left unsplit in the default mode,
|
|
294
|
+
so coverage grows as the lexicon grows. Add your own words or send a pull request.
|
|
295
|
+
- Some forms are ambiguous without context (a final `ም` can be a conjunction or part of the
|
|
296
|
+
word, as in `ወንድም`). The lexicon resolves most cases, not all.
|
|
297
|
+
- Rules reflect one grammar book. Modern usage and dialects may differ; native-speaker
|
|
298
|
+
review is very welcome.
|
|
299
|
+
|
|
300
|
+
## Roadmap
|
|
301
|
+
|
|
302
|
+
- [ ] Punctuation rules from chapter 7 of the source book (pages still to be added)
|
|
303
|
+
- [ ] Verb morphology (agreement, tense, negation, relative `የ…`) from an additional source
|
|
304
|
+
- [ ] Larger open lexicon and a test corpus of annotated sentences
|
|
305
|
+
- [ ] Reduplicated plurals and internal plurals as rules
|
|
306
|
+
- [ ] Subword-vocabulary export for use with ML tokenizers
|
|
307
|
+
- [ ] Evaluation scripts against annotated Amharic data
|
|
308
|
+
|
|
309
|
+
## Contributing
|
|
310
|
+
|
|
311
|
+
Contributions are very welcome, especially from Amharic speakers and linguists. The easiest
|
|
312
|
+
first contribution is adding words to
|
|
313
|
+
[`src/amharic_segmenter/data/lexicon.txt`](src/amharic_segmenter/data/lexicon.txt).
|
|
314
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, rules for adding grammar rules, and the pull
|
|
315
|
+
request checklist.
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
git clone https://github.com/Alki45/amharic-segmenter.git
|
|
319
|
+
cd amharic-segmenter
|
|
320
|
+
pip install -e ".[dev]"
|
|
321
|
+
pytest
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Citation
|
|
325
|
+
|
|
326
|
+
If you use this package in research, please cite it:
|
|
327
|
+
|
|
328
|
+
```bibtex
|
|
329
|
+
@software{amharic_segmenter,
|
|
330
|
+
title = {amharic-segmenter: Sentence, word and morpheme tokenization for Amharic},
|
|
331
|
+
author = {Ali Kibret Muhamed},
|
|
332
|
+
year = {2026},
|
|
333
|
+
url = {https://github.com/Alki45/amharic-segmenter}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
[MIT](LICENSE). The grammar rules are re-implemented in original code; the source book is
|
|
340
|
+
credited above and its text is not redistributed.
|