Back to Manticoresearch

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

manual/russian/Searching/Spell_correction.md

25.9.027.7 KB
Original Source

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

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

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

и так далее, это функциональность программного обеспечения, которая предлагает альтернативы или автоматически исправляет введённый вами текст. Концепция исправления набранного текста восходит к 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

<!-- example Fuzzy_Search_SQL -->
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 не должно быть никаких полнотекстовых операторов, кроме оператора поиска по фразе, и оно должно содержать только слова, которые вы намерены сопоставить.

<!-- intro -->
SQL:
<!-- request SQL -->
sql
SELECT * FROM mytable WHERE MATCH('someting') OPTION fuzzy=1, layouts='us,ua', distance=2;
<!-- request SQL with additional filters -->

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

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

JSON

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

Ссылки

  • <a href="https://github.manticoresearch.com/manticoresoftware/manticoresearch?query=fature&filters%5Bcomment%5D%5B%5D=28798446&filters%5Bcommon%5D%5Brepo_id%5D%5B%5D=95614931&sort=&search=keyword-search-fuzzy-layouts">Это демо</a> демонстрирует функциональность нечёткого поиска: {.scale-0.7}
  • Пост в блоге о Нечётком поиске и автодополнении - https://manticoresearch.com/blog/new-fuzzy-search-and-autocomplete/

CALL QSUGGEST, CALL SUGGEST

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

sql
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Оставляет только слова из словаря с расстоянием Левенштейна меньше или равным N4
result_statsПредоставляет расстояние Левенштейна и количество документов для найденных слов1 (включено)
delta_lenОставляет только слова из словаря с разницей в длине меньше N3
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 (отключено по умолчанию)

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

sql
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');
<!-- example single -->
Пример с одним словом

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

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

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

<!-- intro -->
Пример:
<!-- request Example -->
sql
call suggest('crossbudy', 'products');
<!-- response Example -->
sql
+-----------+----------+------+
| suggest   | distance | docs |
+-----------+----------+------+
| crossbody | 1        | 1    |
+-----------+----------+------+
<!-- end --> <!-- example first -->
CALL SUGGEST берёт только первое слово

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

<!-- intro -->
Пример:
<!-- request Example -->
sql
call suggest('bagg with tasel', 'products');
<!-- response Example -->
sql
+---------+----------+------+
| suggest | distance | docs |
+---------+----------+------+
| bag     | 1        | 1    |
+---------+----------+------+
<!-- end --> <!-- example last -->
CALL QSUGGEST берёт только последнее слово

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

<!-- intro -->
Пример:
<!-- request Example -->
sql
CALL QSUGGEST('bagg with tasel', 'products');
<!-- response Example -->
sql
+---------+----------+------+
| suggest | distance | docs |
+---------+----------+------+
| tassel  | 1        | 1    |
+---------+----------+------+
<!-- end --> <!-- example last2 -->

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

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

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

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

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

<!-- intro -->
Пример:
<!-- request Example -->
sql
CALL SUGGEST('ipohne', 'products', 1 as force_bigrams);
<!-- response Example -->
sql
+--------+----------+------+
| suggest| distance | docs |
+--------+----------+------+
| iphone | 2        | 1    |
+--------+----------+------+
<!-- end -->
Уточнение предложений с помощью 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.

<!-- intro -->
Пример с фразовым соответствием:
<!-- request Example -->
sql
CALL QSUGGEST('bag with tasel', 'products', 1 as sentence, 'phrase' as search_mode);
<!-- response Example -->
sql
+-------------------+----------+------+-------------+
| suggest           | distance | docs | found_docs  |
+-------------------+----------+------+-------------+
| bag with tassel   | 1        | 13   | 10          |
| bag with tazer    | 2        | 27   | 3           |
+-------------------+----------+------+-------------+
<!-- end --> <!-- intro -->
Пример сравнения фразового соответствия и соответствия по словам:
<!-- request Example -->
sql
-- 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);
<!-- response Example -->
sql
-- 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           |
+----------------+----------+------+-------------+
<!-- end -->

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

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

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

{.scale-0.5}

<!-- proofread -->