【2025版】从头搭建Llama 3,GitHub,精通收藏此文,小白秒入门!

Meta最新模型LLaMA细节与代码详解 本文对Facebook Meta AI最新提出的大语言模型LLaMA进行简单的介绍,以及对其开源出的代码和细节进行了详细的说明。 阅读详情


**【新智元导读】**Llama 3发布一个月后,一位开发者在GitHub上创建了名为「从头开始实现Llama 3」的项目,引起了开源社区的广泛关注。代码非常详细地展现了Llama所使用的Transformer架构,甚至让Andrej Karpathy亲自下场「背书」。

Llama系列作为为数不多的优质开源LLM,一直受到开发者们的追捧。在Hugging Face社区的文本生成模型中,几乎是「霸榜」的存在。

就在520这天,一位名叫Nishant Aklecha的开发者在推特上宣布了自己的一个开源项目,名为「从头开始实现Llama 3」。

这个项目详细到什么程度呢——

矩阵乘法、注意力头、位置编码等模块全部都拆开解释。

而且项目全部用Jupyter Notebook写成,小白都可以直接上手运行。

堪比哈佛NLP小组曾经出品的「The Annotated Transformer」。

https://nlp.seas.harvard.edu/annotated-transformer/

才一天多的时间,小哥发表的这篇推特已经有32万次阅读,甚至被Andrej Karpathy大佬亲自点赞——

「全部拆开解释之后,通过模块的嵌套以及互相调用,可以更清楚地看到模型到底做了什么。」

项目也在GitHub上获得了4.6k星。

项目地址:https://github.com/naklecha/llama3-from-scratch

那就让我们来看看作者是如何深入拆解Llama 3的。

下载并读取模型权重

首先需要从Meta官网下载模型权重文件,以便后续运行时使用。

https://github.com/meta-llama/llama3/blob/main/README.md

下载后需要先读取权重文件中的变量名:

model = torch.load("Meta-Llama-3-8B/consolidated.00.pth")  
print(json.dumps(list(model.keys())[:20], indent=4))
[  
    "tok_embeddings.weight",  
    "layers.0.attention.wq.weight",  
    "layers.0.attention.wk.weight",  
    "layers.0.attention.wv.weight",  
    "layers.0.attention.wo.weight",  
    "layers.0.feed_forward.w1.weight",  
    "layers.0.feed_forward.w3.weight",  
    "layers.0.feed_forward.w2.weight",  
    "layers.0.attention_norm.weight",  
    "layers.0.ffn_norm.weight",  
    "layers.1.attention.wq.weight",  
    "layers.1.attention.wk.weight",  
    "layers.1.attention.wv.weight",  
    "layers.1.attention.wo.weight",  
    "layers.1.feed_forward.w1.weight",  
    "layers.1.feed_forward.w3.weight",  
    "layers.1.feed_forward.w2.weight",  
    "layers.1.attention_norm.weight",  
    "layers.1.ffn_norm.weight",  
    "layers.2.attention.wq.weight"  
]

以及模型的配置信息:

with open("Meta-Llama-3-8B/params.json", "r") as f:  
    config = json.load(f)  
config
{'dim': 4096,  
 'n_layers': 32,  
 'n_heads': 32,  
 'n_kv_heads': 8,  
 'vocab_size': 128256,  
 'multiple_of': 1024,  
 'ffn_dim_multiplier': 1.3,  
 'norm_eps': 1e-05,  
 'rope_theta': 500000.0}

根据以上输出,可以推断出模型架构的信息——

  • 32个transformer层

  • 每个多头注意力模块有32个注意力头

  • 分词器的词汇量为128256

直接将模型配置信息存储到变量中,方便使用。

dim = config["dim"]``n_layers = config["n_layers"]``n_heads = config["n_heads"]``n_kv_heads = config["n_kv_heads"]``vocab_size = config["vocab_size"]``multiple_of = config["multiple_of"]``ffn_dim_multiplier = config["ffn_dim_multiplier"]``norm_eps = config["norm_eps"]``rope_theta = torch.tensor(config["rope_theta"])

分词器与编码

那么就从语言模型的第一步——分词器开始,但是这一步并不需要我们自己手写。

Llama 3使用了GPT等大模型常用的BPE分词器,karpathy大佬之前就复现过一个最简版。

https://github.com/karpathy/minbpe

除了Karapthy大佬复现的版本,OpenAI也开源了一个运行速度很快的分词器tiktoken。这两个随便挑,估计都比自己从头训练的要强。

https://github.com/openai/tiktoken

有了分词器,下一步就是要把输入的文本切分为token。

