English translation is not available yet. Showing Russian content.

Как делать feature engineering для RAG (кроме текста)?

Краткий тезис

Feature engineering для RAG — это процесс извлечения и использования дополнительных не-текстовых признаков (метаданных, структурных, социальных, временных) для улучшения поиска, ранжирования и контекстуализации чанков. Помимо семантического эмбеддинга самого текста, добавление таких фич повышает релевантность retrieval, позволяет фильтровать/бустить результаты и обогащает промпт для LLM. Ключевая идея: объединить dense-эмбеддинги с sparse-признаками или встроить метаданные прямо в текст промпта.

1. Термин: Feature Engineering для RAG

Feature engineering в контексте RAG — это создание и выбор признаков, которые описывают документы (чанки) и запросы, помимо содержательного текста. Обычно RAG использует только векторное представление текста (dense embedding) или лексическое совпадение (BM25). Feature engineering выходит за рамки строк: он добавляет числовые, категориальные и структурные характеристики, которые могут существенно повлиять на качество retrieval и генерации.

Проблема — стандартный pipeline (эмбеддинг текста + топ-k) игнорирует:

  • возраст документа (свежесть);
  • источник (надежность);
  • тип контента (таблица vs текст);
  • популярность (лайки/цитирования);
  • авторство и департамент.

Это ведёт к потере контекста и неверному ранжированию. Feature engineering решает эту проблему, добавляя сигнал, не содержащийся в тексте.

2. Зачем добавлять не-текстовые признаки?

  1. Улучшение релевантности — метаданные помогают отсеивать нерелевантные документы (например, по дате или источнику).
  2. Усиление ранжирования — можно бустить свежие или авторитетные документы.
  3. Фильтрация — на этапе pre-retrieval (например, только PDF, только за последний год).
  4. Обогащение контекста для LLMLLM может учитывать источник, автора, дату при генерации ответа (источник влияет на доверие).
  5. Объяснимость — метаданные позволяют понять, почему выбран конкретный чанк.
  6. Компенсация слабой семантики — в некоторых доменах (научные статьи, юридические документы) лексическое/семантическое сходство слабо коррелирует с релевантностью; метаданные (ключевые слова, категории) дают дополнительный буст.

3. Категории признаков для документов и чанков

КатегорияПримеры признаковТип данныхКак используется
Метаданные документаДлина (токены), тип (PDF/DOCX/HTML), домен-источник (wikipedia.com), язык, дата создания/обновления, версияЧисловые, категориальныеФильтрация, boosting, добавление в промпт
АвторствоАвтор, аффилиация (департамент, университет), грант, ORCIDКатегориальныеПовышение доверия (авторитетность), связь с другими документами
СтруктурныеКоличество заголовков, таблиц, изображений, ссылок в чанке; уровень иерархии (section/subsection)ЧисловыеОпределение типа контента (табличный/научный), весовая коррекция
Социальные/поведенческиеКоличество просмотров, лайков, скачиваний, рейтинг (5 звёзд), цитирования, число ретвитовЧисловыеBoosting популярного контента в поиске
ВременныеTimestamp, сезонность, дневная/недельная активностьЧисловые/категориальныеФильтрация по свежести, трендовые темы
Категориальные тегиПредметная область (ML, Physics), жанр (новость, статья, пост), уровень сложности (beginner/expert)КатегориальныеФильтрация по домену, бустинг по сходству с запросом
Эмбеддинги категорий/сущностейSparse vector (one-hot или TF-IDF) для категории; эмбеддинг автора; эмбеддинг даты (cyclical encoding)Числовые (sparse/dense)Fusion с текстовым эмбеддингом (concat или weighted sum)
Деривативные признакиСоотношение длины чанка к длине запроса, плотность ключевых слов, количество определенийЧисловыеRe-ranking, метрики для модели

Пример структуры чанка с фичами:

{
  "chunk_id": "123",
  "text": "Нейронные сети ...",
  "features": {
    "source": "arxiv",
    "year": 2023,
    "citation_count": 150,
    "num_tables": 2,
    "num_figures": 1,
    "embedding_text": [0.1, 0.2, ...],
    "embedding_category": [0.0, 1.0, 0.0, ...]  // one-hot категории "deep learning"
  }
}

