Это первая часть из задуманной серии статей про ИИ. Здесь мы на немного заступим в техническую часть памяти/контекста LLM моделей. Разберем, почему они частенько забывают или выдумывают факты и врут.


Как attention ломается на длинном контексте

Начнём с фундамента. Трансформер работает на self-attention - каждый токен смотрит на все остальные и решает, на что обратить внимание. Квадратичная сложность O(n²) - это причина, по которой модели вынуждены использовать оптимизации: FlashAttention-2/3, RoPE, ALiBi и прочее.

Эти оптимизации не бесплатны. Они создают позиционные смещения:

  • Primacy bias - модель лучше всего помнит начало контекста
  • Recency bias - и конец тоже помнит неплохо
  • Всё, что в середине - получает ослабленное внимание

Представьте, что вы читаете книгу на 500 страниц за один присест. Первую главу помните, последнюю помните, а что было на странице 247? Модель работает примерно так же, только она ещё и не признается, что забыла - вместо этого уверенно додумает.)


Lost-in-the-Middle

Классическую работу Nelson Liu и коллег из Stanford (2023) знают, наверное, все, кто работает с RAG. U-образная кривая: точность падает на 30-50%, когда нужная информация оказывается в середине контекста из 20-30 документов.

С 2023 года модели конечно стали лучше, но проблема все еще остается.

В 2025-2026 годах команды из MIT и других лабораторий подтвердили: эффект Lost-in-the-Middle сохраняется даже у моделей с окном 1M+ токенов. Причина архитектурная - causal attention masking плюс decay в positional embeddings (тот самый RoPE). Чем длиннее окно, тем больше середина, и тем сильнее bias.

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


Бенчмарки 2025-2026

Needle-in-a-Haystack - тест Грега Камрадта из 2023-го. Спрячь факт в длинном тексте, спроси модель - найдёт или нет. Простой, наглядный, убедительный.

К 2025-2026 годам он превратился в целое семейство бенчмарков:

  • U-NIAH (2026) - напрямую сравнивает long-context LLM и RAG
  • NeedleBench, BABILong, LooGLE - проверяют не просто поиск одного факта, а синтез информации из разных частей контекста

Почему галлюцинации растут с длиной контекста

Появляется логичный вопрос, почему модель врет, а не говорит “хз”.

Вот три ключевых наблюдения из свежих исследований:

Vectara Hallucination Leaderboard (HHEM-2.3, февраль 2026): на документах 32K+ токенов уровень галлюцинаций стабильно выше, чем на коротких. Модели начинают додумывать связи между фактами, которых в тексте нет. Они видят фрагмент A и фрагмент C, не видят B посередине - и изобретают собственный B.

OpenAI research (декабрь 2025), “When More Becomes Less”: рост контекста увеличивает стоимость инференса, но не качество. Модель получает частичные доказательства и заполняет пробелы правдоподобно. Это буквально определение галлюцинации.

MIT (январь 2025): самое забавное и неприятное открытие - модели используют более уверенный язык именно при галлюцинациях в длинном контексте. Чем меньше модель видит реальный факт, тем увереннее она его выдумывает.

Если упростить: Длинный контекст -> больше шума -> внимание размывается -> модель не находит нужный факт -> но обучена всегда давать ответ -> начинает креативничать

Это не баг конкретной модели. Это следствие того, как работает архитектура трансформера в сочетании с RLHF, который учит модель быть полезной(всегда отвечать)


Что помогает в продакшене

Теперь немного техники

Chunking - 70% успеха RAG

Если у вас проблемы с галлюцинациями в RAG-системе, первое, на что стоит смотреть - это как вы нарезаете документы.

Не доверяйте дефолтному сплиттеру.

  • RecursiveCharacterTextSplitter (LangChain) - рабочая лошадка. 400-512 токенов, overlap 10-20%. Простой, предсказуемый, хорошо работает на структурированных текстах.
  • SemanticChunker - разбивает по смыслу через эмбеддинги. Даёт +15-20% точности на сложных документах, где логические блоки не совпадают с абзацами.
  • HierarchicalNodeParser (LlamaIndex) - многоуровневые чанки (2048 → 512 → 128). Позволяет сначала найти нужный раздел, потом нужный абзац, потом нужное предложение.

