找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4149

积分

0

好友

545

主题
发表于 2 小时前 | 查看: 4| 回复: 0

如果你还没来得及细看 Kimi K3 的开源代码,海外开发者 Baseten 已经替我们熬了两个通宵,喝掉整整 40 罐气泡水,把模型的技术细节从头到尾研究了一遍。  

他不仅贯通了 K3 当下的设计,还从代码里梳理出一条从 2019 年持续至今的技术演进线。  

先说一个最直观的对比:
2019 年的 GPT-2 有 1.24 亿参数,如今 Kimi K3 的单模型体量,相当于 22580 个 GPT-2 叠加在一起。
从 1.24 亿到 2.8 万亿,Kimi 团队花了七年时间才走到今天这套架构。

但这篇分析真正的价值,是指出了关键事实:两万多倍的跨越,核心不是靠堆叠参数。  

48小时深度拆解Kimi K3代码的个人工作记录

他把线索梳理得非常清楚——Kimi K3 并非在某一时刻突然出现,而是沿着一条技术暗线迭代了多年。  

下面我们就跟着他的思路,看看模型参数增长 22580 倍的过程中,架构究竟经历了哪些关键变化。

一、Kimi 入场前,模型如何处理记忆

2019 年的 GPT-2 虽然只有 1.24 亿参数,却已经定义了后来大模型最常见的工作模式:读入前文,再逐 Token 预测下文。

下面这张 GPT-2 预测下一个 Token 的流程图,展示得很明白:  

语言模型生成下一个Token的流程示意图,展示词汇向量处理与预测结果

可以看出,每生成一个新 Token,模型都得把前面的内容重新算一遍。上下文越长,重复计算就越多。  

为了缓解这个问题,模型引入了 KV Cache,把已经处理过的 Key 和 Value 暂存起来,不必每次从头再算。下面是带 KV 缓存的注意力代码:

if past_kv is not None:
    k_past = past_kv[0]
    v_past = past_kv[1]
    k = torch.cat((k_past, k), dim=2)
    v = torch.cat((v_past, v), dim=2)

这种做法省下了重复计算,但缓存本身会随着上下文拉长而不断增长,显存压力也随之上升。

带KV缓存的注意力机制数据流向图

到了 2020 年,线性注意力机制 出现了。它不再死板地保留每一个 Token 的完整信息,而是把读过的内容压缩进一块固定大小的记忆中。  

对应的核心代码是这样更新记忆的:

k = F.elu(k) + 1
k = k.transpose(-1, -2)
q = F.elu(q) + 1

S, z = cache if cache is not None else (0.0, 0.0)
S = S + k @ v
z = z + k

o = q @ S
denom = q @ z
o_scaled = o / denom

其中 S 就是模型一直维护的固定记忆。无论后续上下文有多长,模型都不需要保留一份越发臃肿的 KV Cache,这让长文本处理成本明显降低。

但线性注意力也存在问题:所有新信息持续写进同一块有限的记忆,时间长了就容易互相干扰。  

为了解决这种干扰,DeltaNet 不再直接叠加新信息,而是先读取当前位置存了哪些内容,再计算新旧信息的差值,只把需要修正的部分写回去。  

DeltaNet 的核心更新代码如下:

q = F.normalize(F.silu(q), dim=-1)
k = F.normalize(F.silu(k), dim=-1)
beta = torch.sigmoid(self.w_beta(x)).view(b, 1, t, 1)

S = cache if cache is not None else 0.0
v_old = k @ S
u = beta * (v - v_old)

S = S + k.transpose(-1, -2) @ u
o = q @ S

其中 v_old 代表从旧记忆中读出的信息,v - v_old 就是新旧之差。模型最终写回去的不是完整的新值,而是经过 beta 调节的修正量。

下面这张对比图能让人一眼看懂线性注意力与 DeltaNet 的差异:

对比线性注意力与DeltaNet更新规则的示意图,展示记忆污染与修正过程

  • 左侧:线性注意力下,两个 Token 共用相同 Key 写入不同内容时,新旧数据直接叠加,最终导致记忆污染。  
  • 中间:DeltaNet 会先读取旧值并计算出修正量,再替换原先的信息。  
  • 右侧:验证更新后的结果——旧内容已被彻底清除,当前位置只保留新的 Value。

尽管如此,DeltaNet 仍需按 Token 顺序一步步修改记忆,这种串行方式对 GPU 很不友好。为了让它适配更大的语言模型,人们重新设计了计算方式:将连续 Token 划分成多个数据块,让每一块内容能够并行处理。

DeltaNet的分块并行处理架构示意图

到 2024 年,这套机制已被扩展到 13 亿参数的模型,并在 1000 亿 Token 的数据上完成训练。  

但 DeltaNet 仍然缺少一种能力:主动遗忘。  

它可以在新信息到来时修改某条旧记录,却无法主动清理一批已经过时的内容。  