prompt = "the answer to the ultimate question of life, the universe, and everything is "``tokens = [128000] + tokenizer.encode(prompt)``print(tokens)``tokens = torch.tensor(tokens)``prompt_split_as_tokens = [tokenizer.decode([token.item()]) for token in tokens]``print(prompt_split_as_tokens)
[128000, 1820, 4320, 311, 279, 17139, 3488, 315, 2324, 11, 279, 15861, 11, 323, 4395, 374, 220]``['<|begin_of_text|>', 'the', ' answer', ' to', ' the', ' ultimate', ' question', ' of', ' life', ',', ' the', ' universe', ',', ' and', ' everything', ' is', ' ']

再使用PyTorch内置的神经网络模块(torch.nn)将token转换为embedding,[17x1]的token维度变为[17x4096]。

embedding_layer = torch.nn.Embedding(vocab_size, dim)``embedding_layer.weight.data.copy_(model["tok_embeddings.weight"])``token_embeddings_unnormalized = embedding_layer(tokens).to(torch.bfloat16)``token_embeddings_unnormalized.shape
torch.Size([17, 4096])

此处应该是整个项目中唯一使用PyTorch内置模块的地方。而且,作者给出了温馨提示——记得经常打印一下张量维度,更容易理解。

之后再使用RMS对embedding进行归一化处理。这一步不会改变张量形状,只是归一化其中的数值,公式如下:

模型配置中的norm_eps变量设置为1e-5,就是用在此处,防止rms值意外设置为0。

# def rms_norm(tensor, norm_weights):``#     rms = (tensor.pow(2).mean(-1, keepdim=True) + norm_eps)**0.5``#     return tensor * (norm_weights / rms)``def rms_norm(tensor, norm_weights):`    `return (tensor * torch.rsqrt(tensor.pow(2).mean(-1, keepdim=True) + norm_eps)) * norm_weights

构建Transformer层

每一个Transformer层都需要经过如下步骤:

由于是从头构建,我们只需要访问模型字典中第一层(layer.0)的权重。

先用刚才定义的rms_norm函数,结合模型权重,进行embedding的归一化处理。

token_embeddings = rms_norm(token_embeddings_unnormalized, model["layers.0.attention_norm.weight"])``token_embeddings.shape
torch.Size([17, 4096])

多头注意力

查询向量

让我们先用一张图复习注意力机制的计算过程:

如果从模型直接加载查询、键、值和输出的权重,我们会得到四个二维矩阵,形状分别为 [4096x4096]、[1024x4096]、[1024x4096]、[4096x4096]。

print(`    `model["layers.0.attention.wq.weight"].shape,`    `model["layers.0.attention.wk.weight"].shape,`    `model["layers.0.attention.wv.weight"].shape,`    `model["layers.0.attention.wo.weight"].shape``)
torch.Size([4096, 4096]) torch.Size([1024, 4096]) torch.Size([1024, 4096]) torch.Size([4096, 4096])

因为大模型考虑了注意力中乘法并行化的需求,压缩了矩阵维度。但是为了更清楚地展示机制,作者决定将这些矩阵都展开。

模型有32个注意力头,因此查询权重矩阵应该展开为[32x128x4096],其中128是查询向量的长度,4096是embedding的维度。

q_layer0 = model["layers.0.attention.wq.weight"]``head_dim = q_layer0.shape[0] // n_heads``q_layer0 = q_layer0.view(n_heads, head_dim, dim)``q_layer0.shape
torch.Size([32, 128, 4096])

于是可以访问第一个注意力头的查询权重,维度是[128x4096]。

q_layer0_head0 = q_layer0[0]``q_layer0_head0.shape
torch.Size([128, 4096])

现在将查询权重与embedding相乘,就得到了查询矩阵,维度为[17x128],表示长度为17的句子,其中每个token都有维度为128的查询向量。

q_per_token = torch.matmul(token_embeddings, q_layer0_head0.T)``q_per_token.shape
torch.Size([17, 128])
位置编码

由于注意力机制中对每个token没有序列「位置」的概念,第一个词和最后一个词在Q、K、V矩阵看来都是一样的,因此需要在查询向量中嵌入维度为[1x128]的位置编码。

位置编码有多种方法,Llama模型采用的是旋转位置编码(RoPE)。

首先将查询向量两两分为一对,共有64对。

q_per_token_split_into_pairs = q_per_token.float().view(q_per_token.shape[0], -1, 2)``q_per_token_split_into_pairs.shape
torch.Size([17, 64, 2])

句子中在m位置的一对查询向量,旋转角度为m*(rope_theta),其中rope_theta也在模型的配置信息中。

