Files
llm-atlas/research/DEEPSEEK_ROUTING_ROLE_MARKER_HEAD_AUDIT.md
T
2026-07-29 20:44:43 +08:00

21 KiB
Raw Blame History

DeepSeek-V2-Lite 角色词头单 Token 控制审计

状态:真实官方权重执行(X)
模型:deepseek-ai/DeepSeek-V2-Lite base checkpoint
revision:604d5664dddd88a0433dbae533b7fe9472482de0
执行边界:layer 0–6;观测 MoE layer 1–6
样本:WikiText-2 / TNEWS / HumanEval / GSM8K 各 32 条
正式运行与独立复跑:byte-exact
完整 JSON SHA-256:9dc0e37fbce6581269428dcfcb84c7a17b466c5239c8171e6741f66d5eeb8caf

0. 一句话先说结论

在固定 DeepSeek-V2-Lite base 权重、固定 128 个公开样本、固定重复词元历史、 固定官方 assistant EOS、固定冒号、固定长度、固定目标位置和固定八格 batch 时:

只把目标内容前面的 User 词头换成 Assistant 或 x,会让后续目标 token 的专家路由发生清晰的直接变化;但是它没有在 24 个 layer×domain 中统一放大或削弱 system message 的路由作用。

目标内容、prompt-balanced 口径下,官方序列与两个前置干预之间的直接 TV 为:

                         system off      system on
User → Assistant            .0222           .0218
User → x                    .0263           .0253

而四种角色词头条件下,system-edge TV 的 24 格平均为:

官方 User:                  .03729
目标 User→Assistant         .03705
目标 User→x                 .03754
后置 Assistant→User         .03729

最后一行不是“小数恰好接近”,而是严格的 causal suffix 负对照:

把目标内容后 generation prompt 的 Assistant 换成 User,在六个 MoE 层、两个 system 水平的 34,488 个目标 layer×token 对上 ordered top-6 全部相同;目标 load、TV、JSD 与 system edge 也全部精确不变。

最准确的命名是:

固定协议中的角色词头单 input-ID 条件化。

它不是“完整角色语义探针”,更不是 Chat 模型能力实验。


1. 为什么要从 EOS 继续拆到角色词头

上一轮已经固定重复词元历史、角色包装、长度和目标位置,只把历史 assistant 后的 EOS 换成三个普通单 token。结果说明 EOS identity 不是普通占位符。

但官方序列仍然是:

Assistant: x <EOS> User: TARGET

所以即便 EOS 被替换,下一条 User: 仍然提供回合入口线索。上一轮不能回答:

  1. User: 中的角色词头是否会条件化后续目标计算;
  2. 这种变化是角色词头的直接作用,还是对 system message 效应的统一调制;
  3. 同一个单 ID 干预如果发生在目标之后,目标路由是否按 causal mask 保持不变。

本轮把这三个问题放进同一个八格 batch。


2. 官方模板中的 User: 不是一个 token

固定 revision 的官方模板仍然是:

{% if message['role'] == 'user' %}
  {{ 'User: ' + message['content'] + '\n\n' }}
{% elif message['role'] == 'assistant' %}
  {{ 'Assistant: ' + message['content'] + eos_token }}
{% elif message['role'] == 'system' %}
  {{ message['content'] + '\n\n' }}
{% endif %}

固定 tokenizer 的真实 tokenization 是:

文本 token IDs token 数 special
User [5726] 1 否
Assistant [77398] 1 否
User: [5726, 25] 2 否
Assistant: [77398, 25] 2 否
x [87] 1 否
<EOS> [100001] 1 是

因此本实验只干预 User: / Assistant: 的词头 ID,冒号 ID 25 始终保留。

这一区分很重要:

User → Assistant 不是把完整 User: 换成完整 Assistant: 的字符串实验, 而是把两个 token 序列中的第一个 ID 替换掉。

官方模板可在 固定 tokenizer_config 直接核查。


3. 四个角色词头水平

两个因子是:

  • S:system 关闭 / 开启;
  • R:角色词头控制。

四个 R 水平如下:

水平 单 ID 改动 相对目标 官方合法序列
official 无 — 是
target_assistant 目标前 User 5726 → Assistant 77398 前 否
target_x 目标前 User 5726 → x 87 前 否
suffix_user 目标后 Assistant 77398 → User 5726 后 否

四种序列可以直观看成:

OFFICIAL
... Assistant: x <EOS> User: TARGET \n\n Assistant:

TARGET_ASSISTANT
... Assistant: x <EOS> Assistant: TARGET \n\n Assistant:

TARGET_X
... Assistant: x <EOS> x: TARGET \n\n Assistant:

