Files
llm-atlas/research/DEEPSEEK_V2_LITE_CHAT_COMPLETION_DEPTH_AUDIT.md
T
2026-07-30 00:24:27 +08:00

14 KiB
Raw Blame History

DeepSeek-V2-Lite-Chat:512-token 完成度与全 27 层传播审计

状态:已执行、已评测、已做独立子集复跑

执行日期:2026-07-29

模型:deepseek-ai/DeepSeek-V2-Lite-Chat

revision:85864749cd611b4353ce1decdb286193298f64c7

前序审计:DEEPSEEK_V2_LITE_CHAT_BEHAVIOR_AUDIT.md

预注册协议:DEEPSEEK_V2_LITE_CHAT_COMPLETION_PROTOCOL.md

0. 先说结论,也先说不能说什么

这轮把 Round 04 的两个缺口分别补上:

  1. 将统一生成预算从 128 提高到 512,区分“达到长度上限”“自然结束”“可评测”和 “答案正确”;
  2. 不再只观察 Base checkpoint 的前六个 MoE 层,而是在同一个官方 SFT Chat checkpoint 上追踪 embedding、27 个 decoder layer、final norm 与 26 个 MoE gate。

最短结果是:

128-token natural EOS     31 / 128
512-token natural EOS    121 / 128
仍在 512 截断             7 / 128

GSM8K 严格完成且数值 exact 23 / 32
HumanEval 官方 tests pass  24 / 32

全深度目标 content tokens   1,537 / condition
隐藏状态阶段                 29
MoE gate                     26
top-6 route decisions         1,918,176

这些数字只来自四域各 4 条 source、八个固定条件。它们证明这组输入上的执行事实,不是 GSM8K、HumanEval、语言能力或“哪种边界更好”的 benchmark 估计。


1. 冻结的实验对象

1.1 模型与条件

  • 官方 DeepSeek-V2-Lite-Chat SFT checkpoint,不是 Base、R1 或蒸馏模型;
  • 12 个模型与 tokenizer 文件固定到同一个 revision;
  • English、Chinese、Code、Math 各 4 条完整公开 source;
  • 每条 source 使用相同八格:
条件 system 历史边界 身份
s0_eos off EOS 官方序列
s1_eos on EOS 官方序列
s0_bos off BOS 单 ID 反事实
s1_bos on BOS 单 ID 反事实
s0_x off x 单 ID 普通词元对照
s1_x on x 单 ID 普通词元对照
s0_period off . 单 ID 普通词元对照
s1_period on . 单 ID 普通词元对照

同一 source 的八格仍在同一个左填充 batch 内 greedy generation。BOS、x 与句点格 不是有效官方聊天格式;它们是只改一个 input ID 的机制对照。

1.2 数据身份

域 数据 本轮判断
English WikiText-2 raw validation EOS / 截断与传播差异
Chinese TNEWS public test EOS / 截断与传播差异
Code OpenAI HumanEval AST、官方 tests、完成状态
Math GSM8K test 数值抽取、gold exact、完成状态

gold answer、HumanEval tests 与 entry point 都没有进入模型 prompt。


2. 为什么不能从 128-token 结果直接读“能力”

Round 04 的 128 个输出里,97 个因为达到 max_new_tokens=128 而停下。此时:

数学没有来得及写最终数值  ≠  推理一定错误
代码 fence 尚未闭合        ≠  完整代码一定不能运行
generation 停止            ≠  模型主动输出 EOS

所以本轮没有只续写那 97 格,而是让全部 128 格从头使用相同的 512-token 预算。选择性续写 会让先前是否完成决定后续算力,破坏八格的固定预算比较。


3. 显存协议:两次 OOM 如何改变了放置,而没有改变输出

本机可见显存为 32,607 MiB,官方 model card 给出的单卡 BF16 需求是 40GB,因此必须 使用 Accelerate 模块级 CPU offload。

3.1 失败链

  1. 初次加载在 allocator 碎片下失败;
  2. 启用 expandable_segments:True 后,29 GiB static placement smoke 成功;
  3. 29 GiB formal 在长 prompt、512-token KV 与 offloaded lm_head 临时回装共同出现时, 额外申请约 400 MiB 失败;
  4. 失败发生在写正式 JSON 之前,没有可供挑选的部分结果。

3.2 正式放置

max_memory[CUDA:0] = 28 GiB
CUDA resident       = embedding + layers 0–23
CPU offload         = layers 24–26 + final norm + lm_head
allocator           = expandable_segments:True
八格 batch          = 保持不拆

hf_device_map 里的 CPU 表示权重驻留 / offload 身份。Accelerate hook 会在执行前搬运模块, 不能把它简写成“后三层在 CPU 上做矩阵乘”。

28 GiB 与成功的 29 GiB smoke 在 32 格上:

prompt hash                 32 / 32 exact
完整 generated token IDs    32 / 32 exact
decoded text                32 / 32 exact
EOS state                   32 / 32 exact

因此改变的是可执行的静态放置余量,不是这 32 格的 greedy 输出。


