# 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。 最短结果是: ```text 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` 而停下。此时: ```text 数学没有来得及写最终数值 ≠ 推理一定错误 代码 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 正式放置 ```text 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 格上: ```text 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 | 只作固定预算诊断 | 最终: ```text 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 | 沙箱固定为: ```text 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 运行首先通过: ```text prompt hash 与 Round 04 相同 128 / 128 前 128 generated token prefix exact 128 / 128 ``` 正式运行后再启动新进程、重新加载模型,每域只取第 1 条 source: ```text 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: ```text 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: ```text 目标 interior content tokens = 1,537 / condition 被排除的 boundary-crossing tokens = 56 / 128 variants ``` 否则比较的可能是“同一位置上的不同 token”,隐藏状态差异会混入 tokenizer 边界变化。 ### 7.3 规模恒等式 ```text 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: ```text 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。逐字段核对: ```text 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. 证据阶梯与下一步 ```text 前六层 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 不是代码安全。