Spell_correction.md 28 KB

Исправление орфографии

Исправление орфографии, также известное как:

  • Автокоррекция
  • Коррекция текста
  • Исправление орфографических ошибок
  • Допуск опечаток
  • "Возможно, вы имели в виду?"

и так далее, это функциональность программного обеспечения, которая предлагает альтернативы или автоматически исправляет введённый вами текст. Концепция исправления набранного текста восходит к 1960-м годам, когда учёный-компьютерщик Уоррен Тейтельман, который также изобрёл команду "отменить", представил философию вычислений под названием D.W.I.M., или "Делай Что Я Имею в Виду". Вместо того чтобы программировать компьютеры на приём только идеально отформатированных инструкций, Тейтельман утверждал, что их следует программировать на распознавание очевидных ошибок.

Первым известным продуктом, предоставившим функциональность исправления орфографии, был Microsoft Word 6.0, выпущенный в 1993 году.

Как это работает

Есть несколько способов реализации исправления орфографии, но важно отметить, что не существует чисто программного способа с достойным качеством преобразовать вашу опечатку "ipone" в "iphone". В основном, необходима система, основанная на наборе данных. Набор данных может быть:

  • Словарём правильно написанных слов, который, в свою очередь, может быть:
    • Основан на ваших реальных данных. Идея здесь в том, что по большей части орфография в словаре, составленном из ваших данных, правильная, и система пытается найти слово, наиболее похожее на введённое (мы скоро обсудим, как это можно сделать с помощью Manticore).
    • Или он может быть основан на внешнем словаре, не связанном с вашими данными. Проблема, которая может здесь возникнуть, заключается в том, что ваши данные и внешний словарь могут слишком сильно отличаться: некоторые слова могут отсутствовать в словаре, в то время как другие могут отсутствовать в ваших данных.
  • Не только основанным на словаре, но и учитывающим контекст, например, "white ber" будет исправлено на "white bear", а "dark ber" — на "dark beer". Контекстом может быть не только соседнее слово в вашем запросе, но и ваше местоположение, время суток, грамматика текущего предложения (чтобы изменить "there" на "their" или нет), история ваших поисков и практически любые другие факторы, которые могут повлиять на ваше намерение.
  • Ещё один классический подход — использовать предыдущие поисковые запросы в качестве набора данных для исправления орфографии. Это ещё более активно используется в функциональности автодополнения, но также имеет смысл и для автокоррекции. Идея в том, что пользователи в основном правы в орфографии, поэтому мы можем использовать слова из истории их поиска в качестве источника истины, даже если у нас нет этих слов в наших документах или мы не используем внешний словарь. Учёт контекста также возможен здесь.

Manticore предоставляет опцию нечёткого поиска и команды CALL QSUGGEST и CALL SUGGEST, которые могут быть использованы для целей автоматического исправления орфографии.

Нечёткий поиск

Функция нечёткого поиска позволяет осуществлять более гибкое сопоставление, учитывая небольшие вариации или опечатки в поисковом запросе. Она работает аналогично обычному оператору SQL SELECT или JSON-запросу /search, но предоставляет дополнительные параметры для управления поведением нечёткого сопоставления.

ПРИМЕЧАНИЕ: Опция fuzzy требует наличия Manticore Buddy. Если она не работает, убедитесь, что Buddy установлен.

ПРИМЕЧАНИЕ: Опция fuzzy недоступна для многозапросов.

Общий синтаксис

SQL

SELECT
  ...
  MATCH('...')
  ...
  OPTION fuzzy={0|1}
  [, distance=N]
  [, preserve={0|1}]
  [, layouts='{be,bg,br,ch,de,dk,es,fr,uk,gr,it,no,pt,ru,se,ua,us}']
}

Примечание: При проведении нечёткого поиска через SQL, в выражении MATCH не должно быть никаких полнотекстовых операторов, кроме оператора поиска по фразе, и оно должно содержать только слова, которые вы намерены сопоставить.

SQL:
SELECT * FROM mytable WHERE MATCH('someting') OPTION fuzzy=1, layouts='us,ua', distance=2;

Пример более сложного запроса нечёткого поиска с дополнительными фильтрами:

