CoolFace
Modelpublic

AtesiT/qwen2.5-1.5b-ru-hallucination-detector

sourceHugging Faceapache-2.0updated 1mo agoView on Hugging Face
2likes215downloads
Model Card

🔍 Детектор галлюцинаций LLM — русский язык

Текущая версия: v5 · Последнее обновление: 2026-08-14 08:11:28

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

Модель дообучена на основе [Qwen2.5-1.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) методом QLoRA (4-bit quantization + LoRA адаптеры) с использованием библиотеки [Unsloth](https://github.com/unslothai/unsloth) для ускоренного обучения на GPU.


📋 Описание задачи

Галлюцинации LLM — это когда языковая модель генерирует ответ, который звучит правдоподобно, но не соответствует реальным фактам или противоречит предоставленному источнику (контексту). Это одна из ключевых проблем при использовании LLM в production-системах, особенно в задачах RAG (Retrieval-Augmented Generation).

Постановка задачи

Модель принимает три входных текста:

  • —Вопрос — то, что пользователь спросил у LLM
  • —Контекст — документ/фрагмент, который был предоставлен LLM как источник фактов
  • —Ответ — то, что LLM сгенерировала в ответ на вопрос

И возвращает бинарную метку:

  • —0 — ответ соответствует контексту (не галлюцинация)
  • —1 — ответ противоречит контексту или содержит неподтверждённые факты (галлюцинация)

Где это применяется

  • —✅ RAG-пайплайны — проверка ответов перед показом пользователю
  • —✅ Автоматическое тестирование LLM-агентов
  • —✅ Мониторинг качества ответов в продакшн-системах
  • —✅ Датасеты для обучения других моделей (серебряная разметка)

📊 Метрики качества

Текущая версия (v5, 2026-08-14 08:11:28)

МетрикаЗначение
Accuracy0.9835
F1-score0.9833
Precision0.9793
Recall0.9874
Размер теста485 примеров

Кривая обучения (Train / Eval Loss)

[image]

График показывает динамику функции потерь на обучающей и валидационной выборках по шагам обучения. Снижение eval loss без роста train loss означает, что модель обобщает, а не запоминает данные.

Confusion Matrix

[image]

По оси X — предсказанный класс, по оси Y — истинный класс. Диагональ показывает правильные предсказания.


🗂️ Данные для обучения

Источник

Датасет собран полностью автоматически на основе русского QA-корпуса [SberQuAD](https://huggingface.co/datasets/kuznetsoffandrey/sberquad) — русскоязычного аналога Stanford SQuAD (~45 000 пар вопрос-параграф-ответ).

Стратегия генерации примеров

Положительные примеры (label=0, не галлюцинация): Берутся напрямую из SberQuAD — оригинальная тройка (вопрос, контекст, правильный ответ), где ответ гарантированно содержится в контексте.

Отрицательные примеры (label=1, галлюцинация) генерируются тремя способами:

СтратегияОписаниеСложность для детектора
MismatchОтвет от другого вопроса/контекстаЛёгкая — ответ явно не связан с контекстом
PerturbationИскажение чисел или слов в правильном ответеСредняя — ответ похож на правду, но неверен
LLM-generatedQwen2.5 генерирует правдоподобный, но неверный ответ (zero-shot)Сложная — похоже на настоящую галлюцинацию

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

Размер датасета (v5)

СплитРазмер
Train3877
Val485
Test485
Итого4847

🛠️ Технические детали обучения

Архитектура

ПараметрЗначение
Базовая модельQwen/Qwen2.5-1.5B-Instruct
Квантизация4-bit (QLoRA)
LoRA rank (r)16
LoRA alpha16
LoRA dropout0.1
Target modulesqproj, kproj, vproj, oproj, gateproj, upproj, down_proj
Обучаемых параметров~20M из ~1.5B (≈1.3%)

Гиперпараметры обучения

ПараметрЗначение
Эпохи2
Learning rate2e-4
Warmup ratio0.05
Batch size (эффективный)16 (2 × grad_accum 8)
OptimizerAdamW 8-bit
Max sequence length512
Планировщик LRcosine

Формат промпта

<|im_start|>system
Ты — эксперт по проверке фактов. Тебе дан вопрос, контекст (источник фактов) и ответ ассистента.
Определи, является ли ответ галлюцинацией — то есть противоречит контексту или не подтверждён им.
Ответь только цифрой: 1 — если это галлюцинация, 0 — если ответ соответствует контексту.
<|im_end|>
<|im_start|>user
Вопрос: {question}
Контекст: {context}
Ответ: {answer}
<|im_end|>
<|im_start|>assistant
{0 или 1}
<|im_end|>

Инфраструктура

ПараметрЗначение
GPUNVIDIA T4 (16 GB VRAM)
ПлатформаGoogle Colab
ФреймворкPyTorch + Hugging Face Transformers
УскорениеUnsloth (2-4x быстрее стандартного обучения)
Время обучения~30-60 минут на T4

💻 Как использовать

Установка

bash
pip install transformers torch accelerate

Код

python

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch, re

# Загружаем модель с Hugging Face Hub
REPO_ID = "AtesiT/qwen2.5-1.5b-ru-hallucination-detector"
tokenizer = AutoTokenizer.from_pretrained(REPO_ID)
model = AutoModelForCausalLM.from_pretrained(
    REPO_ID,
    torch_dtype=torch.float16,
    device_map="auto"
)
model.eval()

SYSTEM_PROMPT = (
    "Ты — эксперт по проверке фактов. Тебе дан вопрос, контекст (источник фактов) и ответ ассистента. "
    "Определи, является ли ответ галлюцинацией — то есть противоречит контексту или не подтверждён им. "
    "Ответь только цифрой: 1 — если это галлюцинация, 0 — если ответ соответствует контексту."
)

def predict(question: str, context: str, answer: str) -> dict:
    """
    Определяет, является ли ответ галлюцинацией.

    Args:
        question: Вопрос, на который отвечала LLM
        context:  Контекст (источник фактов, справочный текст)
        answer:   Ответ LLM, который нужно проверить

    Returns:
        dict с ключами: label (0/1), verdict (str), raw_output (str)
    """
    prompt = (
        f"<|im_start|>system\n{SYSTEM_PROMPT}<|im_end|>\n"
        f"<|im_start|>user\n"
        f"Вопрос: {question}\n"
        f"Контекст: {context}\n"
        f"Ответ: {answer}"
        f"<|im_end|>\n"
        f"<|im_start|>assistant\n"
    )
    inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
    with torch.no_grad():
        out = model.generate(
            **inputs,
            max_new_tokens=3,
            do_sample=False,
            pad_token_id=tokenizer.eos_token_id,
        )
    gen = tokenizer.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)
    m = re.search(r"[01]", gen)
    label = int(m.group()) if m else 0
    return {
        "label":      label,
        "verdict":    "Галлюцинация" if label == 1 else "Не галлюцинация",
        "raw_output": gen.strip(),
    }

# ── Пример 1: очевидная галлюцинация ──────────────────────────────────
result = predict(
    question="Столица Франции?",
    context="Франция — государство в Западной Европе. Столица страны — Париж.",
    answer="Столица Франции — Лондон.",
)
print(result)
# {'label': 1, 'verdict': 'Галлюцинация', 'raw_output': '1'}

# ── Пример 2: правильный ответ ─────────────────────────────────────────
result = predict(
    question="Столица Франции?",
    context="Франция — государство в Западной Европе. Столица страны — Париж.",
    answer="Столица Франции — Париж.",
)
print(result)
# {'label': 0, 'verdict': 'Не галлюцинация', 'raw_output': '0'}

# ── Пример 3: тонкая галлюцинация (неверное число) ────────────────────
result = predict(
    question="В каком году основана компания Apple?",
    context="Apple Inc. была основана 1 апреля 1976 года Стивом Джобсом, "
            "Стивом Возняком и Рональдом Уэйном.",
    answer="Apple была основана в 1985 году.",
)
print(result)
# {'label': 1, 'verdict': 'Галлюцинация', 'raw_output': '1'}

Использование с Unsloth (быстрее, если нужна генерация)

python
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "AtesiT/qwen2.5-1.5b-ru-hallucination-detector",
    max_seq_length = 512,
    load_in_4bit = True,
)
model.eval()
# Далее используйте predict() из примера выше