SUFFIX_USER
... Assistant: x <EOS> User: TARGET \n\n User:

三个干预都在官方 tokenization 完成后修改 ID,因此它们是明确的 counterfactual token sequences,不是官方 apply_chat_template 会自然生成的 合法聊天。


4. 固定了什么

每个 source 的八格共同固定:

  • 同一 DeepSeek-V2-Lite base checkpoint;
  • 同一 system 文本;
  • 同一 repeated-token user / assistant 历史;
  • 同一官方 assistant EOS;
  • 同一目标文本;
  • 同一 canonical 23-token 截断合同;
  • 同一冒号 token;
  • 同一序列长度;
  • 同一目标绝对位置;
  • 同一 attention mask;
  • 同一 right-padding;
  • 同一次 32-row forward 的 batch shape。

正式 renderer 验证:

检查 结果
source prompts 128
system groups 256
四格同长度 256 / 256
四格同目标 span 256 / 256
官方序列零 ID 改动 256 / 256
三种反事实恰好一 ID 改动 768 / 768
前置单 ID 干预 512
后置单 ID 干预 256

5. 为什么必须放一个目标后的角色词头

如果只比较:

User: TARGET
Assistant: TARGET

即使看到差异,也只能知道“前面改一个 ID 会影响后面”,却不知道:

  • renderer 是否错误对齐目标;
  • batch 中的其他条件是否让任意单 ID 改动都污染所有位置;
  • causal mask 是否按预期工作;
  • route 对齐代码是否把 suffix token 错算进目标。

因此加入:

TARGET ... Assistant:
TARGET ... User:

改动发生在所有目标内容 token 之后。对 decoder-only causal mask 而言,过去 位置不能看见未来位置,所以目标路由应精确不变。

这不是统计上的“希望接近零”,而是一条确定性执行闸门。


6. 统计量仍然分三张账

6.1 直接替换距离

在 system 水平 s 下:

TV(P(s, official), P(s, role_control))

回答:

只改这个角色词头,目标内容的聚合专家份额移动了多少?

6.2 system edge

角色水平 r 下:

TV(P(S0, r), P(S1, r))

回答:

固定角色词头时,system 开关让目标路由移动了多少?

6.3 system-edge contrast

TV_system(role_control) - TV_system(official)

回答:

替换角色词头是否改变 system effect 的强度?

直接替换距离非零,不自动推出 system-edge contrast 也应同方向。


7. 先看直接作用:前置角色词头确实改变后续路由

目标内容、prompt-balanced 聚合:

干预 S0 平均 direct TV S1 平均 direct TV S1−S0
User→Assistant .022243 .021804 -.000439
User→x .026305 .025339 -.000966
后置 Assistant→User 0 0 0

两个前置词头替换都产生约 .02–.03 的直接 TV;但 S1−S0 的均值接近零。

逐层平均与逐 token top-6 set exact:

层 U→A direct TV S0 / S1 U→A set exact S0 / S1 U→x direct TV S0 / S1 U→x set exact S0 / S1 suffix direct TV
L1 0.0267 / 0.0253 79.9% / 81.8% 0.0275 / 0.0278 78.2% / 80.5% 0 / 0
L2 0.0187 / 0.0175 82.0% / 83.1% 0.0214 / 0.0240 80.2% / 78.8% 0 / 0
L3 0.0175 / 0.0191 81.7% / 80.3% 0.0235 / 0.0231 79.5% / 76.7% 0 / 0
L4 0.0209 / 0.0238 76.3% / 74.3% 0.0260 / 0.0249 72.2% / 71.4% 0 / 0
L5 0.0229 / 0.0218 71.4% / 73.7% 0.0266 / 0.0251 68.3% / 70.4% 0 / 0
L6 0.0267 / 0.0233 70.0% / 70.5% 0.0329 / 0.0270 66.4% / 68.4% 0 / 0

随着层数增加,直接替换后的 set exact 整体下降,说明一个前置 ID 的差异会沿 残差流累积;但这仍只是 route-set 稳定性,不是专家语义或任务质量。


8. 关键反例:system-edge 强度没有统一方向

目标内容、prompt-balanced 口径,24 个 layer×domain 的平均:

official                  .037290
target_assistant          .037045
target_x                  .037542
suffix_user               .037290

相对官方的 contrast:

contrast 平均 ΔTV 点估计正 / 负 CI 负 / 跨零 / 正
target_assistant − official -.000246 12 / 12 2 / 19 / 3
target_x − official +.000252 13 / 11 3 / 19 / 2
suffix_user − official 0 0 / 0 0 / 24 / 0

因此不允许写:

  • “Assistant 词头让 system 更强”;
  • “x 会屏蔽 system”;
  • “角色标记统一提高路由稳定性”。

数据支持的是:

前置词头会直接改变后续路由,但它与 system message 的组合关系依赖层与域。


9. 全部 24 格

下表只使用目标内容、prompt-balanced 与共享 source bootstrap:

层 域 官方 TV User→Assistant TV Δ / 95% CI User→x TV Δ / 95% CI suffix TV
L1 英文 0.0559 0.0585 +0.0026 / [-0.0033, +0.0068] 0.0625 +0.0066 / [-0.0002, +0.0117] 0.0559
L1 中文 0.0276 0.0251 -0.0025 / [-0.0054, +0.0016] 0.0245 -0.0032 / [-0.0070, +0.0007] 0.0276
L1 代码 0.0571 0.0574 +0.0003 / [-0.0027, +0.0059] 0.0553 -0.0018 / [-0.0054, +0.0027] 0.0571
L1 数学 0.0784 0.0769 -0.0015 / [-0.0070, +0.0045] 0.0889 +0.0105 / [+0.0060, +0.0157] 0.0784
L2 英文 0.0293 0.0298 +0.0004 / [-0.0036, +0.0049] 0.0321 +0.0028 / [-0.0008, +0.0066] 0.0293
L2 中文 0.0204 0.0188 -0.0016 / [-0.0045, +0.0025] 0.0199 -0.0005 / [-0.0042, +0.0038] 0.0204
L2 代码 0.0331 0.0377 +0.0046 / [+0.0005, +0.0082] 0.0375 +0.0043 / [+0.0002, +0.0084] 0.0331
L2 数学 0.0401 0.0364 -0.0037 / [-0.0090, +0.0016] 0.0346 -0.0056 / [-0.0103, -0.0007] 0.0401
L3 英文 0.0312 0.0360 +0.0047 / [-0.0009, +0.0076] 0.0328 +0.0016 / [-0.0043, +0.0060] 0.0312
L3 中文 0.0224 0.0188 -0.0036 / [-0.0075, +0.0011] 0.0234 +0.0009 / [-0.0036, +0.0061] 0.0224
L3 代码 0.0411 0.0464 +0.0053 / [+0.0012, +0.0098] 0.0443 +0.0032 / [-0.0021, +0.0070] 0.0411
L3 数学 0.0337 0.0343 +0.0006 / [-0.0041, +0.0050] 0.0309 -0.0028 / [-0.0057, +0.0024] 0.0337
L4 英文 0.0326 0.0326 -0.0000 / [-0.0057, +0.0052] 0.0360 +0.0033 / [-0.0021, +0.0088] 0.0326
L4 中文 0.0293 0.0250 -0.0043 / [-0.0085, +0.0013] 0.0281 -0.0011 / [-0.0053, +0.0041] 0.0293
L4 代码 0.0390 0.0356 -0.0034 / [-0.0079, +0.0030] 0.0322 -0.0069 / [-0.0107, -0.0015] 0.0390
L4 数学 0.0513 0.0449 -0.0064 / [-0.0127, -0.0012] 0.0494 -0.0019 / [-0.0086, +0.0049] 0.0513
L5 英文 0.0335 0.0366 +0.0031 / [-0.0036, +0.0083] 0.0354 +0.0019 / [-0.0038, +0.0083] 0.0335
L5 中文 0.0244 0.0254 +0.0009 / [-0.0036, +0.0062] 0.0231 -0.0014 / [-0.0059, +0.0038] 0.0244
L5 代码 0.0386 0.0283 -0.0104 / [-0.0144, -0.0036] 0.0252 -0.0135 / [-0.0173, -0.0061] 0.0386
L5 数学 0.0459 0.0424 -0.0035 / [-0.0081, +0.0015] 0.0472 +0.0013 / [-0.0053, +0.0073] 0.0459
L6 英文 0.0303 0.0321 +0.0019 / [-0.0038, +0.0083] 0.0298 -0.0005 / [-0.0073, +0.0058] 0.0303
L6 中文 0.0242 0.0281 +0.0039 / [-0.0020, +0.0091] 0.0245 +0.0002 / [-0.0047, +0.0066] 0.0242
L6 代码 0.0316 0.0395 +0.0080 / [+0.0031, +0.0127] 0.0357 +0.0042 / [-0.0020, +0.0107] 0.0316
L6 数学 0.0436 0.0424 -0.0013 / [-0.0067, +0.0047] 0.0479 +0.0043 / [-0.0022, +0.0096] 0.0436

