Перейти к основному содержимому

Как можно генерировать фентезийные имена через цепи Маркова

··745 слов·4 минут

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

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

Я гуглил, ничего толком не нашёл, и поэтому придумал, как приспособить цепь Маркова для подобной задачи.

Идея

Берём кучу текстов на нужном нам языке.

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

Дальше пишем небольшой манифест для выбранного языка:

  • что считается буквой;
  • что буквой не считается;
  • с каких букв может начинаться слово;
  • с каких букв слово начинаться не должно.

А дальше просто идём по тексту и собираем статистику.

Что анализируем

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

Второе, опционально: считаем среднюю длину слова в языке.

Можно упороться и ещё прикрутить анализ длины слова в зависимости от его состава, но частично эту задачу уже покрывает анализ вероятностей. Конец слова ведь тоже учитывается как возможное следующее состояние.

На Python такой анализ можно сделать простым использованием Counter.

Ну или можно написать свою реализацию, если хочется почувствовать себя человеком, который изобрёл collections.

Как выглядит модель

После анализа получается моделька.

По сути это просто словарь:

{
    "а": {
        "н": 42,
        "л": 17,
        "р": 9,
        "<END>": 6
    },
    "н": {
        "а": 31,
        "о": 14,
        "и": 12
    }
}

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

Потом частоты можно превратить в вероятности, а можно выбирать с весами прямо по частотам.

Как генерировать слово

Дальше по этой модельке можно начать создавать вымышленные слова.

Алгоритм примерно такой:

  1. Выбираем случайную стартовую букву.
  2. Смотрим, какие буквы могут следовать за ней.
  3. С учётом вероятностей выбираем следующую букву.
  4. Повторяем.
  5. Останавливаемся, если выпал конец слова или достигнута максимальная длина.

Получается не настоящее слово, но что-то похожее на слово из нужного языка или стиля.

Символ начала слова

Можно сделать чуть аккуратнее.

При сборе статистики добавить специальный символ начала слова, например:

<START>

И складывать в него вероятности букв, с которых начинаются слова в языке.

Тогда генератор будет стартовать не с любой буквы алфавита, а с тех букв, с которых слова реально начинаются.

Модель будет выглядеть примерно так:

{
    "<START>": {
        "а": 15,
        "б": 9,
        "м": 13
    },
    "а": {
        "н": 42,
        "л": 17,
        "<END>": 6
    }
}

Наверное, так будет достовернее.

Почему это должно работать

Цепь Маркова здесь не понимает язык.

Она не знает смысла слов, грамматики, морфологии и всей этой прекрасной лингвистической боли.

Она просто знает, что после одних символов чаще встречаются другие символы.

И этого уже достаточно, чтобы генерировать слова, которые выглядят “похожими” на исходный корпус.

Если скормить модели русские слова, она будет выдавать что-то русскоподобное.

Если скормить эльфийские имена из фентези, она начнёт выдавать всяких Наливалиэлей.

Если скормить имена из книг по типу Властелина Колец, на выходе появятся Тророподобные и Дуриноподобные имена.

Если скормить что-то совсем странное, ну… вы сами виноваты.

Так и живём

Я думаю, что всякие фентезийные генераторы имён работают примерно по такой схеме.

Наверняка им просто скармливают тысячи имён персонажей на заданную тематику, а они на основе этого создают всяких:

  • Миэлаульфов;
  • Бринготов;
  • Айнетанаминов.

Звучит достаточно фентезийно, чтобы кто-нибудь обязательно оказался древним королём, магом или хотя бы подозрительным NPC у таверны.

Что можно улучшить

Можно анализировать не одну предыдущую букву, а две или три.

Например, не просто:

а -> н

А так:

ма -> р

или:

про -> с

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

Ещё можно:

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

Итог

Получается довольно простая идея:

  1. Собрать корпус слов.
  2. Посчитать вероятности переходов между буквами.
  3. Добавить начало и конец слова.
  4. Генерировать новые слова случайным проходом по этой модели.

Не нейросеть, не магия, не драконья лингвистика. Просто статистика и немного рандома.

upd сильно позже

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

upd2: На 4 мая 2026 года статья с Хабра по какой-то причине удалена автором.

Так что вот вам ссылка на Web Archive, где статья доступна к прочтению.

Кирилл Белоусов
Автор
Кирилл Белоусов
Также известен как cyrmax. Пишу код, тестирую, автоматизирую инфраструктуру и помогаю делать цифровые продукты доступнее.