| --- |
| base_model: |
| - Qwen/Qwen2.5-Coder-3B-Instruct |
| library_name: peft |
| pipeline_tag: text-generation |
| tags: |
| - lora |
| - sft |
| - transformers |
| - unsloth |
| - qlora |
| - macaulay2 |
| - peft |
| - code-generation |
| license: mit |
| datasets: |
| - frupniew/macaulay2-qa-instruct |
| language: |
| - en |
| |
| |
| # Macaulay2 RAG-Coder 3B (LoRA Adapter) |
| |
| This repository contains the **QLoRA adapter weights** trained to turn `Qwen2.5-Coder-3B-Instruct` into a domain expert for Macaulay2 (commutative algebra). |
| |
| ## 🛠️ Training Details & Post-Mortem |
| - **Framework:** [Unsloth](https://github.com/unslothai/unsloth) (QLoRA 4-bit) |
| - **Hyperparameters:** `r=16`, `alpha=32`, `lr=2e-4`, `epochs=5`, `packing=True` (max_seq_len=4096). |
| - **Target Modules:** All linear layers. |
| - **Engineering Post-Mortem (Task Mismatch):** Initial training resulted in a model that perfectly understood M2 syntax but wrapped outputs in JSON (due to the synthetic data generator's system prompt). A **continual learning retrain** (Path A) was executed on pure ChatML formatted data to force raw Markdown code blocks, successfully resolving the issue. |
| - **PEFT Quirk Handled:** Addressed the `tie_word_embeddings` issue (PEFT #2777) specific to Qwen2.5 architecture during the merge process to prevent generation degradation. |
| |
| ## 🐍 Usage with Transformers |
| ```python |
| import torch |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from peft import PeftModel |
| |
| base_model_id = "Qwen/Qwen2.5-Coder-3B-Instruct" |
| adapter_model_id = "frupniew/macaulay2-rag-coder-3b-adapter" |
| |
| tokenizer = AutoTokenizer.from_pretrained(base_model_id) |
| base_model = AutoModelForCausalLM.from_pretrained(base_model_id, torch_dtype=torch.bfloat16, device_map="auto") |
| model = PeftModel.from_pretrained(base_model, adapter_model_id) |
|
|
| prompt = "How do I compute the primary decomposition of an ideal?" |
| inputs = tokenizer(prompt, return_tensors="pt").to(model.device) |
| outputs = model.generate(**inputs, max_new_tokens=512) |
| print(tokenizer.decode(outputs[0], skip_special_tokens=True)) |