4. Feature engineering на стороне запроса

Не только документы, но и запросы могут быть обогащены признаками:

  • Извлечение сущностей — Named Entity Recognition (NER) для выделения дат, имён, организаций. Затем boosting документов с такими же сущностями.
  • Интент запроса — классификация типа запроса: фактоидный, процедурный, сравнение, таблица. Фильтрация по типу контента.
  • Временные рамки — если запрос содержит «в 2023 году», извлечь год и отфильтровать документы только за этот период.
  • Язык и жанр — автоматическое определение языка и предполагаемого жанра (например, «как установить...» → руководство).
  • Гипотезы запросов (HyDE) — генерация гипотетического документа с помощью LLM, который затем эмбедится. Это не текст, а синтетический эмбеддинг — косвенно тоже feature engineering.

Пример pipeline:

Запрос: "Последние исследования по квантовым компьютерам"
→ NER: "квантовые компьютеры" (тема), "последние" (временной фильтр)
→ Создание расширенного запроса: [intent: research, timeframe: last 2 years, topic: quantum computing]
→ Использование этих тегов для boosting при retrieval.

5. Как интегрировать фичи в RAG pipeline

Есть несколько стратегий:

5.1. Векторный fusion (Hybrid Search)

Объединяем dense-эмбеддинг текста с sparse-вектором категориальных признаков (например, one-hot автора + TF-IDF тегов). Итоговое сходство — взвешенная сумма косинусного сходства по dense и sparse:

score = α * cos(emb_query, emb_doc) + β * cos(sparse_query, sparse_doc)

Популярен в Qdrant, Weaviate, Pinecone (поддерживают fusion).

5.2. Boosting с метаданными (Metadata filtering)

На этапе retrieval сразу отфильтровать по метаданным (date > 2022, source = 'arxiv', num_tables > 0). Затем для оставшихся документов — бустинг по дополнительным признакам через re-ranking модель (например, LambdaMART или LLM).

Пример кода с Qdrant (Python):

client.search(
    collection_name="docs",
    query_vector=query_emb,
    query_filter=models.Filter(
        must=[
            models.FieldCondition(key="year", range=models.Range(gte=2020)),
            models.FieldCondition(key="source", match=models.MatchValue(value="arxiv"))
        ]
    ),
    limit=50
)

5.3. Промпт-инжекция (добавление метаданных в контекст LLM)

Перед подачей чанка в LLM формируем блок с метаданными:

[Source: arxiv, Date: 2024, Authority: high, Citations: 150, Length: 2000 tokens]
Текст документа...

Зачем LLM может учесть авторитетность и дату при генерации ответа (например, не выдавать устаревшую информацию). Это уменьшает галлюцинации, связанные с временем.

Важно: чтобы не перегружать токены, включаем только релевантные метаданные (можно выбрать топ-3 признака).

5.4. LLM-ассистированный фич-инжиниринг

Использовать LLM для извлечения структурированных признаков из текста (автор, категория, дата). Затем эти признаки сохраняются как метаданные. Это эффективно для неструктурированных PDF или веб-страниц.

Пример промпта для извлечения:

Given the following text, extract: publication year, number of references, main topic (choose one: ML, NLP, CV, Robotics), and confidence (1-5).
Text: [chunk text]
Output JSON: {"year": ..., "refs": ..., "topic": ..., "confidence": ...}

6. Конкретные техники и примеры

  • BGE-M3 (BAAI) — поддерживает dense + sparse + multi-vector fusion. Можно добавить sparse-признаки как колонку авторов.
  • ColBERT-v2 — ранжирование на уровне токенов, но при помощи контекстуальных весов можно учесть важность полей (например, заголовок важнее остального текста).
  • Hybrid BM25 + Dense — классический пример, где BM25 учитывает точное совпадение полей (автор, ключевые слова), а dense — семантику.
  • Feature hashing — для больших кардинальностей категорий (домен, автор) используем hashing trick, чтобы сжать sparse-вектор.

Экспериментальный результат (из публикаций): добавление фичи "автор" и "цитируемость" улучшает MRR на 15–20% на датасете научных запросов по сравнению с чистым dense retrieval.

