Мы наконец решили задачу омографов. Конечно, с рядом оговорок, куда без них. Получилось пресловутое приключение на 20 минут.

Несмотря на кажущуюся простоту (задача по сути является бинарной классификацией, число кейсов с тремя валидными вариантами ничтожно мало), задача является просто кладезем различных "мин замедленного действия" и типичных граблей в сфере машинного обучения. Да, задачу "ёфикации" (расстановка буквы ё там, где люди её поленились поставить) мы считаем частным случаем задачи простановки ударений и омографов.

Также мы опубликовали наше продуктовое решение для простановки ударений (в омографах в том числе) в рамках репозитория silero-stress и также напрямую через pypi. В ближайшее время добавим эту модель и обновим наши публичные модели синтеза и раскатим более мощную "большую" (тоже маленькую по современным меркам) версию модели в приватные сервисы и для клиентов. Также мы опубликовали бенчмарки качества и скорости публичных академических решений… и там всё очень неоднозначно.

Наливайте себе чай, садитесь поудобнее. Мы постараемся описать наш путь длиной в вечность без лишних подробностей.

Тут оглавление статьи c якорями

Что такое омографы?

Омографы (графические омонимы) — слова, совпадающие по написанию, но различные по звучанию и значению, например, «за́мок» и «замо́к». Если коротко, омографы это вот такие слова:

Что такое омографы?
Что такое омографы
Что такое омографы

То есть простыми словами - на письме слова пишутся одинаково (а у нас довольно "фонетический" алфавит, если знать ударение), но ударение меняет смысл слова. Зачастую особенно старые говорилки грешат "упоротыми" ударениями в стиле "кожаных ублюдков". На момент, когда последний раз это проверяли, к примеру Яндекс хорошо разбирал омографы, а Сбер - практически не разбирал, так что проблема всё ещё актуальна, даже для компаний без каких-либо ограничений на бюджеты.

Также существуют ещё и омофоны, омоформы и полные омонимы, но с точки зрения синтеза речи интерес представляют только омографы.

Почему по-настоящему решить задачу омографов сложно

Габен фигни не скажет
Габен фигни не скажет

Видя, какая задача предстоит, мы не торопились с решением и раза 3 или 4 заходили на повторный круг, это даже стало у нас своеобразным мемом, Габен не даст соврать.

Почему же эта задача сложная? Есть пять основных причин:

  • Сами омографы с первого взгляда кажутся задачей бинарной классификации. Есть условно два класса - «за́мок» и «замо́к». Но это только лишь кажется. На самом деле это задача, где классов N * 2, где N это число рассматриваемых слов. И тут легко наступить на типичные грабли мало понимающего в ML человека - рассматривать задачу просто как классификацию на 2 класса и целевой метрикой считать точность на корпусе в среднем. Почему так - ниже в отдельном разделе;

  • Сами омографы как правило (за минусом десятка сверхчастотных) довольно редкие слова... и второй вариант омографа как правило ещё на порядок реже встречается в тексте. Всего омографов где-то около 15 тысяч (30 тысяч вариантов), но хоть сколько-то частотных всего около 2.5 тысяч (5 тысяч вариантов);

  • В эпоху LLM и терабайтных публичных корпусов... не существует качественных публичных данных с омографами и решений для их простановки (почему текущие публичные решения ими не являются - будет в отдельной главе). Единственный хоть как-то подходящий корпус это подкорпуса НКРЯ, но он по сути как бы "приватизирован" Яндексом, доступ к нему получить проблематично, да и качество данных там очень посредственное на самом деле именно для задачи решения омографов (лучше вообще не использовать их для обучения);

  • Сама суть задачи идёт вразрез с развитием языка. Носителям языка и так всё "понятно" (как и с буквой ё), язык как правило развивается по принципу достаточности и языковой экономии. Наше морфологическое письмо достаточно оптимально решает задачу написать понятно для носителя языка... если конечно знать ударение;

  • Во многих популярных языках проблема омографов стоит гораздо менее остро. Например в английском они существуют (например слово accent - в зависимости от ударения или существительное или глагол), но их количество и встречаемость их на порядок ниже. Не будем погружаться в политику, но если проблемы "нет" в английском (там есть другие проблемы), значит внимания на неё будет на порядок меньше;

В сухом остатке получаем вроде бы простую задачу (с учётом современных инструментов), но с таким количеством нюансов, что тут легко пройти по полю граблей и не дойдя даже до середины объявить, что "получена точность 96% и задача решена". Но это не наш путь {тут обязательная ремарка про отношение шума к сигналу на Хабре}.

