ESPN DeportesMéxico: Alan Cervantes causa baja por lesiónESPNNWSL: Denver the big movers as Gotham retain top spotDaily MaverickGROUNDUP: Police and NPA liable for Gqeberha murder by man out on bailInquirer EntertainmentCeleste Legaspi recalls Lea Salonga’s early theater days before Walk of Fame starInquirerPNP: 2 vandalism suspects in martial law rally pacified, not arrestedCBS NewsBill Gates says Trump's AI views point to societal blind spotGlobal NewsEd Sheeran breaks down during 1st concert amid Macklemore tour fallout01netLa Switch OLED revient d’entre les morts : à ce prix, elle va se vendre par camions 🚛Screen RantPlayStation Officially Unveils Brand-New Hardware And Redesigned ControllerTagesschauMarktbericht: Entspannung am Ölmarkt stützt den DAXVarietyAmerican Film Market Partners With AMC A-List and B-List Movie Club to Offer Screenings to Frequent MoviegoersBusiness AMAmerikaans scheepsbouwbedrijf begint met voorbereidende werk voor de bouw van nieuw vliegdekschip USS William J. Clinton
The Daily Newsstand · Free, Always
Monday, September 21, 2026

Почему ваша LLM тупеет на больших документах и как ее починить

Translate

Меня зовут Андрей Бирюков. Я — независимый эксперт в области ИТ и ИБ, преподаю в учебных центрах и пишу статьи и книги. 

Когда Google анонсировал 2M контекста, а Anthropic подкинул еще 100K, наверняка многие подумали, что RAG теперь можно выкинуть на свалку истории.

Зачем париться с этими чанками, эмбеддингами и всякой прочей ерундой, если можно просто кинуть в модель весь дамп википедии и спросить ее что угодно?

Однако, в реальности возникает эффект, который тихо убивает вашу точность, когда модель читает ваш гигантский промпт как студент перед экзаменом. То есть, первые 5 страниц учит, последние 5 страниц учит, а середину... ну, там что‑то было про котиков, наверное.

И в итоге контекст 2M, а вопрос по документу на 100 страниц модель отвечает хуже, чем GPT-3.5 с контекстом 4K. И да, это не баг, это фича архитектуры внимания.

В этой статье мы поговорим о том, как перестать кормить LLM модели тоннами текста и начать использовать маленькую модель как умного секретаря, повысив точность с 34% до 68%, одновременно сократив расходы в 8 раз.

Пытаем LLM документацией

Давайте для чистоты эксперимента возьмем реальный датасет — 500 страниц технической документации по сетевому оборудованию (наши любимые логи, IP‑адреса, версии прошивок). Разобьем его на 5 сегментов по 100 страниц: A, B, C, D, E.

Далее нам нужно будет задать 10 вопросов, ответы на которые лежат строго в сегменте C (золотая середина) и посмотреть, что из этого выйдет.

Стратегия № 1: Full‑Context (кормим всё целиком)

Начнем с самого простого варианта: запихнуть все 500 страниц в контекст GPT-4o. Но результат оказался не слишком интересным, так как мы получили точность всего 34%, и при этом первый токен появился только через 14 секунд (согласитесь, многовато).

Ну и конечно не обошлось без галлюцинаций: модель начала комбинировать IP‑адреса из сегментов A и E, создавая несуществующие маршруты.

В реальности такой вариант практически бесполезен.

Стратегия № 2: Naive RAG (векторный поиск, топ-5 чанков)

Теперь давайте немного усложним реализацию, нарезав данные на чанки. Здесь мы получаем точность 42%, то есть лучше, но не намного. При этом, ответ пришел через 1.1 секунды, быстро, но зачем скорость, если ответ неправильный?

Здесь суть проблемы заключается в том, что мы теряем контекст между чанками, и из‑за этого модель не понимает общей картины.

В итоге мы приходим к неутешительному выводу о том, что оба подхода неприменимы, так как Full‑Context дорогой и тупой, а Naive RAG быстрый, но тоже недалекий.

RAPTOR, Self‑Refine и прочие модные штуки

Прежде чем перейти к реально работающему решению, давайте разберем, почему некоторые существующие паттерны не работают в 2026 году.

RAPTOR (Recursive Abstractive Processing)

Этот паттерн строит деревья кластеров, суммаризируя их на каждом уровне. Звучит вроде бы мощно, однако, на практике он отлично подходит для пересказа «в целом», но убивает точность.

Например, спросите у RAPTOR версию драйвера на странице 245 из нашей документации, и он выдаст вам среднюю температуру по больнице. Потому что суммаризация усредняет факты, что хорошо подходит для аналитики, но для техподдержки и других задач, требующих точности это смерть.

