Как добавить Natural Language Processing в Minecraft

от автора

Создание хороших примеров по использованию NLP инструментария — не самая простая задача. Они получаются или слишком простыми, так что читателям кажется, что в реальных проектах не стоит даже использовать какие-то внешние системы для решения таких простых NLP задач, а можно и даже желательно все написать самому, или, если постараться, сделать примеры более жизненными, их бизнес логика становится чрезмерно сложной и отвлекает внимание от NLP части. 

Появление этого примера, использование NLP в Minecraft, оказалось самым естественным в истории проекта на данный момент. Запрос на его разработку возник у настоящих и самых преданных пользователей — детей одного из разработчиков, которым показалось сложным и даже скорее просто ненужным запоминать формат некоторых команд новой для них игры. 

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

Системы для сопряжения

Итак нам нужно состыковать две большие системы: 1. игру Minecraft и 2. диалоговую NLP систему на базе Apache NLPCraft.

1. Для разработчика приложений Minecraft это:

  • игровое клиентское приложение и 

  • сервер с возможностью добавления модификаций.  

В нашем случае мы будем работать с серверными модификациями.

2. NLP приложения построенные на базе Apache NLPCraft состоят из трех модулей:

  • NLP Server, выполняющий стандартный для всех моделей NLP процессинг. 

  • клиентские NLP модели, загруженные в Probe.  

  • клиентское бизнес приложение, общающееся через REST с NLP Server.  

Подробнее — по ссылке

Общая архитектура

Итоговая архитектура будет выглядеть следующим образом:

  • В режиме сетевой игры пользовательские запросы на естественном языке с клиентского приложения Minecraft отправляются на Minecraft Server.

  • NLPCraft mod, загруженный в Minecraft сервер, перехватывает эти запросы и перенаправляет их на NLPCraft Server. То есть mod в данном случае является клиентским приложением Apache NLPCraft системы. 

  • NLPCraft Server выполняет начальную обработку запроса и пересылает разобранный запрос на Probe с загруженной в него Minecraft NLP моделью. 

  • На Probe запрос окончательно разбирается, в Minecraft NLP модели находится соответствующий ему интент, в колбеке которого изначальный запрос пользователя транслируется в команду Minecraft. 

  • Probe возвращает результат обратно на NLPCraft Server, который в свою очередь возвращает ответ на Minecraft Server mod, который уже использует эту сконвертированную команду для передачи в Minecraft Server Engine вместо изначальной.

Звучит чуть запутано, но на самом деле все очень просто 🙂 

Таким образом от нас требуется:

  • Создать NLP модель для перевода запросов на естественном языке в команды понятные Minecraft серверу. 

  • Запрограммировать Minecraft mod, то есть NLPcraft клиент.

В зависимости от поставленных целей над первой задачей вы можете провести достаточно продолжительное время. Вам придется отлаживать правильность вашей модели, расширять список поддерживаемых Minecraft команд, развивать точность распознавания запросов и т.д. Все зависит от того, что вы в итоге планируете получить. Просто запустить существующие примеры — задача максимум на пару часов, создание же собственного коммерческого NLP транслятора команд потребует от вас гораздо больших усилий. 

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

Minecraft mod

Основная логика nlpcraft-minecraft mod написанного на java приведена ниже:

@SubscribeEvent public void onCommandEvent(CommandEvent event) {   String cmd = event.getParseResults().getReader().getString();    String convCmd = '/' + askProbe(cmd).state.resBody;    event.setCanceled(true);    server.getCommandManager().handleCommand(     server.getCommandSource(), convCmd   ); }

Краткое пояснение:

  • Сначала мы перехватываем запрос на естественном языке, поступивший на Minecraft Server от пользователя.   

  • Далее пересылаем запрос на NLPCraft Server, который после обработки и коммуникаций с моделью на Probe возвращает разобранную и переведенную в формат Minecraft Server команду. 

  • Полученную сконвертированную команду мы направляем в Minecraft Server Engine вместо изначальной.

Пример: 

Запрос “make a box of sand with the size of 2, 10 meters in front of me” переведется в команду “/execute at @p positioned ~0 ~0 ~10 rotated 0 0 run fill ^-1 ^0 ^-1 ^0 ^0 ^0 minecraft:sand”.

Метод askProbe это обычный REST вызов к NLP server. 

