Такие фрагменты текста естественного языка, как слова и предложения, могут иметь семантическое сходство между собой. На этой концепции основано большинство подсказок, и она реализуется с помощью класса NLEmbedding
фреймворка Natural Language.
Обработка естественного языка позволяет компьютерам понимать человеческий язык и взаимодействовать с ним. Она помогает обрабатывать и анализировать текстовые данные, извлекать значимую информацию и определять взаимосвязи между словами и фразами. Класс NLEmbedding
обеспечивает возможность структурированного отображения и анализа этих связей.
Эта возможность крайне важна для понимания и обработки текста. На ней основан целый ряд функций в экосистеме Apple:
- Она помогает Siri предлагать соответствующие приложения и действия
- Улучшает поиск в Spotlight, уточняя результаты
- Заметки предлагают связанный контент
- Почта предлагает релевантные ответы
- Понимая контекст вашего разговора в Сообщениях, улучшаются предсказания клавиатуры
В этой справочной статье мы рассмотрим класс NLEmbedding
, чтобы понять, как использовать его преимущества.
Вычисление семантического расстояния
Получив строку, NLEmbedding
создает окружение, заполненное другими фрагментами текста, которые имеют семантическое сходство.
Некоторые из них будут расположены дальше от этой строки, а другие — ближе. Это расстояние регулируется семантическим сходством противопоставленных строк. Чем меньше расстояние, тем больше сходство. NLEmbedding
представляет эту окружение — карту строк — в векторном пространстве, где строки — векторы.
import NaturalLanguage func getSemanticDistance(for word: String, in language: NLLanguage) { // 1. Create the embedding for the language the word belongs to if let embedding = NLEmbedding.wordEmbedding(for: language) { // 2. Find the neighbors for the word embedding.enumerateNeighbors(for: word, maximumCount: 10) { neighbor, distance in // 3. Acces the neighbor distance from the word print("\(neighbor): \(distance)") return true } } }
Чтобы приступить к реализации функций получения семантического расстояния с помощью NLEmbedding
, начните с импорта фреймворка NaturalLanguage
, а затем:
- Создайте экземпляр
NLEmbedding
и вызовите методwordEmbedding(for:)
, передав в качестве параметра язык обрабатываемой строки. Если он доступен, то вернет объектNLEmbedding
, в противном случае вернетnil
. - Вызовите метод
enumerateNeighbors(for:maximumCount:distanceType:using:)
, передайте строку, соседи которой вам нужны, и максимальное количество раз, которое нужно вызвать метод. Для каждого найденного соседа будет возвращено его расстояние до обрабатываемого слова.
Объект NLEmbedding
предоставляет доступ к нескольким полезным сведениям, таким как:
- количество слов в словаре, с помощью параметра
vocabularySize
; - язык текста в эмбеддинге слова, с помощью свойства
language
; - проверка наличия термина в словаре с помощью метода
contains(_:)
, а случае наличия запрос его вектора, представленного в виде массива double, с помощью методаvector(for:)
.
Класс NLEmbedding
также предоставляет метод для получения расстояния между одним словом и другим.
func semanticDistanceBetween(firstWord: String, and secondWord: String, for language: NLLanguage) { // 1. Create the embedding for the language the words belongs to if let embedding = NLEmbedding.wordEmbedding(for: language) { // 2. Calculate the distance between words let distance = embedding.distance(between: firstWord, and: secondWord) print("The distance between \(firstWord) and \(secondWord) is \(distance).") } }
Метод distance(between:and:distanceType:)
вычисляет расстояние между двумя строками в векторном пространстве. В качестве параметров он принимает:
- две строки, расстояние между которыми необходимо вычислить
DistanceType
, тип метрики расстояния, которую нужно использовать при определении сходства
Пример с представлением SwiftUI
Ниже приведен пример представления SwiftUI для поиска синонимов слова с использованием фреймворка Natural Language.
import NaturalLanguage struct SynonymsView: View { @State var text: String = "" @State var results: [String] = [] @State var errorMessage: String? = nil var body: some View { List { Section { TextEditor(text: $text) .frame(height: 100) .textFieldStyle(.plain) } Section { Button("Find synonyms") { self.findSynomys() } } if results.isEmpty { ContentUnavailableView( errorMessage != nil ? errorMessage! : "Text wasn't analyzed", systemImage: "doc.text.magnifyingglass" ) } else { Section { ForEach(results, id: \.self ) { item in Text("\(item)") } } } } } private func findSynomys() { do { try self.getSynonyms(word: text) } catch { errorMessage = "Error: \(error)" } } // Detecting the hypothethical languages the word belongs to private func getLanguages(of text: String) -> [Dictionary<NLLanguage,Double>.Element]? { let languageRecognizer = NLLanguageRecognizer() languageRecognizer.processString(text) let hypothesis = languageRecognizer .languageHypotheses(withMaximum: 5) .sorted(by: { $0.value > $1.value }) return hypothesis } // Looking for synonyms private func getSynonyms(word: String) throws { self.results.removeAll() guard let languages = getLanguages(of: word) else { throw ErrorMessage.languageNotRecognized } for language in languages { if let embedding = NLEmbedding.wordEmbedding(for: language.key) { guard embedding.contains(word.lowercased()) else { throw ErrorMessage.wordNotIncludedInEmbedding } embedding.enumerateNeighbors(for: word.lowercased(), maximumCount: 5) { neighbor, distance in self.results.append(neighbor) return true } } } guard (self.results.count > 0) else { throw ErrorMessage.noSynonymFound } } // Handling Errors enum ErrorMessage: Error, CustomStringConvertible { case noSynonymFound case wordNotIncludedInEmbedding case vocabularyNotAvailable case languageNotRecognized var description: String { switch self { case .noSynonymFound: "No synonym found" case .wordNotIncludedInEmbedding: "Word not included in the vocabulary" case .vocabularyNotAvailable: "Vocabulary not available" case .languageNotRecognized: "Language not recognized" } } } }
В приведенном выше примере пользователь вводит слово, и при нажатии кнопки с помощью фреймворка Natural Language происходит поиск его синонимов.
Кнопка «Find synonyms» запускает определение языка, к которому принадлежит слово, и, если он найден, проверяет наличие или отсутствие слова в словаре языка. Затем извлекается коллекция похожих слов, отображаемая в виде списка.
Если синонимы не найдены или слово не распознано, выдается сообщение об ошибке.