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.
@@ -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.
@@ -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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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"
@@ -0,0 +1,3 @@
1
+ """Базові мовні константи."""
2
+ ACUTE = "́"
3
+ UK_VOWELS = set("аеєиіїоуюя")