SELECT * FROM mytable WHERE MATCH('someting') OPTION fuzzy=1 AND (category='books' AND price < 20);
POST /search
{
  "table": "test",
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "*": "ghbdtn"
          }
        }
      ]
    }
  },
  "options": {
    "fuzzy": true,
    "layouts": ["us", "ru"],
    "distance": 2
  }
}
+------+-------------+
| id   | content     |
+------+-------------+
|    1 | something   |
|    2 | some thing  |
+------+-------------+
2 rows in set (0.00 sec)
SELECT * FROM mytable WHERE MATCH('hello wrld') OPTION fuzzy=1, preserve=1;
POST /search
{
  "table": "test",
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "*": "hello wrld"
          }
        }
      ]
    }
  },
  "options": {
    "fuzzy": true,
    "preserve": 1
  }
}
+------+-------------+
| id   | content     |
+------+-------------+
|    1 | hello wrld  |
|    2 | hello world |
+------+-------------+
2 rows in set (0.00 sec)

JSON

POST /search
{
  "table": "table_name",
  "query": {
    <full-text query>
  },
  "options": {
    "fuzzy": {true|false}
    [,"layouts": ["be","bg","br","ch","de","dk","es","fr","uk","gr","it","no","pt","ru","se","ua","us"]]
    [,"distance": N]
    [,"preserve": {0|1}]
  }
}

Примечание: Если вы используете query_string, имейте в виду, что он не поддерживает полнотекстовые операторы, кроме оператора поиска по фразе. Строка запроса должна состоять исключительно из слов, которые вы хотите сопоставить.

Опции

  • fuzzy: Включает или выключает нечёткий поиск.
  • distance: Устанавливает расстояние Левенштейна для сопоставления. По умолчанию 2.
  • preserve: 0 или 1 (по умолчанию: 0). При установке в 1 сохраняет слова, не имеющие нечётких совпадений, в результатах поиска (например, "hello wrld" возвращает и "hello wrld", и "hello world"). При установке в 0 возвращает только слова с успешными нечёткими совпадениями (например, "hello wrld" возвращает только "hello world"). Особенно полезно для сохранения коротких слов или имён собственных, которых может не быть в Manticore Search.
  • layouts: Раскладки клавиатуры для обнаружения ошибок ввода, вызванных несоответствием раскладки клавиатуры (например, ввод "ghbdtn" вместо "привет" при использовании неправильной раскладки). Manticore сравнивает позиции символов в разных раскладках, чтобы предложить исправления. Требуется как минимум 2 раскладки для эффективного обнаружения несоответствий. По умолчанию раскладки не используются. Используйте пустую строку '' (SQL) или массив [] (JSON), чтобы отключить это. Поддерживаемые раскладки включают:
    • be - Бельгийская раскладка AZERTY
    • bg - Стандартная болгарская раскладка
    • br - Бразильская раскладка QWERTY
    • ch - Швейцарская раскладка QWERTZ
    • de - Немецкая раскладка QWERTZ
    • dk - Датская раскладка QWERTY
    • es - Испанская раскладка QWERTY
    • fr - Французская раскладка AZERTY
    • uk - Британская раскладка QWERTY
    • gr - Греческая раскладка QWERTY
    • it - Итальянская раскладка QWERTY
    • no - Норвежская раскладка QWERTY
    • pt - Португальская раскладка QWERTY
    • ru - Русская раскладка JCUKEN
    • se - Шведская раскладка QWERTY
    • ua - Украинская раскладка JCUKEN
    • us - Американская раскладка QWERTY

Ссылки

CALL QSUGGEST, CALL SUGGEST

Обе команды доступны через SQL и поддерживают запросы к локальным (plain и real-time) и распределённым таблицам. Синтаксис следующий:

CALL QSUGGEST(<word or words>, <table name> [,options])
CALL SUGGEST(<word or words>, <table name> [,options])

options: N as option_name[, M as another_option, ...]

Эти команды предоставляют все предложения из словаря для заданного слова. Они работают только с таблицами, у которых включено инфиксирование и используется dict=keywords. Они возвращают предлагаемые ключевые слова, расстояние Левенштейна между предложенным и исходным ключевым словом, а также статистику документов по предложенному ключевому слову.