比如对话突然从旅游规划转向公司财报,原来留存的酒店、机票信息可能已经无用,但 DeltaNet 只能等到新信息出现后逐条替换。  

于是 Gated DeltaNet 增加了一个“遗忘开关”,其更新逻辑如下:

S = cache if cache is not None else 0.0

alpha = gate(x)  # 控制旧记忆的保留比例
beta = torch.sigmoid(self.w_beta(x))  # 控制本次修改的幅度

v_old = k @ S
u = beta * (v - v_old)

S = alpha * S + k.transpose(-1, -2) @ u
o = q @ S

最关键的变化在最后两行:模型先用 alpha * S 衰减旧记忆,再把新的修正量写进去。
当 alpha 接近 1 时,旧记忆大部分继续留存;当 alpha 接近 0 时,旧记忆会被大幅削弱,为新内容腾出空间。

Gated DeltaNet更新流程与遗忘门控机制对比

这样一来,即便没有新信息逐条替换,模型也能主动让整块旧记忆淡出。  

到这一步,模型已经学会了写入、修改和遗忘。  

不过,这个遗忘开关只能统一削弱整块记忆,无法精准决定哪些该留、哪些该忘。  

随着大模型开始处理百万 Token 上下文和更复杂的 Agent 任务,这种“一刀切”的遗忘方式已经明显不够用了。

二、Kimi 重新设计记忆系统

Kimi 在 Gated DeltaNet 的基础上,提出了 Kimi Delta Attention(KDA)。  

最显著的变化,就是 把统一的“遗忘开关”拆成了许多独立开关。  

下图可以清晰地看到从 DeltaNet、Gated DeltaNet 到 KDA 的门控机制演进:

DeltaNet、Gated DeltaNet与KDA门控机制的演进公式对比

在 Gated DeltaNet 中,alpha 还是一个单一的数值;到了 KDA,它变成了 Diag(alpha),也就是从统一控制整块记忆,升级为按通道分别控制不同的记忆维度。  

这样,模型可以让一部分记忆快速淡出,而让另一部分保存更久。  

比如分析一份财报时,公司名称、年份和核心指标可以长期保留,而一些临时性的表述、重复信息则可以更快遗忘。换句话说,模型开始具备更细致的记忆管理能力——它不只知道什么时候该忘,还能判断具体应该忘掉什么。

下面是 Delta Rule、Gated Delta Rule 与 KDA 的代码对比,差异在实现中体现得非常清楚:

Delta Rule、Gated Delta Rule与KDA的代码实现对比

Kimi 官方的实验显示,这种设计在部分任务上的效果可以超过传统的完整注意力,同时还显著提升了长文本生成速度。  

为了验证 KDA,Kimi 团队训练了一款总参数 480 亿、单次激活 30 亿参数的 Kimi Linear 模型,正式进入大规模 MoE 模型阶段。  

在 100 万 Token 上下文下,该模型最多可减少 75% 的 KV Cache 占用,解码吞吐量最高达到传统注意力的 6 倍。

但 KDA 依然有一个先天限制:它会把大量历史信息压缩到固定大小的记忆中。
只要压缩,就必然丢失细节。模型可能记得一段话的大意,却未必能精准找回某个数字、一行代码或一句原文。  

到了 Kimi K3,模型总参数从 480 亿大幅跃升到 2.8 万亿。Kimi 没有把所有希望全押在 KDA 上,而是让 KDA 与传统注意力机制配合工作。  

下图是 Kimi K3 的整体架构,可以清晰看到它以“三层 KDA + 一层 MLA”为一个基本循环,并将这套结构重复 23 次。

Kimi K3的整体架构图,展示KDA与MLA的交互流程

  • KDA 负责维护一块固定大小的长期记忆。它速度更快、成本更低,适合记录上下文的主要信息。  
  • MLA(Gated MLA) 则会定期回到完整上下文中,重新检索原始细节。它更像一次精确查询,适合找回具体数字、代码和原文位置。

可以把它们理解成日常工作的两种方式:平时先看整理好的会议纪要,快速掌握整体情况;需要核对关键数据时,再打开原始会议记录查证。

三、网络太深,Kimi K3 如何找回早期信息?

上文说到,Kimi K3 以“三层 KDA + 一层 Gated MLA”为基本循环。23 个循环组成 92 层,再多加一层 Gated MLA,最终堆叠出 93 个解码器层。  

虽然 KDA 和 MLA 解决了如何在百万 Token 中保存并找回信息,这些信息进入模型后,还要在 93 层网络中不断向后传递。  

传统 Transformer 靠残差连接传递层间信息。每过一层,模型都会把这一层的新结果直接加到原有结果上。层数越深,早期提取的内容就越容易被后面的信息冲淡。  

为了避免这些被稀释的信息丢失,Kimi K3 引入了 AttnRes——也就是 “注意力残差”。  

AttnRes 会根据当前正在处理的内容,为前面不同阶段的结果重新分配权重,让后面的网络层自行判断哪些早期信息更值得参考。  