⚠️ Ограничения и известные проблемы

  1. 1.Домен данных — модель обучена на энциклопедических текстах (Wikipedia-style, SberQuAD). Качество может быть ниже на специализированных доменах (медицина, право, технические тексты).
  1. 1.Длина контекста — максимальная длина входной последовательности 512 токенов. Длинные контексты нужно обрезать перед подачей в модель.
  1. 1.Автоматическая разметка — обучающие данные сгенерированы автоматически без ручной проверки. Часть негативных примеров (особенно perturbation) может содержать "шумные" метки.
  1. 1.Бинарная классификация — модель не объясняет, почему ответ является галлюцинацией, только детектирует сам факт.
  1. 1.Только русский язык — модель дообучалась исключительно на русскоязычных данных, для других языков результаты непредсказуемы.

📈 История версий

ВерсияДата и времяAccuracyF1PrecisionRecallTrain size
v12026-08-11 11:27:280.95870.95730.97390.94123865
v22026-08-12 12:05:190.96280.96150.97830.94543867
v32026-08-13 08:18:030.97940.97920.97510.98333876
v42026-08-13 09:16:070.97940.97920.97510.98333874
v52026-08-14 08:11:280.98350.98330.97930.98743877

Каждая версия — результат отдельной сессии дообучения. Модель загружается с предыдущей версии и дообучается на новых данных.


📚 Связанные работы и датасеты

  • —SberQuAD — базовый датасет
  • —HaluEval — бенчмарк галлюцинаций (английский)
  • —Qwen2.5 — базовая модель
  • —Unsloth — библиотека для ускорения обучения

📄 Лицензия

Apache 2.0 — можно использовать в коммерческих проектах. Базовая модель Qwen2.5 также распространяется под Apache 2.0.


Модель создана в образовательных целях. При использовании в продакшн рекомендуется дополнительная валидация на ваших данных.