zero_to_one_split_into_64_parts = torch.tensor(range(64))/64``zero_to_one_split_into_64_parts
tensor([0.0000, 0.0156, 0.0312, 0.0469, 0.0625, 0.0781, 0.0938, 0.1094, 0.1250,`        `0.1406, 0.1562, 0.1719, 0.1875, 0.2031, 0.2188, 0.2344, 0.2500, 0.2656,`        `0.2812, 0.2969, 0.3125, 0.3281, 0.3438, 0.3594, 0.3750, 0.3906, 0.4062,`        `0.4219, 0.4375, 0.4531, 0.4688, 0.4844, 0.5000, 0.5156, 0.5312, 0.5469,`        `0.5625, 0.5781, 0.5938, 0.6094, 0.6250, 0.6406, 0.6562, 0.6719, 0.6875,`        `0.7031, 0.7188, 0.7344, 0.7500, 0.7656, 0.7812, 0.7969, 0.8125, 0.8281,`        `0.8438, 0.8594, 0.8750, 0.8906, 0.9062, 0.9219, 0.9375, 0.9531, 0.9688,`        `0.9844])
freqs = 1.0 / (rope_theta ** zero_to_one_split_into_64_parts)``freqs
tensor([1.0000e+00, 8.1462e-01, 6.6360e-01, 5.4058e-01, 4.4037e-01, 3.5873e-01,`        `2.9223e-01, 2.3805e-01, 1.9392e-01, 1.5797e-01, 1.2869e-01, 1.0483e-01,`        `8.5397e-02, 6.9566e-02, 5.6670e-02, 4.6164e-02, 3.7606e-02, 3.0635e-02,`        `2.4955e-02, 2.0329e-02, 1.6560e-02, 1.3490e-02, 1.0990e-02, 8.9523e-03,`        `7.2927e-03, 5.9407e-03, 4.8394e-03, 3.9423e-03, 3.2114e-03, 2.6161e-03,`        `2.1311e-03, 1.7360e-03, 1.4142e-03, 1.1520e-03, 9.3847e-04, 7.6450e-04,`        `6.2277e-04, 5.0732e-04, 4.1327e-04, 3.3666e-04, 2.7425e-04, 2.2341e-04,`        `1.8199e-04, 1.4825e-04, 1.2077e-04, 9.8381e-05, 8.0143e-05, 6.5286e-05,`        `5.3183e-05, 4.3324e-05, 3.5292e-05, 2.8750e-05, 2.3420e-05, 1.9078e-05,`        `1.5542e-05, 1.2660e-05, 1.0313e-05, 8.4015e-06, 6.8440e-06, 5.5752e-06,`        `4.5417e-06, 3.6997e-06, 3.0139e-06, 2.4551e-06])
freqs_for_each_token = torch.outer(torch.arange(17), freqs)``freqs_cis = torch.polar(torch.ones_like(freqs_for_each_token), freqs_for_each_token)

经过以上操作后,我们构建了freq_cis矩阵,存储句子中每个位置的、对查询向量每个值的旋转角度。

将每对查询向量转换为复数,之后进行与旋转角度进行点积操作。

q_per_token_as_complex_numbers = torch.view_as_complex(q_per_token_split_into_pairs)``q_per_token_as_complex_numbers.shape
torch.Size([17, 64])
q_per_token_as_complex_numbers_rotated = q_per_token_as_complex_numbers * freqs_cis``q_per_token_as_complex_numbers_rotated.shape
torch.Size([17, 64])

这样我们就得到了旋转后的查询向量,需要再转换回实数形式。

q_per_token_split_into_pairs_rotated = torch.view_as_real(q_per_token_as_complex_numbers_rotated)``q_per_token_split_into_pairs_rotated.shape
torch.Size([17, 64, 2])
q_per_token_rotated = q_per_token_split_into_pairs_rotated.view(q_per_token.shape)``q_per_token_rotated.shape
torch.Size([17, 128])

旋转后的查询向量,维度依旧是 [17x128]。

键向量

键向量的计算与查询向量非常类似,也需要进行旋转位置编码,只是维度有所差异。

键的权重数量仅为查询的1/4,因为需要减少模型计算量,每个权重值被4个注意力头共享。

