"Запись эфира по RAGу без эмбеддингов (ссылка внизу поста) __Выписал самое важное и дополнил__ Главные проблемы поиска на эмбеддингах: 1. Семантическая схожесть ≠ фактическая релевантность (слова те же, смысл другой) 2. Не учитывает ""логические операции"" в запросе (""и"", ""не"") 3. Не умеет делать промежуточные шаги (сходить в другой кусок текста, чтобы посмотреть значение аббревиатуры или определение) 4. Ломается на агрегации __""вот тебе посты из канала, проанализируй слабые и сильные места автора""__ → найдет посты, где я автор сам что-то пишет про посты/канал и сильные/слабые места. Например, обзор чужого канала. 5. Короткие пользовательские запросы отличаются от длинных чанков документации. И по длине, и по формулировкам 6. Плохо работает с таблицами ——— Запрос пользователя: ""Какие отделы нашей компании, кроме отдела продаж, не выполнили KPI в последнем квартале?"" Догадаетесь, в чем будет проблема с эмбеддингами? - ""Отчет по итогам квартала: Отдел продаж блестяще выполнил KPI, показав рекордный рост!"" - ""План на следующий квартал: всем отделам компании, включая отдел маркетинга, поставлена задача выполнить KPI."" - ""В последнем квартале отдел разработки успешно выполнил все поставленные KPI."" ——— Лечим симптомы (все еще эмбеддинги): 1. query rewriting/expansion и/или Instruction Awareness 2. Векторный поиск по __саммари __чанков, а для генерации ответа использовать их __полный__ текст 3. Можно делать не просто саммари чанков, а генерировать возможные вопросы по ним и искать уже по вопросам 4. Добавлять текст соседних чанков на этапе Generation 5. reranking 6. Препроцессинг документов с сохранением структуры (marker-pdf, docling, unstructured) ——— Лечим причину: 1. Не используем эмбеддинги 2. В качестве search engine берем легковесную LLM. Прогоняем по страницам документа и выдаем им true/false в зависимости от релевантности вопросу (запросы к разным страницам идут в параллель => работает быстро) 3. Вместо 2 совсем наглеем и передаем в запросе сразу сотни страниц – просим выписать только номера релевантных (держим до 200-300к токенов на запрос, даже если окно 1м) 4. gemini-2.5-flesh круто с этим справляется, а главное – нативно кушает pdf без препроцессинга. Понимает таблицы и картинки 🔥 5. __Релевантные__ страницы передаем в ризонинг модель для Generation как в ""классическом RAG"" 6. Не забываем делать Structured Output c промежуточными шагами размышлений ——— Альтернативы (Для более структурированного поиска) Для примера возьмем книгу рецептов и вопрос ""что приготовить на ужин, если у меня есть лапша, фарш и 20 минут времени"" 1. Сначала для каждого рецепта вычленить структурированные поля (ингредиенты, время приготовления, тип блюда – первое, второе, десерт и т.д.) 2. Сложить в SQL все извлеченные данные __и__ исходный текст рецепта 3. Использовать text2sql, чтобы по запросу пользователя создавать search query 4. В Generation идут __исходные текста рецептов__ В реальности обычно создаем разные таблички в бд, потому что данные бывают разных типов с разными параметрами В более простой версии этого подхода, тупо назначаем LLMкой ""теги"" разным кусочками текста и фильтруем по ним, а потом делаем классический RAG или сразу передаем в LLM ——— Общие мысли и ответы на вопросы - Data preparation is a king - Промежуточный вызов LLM – хороший reranker, даже для embedding-based подхода - Всегда пытаемся передать ссылки на исходные блоки инфы. Увеличивает надежность и тестируемость. Высший пилотаж – показывать не только страницы, но и конкретные строчки, на которые опиралась модель - Иногда нужно вообще убрать этап Generation и просто показывать найденные куски информации - LLM retrieval стоит сильно дороже, чем эмбеддинги, но для большого числа кейсов это ок. 1 доллар – все дешевле, чем пару часов сотрудника с зп в десятки баксов в час Доп материалы: Ссылка на сам эфир от @r77_ai (больше деталей, примеров и интересных вопросов от слушателей. сначала разгоняюсь, но потом жара начинается) - Instruction Awareness - Промежуточные шаги размышлений в Structured Output - Кормим pdf в gemini через openai-compatible api"