--- language: ru license: apache-2.0 base_model: Qwen/Qwen2.5-1.5B-Instruct tags: - hallucination-detection - fact-checking - qwen2.5 - lora - unsloth - russian - nlp - classification pipeline_tag: text-generation datasets: - kuznetsoffandrey/sberquad metrics: - accuracy - f1 --- # 🔍 Детектор галлюцинаций 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) | Метрика | Значение | |---------|----------| | **Accuracy** | **0.9835** | | **F1-score** | **0.9833** | | Precision | 0.9793 | | Recall | 0.9874 | | Размер теста | 485 примеров | ### Кривая обучения (Train / Eval Loss) ![Loss curve](loss_curve.png) *График показывает динамику функции потерь на обучающей и валидационной выборках по шагам обучения. Снижение eval loss без роста train loss означает, что модель обобщает, а не запоминает данные.* ### Confusion Matrix ![Confusion Matrix](confusion_matrix.png) *По оси X — предсказанный класс, по оси Y — истинный класс. Диагональ показывает правильные предсказания.* --- ## 🗂️ Данные для обучения ### Источник Датасет собран **полностью автоматически** на основе русского QA-корпуса **[SberQuAD](https://huggingface.co/datasets/kuznetsoffandrey/sberquad)** — русскоязычного аналога Stanford SQuAD (~45 000 пар вопрос-параграф-ответ). ### Стратегия генерации примеров **Положительные примеры (label=0, не галлюцинация):** Берутся напрямую из SberQuAD — оригинальная тройка (вопрос, контекст, правильный ответ), где ответ гарантированно содержится в контексте. **Отрицательные примеры (label=1, галлюцинация)** генерируются тремя способами: | Стратегия | Описание | Сложность для детектора | |-----------|----------|------------------------| | **Mismatch** | Ответ от другого вопроса/контекста | Лёгкая — ответ явно не связан с контекстом | | **Perturbation** | Искажение чисел или слов в правильном ответе | Средняя — ответ похож на правду, но неверен | | **LLM-generated** | Qwen2.5 генерирует правдоподобный, но неверный ответ (zero-shot) | Сложная — похоже на настоящую галлюцинацию | Такой микс позволяет модели научиться выявлять галлюцинации разной степени "правдоподобности" — от очевидных несоответствий до тонких фактических ошибок. ### Размер датасета (v5) | Сплит | Размер | |-------|--------| | Train | 3877 | | Val | 485 | | Test | 485 | | **Итого** | **4847** | --- ## 🛠️ Технические детали обучения ### Архитектура | Параметр | Значение | |----------|----------| | Базовая модель | `Qwen/Qwen2.5-1.5B-Instruct` | | Квантизация | 4-bit (QLoRA) | | LoRA rank (r) | 16 | | LoRA alpha | 16 | | LoRA dropout | 0.1 | | Target modules | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj | | Обучаемых параметров | ~20M из ~1.5B (≈1.3%) | ### Гиперпараметры обучения | Параметр | Значение | |----------|----------| | Эпохи | 2 | | Learning rate | 2e-4 | | Warmup ratio | 0.05 | | Batch size (эффективный) | 16 (2 × grad_accum 8) | | Optimizer | AdamW 8-bit | | Max sequence length | 512 | | Планировщик LR | cosine | ### Формат промпта ``` <|im_start|>system Ты — эксперт по проверке фактов. Тебе дан вопрос, контекст (источник фактов) и ответ ассистента. Определи, является ли ответ галлюцинацией — то есть противоречит контексту или не подтверждён им. Ответь только цифрой: 1 — если это галлюцинация, 0 — если ответ соответствует контексту. <|im_end|> <|im_start|>user Вопрос: {question} Контекст: {context} Ответ: {answer} <|im_end|> <|im_start|>assistant {0 или 1} <|im_end|> ``` ### Инфраструктура | Параметр | Значение | |----------|----------| | GPU | NVIDIA 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. **Домен данных** — модель обучена на энциклопедических текстах (Wikipedia-style, SberQuAD). Качество может быть ниже на специализированных доменах (медицина, право, технические тексты). 2. **Длина контекста** — максимальная длина входной последовательности 512 токенов. Длинные контексты нужно обрезать перед подачей в модель. 3. **Автоматическая разметка** — обучающие данные сгенерированы автоматически без ручной проверки. Часть негативных примеров (особенно perturbation) может содержать "шумные" метки. 4. **Бинарная классификация** — модель не объясняет, *почему* ответ является галлюцинацией, только детектирует сам факт. 5. **Только русский язык** — модель дообучалась исключительно на русскоязычных данных, для других языков результаты непредсказуемы. --- ## 📈 История версий | Версия | Дата и время | Accuracy | F1 | Precision | Recall | Train size | |--------|-------------|----------|----|-----------|--------|------------| | v1 | 2026-08-11 11:27:28 | 0.9587 | 0.9573 | 0.9739 | 0.9412 | 3865 | | v2 | 2026-08-12 12:05:19 | 0.9628 | 0.9615 | 0.9783 | 0.9454 | 3867 | | v3 | 2026-08-13 08:18:03 | 0.9794 | 0.9792 | 0.9751 | 0.9833 | 3876 | | v4 | 2026-08-13 09:16:07 | 0.9794 | 0.9792 | 0.9751 | 0.9833 | 3874 | | v5 | 2026-08-14 08:11:28 | 0.9835 | 0.9833 | 0.9793 | 0.9874 | 3877 | *Каждая версия — результат отдельной сессии дообучения. Модель загружается с предыдущей версии и дообучается на новых данных.* --- ## 📚 Связанные работы и датасеты - [SberQuAD](https://huggingface.co/datasets/kuznetsoffandrey/sberquad) — базовый датасет - [HaluEval](https://github.com/RUCAIBox/HaluEval) — бенчмарк галлюцинаций (английский) - [Qwen2.5](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) — базовая модель - [Unsloth](https://github.com/unslothai/unsloth) — библиотека для ускорения обучения --- ## 📄 Лицензия Apache 2.0 — можно использовать в коммерческих проектах. Базовая модель Qwen2.5 также распространяется под Apache 2.0. --- *Модель создана в образовательных целях. При использовании в продакшн рекомендуется дополнительная валидация на ваших данных.*