【免费下载链接】CLM-v0.1-8B-MLX-5bit
CLM-v0.1-8B-MLX-5bit是运行在 Apple Silicon(MLX)上的对比语言模型(Contrastive Language Model,CLM):它不生成文字,而是把「状态(state)」和「候选动作(action)」编码成向量,用相似度打分来回答yes/no、单选、分级评分三类问题。本文将带你快速理解 state/action 概念、三种问题类型和最小运行示例,适合第一次接触对比语言模型的新手。
一、对比语言模型和普通大模型有什么不同?
🤔 新手最容易混淆的一点:CLM不会聊天、不会续写文章。
普通大模型(如 Qwen3)是「生成式」的:给你一句话,它一个字一个字往外蹦。而对比语言模型是「判别式」的:
| 对比维度 | 普通大模型 | CLM 对比语言模型 |
|---|---|---|
| 工作方式 | 逐词生成文本 | 向量相似度打分 |
| 输出形式 | 一段文字 | 概率分布(true 概率 0.87、选 A 概率 0.62…) |
| 擅长场景 | 写作、对话 | 分类、判断、排序、打分 |
| 推理开销 | 长输出很慢 | 一次前向即出结果,非常快 |
CLM-v0.1-8B 的结构可以拆成两块(详见 README.md):
- 冻结的编码器:一个 5bit 量化的 Qwen3-8B,只负责把文本变成向量,不参与生成(
lm_head已被移除); - 两个小型投影头(projection heads):
state_head和action_head,负责分别把「状态」和「动作」的向量投影到同一个 512 维空间,再算余弦相似度。
整体流程一句话概括:文本 → 编码器出向量 → 投影头压缩 → 算相似度 → softmax 变概率。
二、核心概念:state(状态)与 action(动作)
这是理解 CLM 的关键,用一个客服例子就明白了。假设客户发来一句抱怨:
"Customer: my invoice was charged twice and nobody answers the phone!"
这句话就是state(状态)——当前的上下文/情境。你想判断"该由哪个团队处理",于是给出两个action(动作)候选:
billing(账务):Charges, invoices, refundstechnical(技术):Bugs and outages
CLM 会分别把「state + 问题」和「每个 action」编码成向量,算出相似度分数,再转成概率分布。哪个候选的向量离 state 更近,概率就越高——这就是"对比"的由来:不是让模型写答案,而是让候选们在同一个向量空间里"比"出最优项。
几个值得记住的实现细节:
- 向量怎么取:取最后一个 token 的最终隐状态,L2 归一化,见 clm_mlx/encoder.py
- 打分怎么算:
score = scale × cos(state_head(e_s), action_head(e_a)),再除温度后做 softmax,见 clm_mlx/heads.py - 为什么快:action 的向量会被缓存(
Engine内置 LRU 缓存),同一批候选只算一次,之后只对新的 state 收费,见 clm_mlx/engine.py
三、三种问题类型详解:noul / choice / score
CLM 支持三种「类型化问题」(typed questions),定义在 clm_mlx/schema.py:QUESTION_TYPES = ("noul", "choice", "score")。一次answer()调用可以同时问多个不同类型的问题。
3.1 noul —— 是否题(yes / no)
最简单的一类,输出true的概率(0~1):
{"type": "noul", "instructions": "Is this urgent?"} # → 回答形如 {"type": "noul", "noul": 0.87}概率 ≥ 0.5 判为 true,否则 false(见 label_of)。没有给描述时,模型会自动把问题本身渲染成 "Yes. This is true: …" / "No. This is false: …" 两个候选去对比。
3.2 choice —— 单选题
criteria是「选项键 → 选项描述」的对象,键的顺序就是答案顺序:
{"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges, invoices, refunds", "technical": "Bugs and outages"}} # → 回答含 choice(胜出的键)、confidence(置信度)、probabilities(完整概率分布)组装选项候选文本的规则在 candidates():有描述就用描述,没有就用键名本身。
3.3 score —— 分级评分题
criteria是有序列表,表示从轻到重的等级。模型输出的是一个期望分数(各等级概率加权和):
{"type": "score", "instructions": "How frustrated is the customer?", "criteria": ["Calm", "Frustrated", "Very angry"]} # → 回答含 score(期望等级,如 1.7)、confidence、legend(等级对照表)分数越接近列表末尾,说明"愤怒程度"越高。三种类型的完整答案结构见 answer_from_probs。
💡小提示:问题应放在
instructions字段里,而不是重复写进 state——投影头是按照「上下文在前、问题在后」的固定排版训练的(见 build_pairs)。
四、10分钟上手:最小运行示例
环境要求:Apple Silicon Mac、Python 3.10+、约 5 GB 磁盘、运行时约 6 GB 内存(建议 16 GB Mac)。
pip install mlx mlx-lm transformers huggingface_hub然后加载引擎并提问(在下载的模型目录内运行):
from clm_mlx.engine import Engine eng = Engine("encoder", "heads") out = eng.answer( "Customer: my invoice was charged twice and nobody answers the phone!", { "urgency": {"type": "noul", "instructions": "Is this urgent?"}, "department": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "Charges, invoices, refunds", "technical": "Bugs and outages"}}, "frustration": {"type": "score", "instructions": "How frustrated is the customer?", "criteria": ["Calm", "Frustrated", "Very angry"]}, }, ) print(out["answers"]["department"]["choice"]) # 胜率最高的选项键 # rank:对一组候选文本按相关性排序 print(eng.rank("", ["The Moon's gravitational pull.", "Photosynthesis in plants."], "What causes tides on Earth?"))answer和rank的实现在 clm_mlx/engine.py,返回结构与上游 CLM 的 wire format 完全一致,方便与官方服务对接。
五、仓库里都有什么?一分钟看懂目录结构
| 路径 | 内容 | 说明 |
|---|---|---|
| encoder/ | Qwen3-8B 编码器权重(5bit,约 5.2 GB) | 标准 MLX 格式,lm_head已移除 |
| heads/CLM_v0.1-8B.safetensors | state/action 两个投影头(float32) | 为 5bit 量化专门蒸馏重训过 |
| heads/config.json | 投影头结构与logit_scale | width=1536、depth=3、输出 512 维 |
| clm_mlx/ | 推理代码包 | Engine/Encoder/HeadPair |
| parity.json | 与上游参考服务的对齐测试报告 | 778 道类型化问题的对比数据 |
| clm_mlx.json | 导出元信息 | 来源 commit、量化参数、导出日期 |
⚠️ 注意:这是社区非官方移植(未获 CLM 官方发布或审核),方法、投影头与参考实现来自上游 Contrastive-LM/CLM 项目。
六、精度与性能:新手最关心的两个数字
官方用 882 段文本、778 道问题对上游参考服务(vLLM + 8bit,RTX 4090)做了对齐测试(数据见 parity.json):
- top 选项一致率 93.4%;当上游自身置信度 ≥70% 时,本移植一致率 100%(577 题全部一致)
- 不一致基本都发生在"五五开"的临界题上(44 题上游自身概率低于 60%)
- 性能实测(Apple M3 Pro / 18 GB):编码器吞吐342.2 tokens/s,峰值内存6.0 GB
✅新手使用建议:模型自信(概率明显领先)的答案可以放心用;接近 50/50 的临界判断建议人工复核。若对上游对齐精度要求更高,可考虑官方 8-bit 版本。
七、新手常见疑问(FAQ)
Q1:它能写文章、写代码吗?不能。lm_head已被移除,该检查点是纯编码器,只做特征提取和打分,不生成任何文本。
Q2:为什么叫 5bit?有什么代价?编码器采用 5bit 量化(group_size=64),把内存压到约 6 GB 才能跑,但引入了量化噪声,所以精度分级为approximate(近似)——这也是投影头要为该量化单独蒸馏重训的原因。
Q3:输入超过 2048 token 会怎样?和上游服务行为一致:保留前 2048 个 token。如果希望"取结尾"(上游训练时的做法),可以用Engine(..., truncation="tail")切换,见 clm_mlx/encoder.py。
Q4:state 只能是纯文本吗?不是。state 可以是字符串、对象或数组,代码会自动渲染成key: value/- item的纯文本形式(见 to_text),因为投影头是在散文(而非 JSON)上训练的。
八、写在最后
CLM-v0.1-8B-MLX-5bit 展示了「不生成、只打分」的模型形态:冻结编码器 + 两个小投影头,用 state/action 向量对比代替逐词生成,在 Mac 上就能以 342 tokens/s 的速度回答是否题、单选题和分级评分题。理解了 state 与 action 的向量对比思想,你就掌握了读懂整个对比语言模型体系的核心钥匙 🎯。
完整安装与 API 细节请查阅 README.md,对齐测试明细在 parity.json。
【免费下载链接】CLM-v0.1-8B-MLX-5bit
相关推荐
OpenTelemetry Collector 部分重载(Partial Reload):从全量重建到精准组件重启
OpenTelemetry Collector 部分重载(Partial Reload):从全量重建到精准组件重启 本篇技术文章以 Partial Reload
CLM-v0.1-8B-MLX-5bit 代码解读:schema.py 如何构建问题候选项格式(to_text / candidates / build_pairs)
CLM v0.1 8B MLX 5bit 代码解读:schema.py 如何构建问题候选项格式(to_text / candidates / build_pai
Stitch SDK核心概念详解:Project、Screen、Generation三大模型一图看懂
Stitch SDK核心概念详解:Project、Screen、Generation三大模型一图看懂 📖 快速导读 Stitch SDK ( @google/
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考