Реализовать conversational repair (disambiguation) в ассистенте

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать conversational repair (disambiguation) в ассистенте

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

Научиться проектировать и внедрять механизм conversational repair (уточнение неоднозначных запросов) в диалоговом агенте. Система должна детектировать ambiguous queries (запросы, которые можно интерпретировать несколькими способами) и предлагать пользователю выбор из двух-трёх вариантов (например, «Вы имели в виду X или Y?»). Основной фокус — на UX: пользователь не должен путаться, а уточнение должно занимать < 2 шагов.

Ключевой результат Ассистент корректно инициирует repair в ≥50% случаев неоднозначных запросов (ambiguous queries) в тестовом наборе данных, и не предлагает уточнение на однозначные запросы (ложноположительные срабатывания <10%).


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

Перед началом необходимо подготовить:

Что нужноОткуда взять
Набор ambiguous queries (50–100 примеров)Синтезировать вручную или сгенерировать через LLM
Набор однозначных запросов (100+ примеров)Любой существующий датасет (например, Banking77, SNIPS)
LLM‑модель для генерации вариантовOpenAI API / Anthropic / локальная модель (Llama 3.1 70B)
Среда ассистента (fastAPI / Telegram / тестовый чат)Написать минимальное приложение (FastAPI + WebSocket)
Метрики оценки: accuracy детекции, доля repair, время ответаPython скрипты (pandas, scikit-learn)

Если нет реального инструмента (LLM API, датасеты) — симулируем:

  1. Датасет ambiguous queries — сгенерировать с помощью ChatGPT/Claude следующими промптами:
    "Сгенерируй 50 запросов пользователя к ассистенту путешествий, которые могут относиться к двум разным интентам (например, 'билеты' vs 'рейсы в другое время', 'отели в центре' vs 'хостелы').
     Пример: 'Найти гостиницу в Париже' — неоднозначно: 4-звездочный отель или хостел.
     Оформи как JSON: {"query": "...", "ambigous_intents": ["intent1", "intent2"]}"
    
  2. LLM‑генерация — если нет доступа к API, эмулировать заранее подготовленными ответами (hardcode варианты).
  3. Ассистент — минимальный чат-бот на Python (input() → reply() → output()).

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

КомпонентИнструментыНазначение
Язык реализацииPython 3.10+Основной стек
LLM APIOpenAI API / Anthropic / Ollama (локально)Генерация вариантов уточнения
Семантическое сходствоsentence-transformers (all‑MiniLM‑L6‑v2)Измерение близости запроса к интентам
Фреймворк ассистентаLangChain / RASA / простой класс на PythonОркестрация диалога
Веб-интерфейс (опционально)Streamlit / GradioДемо для тестирования
Метрикиscikit-learn, pandasПодсчёт accuracy, precision, recall
ВерсионированиеGit + DVC (data)Отслеживание датасетов

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

Этап 1: Создание датасета ambiguous queries (2–3 часа)

Действия

  1. Выбрать домен (например, travel‑assistant или tech‑support). Ограничиться 3–5 интентами (например: book_flight, book_hotel, cancel_reservation, check_weather, ask_schedule).
  2. Вручную написать 30–50 запросов, которые могут принадлежать двум интентам одновременно.
    Пример:
    • "Я хочу изменить свой рейс" → может быть: change_flight или cancel_and_rebook.
    • "Где мне остановиться в Токио?" → book_hotel или recommend_hotel.
  3. Для каждого запроса указать gold варианты уточнения (что ассистент должен предложить).
  4. Добавить 100 однозначных запросов (из открытых датасетов или сгенерировать).
  5. Разделить на train (80%) и test (20%). Оформить в JSON или CSV.

Ожидаемый результат этапа Файл data/ambiguous_queries.csv с колонками: query, intents_candidates, golden_repair_options. Файл data/clear_queries.csv.


Этап 2: Разработка детекции неоднозначности (3–4 часа)

Действия

  1. Определить метрику неоднозначности

    • Взять эмбеддинги запроса и эмбеддинги всех интентов (предварительно вычислить центроиды по примерам).
    • Неоднозначность = разница между двумя ближайшими интентами мала (например, разница cosine similarity < 0.15).
    from sentence_transformers import SentenceTransformer, util
    model = SentenceTransformer('all-MiniLM-L6-v2')
    
    def ambiguity_score(query, intent_embeddings):
        query_emb = model.encode(query)
        scores = util.cos_sim(query_emb, intent_embeddings)[0]
        sorted_scores = sorted(scores, reverse=True)
        return sorted_scores[0] - sorted_scores[1]  # чем меньше, тем более неоднозначно
    
  2. Установить порог протестировать на validation split, найти порог, при котором recall неоднозначности ≥0.8, а false positive rate ≤0.1.

  3. Реализовать класс AmbiguityDetector с методами is_ambiguous(query) -> bool и get_top_ambiguous_intents(query, k=2) -> list.

  4. Добавить fallback если LLM доступна, можно использовать её для двоичной классификации (промпт "Является ли запрос неоднозначным? Ответь yes/no"), но приоритет — эмбеддинги.

Ожидаемый результат этапа Модуль detector.py, который корректно детектирует неоднозначность на тестовых данных с метриками (accuracy, precision, recall).


Этап 3: Генерация вариантов уточнения (2–3 часа)

Действия

  1. Реализовать RepairGenerator:

    • Вход: query, candidate_intents (список строк, например, ['book_hotel', 'recommend_hotel']).
    • Выход: список из 2–3 вариантов уточнения на естественном языке.
  2. Варианты генерации

    • На основе шаблонов
      f"Вы имели в виду: [{intent1}] или [{intent2}]?"
      (intent преобразовать в читаемый вид: book_hotel → «забронировать отель»).
    • С помощью LLM промпт:
      Query: "{query}"
      Possible intents: {intent1_name}, {intent2_name}
      Сформулируй два кратких уточняющих вопроса (не более 10 слов каждый).
      Формат: 1) ... 2) ...
      
  3. Добавить валидацию исключить пустые или повторяющиеся варианты.

  4. Написать unit‑тесты для проверки корректности шаблонов.

Ожидаемый результат этапа Модуль repair_generator.py, который для набора тестовых запросов выдаёт осмысленные варианты.


Этап 4: Интеграция repair-логики в ассистента (3–4 часа)

Действия

  1. Построить конвейер ассистента:

    User Query → Intent Classifier (основной) → если уверенность > 0.9 → Execute Intent
                 ↓ (если неоднозначность)
           AmbiguityDetector → если True → RepairGenerator → Показать варианты пользователю → Получить выбор → Execute Intent
    
  2. Реализовать простой веб-интерфейс (Gradio/Streamlit):

    • Поле ввода запроса.
    • Вывод ответа ассистента (с кнопками выбора при repair).
    • Логирование всех действий.
  3. Добавить обработку edge‑cases

    • Пользователь вводит свой вариант (не из предложенных).
    • Пользователь отменяет уточнение ("ни то, ни другое").
    • Если repair вызывает зацикливание (повторная неоднозначность после первого уточнения) — прервать через max_repair_count=3.
  4. Написать интеграционные тесты на 10 сценариев.

Ожидаемый результат этапа Рабочий ассистент с repair, доступный через CLI или веб-интерфейс.


Этап 5: Оценка и метрики (1–2 часа)

Действия

  1. Запустить ассистента на тестовом датасете (ambiguous + clear queries). Записать:

    • Сколько раз был вызван repair.
    • Сколько раз пользователь выбрал предложенный вариант (если эмулируем — смотрим на ground truth).
    • Количество false positives и false negatives.
  2. Рассчитать метрики

    • repair_rate = количество repair / количество ambiguous queries.
    • accuracy_of_repair = доля случаев, когда предложенный вариант совпал с ожидаемым.
    • precision, recall детекции неоднозначности.
  3. Построить confusion matrix и ROC‑кривую для порога ambiguity_score.

  4. Сравнить baseline (без repair) с repair-версией: пользователь проходит на 1 шаг больше, но точность ответа выше.

Ожидаемый результат этапа Отчёт evaluation_report.md с таблицами метрик и графиками.


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

  • Реализован детектор неоднозначности на основе эмбеддингов (или LLM) с порогом, обеспечивающим recall ≥0.8 и false positive rate ≤0.1.
  • Генератор repair выводит 2–3 варианта уточнения для всех ambiguous запросов из тестового набора.
  • Ассистент корректно запускает repair в ≥50% случаев неоднозначных запросов (на синтезированном датасете).
  • На однозначных запросах repair запускается не чаще, чем в 10% случаев.
  • Пользователь может выбрать один из вариантов или дать свой ответ; после выбора ассистент выполняет соответствующий интент.
  • Реализована защита от зацикливания (максимум 3 ремонтных цикла).
  • Написан отчёт с метриками (accuracy, precision, recall, repair_rate).
  • Код выложен в Git с README, инструкцией по запуску.

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

Основной артефакт

  • Репозиторий с модулями detector.py, repair_generator.py, assistant.py, app.py (веб-интерфейс).
  • Дашборд или отчёт evaluation_report.md с таблицами.

Дополнительные результаты

  • Датасет ambiguous queries (можно использовать для дальнейших экспериментов).
  • Скрипт для A/B тестирования (сравнение с версией без repair).

Содержание отчёта (evaluation_report.md):

  • Описание архитектуры.
  • Порог ambiguity и его обоснование.
  • Confusion matrix.
  • Итоговая таблица метрик.
  • Выводы (стоило ли внедрять repair, как часто он помога?).

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

СложностьРешение
Детектор неверно определяет неоднозначностьИспользовать ансамбль (эмбеддинги + LLM confidence scores). Оптимизировать порог на кросс-валидации.
Генератор выдаёт нерелевантные вариантыИспользовать шаблонные варианты как fallback; для LLM добавить few-shot примеры.
Пользователь не понимает предложенные вариантыСократить длину фраз, добавить примеры ("Вы имели вду – забронировать отель на эти даты или на другие?").
ЗацикливаниеВвести счётчик repair (max=2), после которого выполнить случайный интент и попросить пользователя уточнить текстом.
Слишком много false positives на однозначных запросахУвеличить порог разницы между топ-2 интентами. Добавить проверку, что оба интента имеют уверенность >0.5.

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

ЭтапВремя (часы)
Этап 1: Создание датасета2–3
Этап 2: Детекция неоднозначности3–4
Этап 3: Генерация вариантов2–3
Этап 4: Интеграция в ассистента3–4
Этап 5: Оценка и метрики1–2
Итого11–16

Примечание Для первого раза рекомендуется заложить 16 часов с учётом отладки.


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

ВопросТема
15User intent classification in dialog systems
42Slot-filling and entity recognition
73Active learning for ambiguous queries
108Evaluation of conversational repair (user satisfaction metrics)
144Handling out-of-domain queries
210Multi-turn dialogue state tracking
298Using embeddings for semantic similarity
357Few-shot prompting for clarification questions
402UX design for clarification dialogs
478Balancing repair frequency and user annoyance

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

  • Я создал датасет, который точно отражает неоднозначности в выбранном домене.
  • Детектор работает на эмбеддингах, и я знаю порог, при котором метрики устроивают.
  • Генератор repair выводит понятные пользователю варианты (не технические термины).
  • Ассистент корректно получает выбор пользователя (кнопки или текстовый ввод).
  • Я протестировал минимум 10 сценариев, включая граничные (пустой запрос, отмена ремонта).
  • Метрики измерены и зафиксированы в отчёте.
  • Код покрыт хотя бы базовыми юнит-тестами для ключевых модулей.