354 lines
16 KiB
Markdown
354 lines
16 KiB
Markdown
---
|
||
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)
|
||
|
||

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

|
||
|
||
*По оси 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.
|
||
|
||
---
|
||
|
||
*Модель создана в образовательных целях.
|
||
При использовании в продакшн рекомендуется дополнительная валидация на ваших данных.*
|