private NCResponse askProbe(String txt) throws Exception {   AskParams params = new AskParams();    params.mdlId = "nlpcraft.minecraft.ex";   params.txt = txt.startsWith("/") ? txt.substring(1) : txt;    if (this.token == null)     this.token = signin();    params.acsTok = this.token;    return post("ask/sync", GSON.toJson(params), NCResponse.class); } 

В методе post реализована логика отправки http запроса, опустим ее. Опущен также также ряд несущественных для понимания общих принципов работы деталей, но основная логика данного mod думаю ясна. 

Подытоживая:

  • Полный код mod для обзора доступен по ссылке

  • Собирать его удобнее через основной проект (потребуется gradle)

  • Если хочется попробовать в деле только описанную ниже NLP часть, а с mod неохота даже возиться — мы собрали его под java 8, вот ссылка на jar, просто поместите его папку mods инсталлированного Minecraft Server. По ссылке приведено описание процесса инсталляции и конфигурации.    

Minecraft NLP Model

Вторая и более важная часть нашей работы — это создание NLP модели, ответственной за перевод запросов с естественного языка в формат команд Minecraft Server. 

В примере поддерживаются всего четыре Minecraft команды, то есть сконфигурированы четыре интента Apache NLPCraft.

Ниже разберем самую простую команду — команду установки времени. Весь процесс работы с системой расписан подробно в статье по ссылке.

1. Определим элементы, которые мы должны найти в тексте для этого типа запроса. Для работы с командой выставления времени нам потребуется определить два элемента: тип команды и значение времени. В примере используется встроенный механизм определения элементов — через модель синонимов, но при желании, для поиска элементов, необходимых для разбора пользовательского запроса, вы можете воспользоваться и нейросетями.

Определим элемент “time:action“, тип команды:

- id: time:action  synonyms:    - "{set|make} {it|_}"

Определим несколько элементов группы “time”:

... - id: afternoon  groups:    - time  synonyms:    - "{{early|late|_} afternoon|noon|midday}" - id: evening  groups:    - time  synonyms:    - "{early|_} {evening}" ...

2. Создадим интент для данной команды:

intents: - "intent=timeIntent      term={tok_id() == 'time:action'}?      term(arg)={has(tok_groups(), 'time')}"

В нем мы указали, что для срабатывания интента timeIntent в запросе должны встретиться следующие элементы: один опциональный с идентификатором “time:action” и один обязательный группы “time”. 

3. Напишем колбек для данного интента:

@NCIntentRef("timeIntent") @NCIntentSample(    "set time to evening",    "now is evening",    "night",    "it's midnight" ) fun onTimeMatch(   ctx: NCIntentMatch, @NCIntentTerm("arg") tok: NCToken ): NCResult {   checkAmbiguous(ctx)    val time: Int = when (tok.id) {      "morning" -> 23000      "day" -> 1000      "afternoon" -> 6000      "evening" -> 12000      "night" -> 12000      "midnight" -> 18000      else -> null    } ?: throw NCException("Invalid token id")     return NCResult.text("time set $time") }
  • NCIntentRef — имя интента. 

  • NCIntentSample — примеры текстовых запросов, использующиеся в частности в процессе автоматического тестирования модели.  

  • Колбек onTimeMatch извлекает данные из элемента группы “time”, переводит их в числовые значения формата Minecraft и формирует в итоге готовую к использованию Minecraft команду. 

Так, например, пользовательский запрос “set time to the evening” будет преобразован в Minecraft команду “time set 12000”. Таким образом конечный пользователь избавлен от необходимости запоминать формат команд Minecraft и может управлять процессом игры на естественном языке. 

Модель создана на языке kotlin, но это может быть java или любой другой java based язык программирования, такой как scala, groovy и т.д.

На старт

Итак все готово, проверим работоспособность всех модулей на одном компьютере. 

  1. Запускам Apache NLPCraft Server. 

  2. Запускаем Apache NLPCraft Probe с Minecraft Example моделью.

  3. Запускаем Minecraft Server с добавленным модом.  

  4. Запускам игру, выбираем сетевую версию, настраиваемся на localhost.

  5. Вводим команду “set the day”, см. первый скрин, левый нижний угол. 

  6. Экран посветлел! 

Probe выдал разобранный запрос:

И информацию о сработавшем интенте:

Minecraft сервер отреагировал логом: 

[NCMinecraftExampleMod]: Command ‘/set the day’ was converted to ‘/time set 1000’

Все отработало как мы и ожидали.  

Полный код примера доступен по ссылке.

Заключение 

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

ссылка на оригинал статьи https://habr.com/ru/post/561230/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *