Downloads · 30 days
9
1% of all-time downloads
HankH18/qwen3-1.7b-forbidden-constraint-holder
qwen3-1.7b-forbidden-constraint-holder is a text generation model from HankH18. Use it when you need the model to write or continue text. It is set up for transformers. The card lists the license as apache-2.0.
A QLoRA fine-tune of Qwen/Qwen3-1.7B trained to hold negative constraints while completing an ordinary writing task — "write this, and never use the letter e / the word 'however' / any quotation marks" — including whe…
Downloads · 30 days
9
1% of all-time downloads
All-time downloads
775
Public
Parameters
1.7B
7 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors3.5 GB · 99%
From the Hugging Face model README
A QLoRA fine-tune of Qwen/Qwen3-1.7B trained to hold negative constraints while completing an ordinary writing task — "write this, and never use the letter e / the word 'however' / any quotation marks" — including when the task itself pulls toward the banned token.
Every constraint has a deterministic checker, so adherence here is measured, not judged: an LLM judge scores task quality only and can never overturn a checker.
Read the results section before using this model. It improves on the constraint families it was trained on and regresses on families it was not. That trade is the finding, and it is stated in full below.
| Base | Qwen/Qwen3-1.7B |
| Base revision (pinned) | 70d244cc86ccca08cf5af4e1e306ecf908b1ad5e |
| Method | QLoRA (NF4 + double quant), LoRA adapter merged to fp16 |
| Hardware | NVIDIA A10, 10.11 GiB peak |
| Training wall clock | 740 s |
This repo holds the merged fp16 model at the root and the LoRA
adapter under adapter/.
| Dataset | data/train/v2.jsonl |
| Rows | 846 |
| sha256 | 9d9fc3f32d522f5cd873ae9af6629e09538f642d26cc652b964f260aff0105c8 |
| Published at | HankH18/forbidden-constraint-holder-sft |
Teacher-distilled and rejection-filtered through the same deterministic checkers used at evaluation: a generated completion that violated its own constraint set was discarded rather than trained on. Constraint types held out for generalization testing appear in zero training rows.
| LoRA rank / alpha / dropout | 16 / 32 / 0.05 |
| Target modules | down_proj, gate_proj, k_proj, o_proj, q_proj, up_proj, v_proj |
| Learning rate | 0.0002 |
| Epochs | 3 |
| Effective batch size | 16 (2 x 8 accumulation) |
| Max sequence length | 2048 |
| Optimizer / schedule | adamw_8bit / linear, warmup ratio 0.03 |
| Seed | 42 |
| Steps | 159 |
| Training loss | 5.7666 -> 2.0033 |
Loss is computed on the completion only; prompt tokens are masked to -100.
Use the chat template with a single user turn and no system message. Training used no system turn, and every training prompt was re-rendered through the evaluation harness's own renderer and compared byte-for-byte before training began, so the training condition equals the evaluation condition. Adding a system prompt puts the model off-distribution.
from transformers import AutoModelForCausalLM, AutoTokenizer
repo = "HankH18/qwen3-1.7b-forbidden-constraint-holder"
tok = AutoTokenizer.from_pretrained(repo)
model = AutoModelForCausalLM.from_pretrained(repo, dtype="auto", device_map="auto")
messages = [{"role": "user", "content": "Write a short paragraph about the ocean. Do not use the letter 'e' anywhere in your response."}]
inputs = tok.apply_chat_template(messages, add_generation_prompt=True,
enable_thinking=False, return_tensors="pt").to(model.device)
print(tok.decode(model.generate(inputs, max_new_tokens=512, do_sample=False)[0][inputs.shape[-1]:]))
enable_thinking=False matters: the training rows were rendered with it
off, and Qwen3's template emits a thinking block otherwise.
Eval set data/scenarios/corpus.jsonl, judge claude-sonnet-4-6, rubric hash 12a0dcaaf29080cb.
spec_pass = every checker passes and judge task-quality >= 3.
robustness is the same quantity over the adversarial subset only.
Scored rows: base 146, tuned 147. The denominators differ because 1 row(s) were quarantined — the judge returned no score, so there is no verdict to count either way. Rates are over scored rows.
| Metric | base | tuned | delta |
|---|---|---|---|
spec_adherence | 0.0890 | 0.0816 | -0.0074 |
robustness | 0.1029 | 0.0870 | -0.0160 |
Violation rate per constraint type — lower is better. Types marked held out appear in zero training rows.
| Constraint type | in training data | base | tuned |
|---|---|---|---|
banned_letter | yes | 1.000 | 0.990 |
banned_phrases | yes | 0.000 | 0.000 |
banned_punctuation | no (held out) | 0.220 | 0.585 |
banned_words | yes | 0.113 | 0.056 |
no_lists | yes | 0.019 | 0.019 |
no_quotation_marks | yes | 0.000 | 0.000 |
sentence_initial_letter | no (held out) | 0.280 | 0.960 |
python eval.py --model hf:HankH18/qwen3-1.7b-forbidden-constraint-holder@<commit> \
--compare-with hf:Qwen/Qwen3-1.7B@70d244cc86ccca08cf5af4e1e306ecf908b1ad5e \
--eval-set data/scenarios/corpus.jsonl
The harness, the checkers, the scenario corpus and the raw judge transcripts are all in the project repo.