4. 512-token completion 结果

4.1 总体完成度阶梯

统一预算 自然 EOS 达到预算仍未 EOS 总输出
128 31 97 128
512 121 7 128

这不是说“512 已经足够”。它只表明在这组固定输入上,增加统一预算解决了 90 个原先的 截断格,仍有 7 格没有自然结束。

4.2 八个条件逐格

条件 自然 EOS 截断 平均生成 tokens Math strict exact Code tests pass
s0_bos 15/16 1 272.6 3/4 4/4
s0_eos 15/16 1 278.0 3/4 3/4
s0_period 15/16 1 270.9 3/4 3/4
s0_x 13/16 3 294.4 2/4 3/4
s1_bos 16/16 0 232.6 3/4 4/4
s1_eos 15/16 1 229.6 3/4 2/4
s1_period 16/16 0 158.3 3/4 3/4
s1_x 16/16 0 177.3 3/4 2/4

分母始终保留。每格的 4 条 math / code 太少,不能把 4/4 与 2/4 排成“边界排行榜”。

4.3 仍截断的 7 格

source 域 条件 状态
WikiText 0443 English s0_bos 512 截断
WikiText 0030 English s0_x 512 截断
WikiText 2909 English s0_x 512 截断
WikiText 2746 English s0_eos 512 截断
WikiText 2746 English s0_x 512 截断
WikiText 2746 English s0_period 512 截断
HumanEval 44 Code s1_eos fence 未闭合、AST 失败、未执行

English / Chinese 没有 gold task terminal,因此“不截断”只表示遇到 EOS,不表示回答正确。


5. 任务评测:完成、可评测、正确各记一张账

5.1 GSM8K

32 个 math cells 的抽取方法:

方法 数量 严格身份
\boxed{} 20 明确 final marker
answer phrase 8 明确 final marker
last-number fallback 4 只作固定预算诊断

最终:

strict-complete numeric exact = 23 / 32

fallback 即使碰巧与 gold 相等,也不会因为“最后一个数字”被升级成严格完成。

5.2 HumanEval

32 个 code cells 使用官方 tests,逐 candidate 进入新容器:

执行分类 数量
passed 24
assertion_failed 5
runtime_error 2
not_run 1

沙箱固定为:

python:3.11-alpine@sha256:25976e9d34a0fab1f278cae931f34c8303d97bf0c0d7f85b6b4dcf641d7702a4
network=none · read-only · user=65534:65534
cap-drop=ALL · no-new-privileges
memory/swap=256m · pids=64 · cpus=0.5
/tmp=16m,noexec,nosuid · host mounts=0 · timeout=5s

通过官方 tests 是这 4 道 HumanEval 上的功能证据,不是生成代码的安全证明。


6. 128-token 前缀与独立复跑

正式 512 运行首先通过:

prompt hash 与 Round 04 相同        128 / 128
前 128 generated token prefix exact 128 / 128

正式运行后再启动新进程、重新加载模型,每域只取第 1 条 source:

prompt hash                 32 / 32 exact
完整 generated token IDs    32 / 32 exact
decoded text                32 / 32 exact
EOS / truncation state      32 / 32 exact

它只能支持“32 格长序列复现”,不能写成 128 / 128 独立复跑。


7. 全 27 层 trace:到底追踪了什么

7.1 两条观察线

对每条 source 的八格做一次 prompt-only、use_cache=false forward:

hidden line:
embedding → layer 00 → ... → layer 26 → final norm
共 29 个阶段

router line:
MoE gate layer 01 → ... → layer 26
共 26 个 gate

每个 hidden 阶段保存目标 content 与完整输入的 shape、dtype、统计量和 tensor SHA-256; 每个 gate 保存 ordered top-6 route hash、route-weight hash、64 专家 load / weighted load 与 描述统计。原始激活 tensor 和逐 token route ID 不写入数据文件。

7.2 为什么排除边界相交 token

八种序列化的字符边界可能落在 tokenizer token 的内部。本轮先验证每个条件的目标内容 token 序列完全相同,再只比较完全位于 content 字符区间内的 token:

目标 interior content tokens = 1,537 / condition
被排除的 boundary-crossing tokens = 56 / 128 variants

否则比较的可能是“同一位置上的不同 token”,隐藏状态差异会混入 tokenizer 边界变化。

7.3 规模恒等式

1,537 target tokens
× 8 conditions
× 26 MoE gates
× top-6 experts
= 1,918,176 route decisions

8. 隐藏状态怎样沿深度分叉

十条 edge 在 embedding 的 1,537 个目标 token 上都 byte-exact:

10 edges × 1,537 rows = 15,370 / 15,370 exact

原因不是“条件没有影响”,而是 embedding 是逐 token lookup;目标内容 token ID 相同, 尚未与前文发生 attention 混合。进入 layer 00 后,十条 edge 的 exact hidden rows 都降为 0, 说明上下文差异已经传播到全部目标行。

四域合计的代表性结果:

