Сопоставления «фраза-фильтр»: семантический поиск для фильтров товаров
В этой статье объясняется, как мы создаём и расширяем сопоставления «фраза-фильтр», которые обеспечивают работу нашей системы извлечения фильтров. Эти сопоставления связывают фразы на естественном языке из поисковых запросов со структурированными фильтрами товаров.
Проблема: извлечение фильтров из естественного языка
Когда пользователи ищут «mini pc with 16gb ram», нам нужно извлечь:
-
Форм-фактор: Mini PC
-
Основная память: 16
Но пользователи выражают ту же цель разными способами:
-
"16gb ram mini pc"
-
"mini computer 16 gb memory"
-
"small pc 16gb"
-
"compact desktop with 16 gigs"
Нам нужна система, которая сопоставляет все эти варианты фраз с правильными значениями фильтров.
Двухэтапный процесс
Мы создаём сопоставления фраз в два этапа:
- Шаг 3a: создание базовых фраз из характеристик товаров с помощью перестановок и правил, специфичных для характеристик
- Шаг 4: расширение с помощью семантической близости на основе эмбеддингов
Этот гибридный подход сочетает точность, основанную на правилах, с семантической гибкостью.
Шаг 3a: генерация базовых фраз
Метаданные характеристик
Каждая характеристика товара имеет метаданные в последовательности характеристик:
-
Заголовок: название категории (например, "Processing" для характеристик процессора)
-
Единица измерения: единица измерения (например, "GB" для памяти, "GHz" для частоты)
Эти метаданные управляют генерацией фраз.
Генерация на основе перестановок
Для каждого значения характеристики мы генерируем все перестановки:
-
Заголовок: "processor"
-
Ключ характеристики: "series"
-
Значение: "i5"
-
Единица измерения: (нет для series)
Это даёт:
-
"processor series i5"
-
"series processor i5"
-
"i5 processor series"
-
"i5 series processor"
-
"processor i5"
-
"series i5"
-
"i5"
Все перестановки гарантируют, что мы сопоставляем запросы независимо от порядка слов.
Комбинации «значение + единица измерения»
Для характеристик с единицами измерения (память, хранилище, частота) мы генерируем варианты с пробелом и без пробела:
-
"16 gb" (с пробелом)
-
"16gb" (без пробела)
Они комбинируются с другими компонентами:
-
"16gb ram"
-
"ram 16gb"
-
"processor 16gb"
Правила добавления суффикса «порт»
Для характеристик подключения (USB, HDMI, DisplayPort) мы добавляем суффиксы, связанные с портами:
-
"usb port"
-
"usb ports"
-
"2 usb ports"
-
"hdmi port"
Это позволяет сопоставлять запросы вида "mini pc with 2 hdmi ports".
Правила для конкретных характеристик
Для каждого типа характеристик есть свои правила генерации фраз:
Серия процессора (i3, i5, N-series):
-
Обозначения процессоров Core порождают варианты: название производителя, бренд ядра, комбинированные формы
-
Процессоры N-series (N100 и т.д.) создают аналогичные комбинации шаблонов
-
Каждый вариант генерирует несколько перестановок со словом "processor"
Основная память:
-
Числовые значения генерируют варианты с "GB" с пробелом и без пробела ("16gb", "16 gb")
-
Автоматически добавляются уточнители "ram" и "memory" ("16gb memory", "16 gb ram")
SSD-хранилище:
-
Числовые значения генерируют варианты с "GB" ("512gb", "512 gb")
-
Значения ≥ 1024 автоматически генерируют варианты с "TB" (например, 1024GB → 1TB)
-
Автоматически добавляются уточнители "ssd" и "storage" ("512gb ssd", "512 gb storage")
Форм-фактор:
-
Mini PC → несколько вариантов, включая форму без пробела
-
All-in-One → "all in one", "aio", сокращённые формы
-
Thin Client → варианты с пробелом и без пробела
-
Industrial PC → сокращённая и полная формы
Поколение:
- Числовые значения поколений превращаются в: "12th gen", "12th generation", "gen 12"
Ядра:
-
2 → "dual core"
-
4 → "quad core"
-
6 → "hexa core"
-
8 → "octa core"
-
Все генерируют варианты "[n] core processor"
Ethernet:
-
"1000" → ["gigabit ethernet", "gbe", "1gbps"]
-
"2500" → ["2.5gbe", "2.5 gigabit", "2.5gbps"]
Операционная система:
-
"Windows 11" → ["windows", "windows 11", "win 11"]
-
"Ubuntu" → ["linux", "ubuntu"]
-
"FreeDOS" → ["freedos", "no os", "without os"]
Белый список для самостоятельных значений
Только отдельные характеристики допускают сопоставление самостоятельных значений, чтобы избежать ложных совпадений:
-
Серия: "i3", "i5", "N100" (но не отдельные буквы)
-
Модель процессора: "N100", "1335U"
-
Операционная система: "Windows", "Linux", "Ubuntu"
-
Поколение: "12th", "13th", "14th"
-
Бренд процессора: "Intel", "ARM"
Например, "2" не должно соответствовать "2 cores", если запрос — "2 hdmi ports". Проверка длины предотвращает сопоставление отдельных букв или очень коротких неоднозначных значений в качестве самостоятельных. Характеристики с явными единицами измерения, такие как Ethernet или порты, генерируют самостоятельные комбинации только при указании единицы измерения.
Предотвращение коллизий
Значения памяти и хранилища пересекаются (обе имеют 64, 128, 256 и т.д.). На шаге 4 применяются правила диапазонов значений для устранения неоднозначности:
-
≤ 64 ГБ: основная память (RAM)
-
≥ 128 ГБ: SSD-хранилище
-
Диапазон 65-127 ГБ: пропускается (неоднозначно)
Фразы с явными уточнителями ("ram"/"memory" или "ssd"/"storage") переопределяют это правило и могут соответствовать любому значению.
Кроме того, на этапе разрешения коллизий с помощью постобработки исключаются неопределённые общие термины, которые соответствуют слишком многим несвязанным фильтрам: такие термины, как "connectivity", "audio", "display", "processor" и "physical", создают слишком много неоднозначности между различными аспектами.
Шаг 4: семантическое расширение
Извлечение N-грамм
Мы извлекаем частотные фразы из реальных поисковых запросов — от отдельных слов (1-граммы, например "mini") до более длинных последовательностей (до 6-грамм, например "mini pc with 16gb ram ssd"). Сохраняются только фразы, встречающиеся не менее 3 раз. Такой подход к фильтрации снижает уровень шума, сохраняя при этом реальные языковые паттерны пользователей.
Генерация поисковых текстов для фильтров
Для каждого значения фильтра мы генерируем поисковые тексты:
Основная память: 16:
-
"16gb ram memory"
-
"16 main memory"
-
"main memory 16"
SSD-хранилище: 512:
-
"512gb storage ssd"
-
"512 ssd storage"
-
"ssd storage 512"
Эти поисковые тексты представляют фильтр в пространстве эмбеддингов.
Эмбеддинги и сопоставление
Мы преобразуем и фразы запросов, и поисковые тексты фильтров в эмбеддинги, а затем вычисляем косинусную близость между ними. Фразы с оценкой близости выше заданного порога добавляются в сопоставление этого фильтра.
Ручные стартовые фразы
Перед расширением мы добавляем высоконадёжные ручные стартовые фразы:
"Series:i5": [
"i5",
"core i5",
"intel i5",
"intel core i5",
"i5 processor",
"cpu i5",
]
Эти стартовые фразы представляют ключевые выражения, которые, как мы знаем, корректны для каждого фильтра. Включая их с максимальными оценками близости, мы направляем алгоритм расширения на поиск связанных фраз со схожим значением. Эти стартовые фразы всегда получают близость 1.0 и направляют расширение.
Инкрементальные эмбеддинги
Мы кэшируем эмбеддинги и для фраз, и для поисковых текстов фильтров. Когда поступают новые запросы:
- Загружаем существующие эмбеддинги
- Создаём эмбеддинги только для новых фраз
- Добавляем их в кэш
Это позволяет избежать повторного создания эмбеддингов для неизменённых данных. Подробнее см. Стратегия эмбеддингов.
Разрешение коллизий
После завершения сопоставления по близости мы разрешаем коллизии между фильтрами памяти и хранилища:
Разрешение на основе чисел:
-
Для неоднозначных фраз, содержащих числа: если значение фразы ≤ 64, сохраняем только для памяти; если > 64 — только для хранилища
-
Это предотвращает соответствие "16gb" фильтрам SSD-хранилища и "512gb" фильтрам памяти
Явные уточнители переопределяют правила:
-
Фразы с ключевыми словами "ram", "memory", "cpu", "processor" → только память
-
Фразы с ключевыми словами "ssd", "storage", "disk", "nvme", "drive" → только хранилище
-
Пример: "processor 8gb" соответствует памяти, несмотря на числовое значение
Неопределённые термины:
- Удаляем фразы типа "connectivity", "audio", "display", которые соответствуют нескольким несвязанным фильтрам
Формат вывода
Итоговые сопоставления сортируются по близости (сначала наибольшие), затем по длине (сначала самые короткие):
{
"Main Memory:16": [
{"phrase": "16gb ram", "similarity": 1.0},
# ... (implementation details omitted)
Интеграция с извлечением фильтров
Эти сопоставления обеспечивают работу алгоритма извлечения фильтров:
- Поступает запрос: "mini pc with 16gb ram"
- Извлекаем фразы: ["mini pc", "16gb ram", "mini", "pc", "16gb", "ram"]
- Сопоставляем фразы с фильтрами с помощью сопоставлений
- Возвращаем фильтры:
{"Form Factor": ["Mini PC"], "Main Memory": ["16"]}
Подробнее см. Алгоритм извлечения фильтров.
Хранение и распространение
Сопоставления фраз сохраняются в виде JSON-файлов и используются во всей системе:
-
Файл базовых сопоставлений: создаётся на шаге 3a, содержит фразы на основе правил
-
Файл расширенных сопоставлений: создаётся на шаге 4, содержит результаты семантического расширения
Расширенные сопоставления используются в:
-
Генерация страниц запросов: извлечение фильтров из текста запроса
-
Поисковый сервис: API извлечения фильтров в реальном времени
-
Сопоставление товаров: фильтрация товаров по извлечённым фильтрам
Характеристики производительности
Базовая генерация (шаг 3a):
-
Время обработки масштабируется в зависимости от количества значений фильтров
-
Генерируется большое количество базовых вариантов фраз
-
Потребление памяти остаётся умеренным во время генерации
Семантическое расширение (шаг 4):
-
Время обработки масштабируется в зависимости от объёма запросов и размера эмбеддингов
-
Выходные данные содержат значительно больше фраз, чем базовая генерация
-
Требования к памяти возрастают из-за хранения эмбеддингов
Расширение является вычислительно интенсивным (CPU-bound) из-за вычисления близости. Использование NumPy с ускорением BLAS значительно ускоряет матричные операции.
Интеграция с SEO-конвейером
Генерация сопоставлений фраз — это шаги 3a и 4 в SEO-конвейере:
- Шаг 0: Встраивание исходных данных — товары, детали, статьи
- Шаг 1: Получение запросов — GSC, Google Ads, live, Algolia
- Шаг 2: Объединение запросов — объединение всех источников
- Шаг 3a: Генерация базовых сопоставлений фраз ← Вы находитесь здесь
- Шаг 3b: Встраивание запросов — преобразование в векторы
- Шаг 4: Расширение сопоставлений фраз ← Вы находитесь здесь
- Шаг 5: Кластеризация запросов — группировка по страницам
- Шаг 6: Сопоставление товаров — сопоставление запросов и товаров
- Шаг 7: Создание страниц запросов — генерация HTML
- Шаг 8: Генерация связанных запросов — поиск связанных запросов
- Шаг 11: Миграция на Valkey — загрузка в поисковый сервис
Полное описание процесса см. в статье Обзор SEO-конвейера.
Зачем нужны два шага?
Базовая генерация (шаг 3a) обеспечивает:
-
Точность: фразы на основе правил соответствуют ровно тому, что мы ожидаем
-
Покрытие: перестановки обеспечивают учёт всех порядков слов
-
Контроль: правила для конкретных характеристик учитывают предметные знания
Семантическое расширение (шаг 4) обеспечивает:
-
Гибкость: обнаруживает фразы, которые мы не предвидели
-
Реальный язык пользователей: учится на фактических поисковых запросах
-
Синонимы: находит эквивалентные фразы ("16 gigs" для "16gb")
Вместе они обеспечивают баланс между точностью и полнотой.
Ссылки
Технические концепции
-
Перестановка — Википедия
-
Косинусная близость — Википедия
-
N-грамма — Википедия
-
NumPy — Официальная документация
-
BLAS — Википедия
Документация по моделям
-
all-mpnet-base-v2 — Hugging Face
-
Sentence Transformers — Официальная документация
Связанные статьи
-
Стратегия эмбеддингов — как мы создаём эмбеддинги
-
Алгоритм извлечения фильтров — использование сопоставлений для извлечения фильтров
-
Обзор SEO-конвейера — полная архитектура конвейера
-
Кластеризация запросов — группировка похожих запросов
-
Сопоставление товаров — семантическое сопоставление
Итоги
Мы создаём сопоставления «фраза-фильтр» в два этапа:
Шаг 3a (базовая генерация):
-
Генерируем все перестановки заголовка, ключа, значения, единицы измерения
-
Применяем правила для конкретных характеристик (серия процессора, память, хранилище, форм-фактор)
-
Добавляем суффиксы портов для характеристик подключения
-
Используем белый список для самостоятельных значений отдельных характеристик
-
Выводим базовый набор фраз на основе правил
Шаг 4 (семантическое расширение):
-
Извлекаем n-граммы из реальных поисковых запросов
-
Создаём эмбеддинги фраз и поисковых текстов фильтров
-
Сопоставляем фразы с оценками близости выше порога
-
Добавляем ручные стартовые фразы для направления расширения
-
Разрешаем коллизии между памятью и хранилищем
-
Выводим расширенный и однозначный набор фраз
В результате получается комплексное сопоставление, которое обрабатывает как ожидаемые фразы (с помощью правил), так и неожиданные варианты (с помощью семантической близости). Эти сопоставления обеспечивают извлечение фильтров на страницах запросов, в поиске и при сопоставлении товаров.