比如处理数学题时,模型可以重新关注早期网络层识别出的公式和条件;处理长文章时,则可以找回前面已经提取出的主题和关键事实。

下图对比了普通残差连接与 ResAttn 的结构差异:

Kimi K3中普通残差连接与ResAttn结构的对比图

左侧的传统残差连接会把之前各层的结果统一累加起来;右侧的 AttnRes 增加了多条跨层路径,并通过 alpha 权重来决定当前层应该从前面哪些阶段读取信息。

但如果每一层都重新检索之前的所有结果,训练成本和推理成本就会非常高。  

因此 Kimi K3 采用了分块式 AttnRes:每经过 12 个解码器层,就把这段网络产生的中间结果整理成一个信息块,供后面的网络层按需访问。  

93 层最终被划分成 8 个 AttnRes 信息块,后续层检索时只需在这些信息块之间选择,不必逐层读取全部历史结果。  

下面是分块式 AttnRes 的核心实现:

V = torch.stack(blocks + [partial_block])  # [N+1, B, T, D]
K = norm(V)

logits = torch.einsum(
    'd, nbt d -> nbt',
    proj.weight.squeeze(),
    K
)

h = torch.einsum(
    'nbt, nbt d -> bt d',
    logits.softmax(0),
    V
)

return h

其中 V 保存了此前各个信息块以及当前块的结果;logits 会计算每个信息块对当前任务的重要程度;经过 softmax 后成为权重,再由模型按权重重新组合历史信息。

MLA 和 AttnRes 一起,解决了两个方向上的信息丢失问题:  

  • 上下文太长时,MLA 负责从前文中找回原始细节;  
  • 网络层数太深时,AttnRes 负责调取早期网络层提取出的中间结果。

四、控制计算量

Kimi K3 拥有 2.8 万亿参数,那这么大的模型怎么控制计算开销?  

K3 采用了更细粒度的专家划分,总共设置 898 个专家,其中 2 个是所有 Token 都会调用的共享专家,另外 896 个则由路由器按需选取。  

每处理一个 Token,最终只有 18 个专家真正参与计算,其余全部保持待命。  

这种设计让 Kimi K3 能继续扩大总参数规模,同时把单 Token 的计算量控制在很有限的范围内。那 2.8 万亿代表的是模型整体容量,而不是生成每个 Token 都要跑遍全部参数。

此外,K3 还采用了潜在空间 MoE:输入先被压缩到更低维度的空间,再交给专家网络处理,计算完成后再重新投影回原来的维度。

Kimi K3中不同专家结构的对比与延迟分析

根据原文分析,这项设计可以让专家网络的 FLOPs 几乎减少一半。Kimi K3 因此能够容纳数量更多、划分更细的专家,同时避免专家规模直接等比转化为计算成本。

五、总结

回头看这条技术演进路线,会发现每一次升级,都在解决上一种方法遗留下来的问题。

注意力机制与大语言模型从2017年到2026年的完整发展历史

  • GPT-2 使用 KV Cache 保存前文所有内容,记得完整,但上下文越长缓存就越大。  
  • 线性注意力把所有历史压缩进固定记忆,降低了长文本成本,却容易让不同信息互相干扰。  
  • DeltaNet 让模型能够修改旧记忆,减少新旧信息之间的冲突。  
  • Gated DeltaNet 加入主动遗忘能力,使模型能清理已经过时的内容。  
  • KDA 将遗忘机制进一步细化,让不同类型的信息拥有不同的保存时间。  
  • MLA 周期性地回到原始上下文,找回压缩记忆中丢失的细节。  
  • MoE 把庞大参数拆分给不同专家,每次只调用与当前内容相关的一小部分。  
  • AttnRes 则让模型重新读取早期网络层的中间结果,避免关键信息随着模型加深而被稀释。

所以,Kimi K3 并不是对传统 Transformer 的简单放大。它把过去七年里出现的多条技术路线组合、精调、融合到一起,才达成了能力层面真正的跨越。  

前沿能力很少由某个孤立的灵感直接催生。  

一篇论文里的技术方案,需要经过长期验证,再被放入完整体系中稳定运行,最终才会转化为用户真正能感受到的能力。  

这也让大模型竞争的准入门槛变得更高。单点突破依然重要,但真正决定最终差距的,往往是一个团队能否把不同阶段的研究成果串联起来,并转化成可以规模化运转的系统。  

站在更长的时间尺度来看,AI 的进步常常显得突然,背后却是多年积累在某个时刻集中成熟。  

Kimi K3 只是这条规律的又一次体现。下一次能力边界的跃迁,大概也会以类似的方式发生。




上一篇:Docker Swarm迁移Kubernetes实录:这6个大坑千万别踩
下一篇:RAG系统性能提升高阶技巧:索引优化、查询转换与微调全指南
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-8-3 05:59 , Processed in 1.205242 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表