edge final-norm cosine final relative L2 cosine 最低阶段
System on−off · EOS 0.99530 0.08474 layer 22
System on−off · BOS 0.99440 0.09614 layer 22
System on−off · x 0.98771 0.14814 layer 22
System on−off · period 0.98747 0.15230 layer 22
BOS−EOS · system off 0.99321 0.10376 layer 01
BOS−EOS · system on 0.99304 0.11123 layer 02
x−EOS · system off 0.99252 0.11333 layer 13
x−EOS · system on 0.98706 0.15694 layer 10
period−EOS · system off 0.99252 0.11368 layer 08
period−EOS · system on 0.98754 0.15810 layer 08

不能只看 cosine 接近 1 就说“几乎一样”:2048 维状态中的小方向变化可以改变后续 router 排序与 logits。也不能把 relative L2 的深度曲线读成单调累积;残差、归一化与注意力会让差异 被放大、旋转或部分抵消。


9. 26 个 gate 怎样分叉

ordered top-6 exact 比 set exact 更严格:前者要求六个专家及顺序完全一致;后者只要求专家集合 一致。四域合计:

edge ordered exact 最低层 最低比例 layer 26 ordered exact layer 26 set exact
System on−off · EOS 24 52.6% 60.2% 71.6%
System on−off · BOS 24 47.0% 56.9% 69.8%
System on−off · x 24 38.1% 45.7% 60.5%
System on−off · period 24 36.6% 44.2% 59.1%
BOS−EOS · system off 01 42.0% 54.1% 67.0%
BOS−EOS · system on 24 40.9% 50.6% 64.9%
x−EOS · system off 21 41.1% 49.1% 63.6%
x−EOS · system on 24 32.9% 44.6% 58.9%
period−EOS · system off 24 42.7% 48.9% 63.8%
period−EOS · system on 24 34.8% 43.4% 57.2%

“最低层常在 24”是这 16 条 source 的描述事实,不是模型普遍规律,也不是 layer 24 的因果 特殊性。更不能把 gate 分叉率直接解释成能力变化:路由只是稀疏 FFN 计算路径的一部分。


10. 全深度独立复跑与元数据缺陷

正式 trace 后重新启动进程,每域复跑第 1 条 source。逐字段核对:

source objects(去除 runtime 字段) 4 / 4 exact
hidden tensor SHA-256             1,856 / 1,856 exact
ordered-route SHA-256             1,664 / 1,664 exact
route-weight SHA-256              1,664 / 1,664 exact
所有隐藏 / 路由比较统计            exact

预发布核对曾发现 content_token_ids_sha256 错误引用了外层循环最后一条 source,并通过 Python set 的迭代顺序让该顶层元数据在两个进程间不同。隐藏 tensor、route hash 与全部比较 统计当时已经 exact;仍然修正脚本为“在每条 source 验证后立即保存其内容 token hash”,随后 正式与复跑两份 trace 全部重跑。当前公开文件是修正后的结果。

这个例子说明:复跑不能只看 headline 数字,也要比较不参与结论的身份字段。


11. 文件、哈希与运行账

文件 bytes SHA-256
512 formal generation 871,946 6af40512c5868caab0ef58356aaa7728384f2b7acc7c502aa89478fdf5a2a468
completion evaluation 138,837 73f4616359d664377405dd989ee15cbf18e540e2f7b916b0ff99a99143091427
512 independent subset 233,300 6c89f85ae783de5dfbe71694ba23307e79ca04f9522dd8684aef8f6f5295424d
full-depth formal 36,019,346 5678ed238f13e3b0d5cf7a3db2268dbddf13f047cdc3730771ba1c66d96426e8
full-depth independent subset 9,166,628 17c367cccce3698df6fa8a0c0455d2b0e52cd27e1f66717a66989a586dfd1098

关键运行账:

运行 GPU placement 模型加载 执行 peak CUDA allocation
512 formal 28 GiB 8.42 s 1,225.27 s generation 31,464,357,376 B
full-depth formal 28 GiB 8.37 s 13.55 s forward 28,754,760,704 B
full-depth subset 28 GiB 8.44 s 3.85 s forward 28,754,760,704 B

这些 eager + offload 延迟不是生产 serving throughput。


12. 证据阶梯与下一步

前六层 Base route
  ↓ 回答早期路由是否分叉

完整 Chat generation
  ↓ 回答最终 token 轨迹是否结束、可评测、正确

29-stage hidden + 26-gate route
  ↓ 回答同一输入差异怎样穿过完整 checkpoint

尚未完成:
  干预式 mediation、更多 source、sampling robustness、
  标准 benchmark harness、generation-time KV / serving trace

本轮最重要的边界仍然是:

  • hidden/router association 不是中介因果;
  • 4 道 math / code 不是 benchmark;
  • 固定 greedy exact 不是采样鲁棒性;
  • counterfactual token 序列不是官方有效聊天;
  • prompt-only use_cache=false trace 不是生成期 KV 或生产服务轨迹;
  • HumanEval tests pass 不是代码安全。