commit d009ed4b2a008b9138efeb2f77b45fad47eb5cd8 Author: ModelHub XC Date: Wed Oct 21 18:32:18 2026 +0800 初始化项目,由ModelHub XC社区提供模型 Model: AtesiT/qwen2.5-1.5b-ru-hallucination-detector Source: Original Platform diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..52373fe --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +tokenizer.json filter=lfs diff=lfs merge=lfs -text diff --git a/README.md b/README.md new file mode 100644 index 0000000..1d7cb8d --- /dev/null +++ b/README.md @@ -0,0 +1,353 @@ +--- +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. + +--- + +*Модель создана в образовательных целях. +При использовании в продакшн рекомендуется дополнительная валидация на ваших данных.* diff --git a/chat_template.jinja b/chat_template.jinja new file mode 100644 index 0000000..bdf7919 --- /dev/null +++ b/chat_template.jinja @@ -0,0 +1,54 @@ +{%- if tools %} + {{- '<|im_start|>system\n' }} + {%- if messages[0]['role'] == 'system' %} + {{- messages[0]['content'] }} + {%- else %} + {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }} + {%- endif %} + {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within XML tags:\n" }} + {%- for tool in tools %} + {{- "\n" }} + {{- tool | tojson }} + {%- endfor %} + {{- "\n\n\nFor each function call, return a json object with function name and arguments within XML tags:\n\n{\"name\": , \"arguments\": }\n<|im_end|>\n" }} +{%- else %} + {%- if messages[0]['role'] == 'system' %} + {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }} + {%- else %} + {{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }} + {%- endif %} +{%- endif %} +{%- for message in messages %} + {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %} + {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }} + {%- elif message.role == "assistant" %} + {{- '<|im_start|>' + message.role }} + {%- if message.content %} + {{- '\n' + message.content }} + {%- endif %} + {%- for tool_call in message.tool_calls %} + {%- if tool_call.function is defined %} + {%- set tool_call = tool_call.function %} + {%- endif %} + {{- '\n\n{"name": "' }} + {{- tool_call.name }} + {{- '", "arguments": ' }} + {{- tool_call.arguments | tojson }} + {{- '}\n' }} + {%- endfor %} + {{- '<|im_end|>\n' }} + {%- elif message.role == "tool" %} + {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %} + {{- '<|im_start|>user' }} + {%- endif %} + {{- '\n\n' }} + {{- message.content }} + {{- '\n' }} + {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %} + {{- '<|im_end|>\n' }} + {%- endif %} + {%- endif %} +{%- endfor %} +{%- if add_generation_prompt %} + {{- '<|im_start|>assistant\n' }} +{%- endif %} diff --git a/config.json b/config.json new file mode 100644 index 0000000..7b45b7b --- /dev/null +++ b/config.json @@ -0,0 +1,62 @@ +{ + "architectures": [ + "Qwen2ForCausalLM" + ], + "attention_dropout": 0.0, + "bos_token_id": null, + "torch_dtype": "float16", + "eos_token_id": 151645, + "hidden_act": "silu", + "hidden_size": 1536, + "initializer_range": 0.02, + "intermediate_size": 8960, + "layer_types": [ + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention", + "full_attention" + ], + "max_position_embeddings": 32768, + "max_window_layers": 21, + "model_type": "qwen2", + "num_attention_heads": 12, + "num_hidden_layers": 28, + "num_key_value_heads": 2, + "pad_token_id": 151654, + "rms_norm_eps": 1e-06, + "rope_parameters": { + "rope_theta": 1000000.0, + "rope_type": "default" + }, + "sliding_window": null, + "tie_word_embeddings": true, + "unsloth_fixed": true, + "unsloth_version": "2026.8.16", + "use_cache": false, + "use_sliding_window": false, + "vocab_size": 151936 +} \ No newline at end of file diff --git a/confusion_matrix.png b/confusion_matrix.png new file mode 100644 index 0000000..a7ccdae Binary files /dev/null and b/confusion_matrix.png differ diff --git a/generation_config.json b/generation_config.json new file mode 100644 index 0000000..94b475f --- /dev/null +++ b/generation_config.json @@ -0,0 +1,14 @@ +{ + "bos_token_id": 151643, + "do_sample": true, + "eos_token_id": [ + 151645, + 151643 + ], + "pad_token_id": 151654, + "repetition_penalty": 1.1, + "temperature": 0.7, + "top_k": 20, + "top_p": 0.8, + "transformers_version": "5.5.0" +} diff --git a/loss_curve.png b/loss_curve.png new file mode 100644 index 0000000..5915e00 Binary files /dev/null and b/loss_curve.png differ diff --git a/model.safetensors b/model.safetensors new file mode 100644 index 0000000..e8c4de0 --- /dev/null +++ b/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9833aa16a672e0f0160fae2054ed0f2352e6695354d4ac294f938a1bc66fb52b +size 3087467144 diff --git a/tokenizer.json b/tokenizer.json new file mode 100644 index 0000000..d73428d --- /dev/null +++ b/tokenizer.json @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b4360dd6a184650ffc48056c2569bc603f896c5adfe94b10f1c79f809638aa5 +size 11422166 diff --git a/tokenizer_config.json b/tokenizer_config.json new file mode 100644 index 0000000..ec09d92 --- /dev/null +++ b/tokenizer_config.json @@ -0,0 +1,194 @@ +{ + "add_prefix_space": false, + "backend": "tokenizers", + "bos_token": null, + "clean_up_tokenization_spaces": false, + "eos_token": "<|im_end|>", + "errors": "replace", + "is_local": false, + "model_max_length": 32768, + "pad_token": "<|vision_pad|>", + "padding_side": "left", + "split_special_tokens": false, + "tokenizer_class": "Qwen2Tokenizer", + "unk_token": null, + "added_tokens_decoder": { + "151643": { + "content": "<|endoftext|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151644": { + "content": "<|im_start|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151645": { + "content": "<|im_end|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151646": { + "content": "<|object_ref_start|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151647": { + "content": "<|object_ref_end|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151648": { + "content": "<|box_start|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151649": { + "content": "<|box_end|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151650": { + "content": "<|quad_start|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151651": { + "content": "<|quad_end|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151652": { + "content": "<|vision_start|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151653": { + "content": "<|vision_end|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151654": { + "content": "<|vision_pad|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151655": { + "content": "<|image_pad|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151656": { + "content": "<|video_pad|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": true + }, + "151657": { + "content": "", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151658": { + "content": "", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151659": { + "content": "<|fim_prefix|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151660": { + "content": "<|fim_middle|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151661": { + "content": "<|fim_suffix|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151662": { + "content": "<|fim_pad|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151663": { + "content": "<|repo_name|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + }, + "151664": { + "content": "<|file_sep|>", + "single_word": false, + "lstrip": false, + "rstrip": false, + "normalized": false, + "special": false + } + }, + "chat_template": "{%- if tools %}\n {{- '<|im_start|>system\\n' }}\n {%- if messages[0]['role'] == 'system' %}\n {{- messages[0]['content'] }}\n {%- else %}\n {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}\n {%- endif %}\n {{- \"\\n\\n# Tools\\n\\nYou may call one or more functions to assist with the user query.\\n\\nYou are provided with function signatures within XML tags:\\n\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n\\n\\nFor each function call, return a json object with function name and arguments within XML tags:\\n\\n{\\\"name\\\": , \\\"arguments\\\": }\\n<|im_end|>\\n\" }}\n{%- else %}\n {%- if messages[0]['role'] == 'system' %}\n {{- '<|im_start|>system\\n' + messages[0]['content'] + '<|im_end|>\\n' }}\n {%- else %}\n {{- '<|im_start|>system\\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- for message in messages %}\n {%- if (message.role == \"user\") or (message.role == \"system\" and not loop.first) or (message.role == \"assistant\" and not message.tool_calls) %}\n {{- '<|im_start|>' + message.role + '\\n' + message.content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {{- '<|im_start|>' + message.role }}\n {%- if message.content %}\n {{- '\\n' + message.content }}\n {%- endif %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {{- '\\n\\n{\"name\": \"' }}\n {{- tool_call.name }}\n {{- '\", \"arguments\": ' }}\n {{- tool_call.arguments | tojson }}\n {{- '}\\n' }}\n {%- endfor %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != \"tool\") %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n\\n' }}\n {{- message.content }}\n {{- '\\n' }}\n {%- if loop.last or (messages[loop.index0 + 1].role != \"tool\") %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n{%- endif %}\n" +} \ No newline at end of file diff --git a/training_history.json b/training_history.json new file mode 100644 index 0000000..e885c08 --- /dev/null +++ b/training_history.json @@ -0,0 +1,77 @@ +[ + { + "datetime": "2026-08-11 11:27:28", + "version": "v1", + "base_model": "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit", + "accuracy": 0.9587, + "f1": 0.9573, + "precision": 0.9739, + "recall": 0.9412, + "train_size": 3865, + "val_size": 483, + "test_size": 484, + "epochs": 2, + "lr": "2e-4", + "lora_r": 16 + }, + { + "datetime": "2026-08-12 12:05:19", + "version": "v2", + "base_model": "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit", + "accuracy": 0.9628, + "f1": 0.9615, + "precision": 0.9783, + "recall": 0.9454, + "train_size": 3867, + "val_size": 483, + "test_size": 484, + "epochs": 2, + "lr": "2e-4", + "lora_r": 16 + }, + { + "datetime": "2026-08-13 08:18:03", + "version": "v3", + "base_model": "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit", + "accuracy": 0.9794, + "f1": 0.9792, + "precision": 0.9751, + "recall": 0.9833, + "train_size": 3876, + "val_size": 484, + "test_size": 485, + "epochs": 2, + "lr": "2e-4", + "lora_r": 16 + }, + { + "datetime": "2026-08-13 09:16:07", + "version": "v4", + "base_model": "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit", + "accuracy": 0.9794, + "f1": 0.9792, + "precision": 0.9751, + "recall": 0.9833, + "train_size": 3874, + "val_size": 484, + "test_size": 485, + "epochs": 2, + "lr": "2e-4", + "lora_r": 16 + }, + { + "datetime": "2026-08-14 08:11:28", + "version": "v5", + "base_model": "unsloth/Qwen2.5-1.5B-Instruct-bnb-4bit", + "accuracy": 0.9835, + "f1": 0.9833, + "precision": 0.9793, + "recall": 0.9874, + "train_size": 3877, + "val_size": 485, + "test_size": 485, + "epochs": 2, + "lr": "2e-4", + "lora_r": 16 + } +] \ No newline at end of file