Qwen2.5-Coder-14B-Instruct → W4A16

int4 weights, BF16 activations. Quantized with AutoRound, calibrated on a code / tool-calling / general mix -- not the stock generic-text calibration most quantization repos ship with.

Built specifically to run on a single 12 GB card (an RTX 3080 Ti) behind a coding agent, where the full-precision model (~28 GB) and even most other current-generation Qwen builds don't fit. See the companion project's log entry for why this specific base model, not a newer one, was the right choice.

Why this base model, not something newer

Qwen's current (3.6/3.8) generation doesn't ship a dense model in the 12-14B range -- it jumps from small models straight to 27B+ dense and 30B+ MoE, none of which fit a 12 GB card at any reasonable quantization. Qwen2.5-Coder-14B-Instruct is older but genuinely well-proven, purpose-built for coding, and small enough to actually fit with real context headroom after quantization. Picked over an unverified community distillation of the newer generation for the same reason every build in this family insists on its own eval numbers: don't publish something you haven't actually checked.

Calibration

45%/40%/15%-style splits don't apply as-is here -- this build leans harder into code specifically, since it's headed for a dedicated coding box, not a general-purpose agent driver:

Source Share Dataset
Code 55% ise-uiuc/Magicoder-OSS-Instruct-75K
Tool-calling 30% NousResearch/hermes-function-calling-v1
General 15% NeelNanda/pile-10k

512 samples, 2048 tokens each, AutoRound W4A16 (group size 128, symmetric).

BF16 keep-list

Unlike the newer hybrid-attention/MoE builds in this family, this is a plain dense transformer (Qwen2ForCausalLM) -- verified against the real architecture with inspect_layers.py, not assumed. The only layer kept BF16 is lm_head (untied output embedding, cheap insurance for logit quality). No linear-attention gates, no MoE experts, no vision tower to worry about here.

Serving

Single GPU, TP=1 -- this model is small enough that multi-GPU serving would be pure overhead.

Tool-calling needs a custom parser, included in this repo (qwen25coder_flex_tool_parser.py). The base model's own chat template asks for Hermes-style JSON wrapped in <tool_call></tool_call>, but it doesn't reliably produce that exact tag -- verified this is a base-model quirk, not something this quantization introduced, by reproducing it against the raw BF16 checkpoint directly. Across a few different prompts it used <tools> (the tag meant for the tool schema, not the call), <function-call> (invented, appears nowhere in its own template), and once no tag at all. What stayed correct every time was the JSON payload itself. The included parser strips every wrapper spelling actually observed and pulls the JSON object out regardless of what (if anything) wraps it -- run install_tool_parser.sh once against your vLLM environment (source its venv first), then:

vllm serve fasolack/Qwen2.5-Coder-14B-W4A16 \
    --served-model-name qwen2.5-coder-14b-w4a16 \
    --tensor-parallel-size 1 \
    --gpu-memory-utilization 0.90 \
    --max-model-len 32768 \
    --kv-cache-dtype fp8 \
    --enable-prefix-caching \
    --enable-auto-tool-choice \
    --tool-call-parser qwen25coder_flex

The stock hermes parser will silently fail on this model -- tool calls land in content as raw text with finish_reason: "stop" instead of a populated tool_calls array. If you don't want to install the custom parser, at minimum know this limitation exists before relying on this model behind an agent.

A LoRA fix was attempted and, on the second try, worked -- with a real cost. See PAPER.md for the full writeup. A LoRA on attention/MLP projections alone left tag compliance at 0/120 (unchanged) despite measurably improving argument correctness and false-positive rate -- root-caused to the frozen lm_head lacking a confident weight for the rare <tool_call> token. Adding lm_head to the LoRA's target modules fixed it completely: 100% tag compliance (120/120), generalizing across every eval category. But a full regression check found real, CI-exceeding drops in HumanEval pass@1 (68.29% -> 58.54%) and GSM8K strict-match (72.10% -> 64.97%), while MMLU-Pro and GSM8K flexible-extract stayed within noise. This is not a free fix -- which build to use depends on deployment context: an agent loop with no custom parser installed may prefer the tag-fixed build despite the coding-capability cost; a deployment already running qwen25coder_flex_tool_parser.py loses little by staying on this shipped build. This build (the one described by this card) is published here. The tag-fixed build (Qwen2.5-Coder-14B-W4A16-toolfix-v2) is not -- it remains a local experimental artifact, not a published alternative.

Evaluation

Measured with EleutherAI lm-evaluation-harness against the served endpoint. No BF16 baseline was measured for this build (unlike the 35B build in this family) -- this model already has well-established public numbers from Qwen themselves and prior community quantizations; the point of measuring here was to validate this specific calibration and quantization, not to re-establish what the base model can do.

Task This build (int4 W4A16)
GSM8K (flexible-extract) 80.21% ± 1.10%
HumanEval (pass@1) 68.29% ± 3.64%
MMLU-Pro (100/subject) 41.71% ± 1.29%

The MMLU-Pro number reads low next to this family's 27B/35B builds (both in the 80s) -- that's not a quantization problem, it's this model: smaller, older-generation, and picked specifically to fit 12 GB of VRAM, not for general-knowledge breadth. HumanEval (the number that actually matters for what this build is for) is solid.

Coverage gap, stated plainly: none of these three benchmarks exercise tool-calling. The custom parser fix described above was verified separately, by hand, against the served model (a single-tool call and a two-tool multi-call, both correctly extracted) -- not by this benchmark suite. If you're relying on tool-calling specifically, that's worth knowing wasn't covered by an automated eval here.

Limitations and intended use

  • Calibrated for code and tool-calling; general-knowledge tasks may be marginally worse than a generically-calibrated W4A16 build of the same model.
  • Built for a single small-VRAM GPU. If you have real multi-GPU headroom, a newer-generation model (this family's Qwen3.8-27B or Qwen3.6-35B-A3B builds) will outperform this one.
  • On a 12 GB card, context headroom is tight enough that any non-model VRAM usage costs real, measurable capacity -- a GPU-accelerated desktop session sharing the card is the most common culprit. Run this class of card headless where possible; see STATUS.md for the concrete before/after this made on the deployment box (roughly 3x the usable context at otherwise-identical settings).
  • Internal build, not independently safety-tuned beyond what the base model already carries.
Downloads last month
-
Safetensors
Model size
3B params
Tensor type
I32
·
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for fasolack/Qwen2.5-Coder-14B-W4A16

Base model

Qwen/Qwen2.5-14B
Quantized
(128)
this model