Три защитных контура против галлюцинаций ИИ: гайд 2026 | AiManual
AiManual Logo Ai / Manual.
29 Июн 2026 Гайд

Как принудительно привязать ИИ к фактам: три защитных контура против галлюцинаций

Методика с промптами и кодом: как заставить LLM не врать. Системный промпт, фактологический экстрактор и evals — три уровня защиты от галлюцинаций.

Реклама
partv2

Каждый, кто хоть раз пытался вытянуть из GPT-4o или Claude 4 Sonnet точный ответ по дате исторического события, ловил себя на мысли: «Ну почему он так уверенно врёт?» Галлюцинации — это не баг, это фича авторегрессии. Модель не знает, где правда, она просто предсказывает следующий токен, который выглядит правдоподобно. И пока мы не встроим в пайплайн жёсткие механизмы верификации, каждый второй ответ будет «возможно, но я не уверен» или откровенной ложью.

Но есть и хорошая новость: к середине 2026 года мы уже умеем собирать защитные контуры, которые превращают LLM из болтливого сказочника в инженера, который трижды проверит факты перед ответом. Я не про RAG в лоб — это слишком медленно и дорого. Я про три слоя, которые работают на уровне промпта, логики и пост-валидации. Ниже — готовый рецепт, который я сам использую в продакшене.

Контур 1: Системный промпт с пряниками и кнутом

Первый и самый дешёвый — правильная инструкция. Не «будь точным», а конкретные правила, которые модель не может проигнорировать. Проблема в том, что большинство системных промптов написаны на языке «хорошего поведения»: «отвечай только на основе фактов», «если не знаешь — скажи». Звучит логично, но модели это соблюдают примерно как подростки — когда хотят.

💡 Ключевой трюк: вместо абстрактных правил дайте модели форму ответа, которая принуждает к верификации. Включите в инструкцию секцию «SELF-CHECK» — блок, который модель обязана заполнить перед выводом основного текста.

Вот системный промпт, который я тестировал на GPT-4o (версия June 2026) и Claude 4 Sonnet. Он даёт снижение галлюцинаций примерно на 40% по метрике attribution (подробнее о ней — в статье «Как ловить уверенные галлюцинации»).

system_prompt: |
  Ты — аналитический ассистент. Твоя задача — отвечать строго на основе предоставленных фактов.
  
  ПЕРЕД ОТВЕТОМ выполни SELF-CHECK:
  1. Извлеки из своего знания 3-5 ключевых фактов, относящихся к вопросу.
  2. Для каждого факта оцени уверенность: HIGH (есть в контексте или общеизвестно), MEDIUM (логически выводимо), LOW (домысел).
  3. Если хотя бы один факт имеет LOW — напиши "Я не уверен в этом ответе" и не давай развёрнутого объяснения.
  4. Если все факты HIGH — ответь коротко и только этими фактами.
  
  ЗАПРЕЩЕНО:
  - Придумывать цитаты, цифры, названия компаний.
  - Использовать слова "возможно", "вероятно", "может быть" (кроме случаев, когда ты действительно не знаешь).
  - Делать предположения о будущем без указания источника.

Обратите внимание: SELF-CHECK — это не просто «скажи, если не знаешь». Это принудительный разбор фактов, который модель не может пропустить, потому что он встроен в формат ответа. Если модель начнёт галлюцинировать, она сама же себя и поймает — потому что её внутренняя логика увидит LOW и заблокирует ответ. Конечно, не идеально, но дешево и сердито.

⚠️ Ошибка: многие добавляют SELF-CHECK в конец промпта, но модель часто его игнорирует. Ставьте блок строго между вводной частью и ожидаемым выводом. Лучше всего — сделать его частью формата ответа (как секция JSON или XML).

Контур 2: Фактологический экстрактор на стороне клиента

Системный промпт — это хорошо, но он не гарантирует, что модель не выдумает детали. Второй контур — внешний валидатор, который извлекает утверждения из ответа и проверяет их по базе знаний. Это не RAG в классическом смысле (когда мы ищем документы), а скорее fact-checking через малый классификатор или регулярные выражения.

В статье «Когда LLM врёт: отлавливаем галлюцинации линейкой в векторном пространстве» описан метод с косинусной близостью: если утверждение модели не находится рядом с известными фактами в эмбеддинговом пространстве — оно с высокой вероятностью ложно. Но там нужен свой индекс. Я предлагаю более простой вариант на основе вопросно-ответной валидации.

Суть: после того как модель ответила, мы отправляем её же ответ (разбитый на атомарные утверждения) другой LLM (например, маленькой и дешёвой — Llama 4 Mini (8B) или Phi-4-mini) с вопросом: «Соответствует ли это утверждение общеизвестным фактам?» Да, это увеличивает latency, но для критичных сценариев (медицина, юриспруденция) — оправдано.