仅 5 / 24 个 User→Assistant 区间、5 / 24 个 User→x 区间完全位于零 的一侧;正负方向同时存在。


10. causal suffix 负对照的完整账

目标后的 Assistant→User:

对象 exact
target ordered top-6 layer×token×system 34,488 / 34,488
target set top-6 layer×token×system 34,488 / 34,488
target route hash prompt×layer×system 1,536 / 1,536
target integer load prompt×layer×system 1,536 / 1,536
target direct TV 0
target direct JSD 0
target system-edge contrast 0
target ΔCV contrast 0

完整输入则不同:

对象 exact
full route hash 0 / 1,536
full integer load 6 / 1,536
mean direct TV at S0 .012134
mean direct TV at S1 .008710

这正是合理分账:

  • 目标内容位于 edit 之前,所以不可见;
  • suffix 自身和其后的冒号位于 edit 之后,所以完整输入可变。

11. 为什么完整输入不能代替目标内容

完整输入的 mean system-edge TV:

official             .138929
target_assistant     .139118
target_x             .140953
suffix_user          .139329

其中 target_x − official 平均为 +.002024,19 / 24 点估计为正; suffix_user − official 也不为零。

但完整输入混入:

  • 被替换的角色词头;
  • 历史包装;
  • 目标前后的换行;
  • generation prompt;
  • suffix 本身。

所以它回答的是:

整条协议流量如何改变?

而不是:

相同目标内容如何被上下文条件化?

网站必须允许 scope 切换,但主结论只能来自 exact target content。


12. ΔCV 与 direct interaction 都不支持统一方向

目标内容、prompt-balanced:

对象 平均 点估计正 / 负 CI 负 / 跨零 / 正
U→A 的 system-edge ΔCV +.003138 16 / 8 4 / 16 / 4
U→x 的 system-edge ΔCV +.003260 15 / 9 4 / 15 / 5
U→A direct TV 的 S1−S0 -.000439 11 / 13 3 / 20 / 1
U→x direct TV 的 S1−S0 -.000966 10 / 14 5 / 17 / 2
suffix 全部上述量 0 0 / 0 0 / 24 / 0

因此不写“角色词头让路由更均衡”或“system 会放大角色作用”。


13. 同 batch shape 仍不等于同 BF16 执行

本轮的官方条件与上一轮 EOS 条件:

  • 256 / 256 messages hash 相同;
  • 256 / 256 rendered text hash 相同;
  • 256 / 256 token-ID hash 相同;
  • 256 / 256 长度与目标 token 合同相同;
  • batch 都是 32 rows。

但同行的其他反事实从:

EOS / x / period / newline

变成:

official / target_assistant / target_x / suffix_user

跨实验 official route exact:

层 full hash target hash full load target load
L1 256 / 256 256 / 256 256 / 256 256 / 256
L2 60 / 256 180 / 256 158 / 256 208 / 256
L3 43 / 256 149 / 256 99 / 256 188 / 256
L4 27 / 256 102 / 256 74 / 256 149 / 256
L5 13 / 256 72 / 256 52 / 256 124 / 256
L6 16 / 256 73 / 256 49 / 256 129 / 256

观察到的事实是:

第一 MoE 层完全相同;经过不同 companion rows 的 MoE 计算后,深层 BF16 route hashes 开始分化。

一种合理但尚未直接验证的工程解释是:其他 rows 改变 expert grouping / microbatch 形状或低精度 kernel 数值路径,细小误差再通过深层 gate 放大。当前证据不能唯一定位 是哪一个 kernel。

因此正式结论继续限定为:

同一次八格 batch 内的配对对比。

“相同 batch shape”不足以支持跨实验 route-byte equality;batch 内容也是执行合同。


14. 与一手文献如何连接

14.1 Hugging Face chat templates

官方文档明确把 messages 转换为模型实际读取的 token sequence,并强调不同 chat model 使用不同控制 token / 格式。

它支持:

  • 必须检查最终 token IDs;
  • 不能把统一的 {role, content} API 当成统一模型输入。

它不支持:

  • DeepSeek 的 User ID 必然有跨模型通用语义。

14.2 LIMA

LIMA在监督数据中用 EOT 标记说话人边界, 说明 speaker / turn serialization 是 alignment 数据合同的一部分。

它支持研究问题的重要性,但不证明本 base checkpoint 的某个 route TV 是 EOT 语义。

14.3 URIAL

The Unlocking Spell on Base LLMs / URIAL 展示 system prompt、风格化示例与固定格式可以显著改变 base model 的生成行为。

它支持:

  • base model 也可能受结构化上下文条件化;
  • “base ≠ 完全不响应模板”。