Если первый параметр содержит несколько слов, то:

  • CALL QSUGGEST вернёт предложения только для последнего слова, игнорируя остальные.
  • CALL SUGGEST вернёт предложения только для первого слова.

Это единственное различие между ними. Поддерживается несколько опций для настройки:

| Опция | Описание | По умолчанию | | - | - | - | | limit | Возвращает N лучших совпадений | 5 | | max_edits | Оставляет только слова из словаря с расстоянием Левенштейна меньше или равным N | 4 | | result_stats | Предоставляет расстояние Левенштейна и количество документов для найденных слов | 1 (включено) | | delta_len | Оставляет только слова из словаря с разницей в длине меньше N | 3 | | max_matches | Количество совпадений для сохранения | 25 | | reject | Отклонённые слова — это совпадения, которые не лучше уже находящихся в очереди совпадений. Они помещаются в очередь отклонённых, которая сбрасывается, если слово всё же может попасть в очередь совпадений. Этот параметр определяет размер очереди отклонённых (как reject*max(max_matched,limit)). Если очередь отклонённых заполнена, движок прекращает поиск потенциальных совпадений | 4 | | result_line | альтернативный режим отображения данных, возвращающий все предложения, расстояния и количество документов каждое в отдельной строке | 0 | | non_char | не пропускать слова из словаря с неалфавитными символами | 0 (пропускать такие слова) | | sentence | Возвращает исходное предложение с заменой последнего слова на подобранное. | 0 (не возвращать полное предложение) | | force_bigrams | Принудительно использовать биграммы (n-граммы из 2 символов) вместо триграмм для всех длин слов, что может улучшить сопоставление для слов с ошибками транспозиции | 0 (использовать триграммы для слов ≥6 символов) | | search_mode | Уточняет предложения, выполняя поиск по индексу. Принимает 'phrase' для точного соответствия фразы или 'words' для соответствия по модели "мешок слов". При включении добавляет столбец found_docs, показывающий количество документов, и пересортировывает результаты по убыванию found_docs, затем по возрастанию distance. | N/A (отключено по умолчанию) |

Чтобы показать, как это работает, создадим таблицу и добавим в неё несколько документов.

create table products(title text) min_infix_len='2';
insert into products values (0,'Crossbody Bag with Tassel'), (0,'microfiber sheet set'), (0,'Pet Hair Remover Glove');
Пример с одним словом

Как видно, слово с опечаткой "crossbUdy" исправляется на "crossbody". По умолчанию CALL SUGGEST/QSUGGEST возвращают:

  • distance — расстояние Левенштейна, означающее, сколько правок потребовалось, чтобы преобразовать заданное слово в предложенное
  • docs — количество документов, содержащих предложенное слово

Чтобы отключить отображение этой статистики, можно использовать опцию 0 as result_stats.

Пример:
call suggest('crossbudy', 'products');
+-----------+----------+------+
| suggest   | distance | docs |
+-----------+----------+------+
| crossbody | 1        | 1    |
+-----------+----------+------+
CALL SUGGEST берёт только первое слово

Если первый параметр — не одно слово, а несколько, то CALL SUGGEST вернёт предложения только для первого слова.

Пример:
call suggest('bagg with tasel', 'products');
+---------+----------+------+
| suggest | distance | docs |
+---------+----------+------+
| bag     | 1        | 1    |
+---------+----------+------+
CALL QSUGGEST берёт только последнее слово

Если первый параметр — не одно слово, а несколько, то CALL SUGGEST вернёт предложения только для последнего слова.

Пример:
CALL QSUGGEST('bagg with tasel', 'products');
+---------+----------+------+
| suggest | distance | docs |
+---------+----------+------+
| tassel  | 1        | 1    |
+---------+----------+------+

Добавление 1 as sentence заставляет CALL QSUGGEST возвращать всё предложение с исправленным последним словом.

CALL QSUGGEST('bag with tasel', 'products', 1 as sentence);
+-------------------+----------+------+
| suggest           | distance | docs |
+-------------------+----------+------+
| bag with tassel   | 1        | 1    |
+-------------------+----------+------+
Другой режим отображения