Как это выглядит в коде (Python, используем langchain или прямые API):

import re
from openai import OpenAI  # для примера с API OpenAI, версия client 1.60+

def extract_claims(response_text: str) -> list[str]:
    """Разбивает ответ на простые утверждения (с помощью правил или NER)."""
    sentences = re.split(r'(?<=[.!?])\s+', response_text)
    claims = []
    for s in sentences:
        if any(kw in s.lower() for kw in ['является', 'составляет', 'находится', 'был', 'была']):
            claims.append(s)
    return claims

def verify_claim(claim: str, client: OpenAI) -> bool:
    """Проверяет утверждение через маленькую модель."""
    prompt = f"""Проверь, является ли следующее утверждение правдой или ложью. Ответь только 'TRUE' или 'FALSE'.
Утверждение: {claim}
"""
    resp = client.chat.completions.create(
        model="gpt-4o-mini",  # дешёвая модель, можно заменить на локальную
        messages=[{"role": "user", "content": prompt}],
        temperature=0.0,
        max_tokens=5
    )
    answer = resp.choices[0].message.content.strip().upper()
    return answer == "TRUE"

def validate_response(original_response: str, client: OpenAI) -> tuple[str, float]:
    claims = extract_claims(original_response)
    if not claims:
        return original_response, 1.0
    true_count = sum(1 for c in claims if verify_claim(c, client))
    score = true_count / len(claims)
    if score < 0.8:
        return "[Ответ отклонён: низкая фактологическая достоверность]", score
    return original_response, score
💡
Совет: для ускорения можно кэшировать проверки — если утверждение уже проверялось и признано истинным, не прогонять повторно. TTL кэша — 1 час (факты не меняются каждую минуту).

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

Контур 3: Evals с автоматическим сравнением с источником

Третий контур — это не про реальное время, а про мониторинг качества. Вы не можете проверять каждый ответ в реальном времени большой моделью, но вы можете раз в N запросов запускать глубокий eval, который оценивает attribution и specificity. Эти метрики подробно разобраны в статье «Как ловить уверенные галлюцинации»: attribution показывает, насколько ответ опирается на предоставленные факты, а specificity — насколько ответ конкретен, а не расплывчат.

Но самый надёжный способ — перекрёстная проверка с золотым источником, если у вас есть размеченный датасет. Например, для юридического чат-бота мы загружаем 1000 вопросов с эталонными ответами из кодексов и каждую неделю прогоняем модель, считая точность и полноту. Если модель начинает «творить» — мы узнаём об этом до того, как оно уйдёт в прод.

Простой скрипт для периодического прогона evals:

# Пример: запуск evals раз в день через cron
python evaluate_llm.py --testset facts_2026.jsonl --model gpt-4o --output report_$(date +%Y%m%d).json

Внутри evaluate_llm.py вы сравниваете ответ с эталоном, используя BERTScore или FactScore (метрика, специально заточенная на фактическую точность). Если средняя FactScore падает ниже 0.85 — бьём тревогу.

Четыре грабли, на которые я наступил лично

  1. Слепая вера в RAG. Добавление контекста не спасает, если модель игнорирует его. Надо заставлять её цитировать источники (пример из жизни: кейс с навигацией во Франкфурте — модель проигнорировала карту и повела не туда).
  2. Переоптимизация на метрики. Если гнаться за 100% attribution, модель начнёт отвечать «не знаю» на всё. Нужен баланс: допускать 5-10% неизвестности.
  3. Использование одной и той же модели для генерации и валидации. Она будет подтверждать свои же ошибки. Лучше брать другую (Claude проверяет GPT, или наоборот).
  4. Игнорирование «тихих галлюцинаций» — когда модель врёт, но очень осторожно, без явных цифр. В работе Tsinghua про H-нейроны показали, что галлюцинации возникают из-за специфических нейронов, и их можно отключать. Но на практике это пока не внедрено.

В итоге: три контура — это не серебряная пуля, но работающая система. Первый контур (промпт) заставит модель думать, второй (экстрактор) — проверит факты, третий (evals) — не даст деградировать. Без одного из них — вы либо платите за враньё, либо за бесконечные проверки.

Что дальше?

К середине 2026 года появились экспериментальные методы контрастного декодирования, которые подавляют H-нейроны прямо во время генерации. Уже есть первые реализации на HuggingFace с патчами для Llama 4. Я бы поставил на то, что через год — полтора внешние контуры станут не нужны, потому что модели научатся сами различать факты и вымысел на уровне архитектуры. Но пока — стройте свои три линии обороны. И помните: лучший способ не получить галлюцинацию — не спрашивать модель о том, чего вы сами не знаете. Проверяйте, как только ответ важен.

Подписаться на канал