Привет! Действительно интересная часть программирования, если вы знаете разговорный язык и язык программирования, — это обработка естественного языка. С помощью НЛП вы можете создавать программы, которые могут понимать людей, и выполнять действия взамен!
Тем не менее, если вы смотрите на это, скорее всего, вы хотите сделать это с помощью JavaScript. Есть некоторые преимущества НЛП с JavaScript по сравнению с другими языками, такими как Python. Например, мы можем использовать TypeScript для поддержки строгой типизации.
Есть несколько проблем с НЛП с помощью JavaScript, но об этом эта серия! Без лишних слов, давайте начнем.
Какую библиотеку НЛП следует использовать?
Первый шаг к созданию программы, способной понимать человеческий язык, — это найти библиотеку, анализирующую язык. Если вы раньше искали JavaScript NLP, вы наверняка сталкивались с полезными библиотеками, такими как compromise.js или wink.js. Эти библиотеки впечатляют на стороне клиента: Penn Treebank оценивает их как ~87% и ~95%.
В этой серии я буду использовать менее известную библиотеку НЛП для JavaScript под названием FinNLP. Это лучшая библиотека, которую я смог найти, с ее POS-теггером, дающим около 96,43% с включенным сглаживанием.
Во-первых, давайте создадим проект для использования FinNLP. FinNLP поддерживает как Node.js, так и клиентский JavaScript с примерно одинаковой производительностью в обоих случаях.
Я буду использовать клиентский JavaScript в CodeSandbox. Если вы используете клиентский JavaScript, убедитесь, что у вас есть инструмент сборки, такой как Parcel и npm
. Если вы используете Node.js, все готово.
Во-первых, давайте добавим FinNLP, используя npm
npm i finnlp
Далее import
FinNLP (require()
, если вы используете Node.js)
import * as Fin from "finnlp"
Этот код импортирует весь FinNLP и помещает его в объект Fin. Теперь, чтобы на самом деле проанализировать текст:
import * as Fin from "finnlp"; var text = "Hey there, client-side JavaScript!"; var analyzedText = new Fin.Run(text);
Приведенный выше код создает новый объект Run
, содержащий объект, который выглядит следующим образом:
{ "raw": "Hey there, client-side JavaScript!", "intercepted": "Hey there, client-side JavaScript!", "sentences": [ { "sentence": "Hey there, client-side JavaScript!", "confidence": -9.166666666666666, "deps": [ { "label": "INTERJ", "type": "UH", "parent": 1 }, { "label": "ROOT", "type": "EX", "parent": -1 }, { "label": "PUNCT", "type": "PUNCT", "parent": 1 }, { "label": "EXT", "type": "NP", "parent": 4 }, { "label": "DEP", "type": "NP", "parent": 1 }, { "label": "PUNCT", "type": "PUNCT", "parent": 4 } ], "tags": [ "UH", "EX", ",", "NN", "NNP", "." ], "depsTree": { "left": [ { "left": [], "right": [], "tokens": [ "hey" ], "tags": [ "UH" ], "index": [ 0, 0 ], "type": "UH", "label": "INTERJ" } ], "right": [ { "left": [], "right": [], "tokens": [ "," ], "tags": [ "," ], "index": [ 2, 2 ], "type": "PUNCT", "label": "PUNCT" }, { "left": [], "right": [ { "left": [], "right": [], "tokens": [ "!" ], "tags": [ "." ], "index": [ 5, 5 ], "type": "PUNCT", "label": "PUNCT" } ], "tokens": [ "client-side", "JavaScript" ], "tags": [ "NN", "NNP" ], "index": [ 3, 4 ], "type": "NP", "label": "DEP" } ], "tokens": [ "there" ], "tags": [ "EX" ], "index": [ 1, 1 ], "type": "EX", "label": "ROOT" }, "tokens": [ "hey", "there", ",", "client-side", "JavaScript", "!" ], "lemmas": [ "hey", "there", ",", "client-side", "JavaScript", "!" ] } ] }
Вау! Это довольно большой объект. Что все это значит, и как мы даже используем это? Не волнуйтесь, мы все покроем.
Первые два свойства, raw
и intercepted
, довольно просты. raw
— это строка, которую вы передали в Fin.Run
, а intercepted
— это то, что Fin получает после запуска всех препроцессоров (мы также рассмотрим это позже).
Свойство sentences
содержит все предложения, которые нашел Fin. У каждого из них есть набор свойств, которые Fin создает для нас.
sentence
- необработанный текст этого предложения
confidence
- Уверенность Фина в анализе предложения (часто это абсурдное число, не беспокойтесь об этом прямо сейчас)
tags
- Массив (по порядку) POS-тегов, соответствующих tokens
(полный список можно посмотреть здесь).
tokens
— Массив (по порядку) токенов (["How","are","you","?"]
), соответствующих tags
lemmas
— Массив (по порядку) стержневых (съел -> съел) токенов, соответствующих tokens
deps
- Массив (не по порядку) зависимостей предложений
depsTree
- Дерево зависимостей предложения, точно такое же, как deps
, но в виде дерева
Ого, сколько информации! С чего начать?
Для нашей первой программы давайте создадим что-то, что может сказать, когда мы задаем вопрос «Wh-».
Во-первых, мы должны проверить, заканчивается ли первое предложение (вопрос) знаком «?»
import * as Fin from "finnlp"; var text = "Where is my phone?"; var analyzedText = new Fin.Run(text); var sentence = analyzedText.sentences[0]; var endsWithQuestionMark = sentence.tokens[sentence.tokens.length - 1] === "?";
Если мы проверим Спецификации POS для FinNLP, мы увидим, что
WDT
для which
that
whatever
whichever
WP
для who
whoever
whom
what
WP$
для whose
WRB
для how
where
На основе этого мы можем сделать детектор, который проверяет, соответствует ли первый тег в предложении одному из этих тегов.
var startsWithWH = ["WDT","WP","WP$","WRB"].includes(sentence.tags[0]) var isWHQuestion = endsWithQuestionMark && startsWithWH; console.log("Result:",isWHQuestion);
Вуаля! Результат:
Result: true
Поздравляю! Вы создали свою первую программу обработки естественного языка на JavaScript!