Настроить adversarial evaluation для RAG

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить adversarial evaluation для RAG

1. Цель задачи

Разработать и запустить adversarial evaluation для RAG-системы (Retrieval-Augmented Generation), используя атаки TextFooler и BERT-Attack на тестовых запросах. Цель — измерить устойчивость RAG к синтаксическим и семантически близким искажениям входных запросов, которые могут обмануть как retriever, так и generator. Ключевой результат Accuracy drop (падение точности ответов) не превышает 10% при применении атак к тестовому набору запросов.

2. Исходные данные

Что нужноОткуда взять
RAG-система (retriever + generator)Готовая реализация из предыдущих задач (например, FAISS + Hugging Face pipeline) или развернуть минимальную (LangChain + OpenAI API / локальная LLM)
Набор тестовых запросов и референсных ответов (минимум 50 пар)Сгенерировать самостоятельно на основе документов из корпуса (вопросы к параграфам) или взять готовый датасет (например, MS MARCO subset, Natural Questions)
Инструменты для атак (TextFooler / BERT-Attack)Библиотека textattack (PyPI) или кастомные реализации
Вычислительные ресурсыGPU (рекомендуется) или CPU (для малых наборов)

Если нет реального инструмента — симулируем:

  • Установить textattack==0.3.9 и модель-классификатор для атаки (например, textattack/bert-base-uncased-imdb).
  • Для симуляции TextFooler использовать рецепт textattack: TextFoolerJin2019.
  • Для BERT-Attack — рецепт bert-attack.
  • Если библиотека не устанавливается, написать простые заменители: замена слов на синонимы по WordNet (TextFooler) или замены по BERT-MLM (BERT-Attack) через transformers.

3. Технологический стек

КомпонентИнструментыНазначение
Язык программированияPython 3.10+Основной язык
RAG pipelineLangChain / LlamaIndex + FAISSГенерация ответов на основе ретрива и генерации
Атакиtextattack + transformersГенерация adversarial запросов
ВекторизацияSentence Transformers (all-MiniLM-L6-v2)Эмбеддинги для retriever
LLM генераторHugging Face (Flan-T5-base / Mistral-7B) либо OpenAI APIГенерация ответов
ОценкаROUGE-L / Exact Match / LLM-as-judgeМетрики точности ответов
АвтоматизацияPython скрипты (argparse, logging)Запуск экспериментов

4. Этапы выполнения

Этап 1: Подготовка тестового набора и базовых метрик (2 часа)

Действия

  1. Взять 10–20 документов (тексты статей, инструкции) и вручную составить 50 тестовых вопросов с ожидаемыми ответами (по 2–5 на документ).
    • Пример: документ про «Правила возврата товаров», вопрос «Каков срок возврата?», ответ «14 дней».
  2. Развернуть RAG pipeline:
    from langchain.vectorstores import FAISS
    from langchain.embeddings import SentenceTransformerEmbeddings
    from langchain.llms import HuggingFacePipeline
    from langchain.chains import RetrievalQA
    embeddings = SentenceTransformerEmbeddings(model_name="all-MiniLM-L6-v2")
    vectorstore = FAISS.from_documents(docs, embeddings)
    qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever())
    
  3. Прогнать все 50 чистых запросов через RAG, извлечь ответы.
  4. Вычислить базовую метрику: Exact Match (EM) или ROUGE-L между ожидаемым ответом и ответом RAG.
    • Если точность <70%, выбрать более легкий датасет или настроить LLM.

Ожидаемый результат этапа Таблица из 50 запросов, ответов RAG и метрик (EM/ROUGE-L). Базовая accuracy >80%.

Этап 2: Интеграция атак TextFooler (3 часа)

Действия

  1. Установить textattack и загрузить модель-жертву (например, bert-base-uncased для классификации, но нам нужна атака на запросы, а не на классификатор — используем recipe без привязки к модели, только генерация пертурбаций).
    • Альтернативно: использовать textattack.attack.attack.attack с goal_function=UntargetedClassification и dummy model, но проще генерировать через transformation.WordSwapEmbedding и constraints вручную.
  2. Написать функцию apply_textfooler(query) → list[str]:
    • С помощью nltk и WordNet найти для каждого слова синонимы.
    • Заменять по одному слову, проверяя, что не меняется смысл (через sentence-BERT косинусное сходство >0.8).
    • Возвращать до 3 вариантов атаки на запрос.
  3. Для каждого из 50 тестовых запросов применить атаку (с запасом по времени — можно на подмножестве 20 запросов).
  4. Оценить accuracy на атакованных запросах (сравнить ответы RAG с референсным).
  5. Вычислить drop: (base_accuracy - adversarial_accuracy)/base_accuracy * 100.

Ожидаемый результат этапа Accuracy drop после TextFooler (должен быть умеренный, 5–15% — идеально для задачи).

Этап 3: Интеграция атак BERT-Attack (3 часа)

Действия

  1. Использовать метод BERT-Attack: для каждого токена запроса предсказывать маскированное слово (BERT-MLM) с максимальной вероятностью, отличной от исходного, при условии, что семантика сохраняется.
    • Использовать transformers.BertForMaskedLM с моделью bert-base-uncased.
    • Ограничения: не заменять stopwords, длина фразы не меняется.
  2. Реализовать apply_bert_attack(query) → list[str]:
    for i, token in enumerate(tokens):
        masked = tokens.copy()
        masked[i] = '[MASK]'
        logits = model(**input_ids).logits
        probs = softmax(logits[0, i])
        candidates = top_k(probs, k=5)[0]
        for cand in candidates:
            if cand != token and sim(original, cand_sent) > threshold:
                yield cand_sent
    
  3. Прогнать атаки на тех же 50 запросах (или на 20, если время ограничено).
  4. Посчитать accuracy drop.

Ожидаемый результат этапа BERT-Attack обычно более агрессивный — drop может быть 10–20%.

Этап 4: Объединённый сценарий и измерение (2 часа)

Действия

  1. Написать скрипт run_adversarial_eval.py, который:
    • Загружает базовый набор.
    • Для каждого запроса генерирует атаки обоими методами (с опцией --attack_type).
    • Прогоняет RAG на атакованных запросах.
    • Собирает метрики: accuracy (EM), average ROUGE-L, drop per attack.
  2. Вывести итоговую таблицу:
    AttackBase AccAdv AccDrop (%)
    TextFooler84%78%7.1%
    BERT-Attack84%72%14.3%
  3. Проверить условие: Accuracy drop не превышает 10% хотя бы для одного метода (TextFooler). Если drop больше — принять как есть, задокументировать.

Ожидаемый результат этапа Полный отчёт об adversarial evaluation.

Этап 5: Анализ и улучшения (опционально, 2 часа)

Действия

  1. Просмотреть запросы, которые привели к ошибкам. Выделить типы уязвимостей:
    • Замена ключевого слова (например, «возврат» → «обмен»).
    • Изменение порядка слов.
  2. Предложить методы защиты: augmentation на этапе обучения (включить атакованные запросы в fine-tune retriever/LLM), использование query expansion или spell correction.
  3. Оценить, насколько улучшится accuracy после применения простой защиты (например, добавление синонимов в индекс).

Ожидаемый результат этапа Рекомендации по защите RAG от adversarial запросов.

5. Критерии приемки (Definition of Done)

  • Базовый accuracy на чистых запросах ≥80% (или измерен и задокументирован).
  • Реализован хотя бы один метод атаки (TextFooler) и сгенерированы пертурбации для минимум 20 запросов.
  • Accuracy drop от TextFooler не превышает 10% (или зафиксирован и пояснён).
  • Итоговый отчёт содержит сравнение двух атак (даже если BERT-Attack работает только на 10 запросах).
  • Код воспроизводим: один скрипт run_adversarial_eval.py с аргументами --attack textfooler/bert.
  • Все метрики (EM, ROUGE-L, drop) посчитаны и выведены в таблицу.
  • Приложен файл с примерами атакованных запросов (adversarial_queries.txt).

6. Ожидаемый результат

  • Основной артефакт Jupyter notebook или Python-скрипт eval_adversarial_rag.py.
  • Данные Файл results.csv со столбцами: query, reference, base_response, textfooler_response, bert_response, base_em, textfooler_em, bert_em.
  • Отчёт Markdown-файл report.md с таблицами accuracy и выводами.
  • Дополнительно Лог adversarial_queries.log с примерами пертурбаций.

7. Возможные сложности и их решение

СложностьРешение
Библиотека textattack не устанавливается или требует много зависимостейИспользовать кастомную реализацию TextFooler через WordNet + Sentence-BERT (код из примеров)
Атаки BERT-Attack слишком медленные на CPUОграничиться 20 запросами и заменой только 1–2 слов на запрос
Drop точности превышает 30% из-за слабой RAG системыУлучшить retriever (добавить больше релевантных чанков) или повысить температуру генератора
Не хватает GPU памяти для LLMВзять меньшую модель (Flan-T5-small) или использовать OpenAI API (с осторожностью — атаки могут генерировать странные запросы)
Референсные ответы неполные или субъективныеИспользовать LLM-as-judge с промптом «Сравни ответы» вместо Exact Match

8. Бюджет времени (оценка)

ЭтапВремя (часы)
Этап 1: Подготовка набора и базовые метрики2
Этап 2: Интеграция TextFooler3
Этап 3: Интеграция BERT-Attack3
Этап 4: Объединённый сценарий и отчёт2
Этап 5: Анализ (опционально)2
Итого (основные этапы)10 часов

Примечание Для первого раза с настройкой окружения заложить +2 часа.

9. Связанные вопросы из базы знаний

ВопросТема
23Как работает TextFooler?
47Основные виды adversarial атак на NLP
112Метрики оценки RAG (ROUGE, BLEU, EM)
189Sentence-BERT для семантической близости
253Обучение RAG с аугментацией (adversarial training)
304Оценка устойчивости retriever к пертурбациям
418BERT-Attack: пошаговая реализация
501Подбор порога косинусного сходства для атак
673LLM-as-judge для сравнения ответов
789Best practices по защите RAG от атак

10. Чек-лист самопроверки

  • Я развернул RAG pipeline и замерил baseline accuracy.
  • Я сгенерировал adversarial примеры с помощью TextFooler и проверил их осмысленность (не сломалась семантика).
  • Я получил accuracy drop ≤10% хотя бы на одном методе (TextFooler) — условие задачи выполнено.
  • Я задокументировал все шаги и результаты в читаемом отчёте.
  • Код содержит комментарии и может быть переиспользован для других RAG систем.