?

Log in

No account? Create an account

Компьютерная лингвистика

Новостная лента www.solarix.ru

Previous Entry Share
Расширение поддержки русского языка в Duckling
kelijah
Duckling - библиотека от Facebook, позволяющая извлекать из текста структурированные данные. Например, с ее помощью из строки "смартфон стоит двенадцать тысяч рублей" можно выделить числительное "двенадцать тысяч". Попутно для извлеченной информации делается некоторая нормализация, то есть получим представление в числовом виде "12000".

Помимо других альтернативных инструментов, Duckling можно использовать в фреймворке чатботов RASA для NER.

Чтобы "пощупать" этот экстрактор, нужно скачать репозиторий, скомпилировать, запустить rest-сервис. После чего через браузер или curl можно прокачивать тексты и видеть json-результаты.

Попробуем:


git clone https://github.com/facebook/duckling
cd duckling
stack init
stack build
stack exec duckling-example-exe



Команда stack это тулинг для хаскеля, на котором собственно и написан утенок. Сборка первый раз будет идти долго, так как будут скачиваться пакеты зависимостей, перечисленные в duckling.cabal.

Последняя команда запускает rest-сервис на https://github.com/facebook/duckling. Чтобы увидеть результаты разбора, можно в новой консоли выполнить:


curl -v -XPOST http://0.0.0.0:8000/parse -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" --data 'locale=ru_GB&text=три'



Почему locale=ru_GB, а не ru_RU? На фоне остальных нюансов это лишь мелкая загадка, стоит это воспринимать просто как данность. Результат работы будет такой:


[{"body":"три",
"start":0,
"value":{"value":3,"type":"value"},
"end":3,
"dim":"number",
"latent":false}]



Видим, что в обработанной строке найдена подстрока, распознанная как "число" - об этом говорит поле "dim":"number". Помимо посимвольной привязки этой подстроки вернулось также нормализованное значение "value": 3

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


curl -v -XPOST http://0.0.0.0:8000/parse -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" --data 'locale=ru_GB&text=тремя'



Упс - результат разбора пустой. Утенок не знает падежные формы русских числительных :(

Извлечение происходит с помощью набора правил, написанных на хаскеле. Не самый плохой язык для парсинга, хотя и явно не мейнстрим. Рекомендую перед написанием своих правил немного освоиться с синтаксисом. Достаточным будет, например, вот этот курс. Читать можно прямо в браузере, если не нужен именно pdf, достаточно открывать страницы в этой папке. Исходники на хаскеле местами будут напоминать птичий язык из-за постоянного использования пунктуационных символов в качестве основных синтаксических маркеров, но до какого-нибудь APL хаскелю, к счастью, далеко, так что нескольких часов будет достаточно для освоения.

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

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


ruleInteger3 = Rule
{ name = "integer 2"
, pattern =
[ regex "(двумя|двум|двух|два|две|двоих|двоими|двоим|двое|пара|паре|парой|пару|парочку|парочка|парочкой)"
]
, prod = \_ -> integer 2
}



Ну и помните, что регулярки коварны, опечатки в паттернах никак не ловятся компилятором хаскеля. И если, например, написать вместо | двойную ||, то полчаса игры в гляделки по коду гарантированы.

Кстати, чтобы упростить расширение, рекомендую с самого начала не лениться и использовать тесты, благо вся инфраструктура уже есть. Во-первых, идем в исходник Corpus.hs, где собраны тесты для проверки разбора русскоязычных числительных. По аналогии с имеющимися тестами вписываем там свои, например:


, examples (NumeralValue (400))
["четыреста", "четырехсот", "четырёхсот", "четыремстам", "четырёмстам", "четырехстах", "четырёхстах"]



Далее, после любых изменений в правилах запускаем тесты командой в консоли:


stack test



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


curl -v -XPOST http://0.0.0.0:8000/parse -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" --data 'locale=ru_GB&text=триста миллионов семнадцать тысяч четыреста'



дает:


[{"body":"триста миллионов семнадцать тысяч четыреста","start":0,"value":{"value":300017400,"type":"value"},"end":43,"dim":"number","latent":false}]



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