Сколько всего омографов и описание нашего датасета

Всего омографов около 15 тысяч (30 тысяч вариантов). Но если сделать банальную отсечку по частотности (оставить только омографы, использование которых позволяет покрыть 99% всех предложений), то останется порядка 5.6 тысяч омографов (~11 тысяч вариантов). Всего омографы можно разбить на такие категории:

  • Частотные омографы. Примеры: +уже / уж+е, вс+е / вс+ё;

  • Слова, которые формально являются омографами, но на практике допустимы и равнозначны оба варианта. Примеры: тв+орог / твор+ог, щ+авель / щав+ель, зв+онишь / звон+ишь (да простят нас учителя русского языка, но с точки зрения реальности, в которой мы живём, это допустимые варианты);

  • Слова, которые фигурировали в публичных списках омографов, но по факту омографами не являются или скорее всего вам никогда не встретятся. Примеры: +еды / ед+ы, жел+езами / желез+ами;

  • Слова, которые являются омографами, но они настолько редкие, что собирать качественные данные с ними проблематично и имеет мало смысла. Пример: т+акая (от слова "т+акать" - говорить "так-так-так") / так+ая;

В итоге мы выделили список из:

  • 5,630 слов омографов (~11.3 тыс. вариантов);

  • 3,473 слов, которые мы не считаем омографами и просто ставим в них одно ударение (которое нам больше нравится);

  • 2,157 слов, которые мы считаем омографами, и будем решать.

Тем не менее, процесс сбора данных для классификатора омографов с нуля - крайне трудозатратный и времязатратный. На данный момент из заявленных 2,157 слов мы сейчас поддерживаем 1,924 слова. Остальные вероятно получится добавить в следующих обновлениях. Всего сейчас в пайплайнах обработки данных находится суммарно где-то 3,500 слов на разных этапах.

Тут нужно сделать важную оговорку, что существуют "настоящие" омографы (например, з+ападу / запад+у, к+урим / кур+им, т+акая / так+ая), у которых настолько большая разница в частотности и настолько редкие "контрпримеры", что precision должен быть выше 95%, а иногда и выше 99%, чтобы оправдать использование модели. На практике такие слова проще переводить в категорию "слов, которые мы не считаем омографами".

Такое исключение имеет под собой и другое практическое основание. Учитывая, что в продакшене будет практически незаметна (если не вредна) классификация слов наподобие такая, нет никакого смысла "замедлять" свой алгоритм, увеличивая размер инпута для классификатора (скорее тут повышается "хрупкость" на пустом месте).

Из большого числа источников (включая ручную разметку с тройным покрытием), мы собрали следующий датасет:

  • Всего 122M предложений;

  • В среднем 60 тыс. предложений на омограф, медиана 11 тыс. предложений на омограф;

  • В среднем 30 тыс. предложений на вариант, медиана 3.2 тыс. предложений на вариант;

  • Гистограмма количества слов на один омограф:

Гистограмма количества слов на один омограф
Гистограмма количества слов на один омограф
Гистограмма количества слов на один омограф
  • Гистограмма количества слов на один вариант:

Гистограмма количества слов на один вариант
Гистограмма количества слов на один вариант
Гистограмма количества слов на один вариант

Нетрудно догадаться, что датасет является очень несбалансированным, как по количеству примеров на один омограф, так и по распределению вариантов внутри одного омографа. Отсюда сразу довольно очевидны первые "детские" грабли, на которые можно наступить при решении задачи. В качестве целевой метрики рассматривать только точность на всём датасете. Если максимизировать только эту метрику, можно получить решение … которое на большом количестве доменов бьётся … тупо выбором самого частотного варианта. Отчасти это чем-то похоже на предсказание того, что у человека никогда нет рака. Точность будет 99%, но вот пользы от такого классификатора будет мало.

Наглядный пример дисбаланса
Иллюстрация на тему классового дисбаланса. Можно получить accuracy 99% просто всегда выбирая только один класс.
Иллюстрация на тему классового дисбаланса. Можно получить accuracy 99% просто всегда выбирая только один класс.

Метрики качества

model

pr

re

f1

word_acc

total_acc

silero-stress

0.84

0.9

0.85

0.92

0.93

silero-stress-private

0.9

0.96

0.91

0.96

0.96

RUAccent-tiny2.1

0.65

0.61

0.56

0.69

0.78

RUAccent-turbo3.1

0.7

0.7

0.64

0.76

0.84

omogre

0.47

0.56

0.46

0.67

0.73

baseline

0.39

0.5

0.43

0.77

0.85

baseline - наивный "классификатор" омографов по принципу "всегда ставь самый частый вариант".
silero-stress-private - закрытая модель с более высоким качеством.

Методология подробно описана тут.

В целом тут нужно понимать только, что F1 независима от частотности слов и вариантов, и показывает точность классификации "в вакууме", а total_acc сильно зависит от точности на самых частых вариантах самых частых слов, и показывает точность в "реальных" продовых сценариях. В предельном случае, если дисбаланс составляет 100 к одному, можно получить точность 99% просто предсказывая всегда один вариант.

Гистограммы метрик по отдельным омографам
Гистограммы метрик по отдельным омографам
Гистограммы метрик по отдельным омографам

Метрики скорости работы

Методология и замечания
  • Замеры проводились на AMD Ryzen Threadripper 3960X, RTX 3090;

  • Замеры проводились на "среднестатистическом" тексте в ~400 символов, в котором есть два омографа. По сути, это один небольшой абзац произвольного текста. Десять омографов - уже скорее синтетический тест краевого случая. В реальных сценариях такой текст крайне редко будет попадаться;

  • silero-stress и omogre замерялись на одном потоке CPU;

  • RUAccent (как tiny2.1, так и turbo3.1) "из коробки" забивают целиком ВЕСЬ процессор в CPU-режиме, и ~6 потоков процессора в GPU-режиме.

Два омографа

Старинный каменный замок на вершине утёса молчаливо взирал на долину, храня вековые тайны. Мы поднимались по извилистой тропе, с каждым шагом погружаясь в прошлое. Воздух был напоён ароматом хвои и влажного камня. Наконец, мы достигли массивных врат. Дубовая дверь, окованная железом, оказалась заперта на ржавый замок. Он висел там, вероятно, не одно столетие, и у нас не было ни ключа, ни сил его сорвать.

Скорость на двух омографах
Скорость на двух омографах
Десять омографов

Старинный каменный замок на вершине утёса молчаливо взирал на замок, храня вековой замок. Мы поднимались по извилистому замку, с каждым шагом погружаясь в замок. Замок был напоён ароматом хвои и влажного замка. Наконец, мы достигли массивного замка. Дубовая дверь, окованная железом, оказалась заперта на ржавый замок. Замок висел там, вероятно, не одно столетие, и у нас не было ни ключа, ни сил его сорвать.

Скорость на 10 омографах
Скорость на 10 омографах

Общее впечатление от публичных решений

  • Публичные продуктовые решения отсутствуют как класс, публичные академические решения имеют очень много проблем, которые скорее делают их относительно малополезными в сравнении с наивными альтернативами (словарь, простановка более частотного варианта);

  • На CPU академические решения имеют скорее отрицательную полезность: omogre в силу очень низкой точности, ruaccent в силу очень низкой скорости (ударения + омографы на CPU могут работать дольше продуктового синтеза речи, и библиотека поедает ВСЕ доступные потоки процессора);

  • На GPU ruaccent уже не является полностью бесполезным, но тут роль начинает играет низкое качество самой архитектуры / самой библиотеки: она удаляет некоторую пунктуацию / пробелы без какой-либо очевидной логики (в документации на эту тему пусто), даже при запуске на GPU занимает до 6-8 потоков CPU … и даже по общей точности на датасете она проигрывает по точности наивному алгоритму (ставим более частотный вариант). Судя по публикациям в социальных сетях разработчиков - они фокусировались только на средней точности на всём датасете, и никак не работали с классовыми дисбалансом, точностью и полнотой;

  • Ещё когда-то давно был rustress, но он не поддерживается, и пару-тройку лет назад мы снимали метрики, и они были печальными.

Получается, что единственная библиотека с нетривиальными метриками выделяет непропорционально большие вычислительные ресурсы на вспомогательную задачу к синтезу речи. Такими темпами скоро будем решать задачи бинарной классификации с помощью нейросетей на 100 миллиардов параметров (шутка).

Запуск нашего решения

Наше решение запускается в 1 строчку путём установки из pypi или напрямую из репозитория через torch.hub (просто пулится с GitHub под капотом). Решение продуктовое, то есть:

  • Размер пакета ~50 мегабайт (архив весит около 30 мегабайт);

  • Решение работает на 1 потоке процессора с поддержкой AVX2 инструкций;

  • Выброшены все лишние зависимости, по сути есть зависимость только от PyTorch и стандартной библиотеки питона. То есть подойдут PyTorch +/- любой свежей версии, поддерживаются все версии питона начиная с 3.10;

  • Наше решение максимально пытается "сохранить" пунктуацию оригинального текста, не применяя к нему произвольные преобразования;

  • Простановка ударения в 1 слове занимает примерно 0.5 миллисекунд, простановка ударения в 1 абзаце (400 символов) с 2 омографами - порядка 30 миллисекунд;

Запуск через pypi:

!pip install -q silero-stress
from silero_stress import load_accentor
# the number of threads is set automatically to 1
accentor = load_accentor()
sample_sent = "Меня зовут Лева Королев. Я из готов. И я уже готов открыть все ваши замки любой сложности!"
print(accentor(sample_sent))
# Мен+я зов+ут Л+ёва Корол+ёв. +Я +из г+отов. +И +я уж+е гот+ов откр+ыть вс+е в+аши замк+и люб+ой сл+ожности!

Запуск через torch.hub (по сути скачивание репозитория):

import torch
torch.set_num_threads(1)
accentor = torch.hub.load(repo_or_dir='snakers4/silero-stress', model='silero_stress')
sample_sent = "Меня зовут Лева Королев. Я из готов. И я уже готов открыть все ваши замки любой сложности!"
print(accentor(sample_sent))
# Мен+я зов+ут Л+ёва Корол+ёв. +Я +из г+отов. +И +я уж+е гот+ов откр+ыть вс+е в+аши замк+и люб+ой сл+ожности!

Наше решение проставляет ударения, ударения в омографах, расставляет букву ё и также решает омографы … с буквой ё.

Пара слов про простановку ударений

Наша библиотека может не только расставлять ударения в омографах (и решать омографы с буквой ё), ставить букву ё, но и также она проставляет ударения в обычных словах.

При этом немаловажно, что точность расстановки ударений в обычных словах составляет 100%, с точностью до имеющегося у нас словаря. Размер словаря составляет порядка 4.1М слов.

С момента прошлого публичного релиза, мы вручную разметили ещё дополнительно 60к слов словаря, и добавили ~70k новых слов, включая некоторые имена собственные, неологизмы, и прочие, пропущенные нами ранее слова. На данный момент наш словарь составляет ~4.1M словоформ, из которых 130k были перепроверены вручную.

Также немаловажно, что по обычными словам есть небольшая генерализация, то есть точность простановки ударений в неизвестных словах и "придуманных" словах и топонимах составляет порядка 60-70%.

Вывод

Мы опубликовали библиотеку silero-stress для расстановки ударений в обычных словах и омографах, которая:

  • Расставляет ударения, решает омографы, ставит букву ё;

  • "Знает" порядка 4М русских слов и словоформ и порядка 2K омографов;

  • Простановка ударения в обычном 1 слове занимает где-то 0.5 ms, а в предложении на 400 символов с 2 омографами - порядка 30 ms;

  • Общий размер библиотеки составляет порядка 50 мегабайт (архив весит порядка 30 мегабайт), что является сжатием словарей и всех датасетов примерно в 400 раз;

  • Опубликована под популярной и простой лицензией (MIT);

  • Не содержит раздутого кода, лишних библиотек, гигабайтов академических артефактов;

  • Зависит только от стандартной библиотеки питона и работает на всех последних версиях PyTorch (используется как движок для ускорения нейросетей);

Ссылки

P.S. Если вы хотите, чтобы мы инкорпорировали ваши словари ударений и / или датасеты в наш инструмент - вы можете создать тикет в репозитории.

