Переранжування в RAG: Вузьке вікно, де крос-енкодери дійсно допомагають
Переранкінг у RAG допомагає лише між нижньою межею відтворення та верхньою межею K. Що таке Phantom Hits та як виміряти обидві межі для ваших власних запитів протягом одного дня.
Джерела: Reranking in RAG — Cross-Encoders, the K Threshold, and the Recall Ceiling in Production Systems
Крос-енкодер допомагає підходу RAG лише в вузькому діапазоні: рівень відтворення інформації на першому етапі має бути достатньо високим, а кількість кандидатів, які ви передаєте, — достатньо малою. Поза цим діапазоном алгоритм переранкінгу або не має чого виправляти, або починає завдавати шкоди. У наступному описано механізм, режим несправності під назвою „Phantom Hits“ та спосіб оцінки всього цього на власних даних.
Уявіть собі систему RAG, яка знайшла правильну відповідь. Не було жодних помилок та втрачених документів. Відповідь просто знаходиться на 37-му місці у списку результатів, тоді як LLM читає лише перші п’ять, тож з практичної точки зору її немає. Жодних сповіщень не відправляється, оскільки за всіма показниками моніторингу запит був успішним.
Це не є особливістю лише однієї версії розгортання. Це випливає з того, як побудована архітектура. Векторний пошук розроблений так, щоб правильна відповідь знаходилася серед перших 50–200 кандидатів, а не обов’язково на самому верху, тому процес, який закінчується отриманням результатів, залишає якість відповіді на волю випадку.
Звичайною реакцією є додавання механізму переранкінгу. Це означає використання крос-кодеру, приблизно дванадцяти рядків коду, незначного підвищення показника nDCG, і справа вважається вирішеною. Ця реакція не є неправильною, оскільки переранкінг дійсно неефективний. Вона є неправильною тому, що переранкінг працює в вузькому діапазоні параметрів, який майже ніхто не вимірює. Нижче ви побачите, як працює ця дорожча друга стадія, де знаходяться межі цього діапазону, та як можна за один день з’ясувати, на якій стороні кожної межі знаходиться ваша система.
Переранкінг — це не кращий векторний пошук
Реранкер — це інша архітектура, яка активується лише після пошуку та застосовується до невеликої кількості кандидатів.
Бі-енкодер у вашому існуючому пошуку векторів кодує запит та кожен документ окремо, заздалегідь та офлайн. Це робить процес швидким та дозволяє масштабуватися до мільйонів документів. Недолік полягає у тому, що він ніколи не розглядає запит та документ разом.
Крос-енкодер робить протилежне. Він читає їх обидва одночасно, токен за токеном, що дозволяє йому помічати заперечення, числові суперечності та тонкощі, яких не бачить бі-енкодер. У відповідь він змушений повторювати цю роботу для кожного кандидата окремо під час пошуку.
Це створює знайому двоступеневу схему обробки. Етап пошуку дешево звужує коло кандидатів до 50–200 варіантів та спрямований на уникнення пропуску правильної відповіді. Потім етап переранжування сортує цей невеликий набір за вищою вартістю та спрямований на точність: серед тих, хто залишився, обирати справді найкращий варіант.
Другий рівень також не є безкоштовним покращенням. Після досягнення певної кількості кандидатів крос-кодер починає сприймати шум як сигнал, і якість справді погіршується. Рішення про використання етапу переранжування — це інженерний розрахунок на основі ваших даних, а не імпульсивний вибір.
Чому пошук не може бути останнім кроком
Симптом, який постійно з’являється у продакшн-системах типу RAG, виглядає так: «модель створює халюцинації, хоча інформація є в нашій базі даних». У більшості випадків, коли це досліджують до кінця, виявляється, що модель нічого не вигадувала самостійно. Правильний документ був серед п’ятдесяти найкращих результатів, просто не потрапив до п’яти найкращих, які були показані генератору.
Причина криється в архітектурі. Бі-енкодер обчислює ембеддинг документа під час індексації, ще до того, як з’явиться будь-яке запитання. Під час пошуку він порівнює два стиснуті резюме, а не справжній текст запиту, із справжнім текстом документа.
Класичний приклад того, що губиться: у запиті зазначено «дешево», а в документі — «500 доларів за ніч». Для векторів обидва варіанти стосуються ціни готельного номера, тому вони знаходяться поруч один з одним. Суперечність стає помітною лише тоді, коли хтось читає їх поруч, а бі-енкодер за своєю суттю цього ніколи не робить.
Краща модель ембеддингів не вирішить цю проблему, оскільки це свідомий компроміс. Метод отримання даних максимізує точність відтворення, тобто ймовірність того, що правильний документ знаходиться серед повернених результатів, і робить це дешево для мільйонів документів. Переміщення правильного документа на саме верхнє місце просто не є частиною його завдань.
Recall@50 та precision@5 вимірюють різні показники та відповідають на різні запитання. Плутання їх призводить до того, що команди змушені оплачувати додатковий рівень обробки для вирішення проблеми, яку він не може вирішити.
Недолік полягає у тому, що бі-енкодер ніколи не розглядає пару разом, тож давайте подивимося, яку перевагу отримує модель, яка дійсно розглядає пару.
Бі-енкодер каталогізує, крос-енкодер читає
Уявіть процес найму. Бі-енкодер виконує роль рекрутера, який сортує тисячу резюме в папки ще до того, як з’явиться опис посади: швидко, поверхнево, рано закінчуючи роботу. Крос-енкодер виконує роль керівника, який має десять фіналістів та читає кожне резюме разом із описом посади, рядок за рядком. Лише тоді з’являються невідповідності, які рекрутер не зміг помітити.
З механічної точки зору різниця очевидна. Крос-енкодер об’єднує запит та документ у одну послідовність у стандартному форматі [CLS] запит [SEP] документ [SEP] та передає її через один трансформер.
Усередині цього процесу роботу виконує механізм крос-уваги: кожен токен запиту може безпосередньо взаємодіяти з кожним токеном документа та навпаки. Результатом є не вектор для порівняння, а окремий логіт — ненормалізоване число, яке відображає ступінь впевненості моделі у тому, що ця конкретна пара є релевантною.
Отже, бі-енкодер створює представлення, а крос-енкодер — вердикт. Це різниця у тому, що саме може бачити модель, а не різниця у ступені.
Від цього негайно випливає один наслідок. Оцінку крос-енкодера неможливо попередньо обчислити та індексувати, оскільки вона залежить від конкретної пари запиту та документа, а не лише від документа. Кожен запит вимагає повного проходження алгоритму для кожного кандидата, що у десятки–сотні разів дорожче за порівняння векторів.
Формула, яка лежить в основі двоетапного підходу, робить масштаб зрозумілим. Знаходження найбільш схожої пари серед 10 000 речень вимагає близько 50 мільйонів порівнянь, що становить приблизно 65 годин за використання повної моделі BERT та близько 5 секунд за архітектури типу SBERT, згідно з дослідженням Sentence-BERT 2019 року від Reimers та Gurevych.
Запам’ятайте це у точній формі, адже поширюються округлені варіанти, наприклад «10 мільйонів документів та 50 годин». Різниця є якісною: вузьке місце полягає у кількості пар, які потрібно оцінити, а не у розмірі корпусу даних.
Саме тому крос-енкодер ніколи не використовується як перший етап. Він не гірший, просто занадто дорогий для обробки всього корпусу. А оскільки його використання є дорогим за одну пару, усе залежить від кількості пар, які ви йому передаєте, та від того, на якому етапі процесу він знаходиться.
Два етапи, два бюджети
Реранкер розташовується після етапу пошуку та перед LLM. Пошук повертає топ-k кандидатів, де k — це кількість документів, які один етап передає наступному, зазвичай від 50 до 200. Реранкер потім перетворює цей список та передає його генератору на позиції від 3 до 20.
Ця ієрархія не виникла разом із LLM, що свідчить про її зрілість. Модель «дешевий фільтр, потім дорогий суддя» походить з епохи Learning-to-Rank, коли другий етап складався з ансамблю дерев прийняття рішень на основі вручну створених ознак, а не з трансформера. Двигун змінився, архітектура — ні.
Нейронне переранжування має конкретну дату появи. У 2019 році стаття „Passage Re-ranking with BERT“ використала BERT як бінарний класифікатор для пар запитів та уривків тексту, що дозволило покращити показник MRR@10 на 27 відсотків порівняно з найкращим результатом, який існував на той час. Саме тоді друга стадія перестала бути частиною процесу оптимізації та стала окремим етапом.
Найвідомішою комерційною реалізацією сьогодні є флагманський інструмент переранжування від Cohere. Протягом усіх версій найбільше змінився один параметр – розмір вхідного вікна з кількох сотень токенів збільшився до понад 32 000, причому для версій v3 та v3.5 цей ліміт становив 4 096 токенів. Це справжня зміна в дизайні, адже вона збільшує розмір фрагментів тексту, які можна оцінювати без обрізання, що дозволяє застосовувати менш агресивне розділення на фрагменти та зменшує втрату контексту.
Постачальники рідше говорять про те, що буде далі. Ціни на одну й ту саму модель у різних джерелах відрізняються в десять разів або більше — від крихти цента до двох з половиною доларів за тисячу пошуків, залежно від того, хто рахує та що включає до поняття „пошук“.
Існує просте правило: якщо ви не можете самостійно повторити розрахунки постачальника для свого трафіку, у вас немає точних даних, а лише припущення. Також існує підступ у формуванні рахунків: документи, довші за встановлений ліміт, розділяються на частини, і кожна з них оплачується окремо, тож один логічний запит на переранжування може перетворитися на кілька оплачуваних запитів.
Формула, яку потрібно пам’ятати, така: отримувати дані дешево у великих обсягах, переорієнтовувати їх за високою ціною у вузькому діапазоні, і дозволяти ШІ бачити лише те, що виживає після обох процедур. Це звучить як безпечний стандарт, проте існує певний поріг, за яким цей підхід перестає ефективно працювати, і це відбувається саме у напрямку, якого майже ніхто не очікує.
Фантомні результати та момент, коли переорієнтація починає завдавати шкоди
Загальноприйнята думка полягає у тому, що чим більше кандидатів ви надасте моделі для переорієнтації, тим безпечніше буде результат. Модель є точнішою за векторний пошук, тож при кількості кандидатів 500 чи 1 000 вона точно не може помилитися. Однак ця інтуїція хибна, і існують докази, які це підтверджують.
У статті 2024 року „Drowning in Documents“ (Jacob та співавтори) повідомляється, що зі збільшенням значення K якість алгоритму переранкінгу підвищується, досягає піку, а потім значно знижується. Коли весь набір даних сканували сліпо, звичайний алгоритм BM25 міг перевершити алгоритм крос-енкодування, який вважався найкращим на той час. Однак слід пам’ятати про один нюанс: ці результати отримані під час сліпого сканування академічних та корпоративних даних, тож вони мало що говорять про типову схему обробки, де значення K становить щонайбільше кілька сотень.
Ця проблема має назву „Phantom Hits“. Алгоритм переранкінгу впевнено присвоює найвищий бал документу, який не має жодного зв’язку з запитом — ні лексичного, ні семантичного.
Автори пропонують ймовірне джерело проблеми та ретельно називають це гіпотезою, а не підтвердженою причиною. Вони вказують на налаштування навчання, яке називають упередженням через експозицію. Моделі для переранкінгу навчаються за допомогою контрастних прикладів „складних негативів“ — документів, які зовні схожі на правильну відповідь, але по суті є неправильними, тож модель стає експертом у виявленні мікроскопічних відмінностей.
У реальних умовах ця експертиза призводить до проблем. Якщо показати моделі простий негатив — просто шум, з яким вона ледве стикалася під час навчання, — у неї немає жодних орієнтирів, і вона починає вгадувати. Модель, навчена розрізняти близнюків, стає безпорадною, коли заходить незнайомець.
Протилежний край є таким само реальним та не скасовує першого. Кілька незалежних аналізів вказують на нижню межу точки беззбитковості для переранжування близько recall@50 = 0,85. При значенні, нижчому за це, немає нічого, що варто було б сортувати, оскільки правильний документ так і не потрапив до списку. Точні порогові значення відрізняються у різних джерелах через різницю в корпусах даних, і їхнє походження має значення: блоги та практичний досвід, а не оцінки колег. Використовуйте їх як гіпотезу для перевірки на власних даних, а ніколи не як встановлений факт.
Ці два висновки не суперечать один одному. Вони є двома крайніми межами одного діапазону функціонування. При пороговому значенні recall у переранжуванні немає на чому працювати. При значенні, вищому за K, воно починає завдавати шкоди. Переранжування — це не монотонне покращення, і припущення про те, що більше завжди краще, є повторенням помилки сліпого довір’я до стандартів постачальника, адже обидва підходи замінюють точні вимірювання на народні перекази.
Оскільки надмірне переранжування може нашкодити, а занадто мало — не буде ефективним, нам потрібна чітка уява про межі того, що цей етап може виправити.
Межа ефективності та що насправді означає 67 відсотків
Інструмент переранжування — це редактор, а не репортер. Він може переупорядкувати матеріал, який вже зібрав хтось інший, але не може створити те, що ніхто не надав.
Цей принцип, межа ефективності, здається тривіальним, доки не зустрічається з найбільш вражаючою статистикою галузі. У своєму звіті про контекстуальне пошукове забезпечення Anthropic описав процес 2024 року, у якому рівень невдач у отриманні топ-20 результатів знизився з 5,7 до 1,9 відсотка, що становить зниження на 67 відсотків.
Це число часто цитується на підтримку використання переранжування. Однак якщо розглядати його за окремими етапами, воно розповідає іншу історію, хоча це не означає, що воно неправдиве.
Шлях був таким. Контекстуальні ембеддинги знизили показник до 3,7 відсотка, додавання BM25 привело його до 2,9, і лише тоді реранкінг дозволив досягти 1,9. Отже, саме реранкінг покриває останню частину – від 2,9 до 1,9 відсотка. Обидва показники є актуальними, оскільки вони вимірюють різні аспекти: 67 відсотків – це результат всієї системи, а не окремого її елемента.
Це розрізнення має велике практичне значення. Перш ніж наводити цифру „67 відсотків“ під час аналізу архітектури, слід усвідомлювати, що ви обіцяєте ефект від чотирьох змін разом, причому три з них відбуваються раніше за реранкінг та забезпечують більшу частину покращень.
Самі автори вказують на це обмеження: показники є середніми за різними доменами, а різниця між ними є значною. Ще один недолік, який випливає з наявних даних: кожен показник якості комерційних інструментів для переранжування надається виробниками на основі їхніх власних наборів даних та з використанням їхніх власних методів пошуку на першому етапі. Не існує незалежної оцінки на рівні всього ринку.
Жодні зовнішні критерії не дозволять вам дізнатися, як буде працювати переранжування у вашій системі, тому вам потрібно тестувати його самостійно.
Розрахунок, який ви можете виконати у понеділок вранці
Уся складність цієї теми зводиться до однієї повторюваної процедури. Саме через те, що команди рідко її виконують, триває дискусія про те, чи справді переранжування є корисним.
Перший крок: виміряйте recall@50 та precision@5 на приблизно ста позначених запитах з реальних даних. Використовуйте власні журнали та власну комбінацію термінів та намірів, а не публічні критерії оцінки. Якщо значення recall@50 значно нижче 0,85, спочатку виправте процес пошуку за допомогою чанкінгу, гібридного пошуку чи ембеддингів, замість того щоб додавати ще один рівень обробки.
Другий крок: шукайте ознаки проблеми. Високий значення recall@50 у поєднанні з низьким precision@5 — саме цей профіль є підставою для використання алгоритму переранкінгу. Правильний документ є в списку, але знаходиться занадто низько у рейтингу.
Третій крок: свідомо оберіть модель. API, що працює на серверах провайдера, забезпечує швидке запуск та відсутність операційних витрат, але ваші дані залишаються поза вашою інфраструктурою. Самостійно розміщена модель для переранкінгу дає контроль над витратами та конфіденційністю, але вимагає наявності GPU та постійного технічного обслуговування. Це скоріше рішення щодо відповідності стандартам та бюджету, ніж питання якості моделі.
Спробувати його також недорого. Локальне переранжування можна реалізувати приблизно за десяток рядків:
from sentence_transformers import CrossEncoder
reranker = CrossEncoder("BAAI/bge-reranker-large", max_length=512)
def rerank(query, docs):
pairs = [(query, d.page_content) for d in docs] # pair: query + candidate
scores = reranker.predict(pairs) # one logit per pair
return sorted(zip(docs, scores), key=lambda x: x[1], reverse=True)
Найчастіше трапляються три помилки. Одна — це завищування значень K „щоб бути впевненим“. Інша — це переранжування після скорочення контексту, через що модель оцінює лише префікс, а не весь документ. Третя — це сприйняття оцінок крос-енкодерів як абсолютних порогів для порівняння між запитами, що є особливо небезпечним, адже це працює у демо-версії, але не функціонує у продакшені.
Є ще одна менш очевидна проблема: фраза „переранжувач не допомагає“ іноді є наслідком числової помилки, а не архітектурного недоліку. У посібнику з міграції Sentence-Transformers описаний випадок, коли сигмоїда, обчислена у форматі bfloat16, досягла свого максимуму, що призвело до зближення найвищих оцінок та фактичного випадкового порядку їх розташування. Як тільки було використано формат float32 замість bfloat16, порядок ранжування повернувся до нормального.
Усе тут вимагає лише вимірювань, без змін архітектури.
Що це означає для архітектора
Повернімося до позиції 37. Документ, який застряг там, ніколи не був проблемою моделі генерації — це була проблема порядку обробки.
- Крос-енкодер — це не краще ембеддингування. Це окрема архітектура, яка активується після пошуку, читає запит та документ разом та повертає вердикт замість представлення. Покращення якості ембеддингу не дає того, що дає одночасне читання пари документів.
- Переранжування має знаходитися в одному місці. Пошук залишається дешевим та масштабним, переранжування — дорогим та вузьким, і саме структура витрат у цьому ланцюжку є основною ідеєю.
- Більше кандидатів — це не надійний стандарт. Після певного значення K якість справді падає, і причина цього криється у способі навчання цих моделей.
- Стела є жорсткою. Те, що не повернулося на першому етапі, не може бути відновлено за допомогою переранжування, як би не стверджували постачальники.
- Ваші дані — це критерій оцінки. Одного дня, присвятованого обчисленню recall@50 та precision@5 для сотні міткованих запитів, достатньо, щоб покінчити з дискусією, яка інакше могла б тривати тижнями.
Багато команд вважають переранжування стандартною частиною кожної системи RAG, подібно до кешу. Це хибна звичка. Більш зрозуміла картина виникає, коли бачиш обидва пороги разом: нижню межу, нижче якої шар не має чого виправляти, та верхню межу, вище якої він починає псувати результати. Коротко кажучи, переранжування є умовним, а не автоматичним.
Залишається одна проблема. У досліджуваному тут матеріалі не було надано окремих показників для польської мови, а кожне багатомовне число є сумою даних з десятків мов. Для корпусу польською мовою чи будь-якою іншою менш поширеною мовою вимірювання на власних даних — це не просто рекомендація. Це єдиний варіант.