Комментарии 7
Инструмент для разбора ошибок отличный! Но есть вопрос по поводу “галлюцинаций”. Допустим, поиск (BM25) найдет три документа, где просто есть нужные слова, но по сути они к аварии не относятся. Сможет ли нейросеть на финальном этапе это раскусить и сказать: “Документы есть, но связи нет”? Или она в любом случае придумает ложную версию?
Спасибо за отличный вопрос! Вы затыкаете пальцем самую уязвимую зону всех RAG-систем.
В текущей реализации WhyTrend эта проблема решается двумя барьерами:
Жёсткий системный промпт (Prompt Engineering): Мы не просто отдаем модели текст со словами "объясни аномалию". В
Explainerзашит системный промпт с правилами:опираться только на переданный event и evidence;
не выдумывать источники, URL и факты;
если evidence слабый или отсутствует — сказать об этом прямо и снизить confidence.
Современные LLM (вроде тех же Qwen 2.5 или DeepSeek) при таком ограничении работают на удивление честно и вместо фантазий выдают что-то вроде: "Контекст найден, но явной причинно-следственной связи не прослеживается".Прозрачность для пользователя: Даже если модель немного притянет версию, в Markdown-отчёте WhyTrend видны cited causes: источники, URL и score. Пользователь может открыть ссылки и понять, на чём строился вывод. Если материалы мусорные — человек это быстро заметит. Инструмент не заменяет аналитика, а готовит первый черновик.
В планах — усилить отсев текстового шума ещё до LLM (например, cross-encoder / более умное переранжирование и явный вывод ranked evidence в отчёт), чтобы такие документы реже доходили до модели.
Интересная статья, спасибо! Но мне кажется, противопоставлять BM25 и эмбеддинги не обязательно. В современном RAG отлично себя показывает гибридный поиск: когда BM25 и векторный поиск работают параллельно, а их результаты объединяются через RRF.
А если применить контекстуальный чанкинг (добавление краткой саммаризации документа к чанку перед векторацией), то качество векторного поиска вырастет в разы и ограниченное количество исходных документов не будет так сильно влиять. Не думали добавить подобный гибридный ранжирующий модуль в пайплайн WhyTrend?
Спасибо, за вопрос)
В статье «BM25 против эмбеддингов» — скорее про почему BM25 появился раньше, а не про то, что эмбеддинги хуже. BM25 и эмбеддинги не противники, а комплементарные сигналы. Сейчас в WhyTrend они просто живут как два независимых Ranker (BM25Ranker / EmbeddingRanker) — в pipeline пока выбирается один, без merge.
Гибрид через RRF как раз хорошо ложится на архитектуру: отдельный HybridRanker, который гоняет оба скорера и склеивает списки. Это логичный следующий шаг по качеству retrieval, рядом с тем, что уже обсуждаем для слоя после ranker (пороги relevance, более умный rerank, меньше ложных корреляций).
По контекстуальному чанкингу — идея сильная для длинных документов, но у WhyTrend evidence чаще уже короткое (title + snippet из API). Там выигрыш меньше, чем в классическом RAG по PDF/базе знаний. Имеет смысл там, где collector тащит длинные тексты (релизы, тикеты, внутренние wiki) — тогда summarize-before-embed как опция к embedding-ветке.
Заголовок, похоже, получился чуть конфликтнее, чем задумывалось 🙂
BM25 и эмбеддинги не противники, а комплементарные сигналы.
Тогда вопросов больше не имею, все четко.
Там выигрыш меньше, чем в классическом RAG по PDF/базе знаний
У меня обратная ситуация получалась, но видимо, у нас разные ситуации с данными и у меня были не настолько короткие документы как я думал.
Заголовок, похоже, получился чуть конфликтнее, чем задумывалось 🙂
Хороший заголовок, стриггерил на комментарий, плохо что ли? Хорошо!
Интересный подход с параллельным запуском коллекторов! Но что делать, если один из внешних источников (например, Reddit или Hacker News) начнет жестко отдавать 429 (Rate Limit) или просто зависнет намертво? Предусмотрены ли в конвейере таймауты «из коробки» для каждого Collector, чтобы самый медленный источник не дропал весь асинхронный pipeline?
Хороший вопрос. Да, это учтено на двух уровнях.
1. Изоляция источников. Коллекторы крутятся через asyncio.gather(..., return_exceptions=True). Если Reddit отдаёт 429 или падает с ошибкой, исключение не валит весь pipeline: этот источник просто не добавляет evidence, остальные продолжают работу.
2. Таймауты HTTP. У встроенных collectors из коробки есть timeout (по умолчанию 10 секунд) на httpx-клиент — «зависший» сокет не держит конвейер бесконечно. Значение можно подкрутить в конструкторе, например RedditCollector(timeout=5.0).
Важно: это таймаут сетевых запросов, а не отдельный deadline на весь кастомный collect(). Retry при 429 и circuit breaker пока не встроены — при желании их легко добавить в свой collector или обертку. Идея та же: один капризный источник не должен ронять объяснение аномалии целиком.

BM25 против эмбеддингов, Protocol против наследования: как рождался фреймворк WhyTrend