This model is a fine-tuned version of JetLM/SDAR-8B-Chat-b8 on the sdarwebshopbs4eighthreason dataset. The following hyperparameters were used during training: - learningrate: 1e-05 - trainbatchsize: 1 - evalbatchsize: 8 - distributedtype: multi-GPU - numdevices: 4 - totaltrainbatchsize: 4 - totalevalbatchsize: 32 - lrschedulertype: constantwithwarmup - lrschedulerwarmupratio: 0.03 - numepochs: 1.0 - Transformers 4.52.4 - Pytorch 2.9.1+cu129 - Datasets 3.6.0 - Tokenizers 0.21.1
CLM-v0.1-8B-MLX-6bit is an open-weight model for feature extraction from Zhu Lin, released under Apache License 2.0. It has 8.2B parameters and a 40,960-token context. At 16-bit it needs about 19.7 GB of GPU memory, which fits on 1x MI300X from $1.85 an hour, at the lowest prices in the SAVRN Index.
This is the 6bit variant. Also available: czl/CLM-v0.1-8B-MLX-4bit, czl/CLM-v0.1-8B-MLX-8bit, and the bf16 reference. The encoder half of Contrastive-LM/CLM-v0.1-8B, quantised for MLX on Apple Silicon.
Runs On
What it takes to serve CLM-v0.1-8B-MLX-6bit (8.2B parameters): the memory its weights need at each precision, and the cheapest way to rent enough data-center GPUs to hold them.
| Precision | Weights | Memory needed | Cheapest setup | Per hour | Also fits |
|---|---|---|---|---|---|
| 16-bit | 16.4 GB | 19.7 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
| 8-bit | 8.2 GB | 9.8 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
| 4-bit | 4.1 GB | 4.9 GB | 1x MI300X (192 GB) Vultr |
$1.85 | 1x H100 $1.99 · 1x MI325X $2.00 |
Memory is the weights at that precision plus 20% for the runtime and a short context; a long context needs more. Prices are the lowest on-demand hourly rates in the SAVRN Index, read Oct 7, 2026.
CLM-v0.1-8B-MLX-6bit on every accelerator the SAVRN Index prices, at every precision
Model Card
By Zhu Lin, published under apache-2.0, revision cc0acf2cc2ae.
This is the 6bit variant. Also available: czl/CLM-v0.1-8B-MLX-4bit, czl/CLM-v0.1-8B-MLX-8bit, and the bf16 reference. The encoder half of Contrastive-LM/CLM-v0.1-8B, quantised for MLX on Apple Silicon. mlxlm is generate-only — it has no embeddings entrypoint, and mlxlm.server routes just /v1/completions, /v1/chat/completions, /v1/models and /health. So clmmlx supplies the pooling pass over mlxlm internals: Qwen3Model.call already returns self.norm(h), the post-final-RMSNorm hidden states, which is what vLLM's pooling runner returns in last-token mode. Agreement against a bf16 MLX reference of the same encoder in the same runtime, over 23,926 scored System One questions, through the real…
Read Zhu Lin's full model card
This is the 6bit variant. Also available: czl/CLM-v0.1-8B-MLX-4bit, czl/CLM-v0.1-8B-MLX-8bit, and the bf16 reference.
CLM-v0.1-8B — MLX encoder (6bit)
The encoder half of Contrastive-LM/CLM-v0.1-8B,
quantised for MLX on Apple Silicon.
What is in this repo
| path | what |
|---|---|
config.json, model*.safetensors, tokenizer* |
the 6bit quantised encoder, standard mlx-community layout with the weights at the repo root so mlx_lm.load and the Hub file browser both work |
clm_mlx/ |
the pooling pass and an OpenAI-compatible /v1/embeddings server |
heads/ |
CLM_v0.1-8B.pt as safetensors, so no PyTorch is needed |
clm_mlx.json |
the pooling / embedding / scale contract |
mlx_lm is generate-only — it has no embeddings entrypoint, and mlx_lm.server routes just
/v1/completions, /v1/chat/completions, /v1/models and /health. So clm_mlx supplies the
pooling pass over mlx_lm internals: Qwen3Model.__call__ already returns self.norm(h), the
post-final-RMSNorm hidden states, which is what vLLM's pooling runner returns in last-token mode.
How to use
# From the Hub, directly (mlx-lm loads MLX repos natively):
mlx_lm.load("czl/CLM-v0.1-8B-MLX-6bit")
# Or serve it for CLM:
python -m clm_mlx.server --model <dir> --port 8092
clm-serve --emb-url http://127.0.0.1:8092/v1/embeddings
Or in process:
from clm_mlx import Encoder
vecs, tokens = Encoder("<dir>", max_tokens=2048).embed(["What causes tides on Earth?"])
Evaluation
Agreement against a bf16 MLX reference of the same encoder in the same runtime, over
23,926 scored System One questions, through the real head stack
(argmax(scale · cos), scale = 100.0 — cosine error is amplified 100×).
| variant | cos min | cos mean | top-1 | top-1 (decisive) | planner acc. Δ | verdict |
|---|---|---|---|---|---|---|
bf16 |
– | – | 1.0000 (ref) | 1.0000 (ref) | – | reference |
8bit |
0.98294 | 0.99985 | 0.9888 | 1.0000 | -0.46 pts | yes |
6bit |
0.89642 | 0.99918 | 0.9828 | 1.0000 | +0.70 pts | yes |
4bit |
0.87825 | 0.99191 | 0.6186 | 0.8897 | -31.95 pts | no |
Pass line. top-1 >= 1.0000 — the measured bf16-vs-bf16 noise floor of this corpus in this runtime — and top-1 (decisive) >= 0.995, where decisive means the reference's own top-1 led by more than 1 nat. A third condition applies: planner accuracy Δ, the change in accuracy against the T-Rex physics planner's label. A variant that holds every decisive decision but still loses measurable accuracy is marked usable rather than recommended.
Against the numbers published in the parent model card
| case | model card (vLLM bf16) | this runtime (bf16 reference) |
|---|---|---|
anchor-invoice/department |
billing |
billing — argmax matches, billing=0.98818, technical=0.01182 |
anchor-tides/rank |
0 |
0 — argmax matches, 0=0.99386, 1=0.00003, 2=0.00611 |
Those probabilities came from vLLM bf16. This runtime reproduces the arg-max on both cases
and agrees with an independent llama.cpp bf16 build to a cosine of 0.998680 minimum and 0.999958 mean over all 4,448 texts, so the residual
difference is cross-runtime bf16 numerics rather than a pooling or tokenisation error. Tokenisation is byte-identical to AutoTokenizer, with no BOS and no EOS. All
quantisation comparisons here are therefore against the same-runtime bf16 reference.
Quantization details
Tool: mlx-lm 0.31.3, one mlx_lm.convert pass per width:
mlx_lm.convert --hf-path Qwen/Qwen3-8B --mlx-path <dir> -q --q-bits N --q-group-size 128
- affine mode, per-group bf16 scale and bias.
group_size = 32— and this is the one number that mattered most in this whole exercise, and it is the opposite of both defaults. mlx-lm's own default is 64; Qwen'smlx-communityQwen3-8B-{4,6,8}bit repos use 128. Both are worse here.
MLX affine stores a bf16 scale and a bf16 bias per group, so it spends 32 bits per
group on quantisation metadata. That makes the group size a first-class quality knob
rather than a rounding detail: gs=128 is 4x coarser than ggml's 32-weight blocks and
stores its scales at bf16's 8-bit significand against ggml's fp16 11-bit. Every 0.25
bits/weight spent on finer groups bought back more accuracy than it cost, monotonically:
| width | group | bpw | top-1 | decisive (>1 nat) | 0.25–1.0 nat | planner acc. Δ |
|---|---|---|---|---|---|---|
| 8-bit | 128 | 8.250 | 0.9461 | 7440/7440 | 0.9588 | −2.60 pts |
| 8-bit | 64 | 8.500 | 0.9849 | 7440/7440 | 0.9990 | −0.59 pts |
| 8-bit | 32 | 9.000 | 0.9888 | 7440/7440 | 1.0000 | −0.46 pts |
| 6-bit | 128 | 6.250 | 0.9459 | 7440/7440 | 0.9487 | −4.23 pts |
| 6-bit | 64 | 6.500 | 0.9477 | 7440/7440 | 0.9566 | −1.94 pts |
| 6-bit | 32 | 7.000 | 0.9828 | 7440/7440 | 0.9971 | +0.70 pts |
At group 32 the decisive bucket is perfect at every width and essentially all remaining disagreement sits below 0.10 nats, i.e. in genuine near-ties. The 6-bit gain is inside the noise of the metric and should be read as "no measurable cost", not as an improvement.
The published artifacts are the group 32 ones. The group 64 and 128 models are not shipped; they exist here only as the measurements above.
--q-bits 6is a supported affine width, not a silent no-op.
Deliberately not used: mlx_lm.awq and mlx_lm.dwq. DWQ distils 16-bit down to 6- and
8-bit and upstream warns it "often doesn't work well" at those widths; AWQ is statistically
indistinguishable from naive round-to-nearest on embedding encoders. See the GGUF repo's
quantisation notes for the measurements behind that choice.
Limitations
- The projection heads are encoder-locked to Qwen3-8B last-token-pooled 4096-d embeddings. The pooling and the head checkpoint must both match.
- This is a ranker, not a generator.
lm_headis never evaluated under pooling. - The head stack amplifies cosine error 100×. A 0.001 cosine error is 0.10 nats. Read the confident-decision column, not the mean cosine.
- Right-padding and the last token.
clm_mlx.Encoderreads each row's own last real index, neverh[:, -1, :]; on a right-padded batch the latter returns the pad token's hidden state for every short row. Attention is causal, so trailing pads cannot change a real token — but only if the right element is indexed. truncate_prompt_tokensis honoured server-side. vLLM truncates to fit; llama.cpp answersERROR_TYPE_EXCEED_CONTEXT_SIZEand 400s instead. CLM sends the field on every request, so ignoring it would break the client on long inputs.- Probabilities are relative to the candidate set, and quantisation moves the logits by 100× the cosine error — see above.
- Upstream asymmetry, reproduced here: CLM's training recipe keeps the last tokens of a state while the serving path truncates from the head.
License
Apache-2.0, inherited from Qwen/Qwen3-8B and Contrastive-LM/CLM-v0.1-8B. This repo is not
gated.
Citation
@misc{kwok2026contrastivelanguagemodels,
title={Contrastive Language Models: A System One Model for Fast and Generalizable Decision-Making},
author={Jacky Kwok and Hangoo Kang and Tarun Suresh and Jon Saad-Falcon and Marco Pavone and Christopher Ré and Azalia Mirhoseini},
year={2026},
note={Notion Blog},
url={https://contrastive-lm.notion.site}
}
Configuration
- Architecture
- Qwen3ForCausalLM
- Context length (tokens)
- 40,960
- Layers
- 36
- Hidden size
- 4,096
- Feed-forward size
- 12,288
- Attention heads
- 32
- Key/value heads
- 8
- Head dimension
- 128
- Vocabulary size
- 151,936
- RoPE base
- 1,000,000
- Stored precision
- bfloat16
- Model type
- qwen3
Identity and Version
- Repository
- czl/CLM-v0.1-8B-MLX-6bit
- Publisher
- Zhu Lin
- Task
- Feature extraction
- Modality
- Text
- Library
- mlx
- Parameters
- 8.2B parameters
- Languages
- en
- Revision
- cc0acf2cc2ae0a556912059e280d0a30e7bba790
- First published
- 2026-09-27
- Last updated
- 2026-09-27
Files and Weights
19 files, 7.3 GB in total. The weights are 3 files totalling 7.2 GB in safetensors.
Every file
| File | Type | Size | SHA-256 |
|---|---|---|---|
| heads/CLM_v0.1-8B.safetensors | Weights | 75.6 MB | 6abdda23dab7 |
| model-00001-of-00002.safetensors | Weights | 5.4 GB | 882735ff3901 |
| model-00002-of-00002.safetensors | Weights | 1.8 GB | 0e1933aad061 |
| clm_mlx.json | Configuration | 804 B | — |
| clm_mlx/__init__.py | Configuration | 966 B | — |
| clm_mlx/encoder.py | Configuration | 6.7 KB | — |
| clm_mlx/server.py | Configuration | 4.8 KB | — |
| config.json | Configuration | 70.6 KB | — |
| generation_config.json | Configuration | 239 B | — |
| heads/config.json | Configuration | 1.7 KB | — |
| model.safetensors.index.json | Configuration | 77.7 KB | — |
| parity.json | Configuration | 157.9 KB | — |
| quantization.json | Configuration | 2.6 KB | — |
| LICENSE | Documentation | 11.4 KB | — |
| README.md | Documentation | 8.2 KB | — |
| chat_template.jinja | Other | 4.2 KB | — |
| .gitattributes | Repository | 101 B | — |
| tokenizer.json | Tokenizer | 11.4 MB | be75606093db |
| tokenizer_config.json | Tokenizer | 729 B | — |
License and Download
- License
- apache-2.0
- Access
- Open weights, no gate
- Download size
- 7.2 GB
Released by Zhu Lin through its official repository on Hugging Face. Read the license.
Built From
- Derived from Contrastive-LM/CLM-v0.1-8B
- Quantized from Contrastive-LM/CLM-v0.1-8B
Memory Requirements
| Precision | Weights in memory |
|---|---|
| As published | 7.2 GB |
| 16-bit | 16.4 GB |
| 8-bit | 8.2 GB |
| 4-bit | 4.1 GB |
Weights only, from the published parameter count; the key-value cache and runtime add to this.
Questions About CLM-v0.1-8B-MLX-6bit
How much GPU memory does CLM-v0.1-8B-MLX-6bit need?
About 19.7 GB at 16-bit and 4.9 GB at 4-bit: the weights (8.2B parameters) plus a working margin. A long context needs more.
What is the cheapest GPU to run CLM-v0.1-8B-MLX-6bit on?
At 16-bit, 1x MI300X from $1.85 an hour; at 4-bit, 1x MI300X from $1.85 an hour, at the lowest on-demand prices the SAVRN Index lists.
Can I use CLM-v0.1-8B-MLX-6bit commercially?
Yes. CLM-v0.1-8B-MLX-6bit is released under Apache License 2.0. The Apache License 2.0 is a permissive open-source license. It permits commercial use, modification and redistribution. It requires keeping the license and copyright notices and any NOTICE file, stating significant changes, and it includes an express patent grant from contributors.
What is CLM-v0.1-8B-MLX-6bit's context length?
40,960 tokens, from the maximum position embeddings in its published configuration.
Similar Models
This is the 8bit variant. Also available: czl/CLM-v0.1-8B-MLX-4bit, czl/CLM-v0.1-8B-MLX-6bit, and the bf16 reference. The encoder half of Contrastive-LM/CLM-v0.1-8B, quantised for MLX on Apple Silicon. mlxlm is generate-only — it has no embeddings entrypoint, and mlxlm.server routes just /v1/completions, /v1/chat/completions, /v1/models and /health. So clmmlx supplies the pooling pass over mlxlm internals: Qwen3Model.call already returns self.norm(h), the post-final-RMSNorm hidden states, which is what vLLM's pooling runner returns in last-token mode. Agreement against a bf16 MLX reference of the same encoder in the same runtime, over 23,926 scored System One questions, through the real…
The encoder half of Contrastive-LM/CLM-v0.1-8B, quantised for MLX on Apple Silicon. One repository per bit width, matching mlx-community. Each has the weights at the repo root, so the Hub file browser lists every file with its size and mlxlm.load(" ") works. Agreement against a bf16 MLX reference of the same encoder in the same runtime, over 23,926 scored System One questions, through the real head stack (argmax(scale · cos), scale = 100.0 — cosine error is amplified 100×). Pass line. top-1 >= 1.0000 — the measured bf16-vs-bf16 noise floor of this corpus in this runtime — and top-1 (decisive) >= 0.995, where decisive means the reference's own top-1 led by more than 1 nat. A third condition…
The Qwen3 Embedding model series is the latest proprietary model of the Qwen family, specifically designed for text embedding and ranking tasks. Building upon the dense foundational models of the Qwen3 series, it provides a comprehensive range of text embeddings and reranking models in various sizes (0.6B, 4B, and 8B). This series inherits the exceptional multilingual capabilities, long-text understanding, and reasoning skills of its foundational model. The Qwen3 Embedding series represents significant advancements in multiple text embedding and ranking tasks, including text retrieval, code retrieval, text classification, text clustering, and bitext mining. Exceptional Versatility: The…
This model is a quantized version of the original model intfloat/e5-mistral-7b-instruct. It's quantized using the BitsAndBytes library to 4-bit using the bnb-my-repo space. - bnb4bitquanttype: nf4 - bnb4bitusedoublequant: True - bnb4bitcomputedtype: bfloat16 - bnb4bitquantstorage: uint8 Improving Text Embeddings with Large Language Models. Liang Wang, Nan Yang, Xiaolong Huang, Linjun Yang, Rangan Majumder, Furu Wei, arXiv 2024 This model has 32 layers and the embedding size is 4096. Below is an example to encode queries and passages from the MS-MARCO passage ranking dataset. Have a look at configsentencetransformers.json for the prompts that are pre-configured, such as websearchquery…
GPTQ Quantized Qwen/Qwen3-Embedding-4B with THUIR/T2Ranking and m-a-p/COIG-CQIA for calibration set. ~0.72% lost in C-MTEB. Evaluation performed with official code. pip install compressed-tensors optimum and auto-gptq / gptqmodel, then goto the official usage guide.