7. Практические рекомендации

  1. Собирай метаданные на этапе индексации — интегрируй парсеры для PDF (PyMuPDF + metadata), HTML (BeautifulSoup + head мета), DOCX (python-docx). Парсинг таблиц, изображений (OCR).
  2. Храни фичи как payload в векторной БДQdrant и Weaviate поддерживают гибкие схемы, можно фильтровать и бустить.
  3. Нормализуй числовые признаки — длина документа (токены) может быть от 10 до 100k, используй log-normalization или min-max scaling.
  4. Не добавляй шум — если признак не улучшает метрики, исключи его. Feature selection через ablation study.
  5. Тестируй на доменной задаче — для поиска вакансий важна дата и зарплата; для новостей — источник и срочность; для научных статей — цитирования и journal.
  6. Анализируй ошибки retrieval — если часто возвращаются не те документы по дате, усили вес признака «год».

8. Риски и недостатки

  • Усложнение пайплайна — больше шагов, больше точек отказа.
  • Неточные метаданные — если дата извлечена неправильно, фильтрация испортит retrieval. Нужна валидация.
  • Перекос по популярности — бустинг по лайкам может сделать систему «популярной», игнорируя малоизвестные, но точные источники.
  • Overfitting — если фичи сильно коррелируют с релевантностью на обучающем датасете, но не обобщаются на новые запросы.
  • Время обработки — извлечение фичей на лету (например, LLM-парсинг) увеличивает latency.

9. Сравнение с альтернативами

ПодходКогда лучшеНедостатки
Только dense-эмбеддингиТексты однородны, семантика достаточнаНе использует контекст метаданных, страдает от «синонимического шума»
Pure BM25 + лексическое совпадениеМного ключевых слов, точные названияПлохо обрабатывает семантику и перефразирование
Dense + boosted by metadataЕсть надёжные метаданные, нужно ранжирование по важностиТребует настройки весов, может доминировать один признак
Prompt injection толькоМалая стоимость, гибкостьЗагружает контекст LLM, не улучшает retrieval этап

10. Инструменты для реализации

  • LangChainDocumentTransformer и MetadataTagger для автоматического извлечения.
  • LlamaIndexMetadataFilter и VectorStoreIndex с фильтром; класс FeatureExtractor.
  • HaystackPreProcessor с metadata extraction, DocumentJoiner для fusion.
  • Qdrantpayload filtering, quantized vectors.
  • WeaviateGraphQL-запросы с фильтрами по метаданным.
  • Pinecone — metadata filtering (до 40KB metadata на вектор).

Пет-проект для закрепления

Задача: Улучшить retrieval для корпуса научных статей (arXiv датасет) путём добавления метаданных — год публикации, количество цитирований, категория (cs.AI, cs.LG, physics...). Оценить MRR@10 до и после.

Инструменты: Python, sentence-transformers (all-MiniLM-L6-v2), Qdrant (in-memory), Datasets from Hugging Face (arxiv dataset).

Шаги:

  1. Загрузи 1000 статей из arxiv (title, abstract, categories, year, citation count).
  2. Разбей на чанки (по 512 токенов), сохраняй метаданные (year, citations, category).
  3. Индексируй в Qdrant с dense-эмбеддингом (текст) и payload’ом метаданных.
  4. Для каждого тестового запроса (10 запросов разных тем):
    • Baseline: только dense search (k=10). Считай MRR.
    • Experiment: фильтр по year >= 2018 + boost citation count (при retrieval увеличиваем score на вес * log(citations+1)). Используй Qdrant’s score_boost или manual rerank. Считай MRR.
  5. Сравни результаты.

Ожидаемый результат: MRR вырос на 10–25% за счёт фильтрации старых статей и приоритезации высокоцитируемых.

Связь с другими вопросами

ВопросТема
5Оценка качества retrieval (метрики, ablation study для фич)
6Стратегии chunking (структурные фичи иерархии)
7Уменьшение latency (feature extraction как overhead)
1Проектирование RAG для 10к документов (какие метаданные хранить)
4Reranking после retrieval (использование фич в модели ранжирования)
9Обновление документов (обновление метаданных, реиндексация)

Навигация