Self‑Refine / ReAct (итеративные уточнения)

Эта модель что называется, ходит кругами, то есть перечитывает контекст и постоянно уточняет.

Она как‑бы работает, но требует 5–7 запросов к дорогой LLM и стоимость одной сессии может достигать $0.5. Теперь умножьте на 1000 пользователей в день и получите достаточно серьезные затраты.

Первым решением, которое может прийти на ум в такой ситуации, это увеличение чанков.

Если модель теряется в середине 500-страничного документа, давайте сделаем чанки по 10K токенов. Но, после такого изменения модель теряется в середине каждого чанка и становится только хуже.

Таким образом, мы приходим к неутешительному выводу о необходимости нового подхода, обеспечивающего точность, скорость и по приемлемой цене.

Семантический привратник

Представьте, что у вас в компании есть дорогой и талантливый юрист (наша большая LLM). Вы не будете скидывать ему 500 страниц договора и говорить «разберись». Вместо этого, вы сначала дадите договор младшему ассистенту, который вытащит оттуда ключевые факты (суммы, даты, стороны), оценит, какая часть договора вообще относится к вашему вопросу. В итоге ассистент подаст юристу только самое важное на одной странице. Именно так и будет работать наш «Семантический привратник».

Роль ассистента будет выполнять Mistral-7B‑Instruct в 4-битной квантизации. Он стоит копейки (в смысле денег и ресурсов), но умеет читать и анализировать.

Давайте посмотрим, как все это работает. В начале, мы делаем грубый векторный поиск по базе знаний и достаем не 5 чанков, а 50, чтобы наверняка не потерять релевантный кусок. Дальше каждый из этих 50 чанков прогоняем через Mistral-7B с простой задачей: «Оцени релевантность чанка вопросу от 0 до 1. Вытащи оттуда 3 ключевых факта. Ответь в формате JSON.»

При этом мы запрещаем модели фантазировать, то есть, она не генерирует связный текст, а только извлекает факты из исходного чанка. Это снижает вероятность галлюцинаций до минимума.

Вот пример ответа Mistral:

Далее мы используем буфер динамического приоритета, то есть сортируем 50 чанков по значению score и всё, что ниже 0.6, выкидываем. Из оставшихся берем ТОП-10 по релевантности.

Здесь важным моментом является то, что мы не кладем эти чанки в том порядке, в котором они были в документе. Вместо этого, мы сортируем их по убыванию важности и самый релевантный становится первым.

Ранее мы говорили о том, что модель забывает середину. Давайте попробуем ее обмануть, и для этого в начало промпта мы положим сжатые синопсисы всех 10 чанков (это примерно 2000 токенов), а в самом конце промпта продублируем наиболее релевантный чанк целиком, без сжатия.

Теперь самые важные факты оказались и в начале (как краткое резюме), и в конце (как развернутый оригинал). Модель видит их в обеих зонах высокой концентрации внимания и увернуться от фактов ей невозможно.

Как это выглядит на практике

Для инференса Mistral-7B мы используем vLLM — он расходует меньше памяти и работает быстрее трансформеров из коробки. Вот рабочий код нашего пайплайна на Python:

from vllm import LLM, SamplingParams
import json

# Загружаем Mistral-7B в 4-битной квантизации
# На A100 40GB влезает без проблем
llm = LLM(
    model="mistralai/Mistral-7B-Instruct-v0.3",
    quantization="AWQ",  # 4-bit квантизация
    dtype="half",
    max_model_len=4096
)

def gatekeeper_filter(query, chunks, top_k=10):
    """
    query: вопрос пользователя
    chunks: список из 50 чанков (текст)
    top_k: сколько лучших оставить
    """
    prompt_template = """
    [INST]
    Твоя задача — проанализировать фрагмент документа.
    Вопрос пользователя: {query}
    
    Текст фрагмента:
    {chunk}
    
    Ответь строго в формате JSON:
    - "score": число от 0 до 1 (насколько чанк релевантен вопросу)
    - "facts": массив из максимум 3 ключевых фактов (короткие предложения из текста)
    
    Пример: {{"score": 0.85, "facts": ["Сервер перезагружен в 14:32", "Ошибка E531"]}}
    [/INST]
    """
    
    # Готовим батч промптов для 50 чанков
    batch_prompts = [
        prompt_template.format(query=query, chunk=chunk) 
        for chunk in chunks
    ]
    
    # Запускаем инференс с низкой температурой (детерминизм)
    sampling_params = SamplingParams(
        temperature=0.0,      # Никакой креативности, только факты
        max_tokens=200,
        stop=["\n\n"]         # Чтобы не генерировала лишнего
    )
    
    outputs = llm.generate(batch_prompts, sampling_params)
    
    # Парсим JSON из ответов
    parsed_results = []
    for i, output in enumerate(outputs):
        raw_text = output.outputs[0].text
        try:
            # Ищем { ... } в ответе
            start = raw_text.find('{')
            end = raw_text.rfind('}') + 1
            json_str = raw_text[start:end]
            data = json.loads(json_str)
            parsed_results.append({
                "score": float(data.get("score", 0.0)),
                "facts": data.get("facts", [])[:3]
            })
        except (json.JSONDecodeError, ValueError):
            # Если модель накосячила — ставим низкий скор
            parsed_results.append({"score": 0.0, "facts": []})
    
    # Сортируем по убыванию скора
    scored_chunks = list(zip(chunks, parsed_results))
    scored_chunks.sort(key=lambda x: x[1]['score'], reverse=True)
    
    # Берем топ-K
    top_chunks = scored_chunks[:top_k]
    
    # Компонент В: формируем сжатый контекст из фактов
    compressed_facts = []
    for chunk_data, meta in top_chunks:
        compressed_facts.extend(meta['facts'])
    
    # Ограничиваем длину, чтобы не переполнить контекст
    compressed_context = " ".join(compressed_facts[:40])
    
    # Дублируем лучший чанк целиком в конец
    best_chunk_raw = top_chunks[0][0] if top_chunks else ""
    
    return {
        "compressed_context": compressed_context,
        "anchor_chunk": best_chunk_raw
    }

# Пример использования
chunks = [...]  # ваши 50 чанков из векторной БД
query = "Какая версия прошивки была на сервере 10.0.4.22 во время сбоя?"

result = gatekeeper_filter(query, chunks)

# Формируем финальный промпт для GPT-4
final_prompt = f"""
Контекст (ключевые факты):
{result['compressed_context']}

Подробный фрагмент документа (самый важный):
{result['anchor_chunk']}

Вопрос пользователя: {query}

Ответь на вопрос, используя только предоставленную информацию.
"""

В итоге, результат будет иметь следующий вид:

Что мы получили в итоге

В заключении давайте посмотрим, какие результаты мы получили. Мы прогнали наш пайплайн на 1000 запросов из реальной техподдержки и сравнили с тремя другими подходами.

Метод

Токенов в промпте

Точность (точное совпадение)

Задержка

Стоимость за 1000 запросов

Full‑Context

~180 000

34.2%

14.5 сек

$180

Naive RAG (Top-5)

~8 000

41.1%

1.4 сек

$15

RAPTOR

~12 000

49.7%

5.2 сек

$40

Semantic Gatekeeper (наш)

~9 000

68.4%

3.8 сек

$22

Если говорить о точности, то мы обогнали Full‑Context почти вдвое (68% против 34%), благодаря тому, что LLM перестала отвлекаться на шум. Мы дали ей только релевантные факты, а не 500 страниц воды.

Также, мы потратили 2.4 секунды на прогон через Mistral-7B, но сэкономили 10 секунд на GPT-4 (потому что промпт стал в 20 раз короче). И наконец, по деньгам, мы потратили $22 против $180, то есть экономия в 8 раз. На загрузке в десятки тысяч запросов вы можете сэкономить значительные суммы.

Таким образом, мы смогли починить наш RAG и получить хороший результат при обработке большого объема запросов.

ЧТО ЕЩЕ ПОЧИТАТЬ ПО ТЕМЕ:

Если вы уже работаете с LLM или только начинаете строить свои AI‑системы, наверняка сталкивались с проблемой: модель знает много, но при работе с большими объёмами данных начинает терять важные детали и выдавать неточные ответы. Разобраться, как управлять качеством работы LLM и строить надёжные сценарии взаимодействия с моделями, — следующий шаг после знакомства с базовыми возможностями ИИ.

На бесплатных уроках разберём, как устроены современные подходы к работе с LLM:

  • 22 сентября в 18:00. «Ландшафт современного NLP: от эмбеддингов и классических ML‑методов до современных LLM». Записаться.

  • 23 сентября в 18:00. «Structured Outputs: как заставить LLM всегда возвращать то, что вам нужно». Записаться.

  • 1 октября в 20:00. «Проверка ответов LLM и борьба с галлюцинациями через промпт‑инжиниринг». Записаться.

View the original on Хабр

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.