Комментарии (42)


  1. Ktilis
    10.10.2025 02:02

    Репозиторий проекта - https://github.com/snakers4/silero-stress;

    В ссылку тихо закралась точка с запятой...


    1. snakers4 Автор
      10.10.2025 02:02

      Поправил


  1. MadMarakuya
    10.10.2025 02:02

    Ого! Вы крутые!!


  1. Survtur
    10.10.2025 02:02

    Я сначала даже не понял, что за предложение "Я из готов". Мозг воспринял гОтов как готОв. Думал это специально какую-то нерусскую конструкцию подсунули.


    1. snakers4 Автор
      10.10.2025 02:02

      Ну это скорее такой небольшой рофл, что даже у такого сверхредкого слова, маленькая сетка научилась по грамматическому признаку отделять краткую форму прилагательного от существительного.

      Ну то есть решать грамматические омографы сильно проще, чем смысловые.


  1. RoasterToaster
    10.10.2025 02:02

    И как оно решит фразу

    "скоро мы все передохнем"


    1. snakers4 Автор
      10.10.2025 02:02

      ск+оро м+ы вс+ё перед+охнем.

      ск+оро м+ы вс+ё хорош+о передохн+ём.

      ск+оро м+ы вс+ё хорош+о передохн+ём +и пойд+ём оп+ять раб+отать.

      ск+оро м+ы вс+ё перед+охнем +и н+аши тел+а забер+ёт земл+я.

      Ну норм имхо, базу выдаёт


      1. sshmakov
        10.10.2025 02:02

        а где вариант "все" без ё?


      1. perfect_genius
        10.10.2025 02:02

        Это шутка или вы не заметили Ё в "всё"?


        1. Sontref
          10.10.2025 02:02

          Заметили. Метрики у нас хоть и хорошие, но не идеальные. Учитывая, что каждое слово формально - это отдельная задача классификации, метрики отдельно взятых слов могут отличаться заметно (см. гистограмму в разделе Метрики качества).

          Конкретно в кейсе именно со словосочетанием "мы все", модель действительно в большинстве случаев ставит "мы всё". Хотя в целом метрики пары "все/всё" неплохие.

          В будущих релизах мы этот кейс (как и другие, до которых дотянемся) постараемся исправить.


  1. Lecron
    10.10.2025 02:02

    Омографы также можно разделить на смысловые, пресловутый "замок" и морфологические — скалы, краю. С последними неплохо справляются морф-таггеры — например Natasha (быстрая) и ее исторический предок DeepPavlov (точнее, но медленно). Не сравнивали с ними? А еще есть сложнейшая задач классификации (не)совершенных глаголов — узнаю, признаюсь; и чуть попроще, но кмк ненамного, изъявительные/повелительные — цените, служите. Не проверяли качество отдельно по таким группам?

    В связи с вышесказанным, есть ли возможность разрешать неоднозначности только у указанных пользователем омографов? Естественно среди списка вами поддерживаемых. Чтобы появилась возможность использовать сильные стороны там, где справляется лучше, и отказаться от использования в областях, где не устроит.


    1. snakers4 Автор
      10.10.2025 02:02

      С последними неплохо справляются морф-таггеры — например Natasha (быстрая) и ее исторический предок DeepPavlov (точнее, но медленно). Не сравнивали с ними? 

      Не сравнивали, но использовали сигнал от них для дистилляции знаний. Но конкретно бить омографы на типы с точки зрения лингвистики для снятия метрик руки не дошли. Это хорошая идея, так как разобрать 5-6к слов из итогового списка на типы будет несложно. И будет такой стресс тест, способ нарезать данные перпендикулярно, когда будем катить новую модель.

      Чисто на правах наброса первое что в голову пришло:

      +Я узн+аю ег+о лиц+о +из т+ысячи.

      +Я н+е узна+ю ничег+о н+ового!

      Но тут оно довольно шаткое на таких кейсах. Шаг влево шаг вправо.

      В связи с вышесказанным, есть ли возможность разрешать неоднозначности только у указанных пользователем омографов? Естественно среди списка вами поддерживаемых. Чтобы появилась возможность использовать сильные стороны там, где справляется лучше, и отказаться от использования в областях, где не устроит.

      Ну есть два способа:

      • Не подавать такие предложения;

      • Подавать, но самому поставить ударение заранее как надо:

      sample_sent = "пр+изнаюсь, я кот!"

      print(accentor(sample_sent))

      пр+изнаюсь, +я к+от!

      И там, где проставлено, оно оставляет как было.


      1. Sontref
        10.10.2025 02:02

        Ну есть два способа:

        Вообще, есть третий, мб кому-то удобнее покажется.

        accentor = torch.hub.load(repo_or_dir='snakers4/silero-stress)

        homodict = accentor.homosolver.homodict

        Можно просто фильтрануть homodict, убрав из него ненужные слова. Поиск по нему как раз идёт.

        Опережая возможный вопрос - туда можно добавить свои. Но когда мы тестили, генерализация по омографам не из трейна была в районе 60%, то есть смысла в этом около нуля. Чисто на случай слов по типу "звонишь" / "творог", если хочется получать рандомное ударение, а не фиксированное.


      1. Lecron
        10.10.2025 02:02

        С обычными ударениями понятно. Нет — поставим, есть — пропустим. Но не помешают ли расставленные плюсы деомо-модели? sent = "Я с легкостью узнаю их л+ица ", если морфологию рд.ед/им.мн решил доверить другой библиотеке.

        Еще, предложу не ставить ударения в словах с одной гласной. Зачем "+я к+от"?

        В целом, отличное решение для "ленивых", просто и достаточно качественно. Намного лучше чем голый текст и другие простые решения. Но если подготовка текста для создания аудиокниг (для личного прослушивания) требует чуть больше перфекционизма, будут проблемы.

        Например немало омографов имен собственных. Начиная с явных Ангара́ и Саха́ра, которые вы наверное отслеживаете, заканчивая более специфичными Ба́совым, Бережно́го и даже среди имен встречается омография — бере(ё)зина, Бере́зина (фамилия), Березина́ (река). У меня таких более 400. Бывает надо поработать с аббревиатурами — КГБешник=кэгэбэ́шник или со словосочетаниями "под руку=по́друку", "не с кем=не́скем" (200 правил).

        Все это делается в программах словарной коррекции, на стадии после омографии, чтобы не помешать ей, но до расстановки ударений. То есть, как минимум, нужна возможность по отдельности снять омографию и проставить ударения.


        1. snakers4 Автор
          10.10.2025 02:02

          Но не помешают ли расставленные плюсы деомо-модели? sent = "Я с легкостью узнаю их л+ица ", если морфологию рд.ед/им.мн решил доверить другой библиотеке.

          Нашей - не помешают. Другой - не могу сказать.

          Еще, предложу не ставить ударения в словах с одной гласной. Зачем "+я к+от"?

          Ну убрать плюсик тут довольно рудиментарная операция, имхо.

          Например немало омографов имен собственных. Начиная с явных Ангара́ и Саха́ра, которые вы наверное отслеживаете, заканчивая более специфичными Ба́совым, Бережно́го и даже среди имен встречается омография — бере(ё)зина, Бере́зина (фамилия), Березина́ (река). У меня таких более 400. Бывает надо поработать с аббревиатурами — КГБешник=кэгэбэ́шник или со словосочетаниями "под руку=по́друку", "не с кем=не́скем" (200 правил).

          Ну тут по идее всё вписывается в вышеописанную логику, меняете на "правильное" прочтение, ставите ударение, библиотека игнорирует. Или правите сами пост-фактум.

          То есть, как минимум, нужна возможность по отдельности снять омографию и проставить ударения.

          Ну по логике можно конечно будет добавить флаги на включение / выключение правки буквы, омографов и простых ударений отдельно. Но вообще решаемых омографов буквально 5000 слов, тут имхо гораздо проще просто поверх менять в них ударение на нужное. Если у вас своё кастомное решение, то у вас уже настроена санация текста, и это по идее буквально пара абзацев кода будет на замену ударения в конкретных словах.


          1. Lecron
            10.10.2025 02:02

            Ну убрать плюсик тут довольно рудиментарная операция, имхо.

            Сразу уточню для чего это. Некоторые синтезаторы, вроде даже Google TTS в Android, не любят такие ударения. А библиотека будет использоваться не только с вашим синтезатором.

            В коде убрать, точнее, найти слова с одной гласной несложно, но для словарной коррекции, это достаточно нетривиально — таких одногласных слов довольно много, в том числе при неожиданном авторском словообразовании. Так может сразу убрать или не ставить в вашем коде? Это может даже на капельку увеличит скорость.

            Аналогично с "поверх менять в них ударение на нужное" при словарной коррекции. Нужно иметь две версии словаря или по два правила — для чистого текста и для неправильного ударения. Усложняется пайплайн. Впрочем, если плюсы вам не мешают, то библиотеку можно поставить в конец цепочки. Что не отменяет влияния правил меняющих сам текст ( "не с кем=не́скем" ).


            1. snakers4 Автор
              10.10.2025 02:02

              Впрочем, если плюсы вам не мешают, то библиотеку можно поставить в конец цепочки.

              Ну я в первом ответе собственно и предложил этот вариант, как самый простой.


          1. Lecron
            10.10.2025 02:02

            Нашей - не помешают. Другой - не могу сказать.

            Коллега, а вы меня обманули.

            Я взял еду на пикник -> Я взял ед+у на пикник

            Я вз+ял еду на пикник -> Я взял +еду на пикник

            То есть коррекция до деомографии недопустима.


            1. snakers4 Автор
              10.10.2025 02:02

              Скорее это баг в коде с этим конкретным словом (не в моделях), скорее всего ударение в начале слова,


              1. Lecron
                10.10.2025 02:02

                Я хотел показать влияние модификации контекста плюсами на распознавание формы. Раз наткнулся в отношении "еду", то и в любом другом омографе можно будет словить. Считать это багом или штатным поведением — на ваше усмотрение. Я скорее отношу к штатному. А вот удвоение ударений +ед+у это действительно баг.

                Также посмотрите, не ставите ли сами себе подножки. Не может ли собственная предыдущая коррекция, попасть в окно оценки следующих за ней омографов. Предыдущий оутпут попадает в инпут следующего. Такое может как помочь ("берегу озера", если контекст указал на "бе́регу", то "о́зера", если на "берегу́", то "озёра"), так и помешать. Сам стараюсь избегать такого seq2seq, но вы там лучше в языках разбираетесь.


            1. Sontref
              10.10.2025 02:02

              То есть коррекция до деомографии недопустима.

              Ну в какой-то степени сейчас так, да. Можно корректировать сами омографы, но не другие слова. Например, как вы писали выше, "доверить морфологию другой библиотеке". В таком случае, "перезаписывать" ударения в омографах наша не будет.

              В остальных случаях сейчас да, результат может измениться.

              В идеале пайплайн сейчас такой для вашего юзкейса, если я правильно понял:

              - корректируете ударения в омографах, если хочется;
              - запускаете наш классификатор омографов;
              - делаете свою коррекцию текста;
              - запускаете нашу расстановку обычных ударений.

              Если будет запрос, в следующих обновлениях мы постараемся сделать предикты более стабильными. Сейчас действительно шальная пунктуация чаще влияет на результат, чем хотелось бы. Заодно флаг для 1-сложных слов прокинем.


              1. snakers4 Автор
                10.10.2025 02:02

                Надо чуть больше санировать инпут. Плюс баг с регуляркой.


  1. AigizK
    10.10.2025 02:02

    Спасибо, особенно за маленький размер. Перевел один проект и освободил 3гига gpu


    1. snakers4 Автор
      10.10.2025 02:02

      Эту модель можно крутить и на CPU. Для 1-2 омографов на 1 предложение разница не прямо существенна.


      1. AigizK
        10.10.2025 02:02

        о, круто. а как этим управлять через silero_stress?


        1. Sontref
          10.10.2025 02:02

          Например, так. Добавим в документацию, забыли.

          accentor = load_accentor()
          accentor.to('cuda:0')
          accentor.to('cpu')


          1. snakers4 Автор
            10.10.2025 02:02

            del


          1. snakers4 Автор
            10.10.2025 02:02

            В идеале, конечно, оно должно принимать torch.device, но для начала думаю и стринга пойдёт.


      1. AigizK
        10.10.2025 02:02

        посмотрел, не хватает таких настроек:

        # CPU
        model = load_accentor(device='cpu')
        
        # GPU (первая видеокарта)
        model = load_accentor(device='cuda')
        # или
        model = load_accentor(device='cuda:0')
        
        # Вторая видеокарта (если есть)
        model = load_accentor(device='cuda:1')
        
        # Автоматический выбор (GPU если доступен, иначе CPU)
        model = load_accentor(device='auto')
        


        1. snakers4 Автор
          10.10.2025 02:02

          Имхо, лучше использовать общепринятую конвенцию из фреймворка, чем плодить параметр, но в документацию это конечно забыли добавить, да и изначально не планировали такой метод, его просто забыли удалить.


  1. perfect_genius
    10.10.2025 02:02

    Примеры: тв+орог / твор+огщ+авель / щав+ельзв+онишь / звон+ишь (да простят нас учителя русского языка, но с точки зрения реальности, в которой мы живём, это допустимые варианты);

    Филологи отмечают, что в русском ударение сейчас потихоньку смещается к началу слова:

    -звони́т -> зво́нит

    -подключён -> подклю́чен

    -новорождённый -> новоро́жденный

    -сбоёв -> сбо́ев

    -творо́г -> тво́рог

    Учителя русского знают, что язык живой и меняется. В этих словах тоже победят варианты с ударением на первую гласную.


    1. Sontref
      10.10.2025 02:02

      Тут открытый вопрос конечно, как с точки зрения акцентора расставлять ударения / ё в таких словах. Конкретных правил, насколько мне известно, на этот счёт нет (если ошибаюсь - буду рад узнать).

      На данный момент мы остановились на том, что просто в таких словах ставим одно фиксированное ударение. Был ещё вариант ставить случайным образом, но мы от него по итогу отказались. А по текстовому контексту определить конкретный вариант произношения в таких словах задачка вряд ли в принципе выполнимая. За исключением быть может конкретных случаев, где реплики нарочито с "говором" прописаны.


  1. perfect_genius
    10.10.2025 02:02

    В русском ещё есть пара (+1) слов, которые пишутся одинаково, но могут звучать по разному - "теста" и "Питер" (+стен). Замечаю, что в русском идёт переход с Е на Э где оно так звучит, поэтому они со временем должны исчезнуть, став "тестом/тэстом" и "Питером/Питэром". А "стен" считается устаревшим и пропадёт сам собой.


    1. snakers4 Автор
      10.10.2025 02:02

      Ох, тут есть ещё бездонная бездна иностранных слов, которые читаются не по правилам, типа шинель / панель / Нинель, мы в нее пока только заглядывали, но пока контакт не наладили. Это скорее имеет отношение уже к синтезу, но в каком-то смысле это похоже на постановку буквы ё.


      1. Lecron
        10.10.2025 02:02

        Возможно вы неправильно поняли. Дело не в измененной, а в контекстно измененной фонетике. Взвесьте килограмм теста и После тэста по математике. Утром придет Стэн и Даже у стен есть уши.


        1. perfect_genius
          10.10.2025 02:02

          А вечером Питэр посмотрит на Питер.


          1. snakers4 Автор
            10.10.2025 02:02

            Да не, я в всё понял, по сути вы просто привели пример ещё более экзотического "омографа", но у вас от смысла меняется звучание, а не ударение (хотя это близкие понятие). Есть нечто похожее в обычных омографах, это слова Один и одИн. Тоже разные языки как бы.

            Просто ваш пример мне напомнил про более частотный кейс с шинелями. Я к тому, что на самом деле бездна всего такого, что учесть крайне сложно.


            1. Lecron
              10.10.2025 02:02

              В ё-омографах — все/всё, отсек/отсёк, сел/сёл, — тоже меняется звучание, а не ударение. Только тут имеем смену звучания е-э, вместо е-ё. Какая вредная буква "е".


              1. snakers4 Автор
                10.10.2025 02:02

                Вы правы, но этот кейс более частотный . Просто ваш кейс более экзотический. Поэтому и перечисляю всякое редкое.


  1. DeXPeriX
    10.10.2025 02:02

    Спасибо огромное. Добавил в свою Читалку книг в голос. Стало прямо намного лучше.

    Я осознанно использую там предыдущую генерацию публичных моделей (третью), т.к. на слух реально слышу обрезанность четвёртой. И раньше имел только одну претензию - очень битые ударения. Сейчас всё ещё иногда бьёт, но реально стало прямо намного лучше. Silero-stress прям спаситель в данной ситуации.

    И отдельное спасибо за фокус на производительность. У меня читалка бежит на слабеньком NAS-хранилище. О большом процессоре или крутой видеокарте там и не мечтается. А читалку с Silero оставляю на ночь, а утром получаю книгу, начитанную приятным голосом. Xenia лучшая :-)


    1. snakers4 Автор
      10.10.2025 02:02

      Когда мы делали релиз 4й версии, мы увидели, что нашу говорилку используют мошенники при звонках, поэтому скрутили звучание.

      В ближайшее время мы планируем сделать релиз 5й версии, там будет ускорение синтеза ещё в несколько раз, повышение качества, и упаковка модели омографов прямо в модель синтеза речи.


      1. Lecron
        10.10.2025 02:02

        В последнее время синтезаторы, в том числе открытые, растут как грибы после дождя. Онлайн Яндекс и Edge; оффлайн Дмитрий/Светлана из edge-пула, в том числе с SAPI адаптером; новые модели Vosk (ver9 и 10), которые по метрикам приблизились к Яндекс/Edge и опередили вашу ver.3; синтезаторы с вообще клонированием голоса, раздолье для мошенников — VITS и базирующиеся на нем, F5, Chatterbox. И это только то что вспомнилось, из последнего обсуждаемого на TTS-форуме.

        Более того, найти вашу ver.3 мошенникам не представляет ни малейшей сложности. То есть можно было не улучшать качество, но в ухудшении точно смысла не много.