Анализ того, как сглаживание структурированных данных может повысить точность и полноту до 20%.
Делиться

При интеграции структурированных данных в систему RAG инженеры часто по умолчанию встраивают необработанный JSON в векторную базу данных. Однако в реальности этот интуитивно понятный подход приводит к значительному снижению производительности. Современные модели встраивания основаны на архитектуре BERT, которая, по сути, является кодирующей частью Transformer, и обучаются на огромном наборе текстовых данных с основной целью улавливания семантического смысла. Современные модели встраивания могут обеспечить невероятно высокую производительность поиска, но они обучаются на большом наборе неструктурированного текста с акцентом на семантический смысл. В результате, хотя встраивание JSON может показаться интуитивно простым и элегантным решением, использование универсальной модели встраивания для объектов JSON покажет результаты, далекие от пиковой производительности.
Глубокое погружение
Токенизация
Первый шаг — токенизация, которая берет текст и разбивает его на токены, обычно представляющие собой общие части слова. Современные модели встраивания используют алгоритмы токенизации Byte-Pair Encoding (BPE) или WordPiece. Эти алгоритмы оптимизированы для естественного языка, разбивая слова на общие подкомпоненты. Когда токенизатор сталкивается с необработанным JSON, он испытывает трудности с высокой частотой небуквенно-цифровых символов. Например, «usd»: 10 не рассматривается как пара ключ-значение; вместо этого он фрагментируется:
- Кавычки («), двоеточие (:) и запятая (,)
- Токены в долларах США и 10
Это приводит к низкому соотношению сигнал/шум. В естественном языке почти все слова вносят вклад в семантический «сигнал». В то время как в JSON (и других структурированных форматах) значительный процент токенов «тратится впустую» на структурный синтаксис, не имеющий никакой семантической ценности.
Расчет внимания
Главная сила трансформеров заключается в механизме внимания. Это позволяет модели взвешивать важность токенов относительно друг друга.
В предложении «Цена составляет 10 долларов США или 9 евро» механизм внимания легко связывает значение 10 с понятием «цена», поскольку эти взаимосвязи хорошо представлены в данных для предварительного обучения модели, и модель встречала этот лингвистический паттерн миллионы раз. С другой стороны, в исходном JSON:
«цена»: { «доллары США»: 10, «евро»: 9, }
Модель сталкивается со структурным синтаксисом, для чтения которого она изначально не была оптимизирована. Без лингвистического соединителя результирующий вектор не сможет отразить истинное предназначение данных, поскольку взаимосвязь между ключом и значением будет скрыта самим форматом.
Объединение средних значений
Заключительным этапом генерации единого векторного представления документа является объединение средних значений (Mean Pooling). Математически, итоговое векторное представление (E) представляет собой центроид всех векторов токенов (e1, e2, e3) в документе:

Именно здесь токены JSON становятся математическим недостатком. Если 25% токенов в документе являются структурными маркерами (фигурные скобки, кавычки, двоеточия), то итоговый вектор сильно зависит от «значения» знаков препинания. В результате вектор фактически «оттягивается» от своего истинного семантического центра в векторном пространстве этими «шумовыми» токенами. Когда пользователь отправляет запрос на естественном языке, расстояние между «чистым» вектором запроса и «шумовым» вектором JSON увеличивается, что напрямую ухудшает показатели поиска.
Сгладьте его
Итак, теперь, когда мы знаем об ограничениях JSON, нам нужно выяснить, как их преодолеть. Самый общий и простой подход заключается в том, чтобы преобразовать JSON в плоский формат и перевести его в естественный язык.
Рассмотрим типичный объект продукта:
{ «skuId»: «123», «description»: «Это тестовый продукт, используемый в демонстрационных целях», «quantity»: 5, «price»: { «usd»: 10, «eur»: 9, }, «availableDiscounts»: [«1», «2», «3»], «giftCardAvailable»: «true», «category»: «демо-продукт» … }
Это простой объект с несколькими атрибутами, такими как описание и т. д. Давайте применим к нему токенизацию и посмотрим, что получится:

Теперь давайте преобразуем это в текст, чтобы упростить работу с встраиванием данных. Для этого мы можем определить шаблон и подставить в него значения JSON. Например, этот шаблон можно использовать для описания продукта:
Товар с артикулом {skuId} относится к категории «{category}». Описание: {description} В наличии {quantity}. Цена: {price.usd} долларов США или {price.eur} евро. Доступные идентификаторы скидок: {availableDiscounts в виде списка, разделенного запятыми}. Подарочные карты для этого товара: {giftCardAvailable ? «available» : «not available»}
Таким образом, конечный результат будет выглядеть следующим образом:
Товар с артикулом 123 относится к категории «демонстрационный товар». Описание: Это тестовый товар, используемый в демонстрационных целях. В наличии 5 штук. Цена: 10 долларов США или 9 евро. Доступные идентификаторы скидок: 1, 2 и 3. Для этого товара доступны подарочные карты.
И примените к нему токенизатор:

