Instructions to use GreenPT/Qwen3.5-9B-honey with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use GreenPT/Qwen3.5-9B-honey with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-9B") model = PeftModel.from_pretrained(base_model, "GreenPT/Qwen3.5-9B-honey") - Notebooks
- Google Colab
- Kaggle
Qwen3.5-9B-honey 🍯
A LoRA adapter that makes Qwen/Qwen3.5-9B answer in Honey-terse style natively: the same correct answer in substantially fewer output tokens — no system prompt required. Style source: Green-PT/honey-for-devs (MIT).
In a paired eval against the base model (details below), the adapter produced 51.6% fewer output tokens at identical pass rates.
Eval results
Paired A/B on one loaded model (adapter toggled per prompt), bf16 on an NVIDIA L4, greedy decoding, non-thinking mode, max_new_tokens=900. 26 prompts in three checkable buckets: exact-answer QA (regex-verified), code generation (outputs executed against tests), and technical explanations (fact-rubric-verified).
| Category | Output tokens, base → honey | Reduction | Pass base | Pass honey |
|---|---|---|---|---|
| Exact QA (n=8) | 254 → 107 | 57.9% | 8/8 | 8/8 |
| Code, executed (n=8) | 248 → 181 | 27.0% | 7/8 | 7/8 |
| Explanations (n=10) | 800 → 352 | 56.1% | 10/10 | 10/10 |
| Overall | 462 → 224 | 51.6% | 25/26 | 25/26 |
Mean tokens per answer. Explanation gains are understated: 8 of 10 base answers were still running at the 900-token cap, while the adapter ended every generation cleanly on <|im_end|> (0 of 26 capped). The single code failure (to_snake_case on HTTPServer) is shared by base and adapter. Full per-prompt outputs: evals/results.json.
What terse looks like
Same prompt, greedy, both pass the tests:
base (149 tokens): docstring with bullet list and examples, commented implementation, prose recap. honey (91 tokens):
def is_palindrome(s: str) -> bool:
"""Return True if s is a palindrome, ignoring case and non-alphanumeric chars."""
cleaned = ''.join(ch.lower() for ch in s if ch.isalnum())
return cleaned == cleaned[::-1]
Official bench: three ways to get a terse 9B
The GreenPT/honey-bench suite (25 explanation cases + 10 code tasks; GLM-5.2-FP8 meaning juror, code executed against unit tests) compares this adapter against injecting the full honey SKILL.md as a system prompt:
| arm | output tokens | total bill (input+output) | meaning | code (think off / on) |
|---|---|---|---|---|
| Base Qwen3.5-9B | 11,959 | 12,706 | — | 10/10 |
| + honey SKILL.md prompt (~3,700 tok/call) | −78% | +654% | 23/25 | 8/10 |
| this LoRA | −46% | −43% | 23/25 | 8/10 / 10/10 |
Same pattern as the 27B sibling: the skill prompt is terser per answer but its re-sent system prompt multiplies the total bill; the LoRA gets most of the saving with zero overhead. (Totals are raw token counts, not dollars — input tokens are cheaper and cache well.) One 9B-specific caveat: with thinking off, the LoRA drops two of the ten bench code tasks (8/10, recovering to 10/10 with thinking on) — the smaller model trades a little code reliability for terseness; the paired suite below saw no such drop on its own code tasks.
Usage
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
ADAPTER = "GreenPT/Qwen3.5-9B-honey"
tok = AutoTokenizer.from_pretrained(ADAPTER)
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.5-9B", torch_dtype=torch.bfloat16, device_map="auto"
)
model = PeftModel.from_pretrained(model, ADAPTER)
# for serving, merge to remove the adapter's per-token overhead:
# model = model.merge_and_unload()
messages = [{"role": "user", "content": "Explain what a race condition is."}]
inputs = tok.apply_chat_template(
messages, add_generation_prompt=True, enable_thinking=False,
return_tensors="pt", return_dict=True,
).to(model.device)
out = model.generate(**inputs, max_new_tokens=512,
eos_token_id=[248046, 248044]) # <|im_end|>, <|endoftext|>
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
⚠️ Stop tokens matter. The base repo ships no
generation_config.jsonand itsconfig.jsonsetseos_token_idto<|endoftext|>(248044) — not the chat template's<|im_end|>(248046). A harness inheriting that config will appear to "never stop" with this adapter, because the adapter cleanly ends every turn with<|im_end|>(and, unlike the base, emits no stray<|endoftext|>afterwards). This repo includes a correctedgeneration_config.json; keep it, or passeos_token_id=[248046, 248044]explicitly as above.
Training
- LoRA r=16, α=32, on all attention, linear-attention, and MLP projections (12 module types, 496 tensors, 173MB).
- 3 epochs, 336 steps, ~3.9M training tokens.
- Final eval: loss 0.794, mean token accuracy 0.793.
- Intermediate checkpoints in
checkpoint-224/andcheckpoint-336/.
Note: the top-level adapter_model.safetensors uses the text-only module tree (model.layers…) so the standard AutoModelForCausalLM + PEFT snippet above works as-is. The checkpoint directories keep the trainer's original keys (model.language_model.layers…, from Qwen3_5ForConditionalGeneration); to load those directly, remap that prefix first.
Limitations
- Style transfer only — factual ability is the base model's; terse phrasing can drop hedges and caveats the base would include.
- Eval suite is small (26 prompts, single greedy seed) and text-only; thinking mode and multi-turn were not evaluated.
- Not additionally safety-tuned beyond the base model.
- Downloads last month
- 365