k_layer0 = model["layers.0.attention.wk.weight"]``k_layer0 = k_layer0.view(n_kv_heads, k_layer0.shape[0] // n_kv_heads, dim)``k_layer0.shape
torch.Size([8, 128, 4096])

因此这里第一个维度的值为8,而不是我们在查询权重中看到的32。

k_layer0_head0 = k_layer0[0]``k_per_token = torch.matmul(token_embeddings, k_layer0_head0.T)``k_per_token_split_into_pairs = k_per_token.float().view(k_per_token.shape[0], -1, 2)``k_per_token_as_complex_numbers = torch.view_as_complex(k_per_token_split_into_pairs)``k_per_token_split_into_pairs_rotated = torch.view_as_real(k_per_token_as_complex_numbers * freqs_cis)``k_per_token_rotated = k_per_token_split_into_pairs_rotated.view(k_per_token.shape)``k_per_token_rotated.shape
torch.Size([17, 128])

照着前面查询向量部分的计算流程,就可以得到句子中每个token的键向量了。

查询和键相乘

对句子进行「自注意力」的过程,就是将查询向量和键向量相乘,得到的QK矩阵中的每个值描述了对应位置token查询值和键值的相关程度。

相乘后,我们会得到一个维度为[17x17]自注意力矩阵。

qk_per_token = torch.matmul(q_per_token_rotated, k_per_token_rotated.T)/(head_dim)**0.5``qk_per_token.shape
torch.Size([17, 17])
掩码

语言模型的学习目标,是根据句子之前的内容预测下一个token,因此训练和推理时需要将token位置之后的QK分数屏蔽。

值向量

值权重数量和键权重一样,都是在4个注意力头之间共享(以节省计算量)。

v_layer0 = model["layers.0.attention.wv.weight"]``v_layer0 = v_layer0.view(n_kv_heads, v_layer0.shape[0] // n_kv_heads, dim)``v_layer0.shape
torch.Size([8, 128, 4096])

之后我们获取第一层第一个注意力头的值权重,与句子embedding相乘,获取值向量。

v_layer0_head0 = v_layer0[0]``v_per_token = torch.matmul(token_embeddings, v_layer0_head0.T)``v_per_token.shape
torch.Size([17, 128])
注意力向量

将进行过掩码的QK矩阵和句子的值向量相乘,就得到了注意力矩阵,维度为[17x128]。

qkv_attention = torch.matmul(qk_per_token_after_masking_after_softmax, v_per_token)``qkv_attention.shape
torch.Size([17, 128])
多头注意力

以上得到的注意力矩阵,是第一层第一个注意力头的计算结果。

接下来需要运行一个循环,对第一层中所有32个注意力头进行上述运算过程。

qkv_attention_store = []``   ``for head in range(n_heads):`    `q_layer0_head = q_layer0[head]`    `k_layer0_head = k_layer0[head//4] # key weights are shared across 4 heads`    `v_layer0_head = v_layer0[head//4] # value weights are shared across 4 heads`    `q_per_token = torch.matmul(token_embeddings, q_layer0_head.T)`    `k_per_token = torch.matmul(token_embeddings, k_layer0_head.T)`    `v_per_token = torch.matmul(token_embeddings, v_layer0_head.T)``   `    `q_per_token_split_into_pairs = q_per_token.float().view(q_per_token.shape[0], -1, 2)`    `q_per_token_as_complex_numbers = torch.view_as_complex(q_per_token_split_into_pairs)`    `q_per_token_split_into_pairs_rotated = torch.view_as_real(q_per_token_as_complex_numbers * freqs_cis[:len(tokens)])`    `q_per_token_rotated = q_per_token_split_into_pairs_rotated.view(q_per_token.shape)``   `    `k_per_token_split_into_pairs = k_per_token.float().view(k_per_token.shape[0], -1, 2)`    `k_per_token_as_complex_numbers = torch.view_as_complex(k_per_token_split_into_pairs)`    `k_per_token_split_into_pairs_rotated = torch.view_as_real(k_per_token_as_complex_numbers * freqs_cis[:len(tokens)])`    `k_per_token_rotated = k_per_token_split_into_pairs_rotated.view(k_per_token.shape)``   `    `qk_per_token = torch.matmul(q_per_token_rotated, k_per_token_rotated.T)/(128)**0.5`    `mask = torch.full((len(tokens), len(tokens)), float("-inf"), device=tokens.device)`    `mask = torch.triu(mask, diagonal=1)`    `qk_per_token_after_masking = qk_per_token + mask`    `qk_per_token_after_masking_after_softmax = torch.nn.functional.softmax(qk_per_token_after_masking, dim=1).to(torch.bfloat16)`    `qkv_attention = torch.matmul(qk_per_token_after_masking_after_softmax, v_per_token)`    `qkv_attention = torch.matmul(qk_per_token_after_masking_after_softmax, v_per_token)`    `qkv_attention_store.append(qkv_attention)``   ``len(qkv_attention_store)
32

为了并行计算的方便,我们需要把上面展开的矩阵压缩回去。

也就是将32个维度为[17x128]的注意力矩阵,压缩成一个维度为[17x4096]的大矩阵。

stacked_qkv_attention = torch.cat(qkv_attention_store, dim=-1)``stacked_qkv_attention.shape
torch.Size([17, 4096])

最后,别忘了乘以输出权重矩阵。

w_layer0 = model["layers.0.attention.wo.weight"]``w_layer0.shape``# torch.Size([4096, 4096])``embedding_delta = torch.matmul(stacked_qkv_attention, w_layer0.T)``embedding_delta.shape
torch.Size([17, 4096])

至此,注意力模块的计算就结束了。

相加与归一化

对照这张Transformer层的架构图,在多头自注意力模块之后还需要完成一些运算。

首先将注意力模块的输出与原始的embedding相加。

embedding_after_edit = token_embeddings_unnormalized + embedding_delta``embedding_after_edit.shape
torch.Size([17, 4096])

之后进行RMS归一化。

embedding_after_edit_normalized = rms_norm(embedding_after_edit, model["layers.0.ffn_norm.weight"])``embedding_after_edit_normalized.shape
torch.Size([17, 4096])

前馈神经网络层

Llama 3的Transformer层中使用了SwiGLU前馈网络,这种架构非常擅长在必要情况下为模型添加非线性,这也是当今LLM中的常见操作。

SwiGLU与Vanilla两种前馈神经网络架构的对比

于是我们从模型中加载前馈网络的权重,并按照公式计算:

w1 = model["layers.0.feed_forward.w1.weight"]``w2 = model["layers.0.feed_forward.w2.weight"]``w3 = model["layers.0.feed_forward.w3.weight"]``output_after_feedforward = torch.matmul(torch.functional.F.silu(torch.matmul(embedding_after_edit_normalized, w1.T)) * torch.matmul(embedding_after_edit_normalized, w3.T), w2.T)``output_after_feedforward.shape
torch.Size([17, 4096])

别忘了前馈层之后还有一次相加。

layer_0_embedding = embedding_after_edit+output_after_feedforward``layer_0_embedding.shape
torch.Size([17, 4096])

以上就是一个完整Transformer层的实现,最终输出的向量维度为[17x4096],相当于为句子中每个token重新计算了一个长度为4096的embedding向量。

预测下一个输出

之后的每一个Transformer层都会编码出越来越复杂的查询,直到最后一层的输出的embedding可以预测句子下一个token。

因此需要再嵌套一个外层循环,将Transformer层的流程重复32次。

final_embedding = token_embeddings_unnormalized``for layer in range(n_layers):`    `qkv_attention_store = []`    `layer_embedding_norm = rms_norm(final_embedding, model[f"layers.{layer}.attention_norm.weight"])`    `q_layer = model[f"layers.{layer}.attention.wq.weight"]`    `q_layer = q_layer.view(n_heads, q_layer.shape[0] // n_heads, dim)`    `k_layer = model[f"layers.{layer}.attention.wk.weight"]`    `k_layer = k_layer.view(n_kv_heads, k_layer.shape[0] // n_kv_heads, dim)`    `v_layer = model[f"layers.{layer}.attention.wv.weight"]`    `v_layer = v_layer.view(n_kv_heads, v_layer.shape[0] // n_kv_heads, dim)`    `w_layer = model[f"layers.{layer}.attention.wo.weight"]`    `for head in range(n_heads):`        `q_layer_head = q_layer[head]`        `k_layer_head = k_layer[head//4]`        `v_layer_head = v_layer[head//4]`        `q_per_token = torch.matmul(layer_embedding_norm, q_layer_head.T)`        `k_per_token = torch.matmul(layer_embedding_norm, k_layer_head.T)`        `v_per_token = torch.matmul(layer_embedding_norm, v_layer_head.T)`        `q_per_token_split_into_pairs = q_per_token.float().view(q_per_token.shape[0], -1, 2)`        `q_per_token_as_complex_numbers = torch.view_as_complex(q_per_token_split_into_pairs)`        `q_per_token_split_into_pairs_rotated = torch.view_as_real(q_per_token_as_complex_numbers * freqs_cis)`        `q_per_token_rotated = q_per_token_split_into_pairs_rotated.view(q_per_token.shape)`        `k_per_token_split_into_pairs = k_per_token.float().view(k_per_token.shape[0], -1, 2)`        `k_per_token_as_complex_numbers = torch.view_as_complex(k_per_token_split_into_pairs)`        `k_per_token_split_into_pairs_rotated = torch.view_as_real(k_per_token_as_complex_numbers * freqs_cis)`        `k_per_token_rotated = k_per_token_split_into_pairs_rotated.view(k_per_token.shape)`        `qk_per_token = torch.matmul(q_per_token_rotated, k_per_token_rotated.T)/(128)**0.5`        `mask = torch.full((len(token_embeddings_unnormalized), len(token_embeddings_unnormalized)), float("-inf"))`        `mask = torch.triu(mask, diagonal=1)`        `qk_per_token_after_masking = qk_per_token + mask`        `qk_per_token_after_masking_after_softmax = torch.nn.functional.softmax(qk_per_token_after_masking, dim=1).to(torch.bfloat16)`        `qkv_attention = torch.matmul(qk_per_token_after_masking_after_softmax, v_per_token)`        `qkv_attention_store.append(qkv_attention)``   `    `stacked_qkv_attention = torch.cat(qkv_attention_store, dim=-1)`    `w_layer = model[f"layers.{layer}.attention.wo.weight"]`    `embedding_delta = torch.matmul(stacked_qkv_attention, w_layer.T)`    `embedding_after_edit = final_embedding + embedding_delta`    `embedding_after_edit_normalized = rms_norm(embedding_after_edit, model[f"layers.{layer}.ffn_norm.weight"])`    `w1 = model[f"layers.{layer}.feed_forward.w1.weight"]`    `w2 = model[f"layers.{layer}.feed_forward.w2.weight"]`    `w3 = model[f"layers.{layer}.feed_forward.w3.weight"]`    `output_after_feedforward = torch.matmul(torch.functional.F.silu(torch.matmul(embedding_after_edit_normalized, w1.T)) * torch.matmul(embedding_after_edit_normalized, w3.T), w2.T)`    `final_embedding = embedding_after_edit+output_after_feedforward

最后一个Transformer层的输出维度与第一层相同,依旧是[17x4096]。

final_embedding = rms_norm(final_embedding, model["norm.weight"])``final_embedding.shape
torch.Size([17, 4096])

此时需要利用输出解码器,将最后一层输出的embedding先进行归一化处理,再转换为token。

final_embedding = rms_norm(final_embedding, model["norm.weight"])``final_embedding.shape``# torch.Size([17, 4096])
model["output.weight"].shape``# torch.Size([128256, 4096])
logits = torch.matmul(final_embedding[-1], model["output.weight"].T)``logits.shape
torch.Size([128256])

输出的向量维度与分词器中词汇数量相同,每个值代表了下一个token的预测概率。

模型预测下一个词是42?

和《银河系漫游指南》的梦幻联动(不知道是不是作者故意设置成这样的)

next_token = torch.argmax(logits, dim=-1)``next_token
tensor(2983)
tokenizer.decode([next_token.item()])
'42'

至此,我们就完成了Llama 3对输入句子进行下一个token预测的全过程。

## AI大模型学习福利

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

四、AI大模型商业化落地方案

img

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取

2025最新版优快云大礼包:《AGI大模型学习资源包》免费分享

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

Llama 架构分析 Meta 开发并公开发布了 Llama系列大型语言模型 (LLM),这是一组经过预训练和微调的生成文本模型,参数规模从 70 亿到 700 亿不等。在大多数任务中,LLaMA-13B要比GPT-3(175B)的性能要好,LLaMA-65B和组好的模型Chinchilla-70B以及PaLM-540B的实力相当。 阅读详情

相关推荐

Github 2025-02-03 开源项目周报 Top14

创建周期:354 天开发语言:TypeScript, JavaScript协议类型:MIT LicenseStar数量:7277 个Fork数量:1269 次关注人数:7277 人贡献人数:75 人Open Issues数量:61 个Github地址:https://github.com/danny-avila/LibreChat.git项目首页: https://docs.librechat.ai/

老孙正经胡说 1347

【大模型】基于 LlaMA2 的高 star 的 GitHub 开源项目汇总

基于 LlaMA2 的高 star 的 GitHub 开源项目汇总

Zack的博客 5771

llama 2 github官方文档

完成此操作后,您可以请求访问 Hugging Face 上的任何模型,并在 1-2 天内您的帐户将被授予访问所有版本的权限。我们最新版本的 Llama 现在可供个人、创作者、研究人员和各种规模的企业使用,以便他们能够负责任地实验、创新和扩展他们的想法。请参阅 llama-recipes 存储库,了解如何向推理代码的输入和输出添加安全检查器的。我们的使命是通过这个机会为个人和行业赋能,同时营造一个发现和道德人工智能进步的环境。一旦您的请求获得批准,您将通过电子邮件收到签名的 URL。开头,则您复制正确。

具身机器人和通用AI 1324

Meta版ChatGPT惨遭“开源”?最新大模型LLaMA被泄露,已在GitHub收获7k+星

与 OpenAI 的 GPT-3 相比,Meta 在一开始就将 LLaMA 定位成一个“开源的研究工具”,该模型所使用的是各类公开可用的数据集(例如 Common Crawl、维基百科以及 C4)。这里测试的是所谓 5-shot 准确率,也就是对于任何特定问题,源材料都至少对其提及 5 次,(随着每次提及,答案的确定性水平都会提高,这与人类推理的过程非常相似。事实上,无论此事是否是 Meta 有意为之,在部分网友看来,LLaMA 原本的设定就是申请之后即可下载,“被公开是迟早的事情”。

IT界那些事儿 3390

Rocky Linux 9.2:利用LVM动态调整/home与/根分区空间分配

本文详细介绍了在Rocky Linux 9.2系统中,如何利用LVM(逻辑卷管理器)动态调整/home与根分区(/)的空间分配。针对根分区空间不足而/home分区闲置的常见问题,文章提供了从检查磁盘布局、备份数据、卸载分区、调整逻辑卷大小到重建文件系统的完整操作步骤,并重点说明了XFS与EXT4文件系统在缩容时的不同处理方法,帮助系统管理员安全、在线地实现存储空间的灵活调配。

weixin_29271263的博客 178

告别天价授权!手把手教你用TwinCAT 3.1搭建EtherCAT主站(Windows 10/11保姆级教程)

本文详细介绍了如何在Windows 10/11系统上使用TwinCAT 3.1免费搭建EtherCAT主站,帮助中小企业和个人开发者低成本实现工业自动化。从环境准备、许可证策略到安装配置和实战开发,提供保姆级教程,涵盖PLC编程、运动控制及硬件选型建议,助您轻松入门工业控制领域。

weixin_30664615的博客 363

盘点2025 GitHub值得关注的十个项目

今天整理了「2025年GitHub年度十大热点项目」,每一个都带真实开源地址,Star数全是全年实时追踪数据,不管是求职涨技、创业落地还是摸鱼提效,收藏这篇就够了!

weixin_45631123的博客 3463

Unity Hub报错The Hub as encountered a critical error and must close

如果注册表HKEY_LOCAL_MACHINE\SOFTWARE\Unity Technologies\这个目录下有Hub文件,直接删掉然后重装就可以。C:\Users\Administrator\AppData\Roaming\Unity 作者:SevenVee。HKEY_CURRENT_USER\Software\Unity 下所有项,尝试过,卸载重装,清除临时文件无果后,最终决定删除所有与Hub有关的文件。重装unity后可以打开了。结果:卸载重装后还是会出现此问题。结果:重装后还是无法解决。

qq_42345116的博客 3638

别再从零学AI Agent,这个GitHub宝库直接抄作业,大模型入门到精通,收藏这篇就足够了!

这是一个堪称 LLM 应用开发“军火库”的 GitHub 项目,它把 AI Agent、RAG、多智能体等热门技术,都变成了你可以直接运行和学习的实例代码。

Y525698136的博客 710

(学习笔记)机器人自主导航从零开始第四步———Rviz、Gazebo、Meshlab的安装

一、Rviz的安装 Rviz是一个

qq_59475883的博客 5057

知识图谱的数据挖掘与分析

1. 背景介绍 1.1 数据挖掘的崛起 随着互联网的普及和大数据技术的发展,数据挖掘已经成为了计算机科学领域的热门研究方向。数据挖掘是从大量的、不完全的、有噪声的、模糊的、随机的实际应用数据中,通过计算机科学、统计学、信息论等多学科交叉的方法,挖掘出有用信息和知识的过程。数据挖掘的目标是从数据中发现有

AI天才研究院 1600

一个开源的大语言模型(LLM)微调框架——LLaMA-Factory,大模型入门到精通,收藏这篇就足够了!

LLaMA-Factory 是一个开源的大语言模型(LLM)微调框架,旨在简化大规模语言模型的微调过程。该项目提供了一个用户友好的界面和全面的工具集,支持从数据准备到模型部署的完整流程。

DEVELOPERAA的博客 1088

搞懂 SAPUI5 Fiori 应用的 OData 授权维护:从 IWSG、IWSV 到 S_SERVICE 的完整实践

本文探讨了SAP Fiori项目中常见的授权问题及其解决方案。文章指出,开发人员常误将OData服务访问问题归咎于前端代码或配置,而实际上多因授权默认值未正确带入角色所致。详细分析了IWSG(前端服务组元数据)和IWSV(后端业务服务)两个关键对象的作用机制,强调应通过PFCG角色的Authorization Default入口维护服务对象,而非直接修改S_SERVICE授权对象。文章还提供了前后端授权配置的具体操作步骤,并特别提醒需同时配置前端和后端授权,才能确保应用完整可用性。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 212

Happy LLM:Github爆火!手把手教你从0手搓个大模型!LLM自学必看!大模型入门到精通,收藏这篇就足够了!

Happy LLM:Github爆火!手把手教你从0手搓个大模型!LLM自学必看!

2301_81940605的博客 916

2023年下半年网络工程师案例分析真题答案解析

R1] ip route-static 0.0.0.0 0.0.0.0 GigabitEthemet2/0/1 (3) track (4) R1 to R2 //配置R1的缺省路由,联动BFD使得R1到2的流量优先走R1->S1->R2链路,当此链路发生故障时,流量切换到R1->R3->R2链路上。当同一VLAN内也需要网络隔离时,我们可采用交换机的(2)功能,若在配置了二层隔离后,部分主机有互通的需求,则可在需求主机的网关上配置(3)功能。不需要,MAC地址是数据链路层封装以太帧的地址标识。

鹿鸣天涯 751

风电光伏功率预测竞赛精华总结:技术解析与实战经验

本文深度解析新能源功率预测竞赛的技术要点与实战经验。首先介绍了风电、光伏功率预测对电网调度优化、降低运营风险的重要性,以及多个竞赛的基本概况。在数据特征分析部分,详细探讨了气象预报数据和功率数据的特征,包括时间周期性、数据质量问题及处理方法。针对异常值检测、数据标准化和特征工程(如时间特征、统计聚合特征、风速风向特征和滞后特征)提供了具体的技术实现方案。文章为新能源功率预测提供了实用的技术指导,对相关竞赛和实际应用具有重要参考价值。

算法工程师 206

这个 GitHub 项目,直接拯救了我做AI Agent的焦虑,大模型入门到精通,收藏这篇就足够了!

最近刷到一个项目,差点没忍住转头拉群推荐所有做 AI 产品的朋友。 它就是这个神奇的开源仓库: 👉 https://github.com/Shubhamsaboo/awesome-llm-apps

pythonhy的博客 854

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

0门槛Llama3微调!GitHub17k标星开源项目带你速通大模型实战

"Hands-On-Large-Language-Models"是一个17k+星标的GitHub学习仓库,提供大模型从基础到实战的全套教程。内容涵盖Transformer原理、Prompt工程、LoRA/QLoRA微调、RLHF实战及模型部署,支持Llama、Mistral等多种主流开源模型。项目提供完整Jupyter Notebook代码,支持本地和云端运行,即使没有显卡也能学习。适合学生、研究员和开发者,是一条系统性的大模型学习路径,代码质量高且适合二次开发。

m0_56255097的博客 761

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Github 20.3K! LightRAG:极简之道,让大模型“秒懂”你的知识库,大模型入门到精通,收藏这篇就足够了!

LightRAG 是由香港大学数据智能系统实验室(HKUDS)开源的 轻量级检索增强生成框架,专注于把大型语言模型(LLM)与外部知识库高效、可扩展地结合在一起。

DEVELOPERAA的博客 1273

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Code Llama vs GitHub Copilot:2025开源代码大模型终极对决

你是否正在经历这些编码痛点?调试三小时只因少写一个分号,API文档翻到眼酸仍找不到参数说明,重复性代码占用40%开发时间?2024年Stack Overflow开发者调查显示,78%的程序员认为AI编码工具已成为工作标配,但83%的团队仍在开源与商业方案间犹豫不决。本文将通过12个技术维度、5组实战场景和3份决策指南,帮你彻底厘清Code Llama(开源)与GitHub Copilot(商业)的...

gitblog_01023的博客 812

GitHub星标破万!Meta开源Llama全系列演进史:从Llama-1到Llama-3

Llama(LargeLanguageModelMetaAI)是Meta(原Facebook)AI研究团队发布的一系列开源大语言模型。该项目旨在构建高性能且易于获取的基础语言模型,推动人工智能技术的民主化进程。自2023年2月首次发布以来,Llama系列已经历了多次重大更新,从初代Llama-1到支持商用的Llama-2,再到性能大幅提升的Llama-3,以及后续引入多模态能力的Llama 3.2。每一代产品都在模型架构、训练数据和性能表现上实现了显著突破。作为开源大语言模型的标杆。

2403_88996352的博客 917

【2025版】最新Langchain-Chatchat大语言模型本地知识库的踩坑、部署、使用,零基础入门到精通,收藏这篇就够了

Langchain-Chatchat是一个基于ChatGLM大语言模型与Langchain应用框架实现,开源、可离线部署的检索增强生成(RAG)大模型的本地知识库问答应用项目。

leah126的博客 3947
上一篇: 记一次任意文件读取漏洞的挖掘,从零基础到精通,收藏这篇就够了!
下一篇: 【2025版】中医大模型开源!从零基础到精通,精通收藏这篇就够了!
程序员_大白
博客等级 码龄5年 1万+粉丝 4001原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值