Ключевая идея - не запихивайте в контекст модели 100K токенов “на всякий случай”. Дайте ей 3-5 релевантных чанков по 500 токенов. Меньше мусора - меньше галлюцинаций.

Пример chunking + reranking

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS

# 1. Recursive + overlap
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=100,  # ~20%
    separators=["\n\n", "\n", ". ", " ", ""]
)

# 2. Semantic splitter (для сложных документов)
from langchain.text_splitter import SemanticChunker
embeddings = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-mpnet-base-v2"
)
semantic_splitter = SemanticChunker(embeddings)

# 3. Reranking
from langchain.retrievers.document_compressors import CrossEncoderReranker

compressor = CrossEncoderReranker(
    model_name="BAAI/bge-reranker-large"
)

compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=vectorstore.as_retriever(
        search_kwargs={"k": 20}  # Достаём 20, reranker оставит топ-5
    )
)

Достаём 20 чанков, reranker отбирает топ-5. Это критически важно. Без reranking вы отправляете в модель кучу почти релевантных чанков, которые только добавляют шума.

Verification layers

Даже с идеальным chunking модель может галлюцинировать. Поэтому нужен второй эшелон обороны.

Self-Consistency / Chain-of-Verification (CoVe) - просим модель сгенерировать ответ, потом сгенерировать вопросы для проверки этого ответа, потом ответить на эти вопросы.

Critic Agent - отдельный LLM (можно дешёвый и маленький) проверяет ответ на соответствие контексту. “Вот контекст, вот ответ. Всё ли в ответе подтверждается контекстом? Да/Нет + объяснение.”

Symbolic verification - после генерации прогоняем через Knowledge Graph или Pydantic-схему с Guardrails. Если ответ содержит дату, число, имя - проверяем программно.

Agentic workflows

Это уже паттерн 2026 года. Вместо одного вызова “контекст -> ответ” строим цикл из нескольких агентов:

  1. Planner - разбивает задачу на подзадачи
  2. Retriever Agent - ищет по чанкам для каждой подзадачи отдельно
  3. Executor - генерирует ответ
  4. Verifier Agent - проверяет и возвращает на доработку, если что-то не сходится

Это дороже. Это медленнее. Но в продакшене, где галлюцинация стоит денег или репутации - это окупается.

Вот минимальный пример verification loop:

from langchain.agents import create_react_agent, AgentExecutor
from langchain.tools import Tool

def verify_answer(answer: str, context: str) -> str:
    """Отдельная модель-критик проверяет ответ"""
    prompt = (
        "Проверь, соответствует ли ответ контексту. "
        "Ответь YES/NO + объяснение.\n"
        f"Context: {context}\n"
        f"Answer: {answer}"
    )
    return llm.invoke(prompt)

tools = [
    Tool(
        name="Verifier",
        func=verify_answer,
        description="Проверяет ответ на соответствие контексту"
    )
]

agent = create_react_agent(llm, tools, prompt=react_prompt)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=5  # Не больше 5 попыток
)

Hybrid neuro-symbolic

Для доменов с жёсткими требованиями к точности - юриспруденция, медицина, финансы - есть ещё один уровень.

Комбинация LLM + Knowledge Graph + symbolic verifier. Идея простая, LLM генерирует ответ, Knowledge Graph проверяет факты и связи, symbolic verifier валидирует логику.

Исследования 2025 года показывают снижение галлюцинаций на 60-80% в таких доменах. Но это тяжёлая инфраструктура. Нужен граф знаний, нужны правила, нужна команда, которая всё это поддерживает.

Если у вас чат-бот для интернет-магазина - это overkill.


По итогу: суй меньше - получишь лучше) Если данная статья была для вас интересна, но перегружена терминами - дайте знать, и я подготовлю версию, где простым языком все объясню.