Теперь в ней не только на 14% меньше токенов, но и гораздо более понятная форма с семантическим смыслом и необходимым контекстом.
Давайте измерим результаты.
Примечание: Полный, воспроизводимый код для этого эксперимента доступен в блокноте Google Colab.
Теперь давайте попробуем измерить эффективность поиска для обоих вариантов. Для простоты мы сосредоточимся на стандартных метриках поиска, таких как Recall@k, Precision@k и MRR, и будем использовать универсальную модель встраивания (all-MiniLM-L6-v2) и набор данных Amazon ESCI с 5000 случайными запросами и 3809 связанными товарами.
Модель miniLM-L6-v2 — популярный выбор, она компактна (22,7 млн параметров), но обеспечивает быстрые и точные результаты, что делает ее хорошим вариантом для данного эксперимента.
Для набора данных используется версия Amazon ESCI, а именно milistu/amazon-esci-data (лицензия Apache 2.0), которая доступна на Hugging Face и содержит коллекцию данных о товарах Amazon и поисковых запросах.
Для преобразования текста используется следующая функция сглаживания:
def flatten_product(product): return ( f»Продукт {product['product_title']} от бренда {product['product_brand']}» f» и идентификатор продукта {product['product_id']}» f» и описание {product['product_description']}» )
Пример исходных данных в формате JSON:
{ «product_id»: «B07NKPWJMG», «title»: «3D-пазлы RoWood для взрослых, деревянные механические наборы шестеренок для подростков и детей от 14 лет», «description»: «
Характеристики
Номер модели: Rowood Treasure box LK502
Среднее время сборки: 5 часов
Количество деталей: 123
Вес модели: 0,69 кг
Вес коробки: 0,74 кг
Размеры в собранном виде: 100*124*85 мм
Размеры коробки: 320*235*39 мм
Сертификаты: EN71,-1,-2,-3,ASTMF963
Рекомендуемый возраст: 14+
Содержимое
Листы фанеры
Металлическая пружина
Иллюстрированная инструкция
Аксессуары
СОЗДАНО ДЛЯ СБОРКИ
— Следуйте инструкциям в буклете и соберите 3D-пазл, получив массу удовольствия. Испытайте гордость от собственного творения, собрав это изысканное деревянное изделие как профессионал.
УКРАШЬТЕ СВОЕ ЖИЛОЕ ПРОСТРАНСТВО
— Возродите загадочное очарование и сделайте ваши вечеринки и встречи незабываемыми, подарив уникальный и интересный опыт.
«, «бренд»: «RoWood», «цвет»: «Шкатулка с сокровищами» }
Для векторного поиска создаются два индекса FAISS: один для сглаженного текста и один для текста в формате JSON. Оба индекса являются плоскими, что означает, что они будут сравнивать расстояния для каждой из существующих записей вместо использования индекса приблизительного ближайшего соседа (ANN). Это важно для того, чтобы гарантировать, что показатели поиска не будут зависеть от ANN.
D = 384 index_json = faiss.IndexFlatIP(D) index_flatten = faiss.IndexFlatIP(D)
Для сокращения набора данных было выбрано случайное число из 5000 запросов, и все соответствующие продукты были включены в индексы. В результате были собраны следующие метрики:

А вот как изменилось производительность сглаженной версии:

Анализ подтверждает, что встраивание исходных структурированных данных в общее векторное пространство является неоптимальным подходом, а добавление простого этапа предварительной обработки в виде сглаживания структурированных данных неизменно обеспечивает значительное улучшение показателей поиска (повышение полноты@k и точности@k примерно на 20%). Главный вывод для инженеров, создающих системы RAG, заключается в том, что эффективная подготовка данных чрезвычайно важна для достижения максимальной производительности системы семантического поиска/RAG.
Ссылки
[1] Полный код эксперимента : https://colab.research.google.com/drive/1dTgt6xwmA6CeIKE38lf2cZVahaJNbQB1?usp=sharing
[2] Модель https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2
[3] Набор данных Amazon ESCI. Использована конкретная версия: https://huggingface.co/datasets/milistu/amazon-esci-data
Исходный набор данных доступен по адресу https://www.amazon.science/code-and-datasets/shopping-queries-dataset-a-large-scale-esci-benchmark-for-improving-product-search
[4] FAISS https://ai.meta.com/tools/faiss/
Источник: towardsdatascience.com



