它不支持:

  • 把本实验的路由差异命名为 alignment;
  • 推出 DeepSeek-V2-Lite-Chat 的行为。

14.4 Prompt template 与安全/能力

Keeping LLMs Aligned After Fine-tuning 在多个 chat model 上显示 fine-tuning / inference prompt template 会影响安全行为。

State of What Art?则在 6.5M 实例上展示单一 instruction template 会造成性能与排名脆弱性。

两者支持“模板不能当无关包装”,但测量对象是行为/评测,不是本模型的专家路由机制。


15. 因果阶梯

当前证据阶梯可以写成:

一级:官方模板精确 tokenization
  已完成

二级:同长度单 ID 干预
  已完成

三级:目标后 suffix causal 负对照
  已完成,34,488 / 34,488 ordered exact

四级:前置角色词头直接改变目标路由
  已完成,direct TV ≈ .02–.03

五级:角色词头统一调制 system
  证据反对;方向混合、均值近零

六级:完整角色协议
  未完成;冒号、换行、EOS、词头组合尚未一起正交

七级:Chat/SFT 行为
  未完成

八级:任务能力 / 安全 / 准确率
  未完成

16. 不允许外推的结论

本实验不能证明:

  • 模型“理解 User 和 Assistant 的社会角色”;
  • Assistant 词头比 User 更强或更弱;
  • 角色词头统一放大 system prompt;
  • 某个专家是 user / assistant 专家;
  • 路由变化等于回答质量变化;
  • base checkpoint 与 Chat checkpoint 使用相同角色机制;
  • 任意 chat template 都可用一个 token 代表;
  • suffix edit 对生成结果没有影响;
  • 完整 27 层与当前前六个 MoE 层相同;
  • 跨 batch 或跨硬件的 route hash 必须相同。

17. 可复现运行

脚本:

experiments/deepseek/v2_lite_routing_role_marker_head_control.py

正式命令:

PYTHONPATH=/tmp/deepseek-v2-lite-pydeps.6ZJAH3:/usr/lib/python3/dist-packages \
/home/wuyang/.pyenv/versions/navi-router-cu128/bin/python -B \
  experiments/deepseek/v2_lite_routing_role_marker_head_control.py \
  --artifact-dir /tmp/deepseek-v2-lite-artifacts.OEjfce \
  --human-eval /tmp/llm-atlas-routing-corpus/human-eval/data/HumanEval.jsonl.gz \
  --gsm8k /tmp/llm-atlas-routing-corpus/gsm8k/grade_school_math/data/test.jsonl \
  --tnews /tmp/llm-atlas-routing-corpus/tnews/test.json \
  --tnews-archive /tmp/llm-atlas-routing-corpus/tnews_public.zip \
  --wikitext /tmp/llm-atlas-routing-corpus/wikitext-2-raw-v1-validation.parquet \
  --output src/data/deepseek-v2-lite-routing-role-marker-head-control.json \
  --per-domain 32 \
  --content-tokens 23 \
  --batch-prompts 4 \
  --layers 7 \
  --bootstrap 2000 \
  --seed 20260729 \
  --captured-at 2026-07-29T12:30:00+00:00

正式结果:

src/data/deepseek-v2-lite-routing-role-marker-head-control.json
53,440,884 bytes
SHA-256 9dc0e37fbce6581269428dcfcb84c7a17b466c5239c8171e6741f66d5eeb8caf

独立复跑:

src/data/deepseek-v2-lite-routing-role-marker-head-control-repro.json
53,440,884 bytes
SHA-256 9dc0e37fbce6581269428dcfcb84c7a17b466c5239c8171e6741f66d5eeb8caf

两份文件 cmp byte-exact。


18. 下一步

角色词头已经拆到单 ID,但完整角色协议仍包含:

角色词头 + 冒号 + 空格/换行 + EOS/EOT + 训练身份

下一批优先级:

  1. special-token family:BOS / EOS / 普通词头使用同长度家族对照;
  2. 完整 User: / Assistant: 两 token 角色块,用等长两 token 控制;
  3. V2-Lite-Chat checkpoint 的同构路由与生成行为;
  4. target role swap 后的 next-token logits / generation / task score;
  5. 固定整批 companion rows 的 dummy-shape 与 batch-content 对照;
  6. 完整 27 层;
  7. gate logits / margin,而不只看离散 top-6。

本轮最重要的收获不是一句“角色很重要”,而是一条更精确的分界:

一个前置角色词头 ID 足以改变后续路由;但它没有把 system 作用变成统一方向。 真正严格的 Chat 角色机制,需要把训练身份、完整控制 token 族与行为指标一起补上。