免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

Transformer架构深度解析:从注意力机制到大模型训练实战

Transformer架构深度解析:从注意力机制到大模型训练实战 在带新人和做技术分享的过程中我被问得最多的一个问题是那些AI大模型到底是怎么生成的为什么模型会懂上下文每次我都会先说一句话如果你把大模型比作一座高楼那Transformer就是承重墙。无论你用的是GPT类产品、各类开源大模型还是正在研究AI大模型应用开发和agent开发底层支撑都离不开这个在2017年提出的架构。这篇内容我尽量不用晦涩的公式吓人而是把Transformer的来龙去脉、核心机制和实际训练中会踩的坑一次性讲透尤其适合0基础但真想把它搞明白的朋友。1. 为什么说Transformer是大模型的地基从RNN的困境说起要真正理解一个东西的价值最好先去理解没有它之前的世界有多麻烦。1.1 在Transformer之前处理序列数据有多难在2017年之前的很多年自然语言处理领域的主流工具是RNN以及它的改良版LSTM、GRU。这些模型的工作方式非常简单直观像读一本书一样一个词一个词地往后读每一步拿着上一步的记忆和当前词一起更新状态。画出来是这样的模型先看我再带着我的信息看爱再带着我爱的信息看北京以此类推。这就有个致命问题串行处理。第n个词必须等前面n-1个词全部处理完才能开始训练效率非常低根本没法用大规模并行计算加速。你想想面对互联网级别的数据量一个个词排队处理得等到什么时候。另一个问题是长距离依赖。句子一长比如一篇论文里第一段提到的一个概念到第三段才再次出现RNN经过多步传递之后早期信息早就被稀释得差不多了。虽然LSTM加了门控机制来缓解但本质上还是无法真正建模长距离关系。梯度爆炸、梯度消失的问题在长序列上依然如影随形。1.2 Attention Is All You Need一篇论文改写AI格局2017年Google在论文《Attention Is All You Need》里扔出了一个当时显得有点叛逆的想法干脆不要循环结构也不要用卷积整个人工神经网络完全建立在注意力机制上。论文标题其实已经说明了一切——只要注意力就够了。这篇论文提出了Transformer架构实验结果在机器翻译任务上大幅刷新了纪录而且训练速度比当时的RNN快了一个数量级。Transformer这个名字本身也有点讲究它不是transform随便加个后缀而是强调这个模型做的事情是序列变换——把一串词变换成另一串词。通俗讲它像一个翻译官输入的是序列输出的也是序列中间通过注意力机制自动学会谁跟谁有关。1.3 为什么现在的AI大模型几乎都是Transformer的天下Transformer出来之后大家发现它解决了两件大事。并行计算友好Transformer不再按顺序处理词而是把整个句子一次性全部送入网络。句子里每个词的位置信息通过位置编码注入模型在每一层都可以同时计算所有词的表示GPU的并行能力被彻底释放。这直接决定了我们后来能把模型规模做到千亿甚至万亿参数。长距离依赖建模注意力机制让任意两个词之间可以直接建立联系即便它们在句子中相隔很远。翻译时我2015年在北京认识的那个朋友里的朋友和认识之间只需要一次计算就能关联起来不用像RNN那样一步步传递。后来无论是Google的BERT、OpenAI的GPT还是T5、LLaMA虽然表层结构有增有减但核心底座全是Transformer。哪怕是多模态大模型比如把图片、音频也变成序列输入用的依然是Transformer的那套编码思路。所以我说它是AI大模型的承重墙一点也不夸张。2. 注意力机制Transformer的灵魂用人话讲清楚注意力机制是整个Transformer唯一的核心思想。如果你只能记住一个概念那就记它。2.1 从人脑的注意力讲起看一张满是人的合照时你不会逐个像素端详而是先扫一眼然后把注意力集中在最想看的几张脸上。这就是注意力的直觉在海量信息里快速找到当前目标最相关的部分并重点处理它。放到文本里也一样。读小明因为考试没考好所以他__________这句话时你填很伤心还是很懊恼关键线索在考试没考好而不在于小明或他。模型不需要平等看待每个词而是要学会在需要时把权重分给相关信息。注意力机制干的就是这件事。2.2 Query、Key、Value用图书馆借书的比喻首次接触注意力机制的人往往被Query、Key、Value这三个词劝退。别怕我用图书馆场景来讲。Query查询你脑子里想找的东西比如关于深度学习的入门书。可以理解成你在搜索引擎里输入的关键词。Key键每本书封面上贴的标签比如机器学习神经网络Python。Value值书的实际内容。注意力机制做的事情就是拿着你的Query和书架上每一本书的Key做匹配计算相似度得分标签越匹配这本书的内容占权重越大最后把每一本书的Value按权重加权求和得到你要的输出。简单说就是**用问题去匹配标签再把内容按匹配度混合起来**。如果替换成文本场景每个词都同时扮演三个角色作为Query去询问其他词、作为Key被其他词询问、作为Value提供内容信息。2.3 缩放点积注意力的数学计算注意力机制的数学形式其实不复杂核心公式是[ Attention(Q, K, V) softmax(\frac{QK^T}{\sqrt{d_k}})V ]拆开看就是三步。用Query和Key做内积算出两者相似度。内积越大说明越相似。除以(\sqrt{d_k})d_k是Key向量的维度这是缩放步骤。因为向量维度一大内积数值会变得非常大softmax输入过大时梯度会非常小影响训练。除以(\sqrt{d_k})把数值拉回正常范围。做softmax归一化得到一组和为1的权重再把这些权重应用到Value上加权求和得到最终输出。举个例子假设一句话只有三个词我 爱 AI。每个词都映射成维度为4的向量三个Query、Key、Value矩阵分别是3×4。第一步算出3×3的相似度矩阵第二步缩放第三步softmax得到注意力权重矩阵第四步乘上Value得到新的词向量。整个过程一眨眼就完成了但每一步都对应着这个词和哪些词有强关系。2.4 多头注意力为什么要多头单做一次注意力相当于只从一个角度判断词与词的关系。但语言里的关系是复杂的有的头负责语法关系有的头负责指代关系有的头负责语义相似性有的头负责位置相邻性。如果只用一个头很难同时把这些关系都学好。多头注意力就是把这个工作复制多份每一份用不同的线性变换投影到不同的子空间。假设模型维度是512用8个头那每个头处理64维再并行计算注意力。计算完8个头的输出后拼回512维再经过一次线性变换输出。图省事可以这么理解一个头看的是整体8个头分别从不同角度观察观察结果再合并。正因如此Transformer才能在高深和细节两个层面同时建模。3. Transformer架构逐层拆解从输入到输出的完整路径现在我们把整个Transformer当作一条流水线看看一个词从进入模型到输出预测结果都经历了哪些环节。3.1 输入嵌入与位置编码如何让模型理解词的顺序模型不认识文字只认识数字。所以第一步每个token比如一个汉字或一个子词都会被转换成固定维度的向量这一层叫词嵌入Embedding。词嵌入向量是通过训练学出来的语义相近的词在向量空间里位置也相近。但到这里有个问题注意力机制本身对位置不敏感。在我打你和你打我里我和你的嵌入是完全一样的如果不能区分顺序模型看到的就是一模一样的两个序列。于是需要位置编码把每个位置的信息也加到词向量里。最经典的做法是Transformer原论文里的正弦余弦位置编码[ PE_{(pos, 2i)} \sin(\frac{pos}{10000^{2i/d_{model}}}), \quad PE_{(pos, 2i1)} \cos(\frac{pos}{10000^{2i/d_{model}}}) ]pos是位置下标i是维度下标。小彩蛋这个公式让模型不仅能区分位置还能通过三角函数性质学习到相对位置关系。不过现在很多大模型改成可学习的位置编码或者旋转位置编码RoPE思路是类似的——给每个token打上我在哪的标签。3.2 多头自注意力子层句子内部的关系建模加了位置编码后一组向量进入多头自注意力子层。这里的自意思是Query、Key、Value都来源于同一个输入序列。每个位置都去关注序列里的其他位置更新自己的表示。还是我 爱 AI的例子。当模型处理爱这个词时它会让爱同时去问我和AI我和你们俩关系大吗结果可能是我和AI都跟爱关系不小于是爱的新表示里就混入了我和AI的信息。这一层的作用可以理解为让序列里的每个元素在整个上下文里重新理解自己。词义消歧就是这么实现的在苹果发布了新手机里苹果经过自注意力后会更多地吸收手机发布的信息从而更偏向公司而非水果的含义。我们在后面会看到这只是编码器里的自注意力还有解码器里的带掩码自注意力和交叉注意力都是注意力机制的不同应用方式。3.3 前馈网络与残差连接信息如何在层间流动每个Transformer层并不是只有注意力它通常包含两个子层一个多头注意力子层一个**前馈网络Feed-Forward NetworkFFN**子层。前馈网络通常由两层全连接加激活函数构成[ FFN(x) ReLU(xW_1 b_1)W_2 b_2 ]直觉上注意力负责收集信息前馈网络负责加工信息。注意力把上下文信息揉到每个位置里前馈网络再逐位置做非线性变换提取更高层次的特征。每个子层都连着残差连接和层归一化Layer Normalization[ x x Sublayer(x)再做LayerNorm ]残差连接的思想来自图像领域的ResNet作用是让梯度在非常深的网络里也能顺畅回传。Transformer动辄几十上百层没有残差连接深层网络几乎无法训练。LayerNorm的作用则是在每个样本上把特征分布拉回正常范围稳定训练缓解梯度变化过大问题。注意它是LayerNorm而不是BatchNorm因为序列长度不固定LayerNorm不依赖batch大小更适配NLP和大模型场景。3.4 编码器与解码器的区别单向与双向的差异原版Transformer是编码器-解码器结构。编码器负责读入完整的输入序列并用双向的上下文来理解每个词看不见的位置能看后面的词也能看。它适合做理解类任务比如情感分类、判断两句话是否语义相近。解码器负责生成输出序列逐token地生成。生成第t个词时模型不能提前偷看第t1个词否则训练就失去意义了。所以解码器里的自注意力是掩码自注意力也叫因果注意力计算注意力权重时右侧的token一律被mask掉强制模型只能依赖已经生成过的内容。原版还有个交叉注意力Cross Attention子层放在解码器的两个子层之间解码器每个位置生成时会拿它的Query去查编码器输出的Key和Value也就是生成每个词时参考一下源句子的哪些部分。机器翻译里的核心行为——看着英文生成中文——就是靠交叉注意力实现的。你可以这样记忆编码器是读完整个句子再理解解码器是看着来源一个词一个词往外蹦。3.5 从输出到损失模型如何学会预测下一个词解码器输出每个位置的向量后还需要把这个向量映射成下一个词的概率。具体做法是拿输出向量过一个线性层把维度变成词表大小比如3万维再经过softmax得到词表里每个词是下一个词的概率。训练时用交叉熵损失和真实的下一个词做对比然后反向传播更新参数。有个实操细节叫Teacher Forcing教师强制。训练时不管模型上一个词生成得对不对我们都把正确的上一个词喂给它预测下一个词这样能让训练非常高效稳定。推理阶段没有标准答案只能让模型用自己的预测结果作为输入一步错就可能步步错这也是大模型生成质量波动的原因之一。4. 从Transformer到大模型GPT、BERT、T5与Agent开发的关系Transformer原论文给出的是完整的编码器-解码器套件。后来研究者发现并不一定整个架构都要用可以按任务需求裁剪。4.1 同一篇论文不同的演进方向我把三大分支整理成了一张表看完基本就明白市面上主流大模型的来历了。架构模型训练目标适合任务代表编码器-解码器Transformer原版最小化翻译损失序列到序列生成T5、BART仅编码器BERT掩码语言建模理解、分类、检索BERT、RoBERTa仅解码器GPT自回归语言建模文本生成、对话、通用大模型GPT系列、LLaMA、ChatGLM这里需要注意现在大家口中说的AI大模型绝大多数指的是仅解码器架构也就是把Transformer解码器堆得很深。这也是为什么理解解码器里的掩码注意力比理解编码器更实用。4.2 GPT只保留解码器走向文本生成GPT的思路简单粗暴把Transformer的解码器组件拿来只保留掩码自注意力和前馈网络去掉交叉注意力然后在一个巨大的文本语料上做任务预测下一个词。这个任务看起来简单神奇之处在于它产生了很强的涌现能力。当模型规模足够大、语料足够多时模型不再只会机械接词而是学会了语句连贯、知识记忆、逻辑推理、甚至代码编写。ChatGPT的出现本质上是把GPT的生成能力和人类反馈RLHF结合让它会遵循指令、符合人类偏好。预训练加微调这两步就是今天大模型应用开发最常见的路径。你拿到一个开源底座模型然后用领域数据做微调让它变成你的专用助手底层依然是Transformer在逐token生成。4.3 BERT只保留编码器走向语言理解BERT走了另一条路只用编码器训练时随机mask掉一部分词让模型根据双向上下文把被遮住的词猜出来。这种完形填空式训练让它特别擅长理解任务语义相似度、文本分类、实体识别效果都很好。但BERT类模型做文本生成很吃力因为你没有一个自然的逐个生成通道。所以在生成式AI时代BERT的存在感没有GPT强。不过在做检索增强生成RAG里的embedding模型、粗排模型时BERT类架构依然扮演着重要角色。4.4 T5把一切都统一成文本到文本T5选择了全都要但它加了一个聪明的设定不管什么任务都用统一的文本到文本格式。翻译任务写成把这句话翻译成英文你好分类任务写成判断情感这部电影太好看了训练目标还是生成一个目标文本。这种把任务也写进文本的做法启发了后来很多Prompt工程、指令微调的思路。现在的AI大模型开发实际上已经默认所有任务都通过自然语言指令来表达了。4.5 大模型应用开发与Agent开发里Transformer出现在哪很多人做agent开发、RAG、AI工作流觉得自己跟Transformer八竿子打不着。其实底层逻辑逃不开你给大模型发的用户消息先要走tokenizer切分成token再变成embedding向量这是Transformer的输入侧。大模型的推理过程就是Transformer解码器逐token生成每一步都在计算当前上下文下最可能的下一个token。你做模型微调、LoRA、量化部署改来改去都是Transformer的权重和矩阵运算。agent开发里让模型调用工具、决定下一步动作本质上是模型在生成带特定格式的文本然后代码去解析这份文本再执行函数。所以哪怕你只想做应用层开发对Transformer了解得越透彻调试prompt、处理token长度限制、理解幻觉来源、优化推理速度时就越有方向感。5. 0基础动手实现用PyTorch写一个最小可运行的Transformer讲了这么多理论下面动手。我们实现一个极简Transformer不需要GPU普通笔记本电脑也能跑。目标是让模型学会一个小任务根据前缀预测下一个词。5.1 环境准备与数据准备建议环境Python 3.10、PyTorch 2.0以上版本。安装很简单pip install torch我们用一段极简的英文姓氏表当作训练语料让模型学会补全名字。比如输入Jame模型应该预测s。这里我直接用英文单词切分到字符级别简化代码。import torch import torch.nn as nn import math text lebron james stephen curry kevin durant giannis antetokounmpo tokens sorted(list(set(text.replace( , )))) vocab_size len(tokens) 2 # 加 pad 和 eos char2idx {c: i for i, c in enumerate(tokens)} idx2char {i: c for c, i in char2idx.items()} # 构造训练数据把名字拆成一串字符目标是预测下一个字符 data [] for name in text.split(): seq [start] list(name) [end] data.append([char2idx.get(c, 0) for c in seq if c in char2idx or c start])为了处理方便我把词汇表收紧把特殊符号也映射成索引了。实际项目里你会用现成tokenizer比如BPE或SentencePiece原理一致。5.2 从零实现注意力层先写最核心的缩放点积注意力。def scaled_dot_product_attention(q, k, v, maskNone): # q, k, v shape: (batch, heads, seq_len, d_k) d_k q.size(-1) scores torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k) if mask is not None: scores scores.masked_fill(mask 0, -1e9) attn_weights torch.softmax(scores, dim-1) out torch.matmul(attn_weights, v) return out再实现多头注意力class MultiHeadAttention(nn.Module): def __init__(self, d_model, n_heads): super().__init__() self.d_model d_model self.n_heads n_heads self.d_k d_model // n_heads self.wq nn.Linear(d_model, d_model) self.wk nn.Linear(d_model, d_model) self.wv nn.Linear(d_model, d_model) self.wo nn.Linear(d_model, d_model) def forward(self, x, maskNone): batch, seq_len, _ x.size() q self.wq(x).view(batch, seq_len, self.n_heads, self.d_k).transpose(1, 2) k self.wk(x).view(batch, seq_len, self.n_heads, self.d_k).transpose(1, 2) v self.wv(x).view(batch, seq_len, self.n_heads, self.d_k).transpose(1, 2) out scaled_dot_product_attention(q, k, v, mask) out out.transpose(1, 2).contiguous().view(batch, seq_len, self.d_model) return self.wo(out)注意这里d_model要能被n_heads整除。比如d_model64、n_heads4那每个头处理16维。5.3 实现Transformer解码器层因为我们要做的是预测下一个词用解码器就够了。解码器层包含掩码自注意力、前馈网络、残差连接和层归一化。class DecoderLayer(nn.Module): def __init__(self, d_model, n_heads, d_ff, dropout0.1): super().__init__() self.self_attn MultiHeadAttention(d_model, n_heads) self.ffn nn.Sequential( nn.Linear(d_model, d_ff), nn.ReLU(), nn.Linear(d_ff, d_model) ) self.norm1 nn.LayerNorm(d_model) self.norm2 nn.LayerNorm(d_model) self.dropout1 nn.Dropout(dropout) self.dropout2 nn.Dropout(dropout) def forward(self, x, mask): attn_out self.self_attn(x, mask) x self.norm1(x self.dropout1(attn_out)) ffn_out self.ffn(x) x self.norm2(x self.dropout2(ffn_out)) return x class MiniTransformer(nn.Module): def __init__(self, vocab_size, d_model64, n_heads4, d_ff128, num_layers2, max_len32): super().__init__() self.embedding nn.Embedding(vocab_size, d_model) self.pos_embedding nn.Embedding(max_len, d_model) self.layers nn.ModuleList([DecoderLayer(d_model, n_heads, d_ff) for _ in range(num_layers)]) self.norm nn.LayerNorm(d_model) self.fc_out nn.Linear(d_model, vocab_size) def forward(self, x): seq_len x.size(1) pos torch.arange(0, seq_len, devicex.device).unsqueeze(0) x self.embedding(x) self.pos_embedding(pos) mask torch.tril(torch.ones(seq_len, seq_len, devicex.device)).view(1, 1, seq_len, seq_len) for layer in self.layers: x layer(x, mask) logits self.fc_out(self.norm(x)) return logits这里我用了一个可学习的pos_embedding代替原论文的正弦余弦公式。两种方式在实践里都能用GPT走的就是可学习位置编码路线现在也有用RoPE的。5.4 训练一个简单的字符生成任务训练代码很短model MiniTransformer(vocab_sizelen(char2idx) 2) optimizer torch.optim.Adam(model.parameters(), lr1e-3) loss_fn nn.CrossEntropyLoss() def make_batch(data, block_size8): inputs, targets [], [] for seq in data: for i in range(len(seq) - block_size): x seq[i:iblock_size] y seq[i1:iblock_size1] inputs.append(x) targets.append(y) return torch.tensor(inputs), torch.tensor(targets) X, Y make_batch(data) model.train() for epoch in range(200): optimizer.zero_grad() logits model(X) loss loss_fn(logits.view(-1, logits.size(-1)), Y.view(-1)) loss.backward() optimizer.step() if epoch % 20 0: print(fepoch {epoch} loss {loss.item():.4f})真实跑起来loss会快速下降大概几十个epoch后就能学到几个固定名字的模式。推理时用贪心解码每次把已经生成的序列喂给模型取概率最大的那个字符作为下一个。5.5 从小模型到大模型的扩展参数量、数据和算力你可能会问这个玩具模型和大模型开发里说的预训练是一回事吗流程完全一样只是规模不同。Transformer的模型参数主要来自三块词嵌入矩阵词表大小 × 隐藏维度每层注意力的四个线性层4 × d_model × d_modelQ、K、V、O每层前馈网络2 × d_model × d_ff估算公式很好记[ \text{参数量} \approx \text{层数} \times (4 \times d_{model}^2 2 \times d_{model} \times d_{ff}) \text{词表} \times d_{model} ]比如d_model768、d_ff3072、12层、词表3万算下来大约1.1亿参数这就是BERT-base的规模。GPT-3做到1750亿参数就是在层数、维度、层数上全面放大同时配上了几个TB级别的训练语料。这里涉及一个核心规律模型参数量、训练数据量、算力三者基本要同步增长只把模型变大但数据不够效果并不会好。作为初学者我建议不要一上来就想着复现LLaMA。把上面的玩具模型训练到loss收敛打印几次真实生成的样例你对大模型是怎么生成文本的会有非常直观的感受。然后下一步可以做几件事把数据集换成中文新闻、把模型换成大规模预训练权重做微调如用Hugging Face的transformers库加载一个小模型、用LoRA做高效微调。6. 训练Transformer时最常踩的坑和我的调试经验最后这部分是我的实操经验。很多坑是看起来正常但其实模型压根没学到东西我按照踩坑频率从高到低排序。6.1 loss不降或直接变成nan先排查这几件事如果训练了好几轮loss纹丝不动先不要怀疑模型写错。按这个顺序检查学习率过大导致nan。Transformer对学习率很敏感Adam优化器配太大初始学习率特别容易炸。建议初始学习率设在5e-5到1e-4之间大模型的预训练更是要在3e-4附近做warmup。mask没写对。解码器的掩码应该是下三角矩阵让每个位置只能看到它之前的位置。如果mask是上三角模型会提前看到后面的答案训练时loss低得离谱但推理一塌糊涂。输入没有归一化。文本转索引时常见问题是有未登录词被扔成了0结果0恰好是pad干扰模型。要把vocab稳好未知token用一个统一的unk表示。梯度爆掉。加一个梯度裁剪一句代码见效torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)6.2 优化器、学习率调度与warmupTransformer论文里用的是Adam而且专门建议beta20.98而不是默认的0.999因为训练初期梯度方差大beta2太大反而让自适应学习率不稳定。学习率调度通常采用warmup 线性衰减/余弦退火。前几千步从很小的学习率线性升到最大值之后逐步下降。warmup的意义是让模型先稳住阵脚再冲刺不然一开始就大步长更新特别容易跑飞。做微调时也可以用这个思路只是warmup步数可以短一些。6.3 显存不够梯度累积、混合精度、梯度检查点显存不够是训练和推理中最常见的硬瓶颈。几个实用手段减小batch size但batch太小loss震荡厉害这时可以用梯度累积每多少步更新一次。本质上是把小batch的梯度攒起来等效成大batch。混合精度训练PyTorch里一句话torch.autocast(device_typecuda, dtypetorch.float16)配合scaler.scale(loss).backward()。显存减半速度还能快。DeepSpeed和FlashAttention这类库也把注意力计算做了大量优化地址空间和访存效率大幅提升。梯度检查点不保留前向传播的中间激活值反向传播时重新计算。用更多时间换显存。推理时显存不够可以用KV Cache优化或者把模型量化到int8、int4。量化后模型可能掉点需要评估。6.4 复现结果时的细节随机种子、参数初始化、权重共享复现论文或别人的代码时经常结果对不上。常见原因随机种子没固定。至少固定Python、NumPy、PyTorch的种子。参数初始化方式不同。Transformer里线性层默认初始化范围是均匀分布但有些实现会用Xavier初始化或标准差更小的初始化。初始化分布对深层模型影响非常大。嵌入权重是否共享。编码器输入嵌入、解码器输入嵌入、输出层前面的投影可以共享一套权重能大幅减少参数量但会影响部分任务的表示空间。共享不共享结果也会有差异。batch顺序文本长度排序后分组padding能提高训练效率但如果你要严格对比效果数据集的batch组成也会有影响。最后分享一点我自己的学习体会不少人一开始就啃原论文啃到注意力公式就卡住了。我的建议是反过来先跑那个玩具Transformer看着它一个字符一个字符地生成名字你脑子里那些Query、Key、Value掩码多头全部会变得具体。然后再回来看论文每一节都能和代码对应上。我在带新人时还会让他们做一个小实验把mask去掉改成完全可见的双向注意力重新训练同样的数据。对比两个模型在预测下一个词任务上的表现你会非常直观地理解为什么自回归生成必须用因果掩码。这种自己动手对比的收获比看十篇文章都大。Transformer发展到现在已经快十年新的位置编码、新的注意力变体层出不穷但底层的用注意力去加权聚合信息这个核心思想始终没变。把这个根基打牢后面看再复杂的大模型架构你都不会迷路。
返回列表