Опция 1 as result_line меняет способ отображения предложений в выводе. Вместо показа каждого предложения в отдельной строке, она отображает все предложения, расстояния и количество документов в одной строке. Вот пример, демонстрирующий это:

Пример:
CALL QSUGGEST('bagg with tasel', 'products', 1 as result_line);
+----------+--------+
| name     | value  |
+----------+--------+
| suggests | tassel |
| distance | 1      |
| docs     | 1      |
+----------+--------+
Использование force_bigrams для лучшей обработки транспозиций

Опция force_bigrams может помочь со словами, содержащими ошибки транспозиции, например, "ipohne" и "iphone". Используя биграммы вместо триграмм, алгоритм может лучше обрабатывать перестановки символов.

Пример:
CALL SUGGEST('ipohne', 'products', 1 as force_bigrams);
+--------+----------+------+
| suggest| distance | docs |
+--------+----------+------+
| iphone | 2        | 1    |
+--------+----------+------+
Уточнение предложений с помощью search_mode

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

Опция принимает два значения:

  • 'phrase' - Выполняет поиск точных фраз. Например, при предложении "bag with tassel" выполняется поиск точной фразы "bag with tassel" и подсчитываются документы, содержащие эти слова как смежную фразу.
  • 'words' - Выполняет поиск по модели "мешок слов". Например, при предложении "bag with tassel" выполняется поиск bag with tassel (без кавычек) и подсчитываются документы, содержащие все эти слова, независимо от порядка или наличия других слов между ними.

ПРИМЕЧАНИЕ: Опция search_mode работает только тогда, когда включен режим sentence (т.е. когда ввод содержит несколько слов). Для запросов из одного слова search_mode игнорируется.

ПРИМЕЧАНИЕ: Соображения производительности: Каждый кандидат на предложение запускает отдельный поисковый запрос к индексу. Если вам нужно оценить много кандидатов, рассмотрите использование меньшего значения limit, чтобы сократить количество выполняемых поисков.

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

Пример с фразовым соответствием:
CALL QSUGGEST('bag with tasel', 'products', 1 as sentence, 'phrase' as search_mode);
+-------------------+----------+------+-------------+
| suggest           | distance | docs | found_docs  |
+-------------------+----------+------+-------------+
| bag with tassel   | 1        | 13   | 10          |
| bag with tazer    | 2        | 27   | 3           |
+-------------------+----------+------+-------------+
Пример сравнения фразового соответствия и соответствия по словам:
-- With phrase matching: finds exact phrases only
CALL QSUGGEST('test carp', 'products', 1 as sentence, 'phrase' as search_mode);

-- With words matching: finds documents with all words regardless of order
CALL QSUGGEST('test carp', 'products', 1 as sentence, 'words' as search_mode);
-- Phrase mode results:
+----------------+----------+------+-------------+
| suggest        | distance | docs | found_docs  |
+----------------+----------+------+-------------+
| test car       | 1        | 17   | 5           |
| test carpet    | 2        | 19   | 4           |
+----------------+----------+------+-------------+

-- Words mode results (more matches for "test carpet" due to word separation):
+----------------+----------+------+-------------+
| suggest        | distance | docs | found_docs  |
+----------------+----------+------+-------------+
| test carpet    | 2        | 19   | 19          |
| test car       | 1        | 17   | 5           |
+----------------+----------+------+-------------+

Понимание разницы:

  • Фразовое соответствие ('phrase'): Ищет точные последовательности. Запрос "test carpet" соответствует только документам, где эти слова встречаются вместе в точном порядке (например, "test carpet cleaning" соответствует, а "test the carpet" или "carpet test" - нет).
  • Соответствие по модели "мешок слов" ('words'): Ищет наличие всех слов в документе, порядок не имеет значения. Запрос test carpet соответствует любому документу, содержащему оба слова "test" и "carpet" где угодно (например, "test the carpet", "test red carpet", "carpet test" - все соответствуют).

Демонстрация

Пример CALL SUGGEST{.scale-0.5}