LongTracer: как поймать галлюцинации в RAG без LLM-судьи
LongTracer — open-source Python-пакет, который ловит галлюцинации LLM в RAG-пайплайнах через гибридный STS + NLI подход. Без внешних API, без LLM-as-a-judge. Разбираю механику, сравниваю с LLM-судьёй и показываю паттерны интеграции.
У RAG-систем есть неприятное свойство: они галлюцинируют уверенно. Модель получила правильные документы, построила красивый ответ — и подмешала туда факт, которого в источниках нет. Или, хуже того, противоречащий им.
Стандартный способ ловить такое — LLM-as-a-judge. Берём второй вызов к GPT-4 / Claude, просим оценить faithfulness ответа. Работает. Но у этого подхода три системных проблемы, которые делают его непригодным для production-критичных сценариев.
LongTracer предлагает альтернативу: детерминированный пайплайн на базе STS + NLI, который работает локально, без API-ключей и без вызова LLM.
Проблема: почему LLM-as-a-judge — слабое звено
Латентность удваивается
Каждый вызов LLM-судьи — это ещё один round-trip к API. В типичном RAG-пайплайне цепочка выглядит так: retrieval → generation → judge evaluation. Третий шаг добавляет 1–5 секунд в зависимости от провайдера и длины контекста. Для интерактивных приложений это неприемлемо.
Стоимость масштабируется линейно
Каждый запрос пользователя стоит вдвое дороже. При 10 000 запросов в день на GPT-4o это ощутимые суммы. А если нужно проверять несколько claims в ответе с детализацией — токены множатся.
Судья тоже галлюцинирует
Это фундаментальная проблема: мы используем вероятностную систему для проверки другой вероятностной системы. LLM-судья может пропустить противоречие, потому что «понял контекст» и решил, что всё корректно. Или наоборот — пометить верный факт как галлюцинацию. Детерминированности нет.
Исследование от Amazon (Developing a Reliable, General-Purpose Hallucination Detection Service, 2024) прямо фиксирует: prompt-based методы «tend to have higher cost and higher latency» при сопоставимом качестве с fine-tuned моделями.
LongTracer: механика под капотом
LongTracer — open-source Python-пакет от ENDEVSOLS (MIT-лицензия, pip install longtracer). Его пайплайн состоит из четырёх этапов.
1. Claim splitting
Ответ LLM разбивается на отдельные утверждения (claims). Каждое предложение — потенциально проверяемый факт.
2. STS matching — быстрый поиск релевантного источника
Для каждого claim используется bi-encoder all-MiniLM-L6-v2 — та самая модель из sentence-transformers, которая генерирует эмбеддинги за микросекунды. Она находит наиболее похожее предложение в source documents. Это этап Semantic Textual Similarity — грубый, но быстрый фильтр.
Зачем отдельный STS-этап? Потому что cross-encoder (NLI) работает медленнее. Если отправить каждый claim на проверку против каждого предложения из всех документов — получим квадратичную сложность. STS сужает пространство поиска до одного кандидата на claim.
3. NLI verification — классификация противоречий
Пара (claim, best_match_source) передаётся в cross-encoder nli-deberta-v3-xsmall — модель Natural Language Inference. Она классифицирует отношение как:
- Entailment — claim подтверждается источником
- Contradiction — claim противоречит источнику
- Neutral — claim не подтверждается и не опровергается
Это ключевое отличие от LLM-судьи. DeBERTa не «рассуждает» и не «интерпретирует». Она классифицирует — детерминированно, с фиксированным временем инференса.
4. Verdict — trust score и флаги
На выходе — числовой trust_score (0.0–1.0), количество hallucinations и детализация по каждому claim: какой факт проблемный, какой источник его опровергает.
from longtracer import check
result = check(
"Эйфелева башня высотой 330 метров и находится в Берлине.",
["Эйфелева башня — кованая решётчатая башня в Париже, Франция. Высота 330 метров."]
)
print(result.verdict) # "FAIL"
print(result.trust_score) # 0.5
print(result.hallucination_count) # 1 — "Берлин" vs "Париж"
Сравнение: LongTracer vs LLM-as-a-judge
Сравнение по ключевым параметрам:
- Латентность: LongTracer — 50–200 мс на claim; LLM-as-a-judge — 1–5 с на запрос
- Стоимость: LongTracer — $0 (локальная модель); LLM-as-a-judge — $0.01–0.10 за проверку
- Детерминированность: LongTracer — да (одинаковый вход → одинаковый выход); LLM-as-a-judge — нет
- Объяснимость: LongTracer — точная пара claim↔source; LLM-as-a-judge — «я считаю, что ответ неверен»
- Внешние зависимости: LongTracer — нет; LLM-as-a-judge — API-ключ, сеть
- Сложные рассуждения: LongTracer — слабо (только поверхностные противоречия); LLM-as-a-judge — хорошо
Честный ответ: LongTracer не заменяет LLM-judge полностью. NLI-модель размером в 22M параметров не уловит тонкие логические несоответствия, которые требуют цепочки рассуждений. Но для фактологических проверок — имена, числа, даты, локации, прямые утверждения — она работает надёжнее, потому что не добавляет собственную вероятностную ошибку.
Паттерны интеграции в production RAG
Паттерн 1: Guard rail на выходе
Самый простой — обернуть генерацию проверкой:
from longtracer import check
def guarded_rag(query, retriever, llm):
docs = retriever.get_relevant_documents(query)
response = llm.invoke(query, context=docs)
result = check(response, [d.page_content for d in docs])
if result.trust_score < 0.7:
return "Не могу дать достоверный ответ на основе имеющихся документов."
return response
Подходит для: чат-ботов, где лучше отказать, чем соврать.
Паттерн 2: Инструментация фреймворка
LongTracer имеет адаптеры для LangChain, LlamaIndex, Haystack и LangGraph:
from longtracer import LongTracer, instrument_langchain
LongTracer.init(project_name="chatbot-prod", backend="sqlite")
instrument_langchain(your_chain)
# Каждый chain.invoke() теперь автоматически верифицируется
Трейсы сохраняются в SQLite / MongoDB / PostgreSQL / Redis. Можно строить дашборды, экспортировать в HTML/JSON, фильтровать по проектам.
Паттерн 3: Двухуровневая проверка
Для критичных доменов — fintech, legal, медицина — имеет смысл комбинировать:
- LongTracer — быстрый первый проход, ловит очевидные противоречия за миллисекунды
- LLM-judge — только для ответов с trust_score в серой зоне (0.4–0.7)
Это снижает стоимость LLM-judge на 60–80% (большинство ответов либо явно верны, либо явно ошибочны) и убирает латентность с критического пути.
Паттерн 4: Batch-аудит
from longtracer import check_batch
results = check_batch([
{"response": resp, "sources": srcs}
for resp, srcs in production_logs
])
flagged = [r for r in results if r.trust_score < 0.5]
Прогнать вчерашние логи, найти проблемные ответы, скорректировать retrieval — без единого API-вызова.
Ограничения, которые нужно понимать
Поверхностное сравнение. NLI-модель сравнивает предложения на уровне лексики и простой семантики. «Компания основана в 2020 году» vs «Компания работает уже 6 лет» — LongTracer может не увидеть противоречия (или подтверждения), потому что это требует арифметики.
Зависимость от quality of retrieval. Если retriever вернул нерелевантные документы, LongTracer честно пометит всё как neutral/contradiction. Garbage in — garbage out.
Мультиязычность. Базовые модели (MiniLM, DeBERTa) обучены преимущественно на английском. Для русского, китайского, арабского нужны соответствующие модели — и LongTracer пока не предлагает их из коробки.
Не ловит omissions. Если LLM пропустил критически важный факт из документа — это не противоречие, и LongTracer его не найдёт.
Почему это важно именно сейчас
RAG стал default-архитектурой для enterprise AI. Банки, юридические компании, медицинские системы строят на нём свои продукты. В этих доменах галлюцинация — это не «неудобный ответ», а комплаенс-нарушение, врачебная ошибка, юридическая ответственность.
LLM-as-a-judge добавляет проверку, но не добавляет гарантий. Он сам вероятностный. Он сам может ошибиться. Регуляторы fintech и healthtech всё чаще требуют объяснимых, аудируемых процессов верификации — а «мы спросили другую LLM, и она сказала что всё ок» не пройдёт аудит.
LongTracer предлагает детерминированный, объяснимый, локальный слой верификации. Не серебряная пуля — но конкретный инструмент для конкретной проблемы. С pip install и пятью строками кода до первого результата.
GitHub: ENDEVSOLS/LongTracer (https://github.com/ENDEVSOLS/LongTracer) | Лицензия: MIT