--- base_model: Qwen/Qwen3-4B-Instruct-2507 library_name: peft license: apache-2.0 tags: - lora - peft - pii - pii-masking - qwen3 --- # Qwen3-4B-Instruct-2507 — PII Masking (SFT LoRA) LoRA adapter that fine-tunes [Qwen/Qwen3-4B-Instruct-2507](https://huggingface.co/Qwen/Qwen3-4B-Instruct-2507) to detect personally identifiable information (PII) in text, replace it with `[PII]` tags, and return the masked text wrapped in `...`. ## Results Greedy exact-match on a 5,914-row held-out split (provably disjoint from training by input): | Model | Exact-match | Relaxed-match | mean_reward\* | |---|---|---|---| | Base Qwen3-4B-Instruct-2507 | 0.409 | 0.577 | 0.472 | | **This adapter (SFT)** | **0.932** | 0.976 | 0.939 | \*`mean_reward` is the normalized reward `(exact·1.0 + pii_count·0.5 + format·0.1) / 1.6` (max 1.0). The Prime Intellect verifier for this task reports the same three components **un-normalized** (max 1.6), so e.g. a Prime reward of ~1.50 corresponds to ~0.94 here. Format compliance is already ~1.00 on the base model; the adapter's gain is almost entirely learning the exact `[PII]` segmentation convention (it cuts the relaxed-minus-exact gap from 0.168 to 0.045). ## Training - **Method:** supervised fine-tuning, completion-only loss (loss on the gold masked answer + EOS only). - **LoRA:** r=8, α=16, dropout 0, all-linear (q/k/v/o/gate/up/down projections). - **Data:** 5,000 examples from [`AdamLucek/open-pii-masking-en-us-30k`](https://huggingface.co/datasets/AdamLucek/open-pii-masking-en-us-30k) (train split). - **Schedule:** 2 epochs, lr 2e-4 cosine, bf16, gradient checkpointing. The published adapter was extracted from the merged SFT checkpoint by a per-layer rank-8 SVD of `(W_merged − W_base)`. Base + this adapter reproduces the merged model's held-out exact-match to within bf16 rounding (0.9319 vs 0.9325). ## Usage ```python from peft import PeftModel from transformers import AutoModelForCausalLM, AutoTokenizer base = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen3-4B-Instruct-2507", torch_dtype="bfloat16", device_map="auto") model = PeftModel.from_pretrained(base, "ichetandhembre/Qwen3-4B-Instruct-2507-PII-SFT-LoRA") tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-4B-Instruct-2507") SYSTEM = ("Replace all personally identifiable information (PII) in the text with [PII] tags. " "PII includes: names, dates, phone numbers, SSNs, account numbers, addresses, " "email addresses. Wrap the masked text in ....") msgs = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": "Hi, this is John Smith, call me at 555-0123."}] ids = tok.apply_chat_template(msgs, add_generation_prompt=True, return_tensors="pt").to(model.device) print(tok.decode(model.generate(ids, max_new_tokens=384, do_sample=False)[0][ids.shape[1]:], skip_special_tokens=True)) ``` Or serve base + adapter with vLLM (`enable_lora=True`, `max_lora_rank>=8`).