【免费下载链接】Qwen3.6-35B-A3B-singprobe
本文带你逐行走读Qwen3.6-35B-A3B-singprobe的完整源码。它是构建在 Qwen3.6-35B-A3B 之上的轻量级流式安全护栏探针SingProbe,用仅 4.2M 的参数,在模型生成每个 token 时实时完成意图识别、不安全响应检测与幻觉检测,解码开销不到 0.5%。全文围绕 configuration_sing_probe.py 与 modeling_sing_probe.py 双文件展开,配合 config.json 一起看,帮你从零读懂这个探针是如何工作的。
一、项目速览:4.2M 参数如何守住安全底线
传统做法是在大模型旁边再挂一个独立安全模型,成本高、延迟大。SingProbe 的思路是复用基座模型的隐藏状态(hidden states):在生成过程中"偷看"模型内部的中间表示,用一个极小的探针网络直接打分。
| 基座模型 | 探针参数量 | 抽样的隐藏层 | 输出内容 |
|---|---|---|---|
| Qwen3.6-35B-A3B | 4.2M | 第 12、25、38 层 | 8 类意图 + 不安全 + 幻觉 |
核心优势一览:
- ⚡流式逐 token 打分:边生成边检测,不必等完整回复
- 🧩开销极低:解码额外耗时 < 0.5%
- 🛡️误报率极低:良性回复平均误报率仅 0.03%
整个仓库只有 4 个关键文件,结构一目了然:
| 文件 | 作用 |
|---|---|
| config.json | 模型配置("身份证"),声明架构与超参数 |
| configuration_sing_probe.py | 配置类定义,告诉 Transformers 如何加载配置 |
| modeling_sing_probe.py | 模型结构与前向传播,全部网络逻辑都在这 |
| README.md | 模型卡片,含评测结果与快速上手 |
二、config.json 配置详解:读懂探针的"身份证"
打开 config.json,每个字段都有明确分工:
{ "architectures": ["SingProbeAttnModel"], "model_type": "sing_probe_attn", "auto_map": { "AutoConfig": "configuration_sing_probe.SingProbeAttnConfig", "AutoModel": "modeling_sing_probe.SingProbeAttnModel" }, "hidden_size": 2048, "base_model_layer_ids": [12, 25, 38], "num_attention_heads": 8, "head_dim": 64, "sliding_window": 2048, "num_labels": 10, "torch_dtype": "bfloat16" }关键字段逐个解读:
| 字段 | 值 | 含义 |
|---|---|---|
auto_map | — | Hugging Face 的"路由表",指定从哪个文件加载哪个类,这是自定义模型能被AutoModel识别的关键 |
hidden_size | 2048 | 基座模型每一层的隐藏维度 |
base_model_layer_ids | [12, 25, 38] | 从基座模型的哪几层"取样",3 层特征拼接送入探针 |
num_attention_heads | 8 | 探针内部注意力的查询头数 |
head_dim | 64 | 每个注意力头的维度 |
sliding_window | 2048 | 滑动窗口长度,限制每个 token 的注意力范围 |
num_labels | 10 | 输出 10 个分数(8 意图 + unsafe + hallucination) |
💡 注意:
hidden_size为 2048 而非 Python 文件里的默认值 2560——config.json 会覆盖代码默认值,这也是为什么看配置类时必须对照 JSON 一起读。
三、configuration_sing_probe.py 逐行走读
整个 configuration_sing_probe.py 只有 55 行,却定义了两种探针的配置:MLP 版和注意力版。
3.1 公共骨架:继承 PretrainedConfig
文件首行from transformers import PretrainedConfig导入基类。两个配置类都继承它,并各自声明model_type:
sing_probe_mlp(L5)sing_probe_attn(L31)
model_type是模型的"类型标识",config.json中的同名字段必须与它一致,加载时二者互相校验。
3.2 SingProbeMlpConfig:极简 MLP 配置
第 4 行起的SingProbeMlpConfig服务于"两层全连接"的简化探针,参数含义直白:
hidden_size=2560、base_model_layer_ids=None:输入特征来源intermediate_size=1024:中间层宽度num_labels=10、hidden_act="gelu":分类数与激活函数
每个参数在__init__里都做了int(...)强制转换(如 L18),防止 JSON 反序列化出字符串类型的超参数,这是一个容易忽略但很实用的防御性写法。
3.3 SingProbeAttnConfig:注意力版配置
第 30 行起的SingProbeAttnConfig多了三个注意力专属参数:
num_attention_heads=4:查询头数head_dim=64:每头维度sliding_window=None:窗口长度,None表示不限制(见 L49 的归一化处理)
3.4 关键属性 input_size:一行代码定生死
两个配置类都定义了同一个计算属性(以注意力版 L53-L55 为例):
@property def input_size(self) -> int: return self.hidden_size * len(self.base_model_layer_ids)这是全文最重要的设计约定:探针输入 = 单层隐藏维度 × 抽样层数。对照 config.json:2048 × 3 = 6144。模型代码中所有输入线性层都以它作为输入维度,配置改错任何一处都会在加载或前向时立即报错——后文的输入校验正是基于这个值。
四、modeling_sing_probe.py 逐行走读
modeling_sing_probe.py 共 142 行,分三层结构:公共基类 → MLP 模型 → 注意力模型。
4.1 基类 SingProbePreTrainedModel:初始化与校验
第 13 行起的基类做了两件"守门"的事:
- 声明主输入:
main_input_name = "hidden_states"(L15)。探针不吃input_ids,只吃基座模型的隐藏状态——这一行点明了它的"寄生"定位。 - 统一权重初始化
_init_weights(L17-L23):nn.Linear:权重 N(0, 0.02) 小方差正态分布,偏置置零nn.RMSNorm:权重置 1- 小方差初始化让探针初期输出接近中性,避免干扰主模型行为
4.2 输入校验:出错就大声报错
静态方法_validate_input(L25-L31)在前向入口检查最后一维是否等于config.input_size,不匹配时抛出带具体数值的ValueError,例如:
input feature size 2048 does not match hidden_size * number of tapped layers (6144)这意味着你如果抽错层数或忘记拼接多层特征,会得到一眼能看懂的报错,而不是难以排查的训练发散。
4.3 SingProbeMlpModel:最简两层探针
第 34 行起的 MLP 版结构直白到教科书级别:
hidden_states → fc1 (6144→1024) → GELU → fc2 (1024→10) → logits前向流程(L44-L57)依次是:输入校验 → 强制转为fc1的权重精度(保证 bf16 场景不出 dtype 错误)→ 两层线性 → 返回TokenClassifierOutput。return_dict=False时退回元组,兼容不同调用习惯。它是理解注意力版的良好"对照物"。
4.4 SingProbeAttnModel:参数构建与不对称投影
真正的生产模型在 第 60 行起。__init__先做参数合法性检查(头数、维度、窗口必须为正),然后构建 5 个核心模块:
| 模块 | 形状 | 说明 |
|---|---|---|
proj_q | 6144 → 512 | 查询投影:8 头 × 64 维,无偏置 |
proj_k | 6144 → 64 | 键投影:仅 1 个头 |
proj_v | 6144 → 64 | 值投影:仅 1 个头 |
o_proj | 512 → 512 | 输出投影 |
norm+classifier | 512 → RMSNorm → 10 | 归一化后接分类头 |
这里藏着一个精巧的非对称分组注意力(GQA 风格):Q 有 8 个头,而 K/V 只有 1 个头供 8 个 Q 头共享(enable_gqa=True,见 L106)。配合所有投影层bias=False,参数量被压到极限。算一笔账:
proj_q 3,145,728 + proj_k 393,216 + proj_v 393,216 + o_proj 262,144 + classifier 5,130 + norm 512 ≈ 4.2M ✅正好对上 README 宣称的 4.2M 参数——源码与文档完全自洽。
4.5 滑动窗口注意力:长序列的刹车片
_sliding_window_attention(L80-L109)把长序列切成 2048 的窗口逐块处理:
- 对每个查询块
[start, end),可用的 key 范围是[max(0, start-2047), end)——每个 token 最多"回头看" 2048 个 token - 用相对位置掩码
(relative_positions >= 0) & (relative_positions < window)同时保证因果性(不看未来)和窗口限制 - 每块调用 PyTorch 高效的
F.scaled_dot_product_attention,最后按序列维拼接
在 forward(L126-L135)中,只有当sliding_window < seq_len时才走窗口路径,否则直接用标准因果注意力——短序列不浪费,长序列不爆炸,这正是"流式"场景下控制显存与延迟的关键。
4.6 forward 完整数据流
注意力版前向(L111-L142)可以浓缩为一条流水线:
校验 → 精度对齐 → Q/K/V 投影(Q: B,S,8,64;K/V: B,S,1,64) → 窗口或因果 SDPA 得到 context (B,S,512) → o_proj(context) + Q残差([L138](https://link.gitcode.com/i/dd738c6715f72620fbee95eb939f5aec#L138)) → RMSNorm → classifier → 10 维 logits值得注意 L138 的+ query_features:探针给注意力输出加了一条来自 Q 的残差连接,保证浅层原始信息不被深层变换稀释。最终输出的 10 个分数对应label_0–label_9(8 类意图 + 不安全 + 幻觉),每个 token 一份,支撑逐 token 流式判定。
五、三大设计亮点总结
- 🎯 配置与模型解耦:所有结构参数收口在 config 类,
input_size属性作为单一事实来源,跨文件强校验,改错必报错 - 📉 极致省参:无偏置投影 + 单 KV 头共享,8 个查询头复用 1 套键值,4.2M 参数换来 < 0.5% 解码开销
- 🔍 流式友好:滑动窗口把注意力复杂度从 O(n²) 拉回可控范围,边生成边打分,误报率仅 0.03%
六、快速上手:在推理服务中加载探针
探针通过推理框架的集成分支加载,启动时加上探针检查点参数即可(以 SGLang 为例):
python -m sglang.launch_server \ --model-path Qwen/Qwen3.6-35B-A3B \ --probe-ckpt inclusionAI/Qwen3.6-35B-A3B-singprobe \ --port 30000两个使用提醒:
- 服务会对每个生成 token 返回一个
label_0–label_9分数字典,可直接对接安全策略 - 必须使用精确的基座/探针配对:本检查点只与 Qwen3.6-35B-A3B 搭配,
hidden_size=2048的约定决定了它无法跨基座迁移
七、结语
Qwen3.6-35B-A3B-singprobe 用最克制的方式示范了"小模型守护大模型":55 行的配置类 + 142 行的建模代码,4.2M 参数守住意图、安全、幻觉三道关卡。如果你正在为大模型部署寻找低成本的流式安全护栏,这份源码值得逐行收藏——它的每一行都在回答同一个问题:如何把开销压到几乎为零,同时不让安全能力打折。
【免费下载链接】Qwen3.6-35B-A3B-singprobe
相关推荐
逐字段解读Qwen3.6-35B-A3B-w8a8-llmcompressor的config.json量化配置:compressed-tensors INT8格式完整指南
逐字段解读Qwen3.6 35B A3B w8a8 llmcompressor的config.json量化配置:compressed tensors INT8格
修复 iqk_mul_mat 在缺少 AVX512BF16 支持的 CPU 上的编译失败:以 ik_llama.cpp PR 204 为案例的 BF16 内核条件编译剖析
修复 iqk_mul_mat 在缺少 AVX512BF16 支持的 CPU 上的编译失败:以 ik_llama.cpp PR 204 为案例的 BF16 内核条
用 100 行 Python 写出高性能 GPU 算子:TileLang 实战指南
用 100 行 Python 写出高性能 GPU 算子:TileLang 实战指南 TileLang 是一个用 Python 语法编写 GPU 算子的领域特定语
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考