<aside> 🧭

Кейс: агент підтримки, який відповідає тільки з документів компанії, дає посилання на джерело для кожного факту і чесно відмовляється, коли відповіді немає. Власний проєкт, зібраний як демонстрація роботи з RAG у продакшн-режимі, а не як туторіал. Результат на тестовому наборі: 18 із 20, 3 з 3 коректних відмов, нуль вигаданих цитат.

</aside>

1) Context 🏙️

2) Problem ⚠️

Два провали роблять бота по документах непридатним до реальної роботи, і жоден із них не лікується кращим промптом.

Обидва — проблеми довіри. А довіра тут і є продуктом.

3) Solution ✅

Усе рішення побудоване за одним принципом: модель робить твердження, яке може перевірити код. Там, де я замість цього просив її бути уважною, поведінка була нестабільною — те саме питання отримувало різні відповіді з різницею в п'ять хвилин. Там, де твердження ставало перевіряємим, поведінка ставала детермінованою.

Ідемпотентна індексація. Перед записом чанків документа система видаляє всі наявні чанки з цим file_id. Переіндексація замінює, а не накопичує. Нативна нода Qdrant видаляти не вміє, тому це прямий виклик API з фільтром по метаданих і ?wait=true, щоб видалення завершилось до запису.

Перевірка емпірична, а не візуальна: проіндексувати, порахувати точки, проіндексувати ще раз, порахувати знову. Однакові числа означають, що фільтр спрацював. Qdrant відповідає ok навіть на фільтр, який нічого не знайшов, тому зелена нода на канві не доводить нічого.

Чотири перевірки на кожній відповіді. Модель повертає структурований об'єкт, а не текст: чи відповіла, сама відповідь, і для кожного факту код документа плюс дослівна цитата. Далі Code-нода перевіряє:

  1. Цитата справжня — присутня в знайдених чанках і належить документу, який реально знайшовся
  2. Числа з відповіді підперті цитатою — ловить тонкий випадок: справжня цитата, правильно атрибутована, яка нічого не каже про назване число
  3. Числа з питання підперті цитатою — на питання про розстрочку на 12 місяців бот раніше відповідав, цитуючи неспоріднений строк у 14 днів