stress-uk 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.
- stress_uk-0.1.0/LICENSE +21 -0
- stress_uk-0.1.0/PKG-INFO +142 -0
- stress_uk-0.1.0/README.md +121 -0
- stress_uk-0.1.0/pyproject.toml +35 -0
- stress_uk-0.1.0/setup.cfg +4 -0
- stress_uk-0.1.0/src/stress_uk/__init__.py +9 -0
- stress_uk-0.1.0/src/stress_uk/constants.py +3 -0
- stress_uk-0.1.0/src/stress_uk/data/train.jsonl +500 -0
- stress_uk-0.1.0/src/stress_uk/data/val.jsonl +60 -0
- stress_uk-0.1.0/src/stress_uk/data/vocab.json +45 -0
- stress_uk-0.1.0/src/stress_uk/data/word_patterns.json +1 -0
- stress_uk-0.1.0/src/stress_uk/data_utils.py +40 -0
- stress_uk-0.1.0/src/stress_uk/heteronyms.py +2069 -0
- stress_uk-0.1.0/src/stress_uk/hub.py +33 -0
- stress_uk-0.1.0/src/stress_uk/infer.py +176 -0
- stress_uk-0.1.0/src/stress_uk/model.py +83 -0
- stress_uk-0.1.0/src/stress_uk/train.py +263 -0
- stress_uk-0.1.0/src/stress_uk.egg-info/PKG-INFO +142 -0
- stress_uk-0.1.0/src/stress_uk.egg-info/SOURCES.txt +20 -0
- stress_uk-0.1.0/src/stress_uk.egg-info/dependency_links.txt +1 -0
- stress_uk-0.1.0/src/stress_uk.egg-info/requires.txt +5 -0
- stress_uk-0.1.0/src/stress_uk.egg-info/top_level.txt +1 -0
stress_uk-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 stress-uk contributors
|
|
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.
|
stress_uk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stress-uk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Розставляє наголоси (U+0301) в українському тексті - char-level BiLSTM + контекстний резолвер омографів
|
|
5
|
+
Author: stress-uk contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/MykhailoMS/stress-uk
|
|
8
|
+
Keywords: ukrainian,nlp,stress,accent,g2p,tts
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: torch>=2.0
|
|
17
|
+
Requires-Dist: huggingface_hub>=0.20
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest; extra == "dev"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# stress-uk
|
|
23
|
+
|
|
24
|
+
Розставляє наголоси в українському тексті символом **U+0301** (combining
|
|
25
|
+
acute accent), напр. `рука` → `рука́`. Гібрид: char-level нейромережа
|
|
26
|
+
(BiLSTM) для самого слова + rule-based шар для слів, де наголос залежить
|
|
27
|
+
від ЗНАЧЕННЯ в контексті (омографи, напр. за́мок-фортеця проти
|
|
28
|
+
замо́к-механізм).
|
|
29
|
+
|
|
30
|
+
## Встановлення
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install stress-uk
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Вага моделі (~9.5MB) НЕ входить у пакет — підвантажується автоматично з
|
|
37
|
+
HuggingFace Hub при першому використанні й кешується locally
|
|
38
|
+
(`~/.cache/huggingface/`), повторні запуски вже offline.
|
|
39
|
+
|
|
40
|
+
## Використання
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
from stress_uk import stressify_text, stressify
|
|
44
|
+
|
|
45
|
+
print(stressify_text("Привіт, як справи?"))
|
|
46
|
+
# Приві́т, я́к спра́ви?
|
|
47
|
+
|
|
48
|
+
print(stressify("електрифікація"))
|
|
49
|
+
# електрифіка́ція
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Для ансамблю кількох чекпоінтів або власної моделі:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from stress_uk import Stressifier
|
|
56
|
+
|
|
57
|
+
s = Stressifier(checkpoint_paths=["шлях/до/мого_чекпоінта.pt"])
|
|
58
|
+
print(s.stressify_text("Текст."))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Розстановка наголосу в омографах залежить від слів навколо (±8 слів, без
|
|
62
|
+
перетину пунктуації, ближчі слова важать більше) — словник сенсів і
|
|
63
|
+
контекстних тригерів у `stress_uk/heteronyms.py` можна редагувати/
|
|
64
|
+
розширювати напряму, формат самоописний
|
|
65
|
+
(`HETERONYMS: dict[слово, tuple[Sense, ...]]`).
|
|
66
|
+
|
|
67
|
+
## Тренування власної моделі
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pip install stress-uk
|
|
71
|
+
python -m stress_uk.train --epochs 2 # демо на маленькій вибірці, що йде з пакетом
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Формат даних — JSONL, один приклад на рядок:
|
|
75
|
+
```json
|
|
76
|
+
{"word": "рука", "stress": [0, 0, 0, 1]}
|
|
77
|
+
```
|
|
78
|
+
де `word` — слово малими буквами без наголосу, `stress` — бінарна маска
|
|
79
|
+
тієї самої довжини (1 на позиції наголошеної букви). За замовчуванням
|
|
80
|
+
використовується невелика ілюстративна вибірка з пакета (НЕ повний
|
|
81
|
+
навчальний набір) — передай `--data-dir шлях/до/своїх/даних` зі своїми
|
|
82
|
+
`train.jsonl`/`val.jsonl`/`vocab.json`/`word_patterns.json` того самого
|
|
83
|
+
формату (`word_patterns.json` потрібен лише для лагідної оцінки під час
|
|
84
|
+
тренування: `{слово: {"best": [...], "all": [[...]]}}`).
|
|
85
|
+
|
|
86
|
+
Звичайний прогін ділить дані на train/val і зупиняється сам через early
|
|
87
|
+
stopping, чекпоінт зберігається в `./models/`. Для фінального
|
|
88
|
+
прод-чекпоінта (тренування на train+val разом, без held-out оцінки) —
|
|
89
|
+
`--full-data --epochs N`, де `N` — номер найкращої епохи звичайного
|
|
90
|
+
прогону.
|
|
91
|
+
|
|
92
|
+
## Розробка/публікація
|
|
93
|
+
|
|
94
|
+
Якщо клонував репозиторій (не просто `pip install`):
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cd release
|
|
98
|
+
pip install -e .
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Інструкції з публікації нової версії моделі на HuggingFace Hub і пакета
|
|
102
|
+
на PyPI — `scripts/PUBLISHING.md`.
|
|
103
|
+
|
|
104
|
+
## Вимоги
|
|
105
|
+
|
|
106
|
+
`torch` + `huggingface_hub` (CPU достатньо — інференс на слово займає
|
|
107
|
+
частки мілісекунди, тренування на CPU теж практично, бо модель невелика).
|
|
108
|
+
|
|
109
|
+
## Історія розробки (коротко)
|
|
110
|
+
|
|
111
|
+
Базова модель — символьний (character-level) bidirectional LSTM:
|
|
112
|
+
embedding → 2-шаровий BiLSTM → лінійний шар, що для кожної букви слова
|
|
113
|
+
передбачає "ця буква наголошена чи ні" (multi-label, не softmax —
|
|
114
|
+
природно підтримує рідкі слова з кількома наголосами, зокрема дефісні
|
|
115
|
+
композити). Навчена на великому корпусі акцентованих українських
|
|
116
|
+
словоформ із кількох лексикографічних джерел, об'єднаних і узгоджених
|
|
117
|
+
між собою (конфліктні випадки — або очевидна друкарська помилка
|
|
118
|
+
джерела, яку виправляли голосуванням, або справжня граматична
|
|
119
|
+
омонімія, яку свідомо НЕ форсували до єдиної відповіді, а лишали
|
|
120
|
+
моделі вчити обидва варіанти з емпіричного розподілу).
|
|
121
|
+
|
|
122
|
+
Окремо — rule-based шар для омографів (слів, де те саме написання має
|
|
123
|
+
різний наголос залежно від значення): словник із кількох сотень
|
|
124
|
+
ручно/LLM-курованих записів, кожен запис — наголошені варіанти +
|
|
125
|
+
контекстні слова-тригери. Резолвер шукає тригери в ±8 словах навколо
|
|
126
|
+
цілі (з розривом контексту по будь-якій пунктуації) і зважує кандидатів
|
|
127
|
+
за відстанню (ближче слово — сильніший доказ), а не просто рахує
|
|
128
|
+
бінарний "матч/не матч".
|
|
129
|
+
|
|
130
|
+
Якість систематично перевірялась проти опублікованого незалежного
|
|
131
|
+
бенчмарку (Senyk et al., "Context-Aware Lexical Stress Prediction and
|
|
132
|
+
Phonemization for Ukrainian TTS Systems", UNLP 2025) — це дозволило
|
|
133
|
+
порівняти результат із кількома іншими опублікованими підходами на
|
|
134
|
+
тому самому тестовому наборі речень, а не лише на власних тестах.
|
|
135
|
+
Кілька раундів цільової діагностики (які саме слова й чому помиляються
|
|
136
|
+
на цьому бенчмарку, а не "сліпе" розширення словника) підняли
|
|
137
|
+
Macro-F1 на омографах із ~34% до ~49%, а також виявили і виправили
|
|
138
|
+
системний баг у підрахунку голосів між джерелами навчальних даних
|
|
139
|
+
(рідкісна граматична колізія могла переважити частотою формальних
|
|
140
|
+
словоформ значно частотніше в реальному вжитку слово). Фінальний
|
|
141
|
+
результат — найкращий за всіма п'ятьма метриками порівняння серед
|
|
142
|
+
усіх перевірених систем (включно з гібридними).
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# stress-uk
|
|
2
|
+
|
|
3
|
+
Розставляє наголоси в українському тексті символом **U+0301** (combining
|
|
4
|
+
acute accent), напр. `рука` → `рука́`. Гібрид: char-level нейромережа
|
|
5
|
+
(BiLSTM) для самого слова + rule-based шар для слів, де наголос залежить
|
|
6
|
+
від ЗНАЧЕННЯ в контексті (омографи, напр. за́мок-фортеця проти
|
|
7
|
+
замо́к-механізм).
|
|
8
|
+
|
|
9
|
+
## Встановлення
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install stress-uk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Вага моделі (~9.5MB) НЕ входить у пакет — підвантажується автоматично з
|
|
16
|
+
HuggingFace Hub при першому використанні й кешується locally
|
|
17
|
+
(`~/.cache/huggingface/`), повторні запуски вже offline.
|
|
18
|
+
|
|
19
|
+
## Використання
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from stress_uk import stressify_text, stressify
|
|
23
|
+
|
|
24
|
+
print(stressify_text("Привіт, як справи?"))
|
|
25
|
+
# Приві́т, я́к спра́ви?
|
|
26
|
+
|
|
27
|
+
print(stressify("електрифікація"))
|
|
28
|
+
# електрифіка́ція
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Для ансамблю кількох чекпоінтів або власної моделі:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from stress_uk import Stressifier
|
|
35
|
+
|
|
36
|
+
s = Stressifier(checkpoint_paths=["шлях/до/мого_чекпоінта.pt"])
|
|
37
|
+
print(s.stressify_text("Текст."))
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Розстановка наголосу в омографах залежить від слів навколо (±8 слів, без
|
|
41
|
+
перетину пунктуації, ближчі слова важать більше) — словник сенсів і
|
|
42
|
+
контекстних тригерів у `stress_uk/heteronyms.py` можна редагувати/
|
|
43
|
+
розширювати напряму, формат самоописний
|
|
44
|
+
(`HETERONYMS: dict[слово, tuple[Sense, ...]]`).
|
|
45
|
+
|
|
46
|
+
## Тренування власної моделі
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install stress-uk
|
|
50
|
+
python -m stress_uk.train --epochs 2 # демо на маленькій вибірці, що йде з пакетом
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Формат даних — JSONL, один приклад на рядок:
|
|
54
|
+
```json
|
|
55
|
+
{"word": "рука", "stress": [0, 0, 0, 1]}
|
|
56
|
+
```
|
|
57
|
+
де `word` — слово малими буквами без наголосу, `stress` — бінарна маска
|
|
58
|
+
тієї самої довжини (1 на позиції наголошеної букви). За замовчуванням
|
|
59
|
+
використовується невелика ілюстративна вибірка з пакета (НЕ повний
|
|
60
|
+
навчальний набір) — передай `--data-dir шлях/до/своїх/даних` зі своїми
|
|
61
|
+
`train.jsonl`/`val.jsonl`/`vocab.json`/`word_patterns.json` того самого
|
|
62
|
+
формату (`word_patterns.json` потрібен лише для лагідної оцінки під час
|
|
63
|
+
тренування: `{слово: {"best": [...], "all": [[...]]}}`).
|
|
64
|
+
|
|
65
|
+
Звичайний прогін ділить дані на train/val і зупиняється сам через early
|
|
66
|
+
stopping, чекпоінт зберігається в `./models/`. Для фінального
|
|
67
|
+
прод-чекпоінта (тренування на train+val разом, без held-out оцінки) —
|
|
68
|
+
`--full-data --epochs N`, де `N` — номер найкращої епохи звичайного
|
|
69
|
+
прогону.
|
|
70
|
+
|
|
71
|
+
## Розробка/публікація
|
|
72
|
+
|
|
73
|
+
Якщо клонував репозиторій (не просто `pip install`):
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cd release
|
|
77
|
+
pip install -e .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Інструкції з публікації нової версії моделі на HuggingFace Hub і пакета
|
|
81
|
+
на PyPI — `scripts/PUBLISHING.md`.
|
|
82
|
+
|
|
83
|
+
## Вимоги
|
|
84
|
+
|
|
85
|
+
`torch` + `huggingface_hub` (CPU достатньо — інференс на слово займає
|
|
86
|
+
частки мілісекунди, тренування на CPU теж практично, бо модель невелика).
|
|
87
|
+
|
|
88
|
+
## Історія розробки (коротко)
|
|
89
|
+
|
|
90
|
+
Базова модель — символьний (character-level) bidirectional LSTM:
|
|
91
|
+
embedding → 2-шаровий BiLSTM → лінійний шар, що для кожної букви слова
|
|
92
|
+
передбачає "ця буква наголошена чи ні" (multi-label, не softmax —
|
|
93
|
+
природно підтримує рідкі слова з кількома наголосами, зокрема дефісні
|
|
94
|
+
композити). Навчена на великому корпусі акцентованих українських
|
|
95
|
+
словоформ із кількох лексикографічних джерел, об'єднаних і узгоджених
|
|
96
|
+
між собою (конфліктні випадки — або очевидна друкарська помилка
|
|
97
|
+
джерела, яку виправляли голосуванням, або справжня граматична
|
|
98
|
+
омонімія, яку свідомо НЕ форсували до єдиної відповіді, а лишали
|
|
99
|
+
моделі вчити обидва варіанти з емпіричного розподілу).
|
|
100
|
+
|
|
101
|
+
Окремо — rule-based шар для омографів (слів, де те саме написання має
|
|
102
|
+
різний наголос залежно від значення): словник із кількох сотень
|
|
103
|
+
ручно/LLM-курованих записів, кожен запис — наголошені варіанти +
|
|
104
|
+
контекстні слова-тригери. Резолвер шукає тригери в ±8 словах навколо
|
|
105
|
+
цілі (з розривом контексту по будь-якій пунктуації) і зважує кандидатів
|
|
106
|
+
за відстанню (ближче слово — сильніший доказ), а не просто рахує
|
|
107
|
+
бінарний "матч/не матч".
|
|
108
|
+
|
|
109
|
+
Якість систематично перевірялась проти опублікованого незалежного
|
|
110
|
+
бенчмарку (Senyk et al., "Context-Aware Lexical Stress Prediction and
|
|
111
|
+
Phonemization for Ukrainian TTS Systems", UNLP 2025) — це дозволило
|
|
112
|
+
порівняти результат із кількома іншими опублікованими підходами на
|
|
113
|
+
тому самому тестовому наборі речень, а не лише на власних тестах.
|
|
114
|
+
Кілька раундів цільової діагностики (які саме слова й чому помиляються
|
|
115
|
+
на цьому бенчмарку, а не "сліпе" розширення словника) підняли
|
|
116
|
+
Macro-F1 на омографах із ~34% до ~49%, а також виявили і виправили
|
|
117
|
+
системний баг у підрахунку голосів між джерелами навчальних даних
|
|
118
|
+
(рідкісна граматична колізія могла переважити частотою формальних
|
|
119
|
+
словоформ значно частотніше в реальному вжитку слово). Фінальний
|
|
120
|
+
результат — найкращий за всіма п'ятьма метриками порівняння серед
|
|
121
|
+
усіх перевірених систем (включно з гібридними).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stress-uk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Розставляє наголоси (U+0301) в українському тексті - char-level BiLSTM + контекстний резолвер омографів"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "stress-uk contributors" }]
|
|
13
|
+
keywords = ["ukrainian", "nlp", "stress", "accent", "g2p", "tts"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Topic :: Text Processing :: Linguistic",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"torch>=2.0",
|
|
22
|
+
"huggingface_hub>=0.20",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = ["pytest"]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://github.com/MykhailoMS/stress-uk"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.packages.find]
|
|
32
|
+
where = ["src"]
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.package-data]
|
|
35
|
+
stress_uk = ["data/*.json", "data/*.jsonl"]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""stress-uk - розставляє наголоси в українському тексті символом U+0301.
|
|
2
|
+
|
|
3
|
+
from stress_uk import stressify_text
|
|
4
|
+
print(stressify_text("Привіт, як справи?"))
|
|
5
|
+
"""
|
|
6
|
+
from .infer import Stressifier, get_default_stressifier, stressify, stressify_text
|
|
7
|
+
|
|
8
|
+
__all__ = ["Stressifier", "get_default_stressifier", "stressify", "stressify_text"]
|
|
9
|
+
__version__ = "0.1.0"
|