--- license: apache-2.0 base_model: unsloth/Qwen2.5-1.5B-Instruct language: - en - ru library_name: transformers pipeline_tag: text-generation tags: - qwen2 - unsloth - trl - sft - lora - education - tutoring - conversational datasets: - ptvnck/TutoringDialogs - eth-nlped/mathdial model-index: - name: qwen2.5-1.5b-exam-tutor results: [] ---
Qwen2.5-1.5B Exam Tutor **Tutoring assistant for preparing to exams, fine-tuned to help you *think*, not just get answers.** [![Base Model](https://img.shields.io/badge/base-Qwen2.5--1.5B--Instruct-blue)](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) [![License](https://img.shields.io/badge/license-Apache%202.0-green)](https://www.apache.org/licenses/LICENSE-2.0) [![Made with Unsloth](https://img.shields.io/badge/made%20with-Unsloth%20%2B%20TRL-orange)](https://github.com/unslothai/unsloth) [![Method](https://img.shields.io/badge/method-LoRA%20SFT-purple)]()
--- ## Overview `qwen2.5-1.5b-exam-tutor` is a LoRA fine-tune of [`Qwen2.5-1.5B-Instruct`](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct), trained to behave like a **patient human tutor** rather than an answer-dispensing machine. Instead of solving a problem outright, the model is trained to ask guiding questions, probe for misconceptions, and walk the student toward the solution themselves — the same pattern a good teacher uses during exam prep. This model is the **first stage** of a larger personal-assistant project for exam preparation, which also includes a RAG pipeline over practice problems and a FastAPI serving layer accelerated with vLLM/Ollama. > This is an educational / portfolio project, not a production system. Scope, dataset size, and evaluation depth are intentionally sized for a learning exercise — see [Limitations](#-limitations--scope) below. ## Model Details | | | |---|---| | **Base model** | [`unsloth/Qwen2.5-1.5B-Instruct`](https://huggingface.co/unsloth/Qwen2.5-1.5B-Instruct) | | **Fine-tuning method** | LoRA (rank 16), full precision (no 4-bit quantization) | | **Frameworks** | [Unsloth](https://github.com/unslothai/unsloth) + [TRL](https://github.com/huggingface/trl) `SFTTrainer` | | **Weights format** | Merged 16-bit safetensors (adapter merged into base) | | **Language** | English / Russian | | **License** | Apache 2.0 (inherited from base model) | ## Intended Use - Conversational tutoring for exam preparation: math word problems, conceptual explanations, step-by-step reasoning practice. - Designed to be embedded as the generation backend of a larger RAG + FastAPI tutoring assistant (see [Roadmap](#-roadmap)). - **Not intended** as a general-purpose assistant, factual knowledge base, or replacement for a real teacher — the model's job is to *guide*, its factual accuracy on niche topics is not separately verified. ## Training Data 650 student ↔ tutor dialogues, combined from two sources: | Source | Dialogues used | Notes | |---|---|---| | [`ptvnck/TutoringDialogs`](https://huggingface.co/datasets/ptvnck/TutoringDialogs) | 500 | Synthetically generated, manually curated tutoring dialogues across mixed subjects | | [`eth-nlped/mathdial`](https://huggingface.co/datasets/eth-nlped/mathdial) | 150 | Filtered (dialogues with >11 turns) and reformatted subset, added specifically to cover math word-problem tutoring, which was underrepresented in the primary dataset | Data was split 85/15 into train/validation (≈552 / 98 examples), formatted with the tokenizer's ChatML template, and capped at 2500 tokens (covering the 99th percentile of dialogue length with no truncation). ## Training Procedure
LoRA configuration | Parameter | Value | |---|---| | Rank (`r`) | 16 | | Alpha (`lora_alpha`) | 32 | | Target modules | `q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj` | | Dropout | 0.1 | | Bias | none | | Gradient checkpointing | Unsloth-optimized |
Optimization hyperparameters | Parameter | Value | |---|---| | Effective batch size | 12 (4 × grad. accumulation 3) | | Epochs | 4 (best checkpoint auto-selected) | | Learning rate | 2e-4, cosine schedule | | Warmup | 10% of total steps | | Optimizer | AdamW (torch) | | Precision | fp16 | | Loss masking | Response-only (`train_on_responses_only`) — loss computed exclusively on tutor turns | | Hardware | 1× NVIDIA T4 (Google Colab) |
**Response-only loss masking.** Only the tutor's turns contribute to the training loss; the student's turns are masked out. This keeps the adapter's limited capacity focused entirely on learning *how to tutor*, rather than also learning to imitate the student side of the conversation. ## Results | Epoch | Training Loss | Validation Loss | |---|---|---| | 1 | 1.655 | 1.724 | | 2 | 1.389 | 1.516 | | **3** | **1.050** | **1.506** ← best | | 4 | 0.703 | 1.580 | - **Best validation loss:** 1.506 (epoch 3) → **perplexity ≈ 4.51** - Training loss keeps decreasing through epoch 4, while validation loss starts rising after epoch 3 — a clear sign of overfitting setting in on the final epoch, expected given the modest dataset size (~550 training examples). - `load_best_model_at_end=True` automatically restored the epoch-3 checkpoint as the final model, so the released weights are **not** the last-epoch weights, but the best-validation checkpoint. Full training curves (loss, LR schedule) were tracked with Weights & Biases. ## How to Use **With 🤗 Transformers:** ```python from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("ptvnck/qwen2.5-1.5b-exam-tutor") model = AutoModelForCausalLM.from_pretrained("ptvnck/qwen2.5-1.5b-exam-tutor") messages = [ {"role": "user", "content": "I need to solve 2x + 5 = 15 but I don't know where to start."} ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt" ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=200, temperature=0.7) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:], skip_special_tokens=True)) ``` **With Unsloth (2x faster inference):** ```python from unsloth import FastLanguageModel model, tokenizer = FastLanguageModel.from_pretrained( model_name="ptvnck/qwen2.5-1.5b-exam-tutor", max_seq_length=2048, ) FastLanguageModel.for_inference(model) ``` **With vLLM:** ```bash pip install vllm vllm serve "ptvnck/qwen2.5-1.5b-exam-tutor" ``` ## Limitations & Scope - Trained on 650 dialogues — sufficient to learn a tutoring *pattern*, but not a broad knowledge base. Expect a strong grasp of *conversational tutoring style*, and a shallower grasp of niche subject-matter facts. - No dedicated generation-quality evaluation (human eval / LLM-as-judge) was run as part of this stage — this is deferred to the RAG + FastAPI integration stage of the project, where end-to-end assistant responses will be evaluated in context rather than in isolation. - Not safety-tuned beyond what the base `Qwen2.5-1.5B-Instruct` already provides. ## Acknowledgements - Base model: [Qwen2.5-1.5B-Instruct](https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct) by the Qwen team - Training accelerated with [Unsloth](https://github.com/unslothai/unsloth) - Trained using Hugging Face [TRL](https://github.com/huggingface/trl) - `mathdial` subset: [eth-nlped/mathdial](https://huggingface.co/datasets/eth-nlped/mathdial)