karpathy/llama2.c

GitHub: karpathy/llama2.c

一个极简的教育性全栈框架,用于在 PyTorch 中训练 Llama 2 架构,并使用单个纯 C 文件进行无依赖推理。

Stars: 19223 | Forks: 2450

## llama2.c

Cute Llama

你曾经想过用纯 C 语言对一个迷你 [Llama 2](https://ai.meta.com/llama/) 模型进行推理吗?没想过?嗯,现在你可以了! 在 PyTorch 中训练 Llama 2 LLM 架构,然后用一个简单的 700 行 C 文件 ([run.c](run.c)) 对其进行推理。你可能认为需要数十亿参数的 LLM 才能做任何有用的事情,但实际上,如果你将领域限定得足够狭窄,非常小的 LLM 也能表现出令人惊讶的强大性能(参考:[TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories) 论文)。本仓库是 Llama 2 LLM 的一个“全栈”训练 + 推理解决方案,重点是极简主义和简单性。 由于架构相同,你也可以加载并推理 Meta 的 Llama 2 模型。但是,当前的代码仅支持 fp32 模式的推理,因此你很可能无法高效地加载超过 7B 的模型。模型量化方面的工作目前正在进行中。 请注意,这个仓库是最近作为一个有趣的周末项目开始的:我拿了我之前的 [nanoGPT](https://github.com/karpathy/nanoGPT),对其进行调整以实现 Llama-2 架构而不是 GPT-2,其中的核心工作是编写 [run.c](run.c) 中的 C 推理引擎。所以这个项目还很年轻,发展很快。向很棒的 [llama.cpp](https://github.com/ggerganov/llama.cpp) 致敬,它启发了这个项目。与 llama.cpp 相比,我想要一些超级简单、最小化且具有教育意义的东西,所以我选择硬编码 Llama 2 架构,并且只编写一个无依赖的纯 C 推理文件。 ## 感受魔法 [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/karpathy/llama2.c/blob/master/run.ipynb) 首先,导航到你保存项目的文件夹,并将此仓库克隆到该文件夹: ``` git clone https://github.com/karpathy/llama2.c.git ``` 然后,打开仓库文件夹: ``` cd llama2.c ``` 现在,让我们用 C 语言运行一个迷你 Llama 2 模型。你需要一个模型 checkpoint。下载这个我在 [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories) 数据集上训练的 15M 参数模型(下载约 60MB): ``` wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin ``` 编译并运行 C 代码: ``` make run ./run stories15M.bin ``` 你会看到文本流式输出一个样本。在我的 M1 MacBook Air 上,这以约 110 tokens/s 的速度运行。请参阅 [performance](#performance) 或 Makefile 以了解可以显著加速的编译标志。我们也可以尝试一个稍大的 42M 参数模型: ``` wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories42M.bin ./run stories42M.bin ``` 这仍然可以以交互速度运行,并生成更连贯、更多样的故事: 你也可以使用前缀或一些额外的命令行参数来提示模型,例如,在温度为 0.8 的情况下采样 256 步,并带有一个提示词: ``` ./run stories42M.bin -t 0.8 -n 256 -i "One day, Lily met a Shoggoth" ``` 还有一个更好的 110M 参数模型可用,请参阅 [models](#models)。 关于采样的快速说明,为了获得 ~最佳结果,建议使用 `-t 1.0 -p 0.9` 进行采样,即温度 1.0(默认),同时使用 top-p 0.9(默认)。直观地说,top-p 确保概率极小的 tokens 不会被采样,这样我们在采样过程中就不会“运气不好”,之后也不太可能“跑偏”。更一般地说,要控制样本的多样性,可以使用温度(即在 0 和 1 之间改变 `-t` 并用 `-p 0` 关闭 top-p)或 top-p 值(即在 0 和 1 之间改变 `-p` 并保持 `-t 1`),但不要同时使用两者。关于 LLM 采样策略的精彩解释包括 [这个](https://peterchng.com/blog/2023/05/02/token-selection-strategies-top-k-top-p-and-temperature/)、[这个](https://docs.cohere.com/docs/controlling-generation-with-top-k-top-p) 或 [这个](https://huggingface.co/blog/how-to-generate)。 ## Meta 的 Llama 2 模型 由于神经网络架构是相同的,我们也可以推理 Meta 发布的 Llama 2 模型。遗憾的是,由于许可原因,这里有一点摩擦(我认为我不能直接上传 checkpoints)。所以第一步,按照 [Meta 说明](https://github.com/facebookresearch/llama) 获取 Llama 2 checkpoints。一旦我们有了这些 checkpoints,我们必须将它们转换为 llama2.c 格式。 为此,我们需要安装 python 依赖项(`pip install -r requirements.txt`),然后使用 `export.py` 文件,例如对于 7B 模型: ``` python export.py llama2_7b.bin --meta-llama path/to/llama/model/7B ``` 导出大约需要 10 分钟,并生成一个 26GB 的文件(float32 格式的 7B 模型权重),在当前目录下名为 `llama2_7b.bin`。据[报道](https://github.com/karpathy/llama2.c/pull/85),尽管付出了努力。我现在不建议运行任何超过 7B 的模型,原因有二:首先,由于指针算术中的整数流问题,13B+ 目前无法工作,这有待修复;其次,即使修复了,这个仓库目前正在进行 float32 推理,所以会慢得无法使用。导出完成后,我们可以运行它: ``` ./run llama2_7b.bin ``` 在我的云 CPU Linux 机器上使用 96 个线程并编译启用 [OpenMP](#OpenMP),运行速度约为 4 tokens/s。(在我的 MacBook Air M1 上,如果你只是用 `make runfast` 构建,目前每个 token 接近 30 秒。)示例输出: 基础模型... ¯\\_(ツ)_/¯。既然我们可以推理基础模型,那么也应该可以很容易地推理聊天模型,并与它进行对话。如果我们能找到更高效运行 7B 的方法,我们就可以开始在我们的训练脚本中添加 LoRA,并在仓库中尽情进行微调! 你也可以与 Llama Chat 模型聊天。完全按照上面的方法导出聊天模型: ``` python export.py llama2_7b_chat.bin --meta-llama /path/to/7B-chat ``` 然后使用 `-m` 标志指定聊天模式与其聊天,例如: ``` ./run llama2_7b_chat.bin -m chat ``` 你也可以尝试 Meta 的 Code Llama 模型,即使对它们的支持还不完整。特别是,一些超参数发生了变化(例如 RoPE 层中的常量),因此推理目前不完全正确,并且有点问题。正在寻找修复方法。请务必为 plain 和 instruct 变体构建 tokenizer,并在推理时传递它。 ``` python export.py codellama2_7b.bin --meta-llama /path/to/CodeLlama-7b python tokenizer.py --tokenizer-model=/path/to/CodeLlama-7b/tokenizer.model ./run codellama2_7b.bin -z /path/to/CodeLlama-7b/tokenizer.bin ``` 与 Code Llama Instruct 聊天: ``` python export.py codellama2_7b_instruct.bin --meta-llama /path/to/CodeLlama-7b-Instruct python tokenizer.py --tokenizer-model=/path/to/CodeLlama-7b-Instruct/tokenizer.model ./run codellama2_7b_instruct.bin -m chat -z /path/to/CodeLlama-7b-Instruct/tokenizer.bin ``` ## int8 量化 (默认)脚本 [run.c](run.c) 使用 float32 前向传播,其中前向传播的整个计算都保持在 fp32。就参考代码而言,这非常容易理解,但它有以下缺点:模型 checkpoint 文件非常大(每个单独的权重占用 4 个字节),并且前向传播相对较慢。实践中采用的(非常)常见的推理优化是将模型参数量化为较低的精度,牺牲一点正确性以换取更小的 checkpoint 大小和更快的前向传播(因为大多数推理使用整数算术)。根据经验,LLM 可以容忍低至 4 位(甚至更低)的精度,但这里我们使用 int8,因为它是一个“安全”的设置,既能让我们受益,又不会牺牲太多的模型精度。只有参与矩阵乘法的权重会被量化。所有其他参数(例如 RMSNorm 中的 scale 和 bias)都保留在 float32 中,因为这些层非常敏感。现在,如果你只是追求减小 checkpoint 大小,你可以量化权重,保存 checkpoint,然后在 run.c 中对其反量化,并像往常一样进行 float32 推理,这就完事了。这也完全没问题。但在这里,我们要更进一步(这也是标准做法),额外量化前向传播中的激活。这要求我们在运行时在 float32 和 int8 之间动态量化和反量化,这增加了开销。但好处是现在大部分计算(特别是矩阵乘法!)都在使用纯整数算术,其中权重和激活都以 int8 输入。这是速度提升的根本来源。我们使用的版本是“Q8_0”量化(llama.cpp 术语),其中 0 表示权重量化在 0 附近对称,量化到范围 [-127, 127]。 量化的前向传播在 [runq.c](runq.c) 中实现。要使用它,我们必须以量化格式导出模型。例如,Llama 2 7B 的 float32 版本导出为: ``` python export.py llama2_7b.bin --meta-llama path/to/llama/model/7B ``` 这会创建一个 26GB 的文件,因为 7B 个参数中的每一个都是 4 字节 (fp32)。要将其量化导出,我们改为使用版本 2 导出: ``` python export.py llama2_7b_q80.bin --version 2 --meta-llama path/to/llama/model/7B ``` 这会运行几分钟,但现在只创建一个 6.7GB 的文件。对于导出非 meta checkpoints,你需要使用 --checkpoint 参数而不是 --meta-llama 参数(稍后在下面有更多文档)。现在让我们推理它们。我喜欢在这里使用 OMP,因为这些是大模型,例如在我的 Linux 机器上: ``` make runomp OMP_NUM_THREADS=64 ./run llama2_7b.bin -n 40 OMP_NUM_THREADS=64 ./runq llama2_7b_q80.bin -n 40 ``` 这运行 40 步只是为了计时。对我来说,float32 版本运行速度为 4.6 tok/s,而 int8 版本为 14 tok/s。因此,我们在将 checkpoint 大小减少 4 倍的同时实现了 3 倍的加速。但是,前向传播被量化为 int8,因此质量会隐约有非常轻微的下降。 ## huggingface 模型 我们可以加载任何使用 Llama 2 架构的 huggingface 模型。请参阅脚本 [export.py](export.py) 和 `--hf` 标志以导出模型 .bin 文件。 ## 模型 为了提供更小的、从头开始训练的模型示例,我在 TinyStories 上训练了一个小型模型系列。所有这些都在我的训练设置(4X A100 40GB GPU)上在几个小时内完成训练。110M 模型花费了大约 24 小时。我将它们托管在 huggingface hub [tinyllamas](https://huggingface.co/karpathy/tinyllamas) 上,既有原始的 PyTorch .pt 格式,也有 llama2.c 格式的 .bin: | model | dim | n_layers | n_heads | n_kv_heads | max context length | parameters | val loss | download | --- | --- | --- | --- | --- | --- | --- | --- | --- | | 260K | 64 | 5 | 8 | 4 | 512 | 260K | 1.297 | [stories260K](https://huggingface.co/karpathy/tinyllamas/tree/main/stories260K) | OG | 288 | 6 | 6 | 6 | 256 | 15M | 1.072 | [stories15M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin) | | 42M| 512 | 8 | 8 | 8 | 1024 | 42M | 0.847 | [stories42M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories42M.bin) | | 110M| 768 | 12 | 12 | 12 | 1024 | 110M | 0.760 | [stories110M.bin](https://huggingface.co/karpathy/tinyllamas/resolve/main/stories110M.bin) | 你会发现 110M 模型在大小上相当于 GPT-1。或者,这也是 GPT-2 系列中最小的模型(`GPT-2 small`),只是最大上下文长度只有 1024 而不是 2048。与 GPT-1/2 架构相比,唯一值得注意的变化是 Llama 使用 RoPE 相对位置嵌入而不是绝对/学习位置嵌入,MLP 中更花哨一点的 SwiGLU 非线性,RMSNorm 代替 LayerNorm,所有 Linear 层的 bias=False,以及可选的多查询。 ## 训练 让我们看看如何使用这个仓库中的代码从头开始训练一个迷你 Llama 2。首先让我们下载并预分词一些源数据集,例如我喜欢 [TinyStories](https://huggingface.co/datasets/roneneldan/TinyStories),所以这是这个仓库中目前可用的唯一示例。但添加数据集应该很容易,请参阅代码。 ``` python tinystories.py download python tinystories.py pretokenize ``` 然后训练我们的模型: ``` python train.py ``` **简要训练指南**。有关更奇特的启动和超参数覆盖,请参阅 train.py 脚本。这里有一个关于如何设置参数的简要指南。查看 [Chinchilla paper](https://arxiv.org/abs/2203.15556) 最后的表格,了解 Transformer 参数(dim, n_layers, n_heads)是如何一起增长或缩小的。推断/插值这种模式以获得更大或更小的 transformer。根据问题随意设置最大上下文长度:这应该是预测下一个 token 所需的最大 token 数。例如 Llama 2 使用 2048。接下来,你希望每次更新的 _总_ 批大小(脚本打印为 "tokens per iteration will be:")在中等规模的应用中约为 100K tokens。对于小型应用它可能更低,对于大型训练(例如 GPTs/LLamas)通常约为 0.5M 或更多。你首先通过将 batch_size 扩展到系统允许的最大值(例如在我最近的一次运行中是 16,因为超过这个值我的 GPU 内存就会耗尽),然后你希望增加 gradient_accumulation_steps 到足够高以达到约 100K 的总批大小。最后,你想调整你的 learning_rate (LR)。你希望它尽可能高,只要你的训练允许。非常小的网络可以使用较大的 LR(例如 1e-3 甚至更高)。大型网络需要较低的 LR。3e-4 在大多数中等规模的应用中是一个安全的选择,但对于小型网络可能太低,所以尝试增加它!最后,max_iters 是训练的长度。尝试不同的设置。我主要只调整这些参数,而其他大部分保持不变。这是我如何训练110M 模型的一个例子,我认为这离最优还差得远,但对我来说看起来很合理:dim 768, n_layers 12, n_heads 12(所以每个 head 的大小是 768 / 12 = 64 个通道),seq len 为 1024,batch size 16(这是我的 A100 40GB GPU 能容纳的最大值),gradient_accumulation_steps = 8 是将总 token 批大小达到 16 batch size * 1024 tokens in sequence * 8 grad_accum = 131,072 tokens per update 所必需的。很好。学习率 4e-4(可能有点太低)。max_iters 200K(可能有点太高)。Dropout 0.1,因为这通常在中等规模上有一点帮助。就是这样。我在我的云机器上使用 Distributed Data Parallel (DDP) 在 4 个 GPU 上运行,训练花了大约一天左右的时间。 完全可以理解如果你想跳过模型训练,为了简单的演示,只需下载预训练模型之一(参见 [models](#models) 部分),例如: ``` wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin ``` 一旦我们有了 model.bin 文件,我们就可以用 C 进行推理。首先编译 C 代码: ``` make run ``` 你现在可以简单地运行它 ``` ./run stories15M.bin ``` 看着 token 流过,很有趣!我们也可以运行 PyTorch 推理脚本进行比较。再次从 huggingface hub 下载其中一个模型,并将 `sample.py` 脚本指向它: ``` wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.pt -P out15M python sample.py --checkpoint=out15M/stories15M.pt ``` 这给出了相同的结果。 ## 自定义 tokenizers 在上面的所有内容中,我们假设使用带有 32,000 个 token 的自定义 Llama 2 tokenizer。但是,在许多小型 LLM 中,使用这么大的词汇表可能有点大材小用。如果你心目中有一个小型应用,你最好训练自己的 tokenizer。这可以让一切变得更好——词汇表更小,你的模型参数更少(因为 token 嵌入表要小得多),推理更快(因为需要预测的 token 更少),并且每个例子的平均序列长度也可能变小(因为压缩对你的数据更有效)。所以让我们看看如何训练自定义 tokenizer。 默认情况下,为了预分词 tinystories 数据集,我们需要按顺序运行: ``` python tinystories.py download python tinystories.py pretokenize ``` 这里的 `pretokenize` 阶段加载 Llama 2 tokenizer(词汇表大小 32,000)并使用它将下载的文本转换为整数,并将其保存到文件中。我们现在将其更改如下,以训练一个示例 4096-token tokenizer: ``` python tinystories.py download python tinystories.py train_vocab --vocab_size=4096 python tinystories.py pretokenize --vocab_size=4096 ``` `train_vocab` 阶段将调用 `sentencepiece` 库来训练 tokenizer,并将其存储在新文件 `data/tok4096.model` 中。我尽可能好地重现了我认为 Meta 用来训练其词汇表的设置。这使用了字节对编码算法,该算法从文本数据的原始 utf8 字节序列开始,然后迭代地合并最常见的连续 token 对以形成词汇表。检查 `tinystories.py` 文件——自定义 tokenizers 存储在一个按词汇表大小索引的特殊目录结构中。 一个有趣的小注记是,专门在 tinystories 上训练的 4096 词汇表大小生成的整数序列的每个示例序列长度与默认的 32000 token 的 Llama 2 tokenizer 大致相同!这意味着我们的自定义、量身定制的 tokenizer 更好地适应了我们的特定文本,并且可以非常有效地压缩它。所以我们训练的模型更小更快。 现在我们已经使用自定义 tokenizer 对数据集进行了预分词,我们可以训练模型。训练脚本 `train.py` 不关心具体的 token,它只关心词汇表大小,以便它可以正确初始化模型。所以在训练模型时,一定要传入 ``` python train.py --vocab_source=custom --vocab_size=4096 ``` (默认值分别是 `llama2` 和 `32000`,这表示默认的 Llama 2 tokenizer)。这将训练模型。最后,我们准备使用我们的 `run.c` 脚本运行推理。为此我们需要两件事。第一,我们必须以 `.bin` 格式导出我们的 tokenizer,这样做: ``` python tokenizer.py --tokenizer-model=data/tok4096.model ``` 这将 tokenizer 写入 `data/tok4096.bin`。现在我们可以运行推理,使用 `-z` 标志将其指向此 tokenizer: ``` ./run out/model.bin -z data/tok4096.bin ``` 这应该打印样本。如果你省略 `-z` 标志,它将使用默认的 Llama 2 tokenizer,这会生成一个好的整数序列,但它们会使用不同的词汇表转换为文本,所以看起来像乱码。 ## 性能 根据你的系统,有许多方法可以潜在地加速这段代码。看看 [Makefile](Makefile),里面包含了很多注释。`make run` 命令目前默认使用 `-O3` 优化,即: ``` gcc -O3 -o run run.c -lm ``` -O3 包括在编译时间和内存使用方面代价高昂的优化。包括向量化、循环展开和分支预测。 要获得更好的性能,请尝试使用 `make runfast` 进行编译。这开启了 `-Ofast` 标志,该标志包括除了 `-O3` 之外,可能违反 C/IEEE 规范的额外优化。有关更多信息,请参见 [the GCC docs](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)。 尝试 `-march=native` 来编译程序以使用你正在编译的机器的架构,而不是更通用的 CPU。这可能会启用额外的优化和特定于硬件的调整,例如改进的向量指令/宽度。 到目前为止,我在我的 MacBook Air (M1) 上看到的最快吞吐量是使用 `make runfast`。 你也可以尝试用 `clang` 替换 `gcc`。 如果使用 gcc 编译,尝试尝试 `-funroll-all-loops`,参见 PR [#183](https://github.com/karpathy/llama2.c/pull/183) **OpenMP**。通过使用 OpenMP 编译也可以实现巨大的改进,它“激活”了 matmul 和 attention 内部的 `#pragma omp parallel for`,允许将循环中的工作分配给多个处理器。 你需要先安装 OpenMP 库和 clang 编译器(例如在 ubuntu 上使用 `apt install clang libomp-dev`)。然后你可以用 `make runomp` 编译,它会: ``` clang -Ofast -fopenmp -march=native run.c -lm -o run ``` 当你运行推理时,确保使用 OpenMP 标志来设置线程数,例如: ``` OMP_NUM_THREADS=4 ./run out/model.bin ``` 根据你的系统资源,你可能需要调整这些超参数并使用更多线程。但更多并不总是更好,通常是 U 形的。特别是,如果你的 CPU 支持 SMT(多线程),尝试将线程数设置为物理核心数而不是逻辑核心数。由于缓存颠簸和通信开销,性能差异可能很大。PyTorch 文档 [CPU specific optimizations ](https://pytorch.org/tutorials/recipes/recipes/tuning_guide.html#cpu-specific-optimizations) 有一些也适用于这里的好的信息。 ## 平台 在 **Windows** 上,在 Visual Studio 命令提示符中使用 `build_msvc.bat` 用 msvc 构建,或者你可以使用 `make win64` 从 linux 或 windows 使用 mingw 编译器工具链来构建 windows 目标。MSVC 构建将自动使用 openmp 和适合你 CPU 的最大线程数,除非你设置 `OMP_NUM_THREADS` 环境变量。 在 **Centos 7**、**Amazon Linux 2018** 上,使用 `rungnu` Makefile 目标:`make rungnu` 或 `make runompgnu` 以使用 openmp。 在 **Mac** 上,使用 brew 的 clang 进行 openmp 构建。安装 clang:`brew install llvm` 并使用安装的 clang 二进制文件用 openmp 编译:`make runomp CC=/opt/homebrew/opt/llvm/bin/clang` ## 测试 你可以简单地使用 pytest 运行测试: ``` $ pip install pytest $ pytest ``` 这目前会调用 `test_all.py` 中的两个测试,它们在 C 和 Python 中前向传播模型 200 步,并根据已知的良好预期输出检查输出。测试目前只运行几秒钟,但需要在临时 `test` 目录中下载和缓存 stories260K 模型(仅下载约 2MB)。 在 [test.c](test.c) 文件中还有一些 C 语言测试。你可以用 `make testcc` 运行这些,或者查看更多打印信息: ``` make testcc VERBOSITY=1 ``` 请求帮助:帮助添加更多测试。 ## 致谢 我在由优秀的 [Lambda labs](https://lambdalabs.com/service/gpu-cloud) 慷慨提供的 4X A100 40GB 机器上训练了 llama2.c storyteller 模型,谢谢。 ## discord figured 可以重复使用我现有的 discord 频道(我用于我的 [zero to hero youtube series](https://karpathy.ai/zero-to-hero.html)),请参阅 [discord](https://discord.gg/3zy8kqD9Cp) 上的 #llama2c 频道,用于任何快速问题、相关讨论等。 ## 贡献 关于这个仓库和可能被接受的 PR 类型有几句说明。这个仓库的目标是什么?基本上,我认为在各种各样的应用中,人们会对训练或微调自定义微型 LLM(想想 ~100M - ~1B 参数,但比如说高达 ~10B 参数)并在边缘相邻的环境中部署它们(想想 MCU、手机、Web 浏览器、笔记本电脑等)有很大兴趣。我希望这个仓库成为支持这一工作流程(包括训练和推理)的最简单、最小、最易黑客的仓库。特别是,这个仓库不是一个复杂的框架,拥有 1000 个旋钮来控制跨越数百个文件的嵌套目录结构中难以理解的代码。相反,我希望大多数应用会希望创建这个仓库的一个分支,并将其黑客改造以满足其特定需求和部署平台。 关心部署效率高于一切的人应该看看 [llama.cpp](https://github.com/ggerganov/llama.cpp)。这个仓库仍然关心效率,但不是以牺牲简单性、可读性或可移植性为代价。基本上,我希望很多人来到这个仓库是因为训练代码是 2 个可读的 .py 文件,推理代码是 500 行 C。所以我希望这继续是一种最简单的“参考实现”,可以在一个单独的分支中很容易地被黑客改造成人们兴奋的任何下游应用。它不应该是功能齐全的。它不应该有 100 个不同的选项或设置。它不应该是最高效的。几个例子: - 有人重新排序了两个循环以提高数据局部性,从而获得一点效率提升 => 立即合并。 - 有人添加了一行“pragma omp parallel for”,这允许你使用 OpenMP 编译并显著加快代码速度,或者如果你不那样编译,它只是作为一个注释 => 立即合并。 - 错误修复和润色等 => 很乐意合并 几个不太适合的 PR 例子: - 在代码中到处添加超过几个 #ifdefs。如果它们是局部的/很少的,可能没关系。 - 添加大量非常特定于某个特定平台的代码(例如 MCU,或某个特殊版本的 linux 或处理器)。这些可能更适合项目的分支,我很乐意在下面的部分中维护这些分支的列表。 - 向 run.c 添加数百行仅在特定场景或平台中处于活动状态的代码。 如果你的候选 PR 有这些因素,并不意味着它们不会被合并,这只是意味着它们会进入灰色地带。简而言之:我渴望合并任何主要以小型、局部、广泛适用、干净为主的更改,这些更改提高了仓库的效率和可移植性,同时保持其可黑客性和可读性。感谢所有寻求帮助我改进项目的 PR,谢谢!<3。 ## 著名分支 - Rust - [llama2.rs](https://github.com/gaxler/llama2.rs) 作者 @[gaxler](https://github.com/gaxler):此项目的 Rust 移植 - [llama2.rs](https://github.com/leo-du/llama2.rs) 作者 @[leo-du](https://github.com/leo-du):此项目的 Rust 移植 - [llama2-rs](https://github.com/danielgrittner/llama2-rs) 作者 @[danielgrittner](https://github.com/danielgrittner):此项目的 Rust 移植 - [llama2.rs](https://github.com/lintian06/llama2.rs) 作者 @[lintian06](https://github.com/lintian06):此项目的 Rust 移植 - [pecca.rs](https://github.com/rahoua/pecca-rs) 作者 @[rahoua](https://github.com/rahoua):利用 [ndarray](https://github.com/rust-ndarray/ndarray) 的 Rust 移植,支持 BLAS。 - [llama2.rs](https://github.com/flaneur2020/llama2.rs) 作者 @[flaneur2020](https://github.com/flaneur2020):此项目的 Rust 移植。 - [llama2-burn](https://github.com/code-cp/llama2-burn):利用 [Burn](https://github.com/tracel-ai/burn) 的此项目的 Rust 移植 - Go - [go-llama2](https://github.com/tmc/go-llama2) 作者 @[tmc](https://github.com/tmc):此项目的 Go 移植 - [llama2.go](https://github.com/nikolaydubina/llama2.go) 作者 @[nikolaydubina](https://github.com/nikolaydubina):此项目的 Go 移植 - [llama2.go](https://github.com/haormj/llama2.go) 作者 @[haormj](https://github.com/haormj):此项目的 Go 移植 - [llama2.go](https://github.com/saracen/llama2.go) 作者 @[saracen](https://github.com/saracen):此项目的 Go 移植 - Android - [llama2.c-android](https://github.com/Manuel030/llama2.c-android): 作者 @[Manuel030](https://github.com/Manuel030):添加了此项目的 Android 二进制文件 - [llama2.c-android-wrapper](https://github.com/celikin/llama2.c-android-wrapper): 作者 @[celikin](https://github.com/celikin):添加了 JNI wrapper,PoC - C - [llama3.c](https://github.com/jameswdelancey/llama3.c): 作者 @[jameswdelancey](https://github.com/jameswdelancey):此项目的 LLaMA 3 8B Base 和 Instruct 移植 - C++ - [llama2.cpp](https://github.com/leloykun/llama2.cpp) 作者 @[leloykun]():此项目的 C++ 移植 - [llama2.cpp](https://github.com/coldlarry/llama2.cpp) 作者 @[coldlarry](https://github.com/coldlarry):此项目的 C++ 移植 - JavaScript - [llama2.js](https://github.com/epicure/llama2.js) 作者 @[epicure](https://github.com/epicure):此项目的 JavaScript 移植 - [llamajs](https://github.com/agershun/llamajs) 作者 @[agershun](https://github.com/agershun):此项目的 JavaScript 移植 - [llama2.ts](https://github.com/wizzard0/llama2.ts) 作者 @[oleksandr_now](https://twitter.com/oleksandr_now):此项目的 TypeScript 移植。完全支持 Llama2-7B。 - [llama2.c-emscripten](https://github.com/gohai/llama2.c-emscripten) 作者 @[gohai](https://github.com/gohai):Emscripten (JavaScript) 移植,基于 @ggerganov 的初始原型 - Zig - [llama2.zig](https://github.com/cgbur/llama2.zig) 作者 @[cgbur](https://github.com/cgbur):此项目的 Zig 移植 - [llama2.zig](https://github.com/vodkaslime/llama2.zig) 作者 @[vodkaslime](https://github.com/vodkaslime):此项目的 Zig 移植 - [llama2.zig](https://github.com/clebert/llama2.zig) 作者 @[clebert](https://github.com/clebert):此项目的 Zig 移植 - Julia - [llama2.jl](https://github.com/juvi21/llama2.jl) 作者 @[juvi21](https://github.com/juvi21):此项目的 Julia 移植 - Scala - [llama2.scala](https://github.com/jrudolph/llama2.scala) 作者 @[jrudolph](https://github.com/jrudolph):此项目的 Scala 移植 - Java - [llama2.java](https://github.com/mukel/llama2.java) 作者 @[mukel](https://github.com/mukel):此项目的 Java 移植 - [llama2.java](https://github.com/neoremind/llama2.java) 作者 @[neoremind](https://github.com/neoremind):此项目的 Java 移植 - [llama2.tornadovm.java](https://github.com/mikepapadim/llama2.tornadovm.java) 作者 @[mikepapadim](https://github.com/mikepapadim):llama2.java 的扩展,通过 [TornadoVM](https://github.com/beehive-lab/TornadoVM) 支持 GPU。 - Kotlin - [llama2.kt](https://github.com/madroidmaq/llama2.kt) 作者 @[madroidmaq](https://github.com/madroidmaq):此项目的 Kotlin 移植 - [llama2-kmp](https://github.com/stepango/llama2-kmp) 作者 @[stepango](https://github.com/stepango):此项目的 Kotlin 多平台 (KMP) 移植 - Python - [llama2.py](https://github.com/tairov/llama2.py) 作者 @[tairov](https://github.com/tairov):此项目的简单单文件纯 Python 移植,零依赖 - C# - [llama2.cs](https://github.com/trrahul/llama2.cs) 作者 @[trrahul](https://github.com/trrahul):此项目的 C# 移植 - F# - [llama2.fs](https://github.com/micsh/llama2.fs) 作者 @[micsh](https://github.com/micsh):此项目的 F# 移植 - Dart - [llama2.dart](https://github.com/yiminghan/llama2.dart) 作者 @[yiminghan](https://github.com/yiminghan/llama2.dart):此项目的单文件 dart 移植,可与 Flutter 配合使用! - Web - [llama2c-web](https://github.com/dmarcos/llama2.c-web) 作者 @[dmarcos](https://github.com/dmarcos):将未修改的 llama2.c 构建为 WASM 并在浏览器中运行的超简单方法。[Demo](https://diegomarcos.com/llama2.c-web/) - [llama2.rs.wasm](https://github.com/mtb0x1/llama2.rs.wasm) 作者 @[mtb0x1](https://github.com/mtb0x1/) :列出的所有 Rust 移植到 WASM 的 [Demo](https://mtb0x1.github.io/llama2.rs.wasm/),全部在一个网页中。 - WebAssembly - [icpp-llm](https://github.com/icppWorld/icpp-llm):用于 Internet Computer 的 LLM - Fortran - [llama2.f90](https://github.com/rbitr/llama2.f90):此项目的 Fortran 移植 - Mojo - [llama2.🔥](https://github.com/tairov/llama2.mojo) 作者 @[tairov](https://github.com/tairov):此项目的纯 Mojo 移植 - OCaml - [llama2.ml](https://github.com/jackpeck/llama2.ml) 作者 @[jackpeck](https://github.com/jackpeck):此项目的 OCaml 移植 - Hare - [llama2.ha](https://sr.ht/~dvshkn/llama2.ha) 作者 @[dvshkn](https://git.sr.ht/~dvshkn):此项目的 Hare 移植 - [llama2.c - Llama 2 Everywhere](https://github.com/trholding/llama2.c) 作者 @[trholding](https://github.com/trholding):独立、可启动和可移植的二进制 Llama 2 - [llama2.c-zh - Bilingual Chinese and English](https://github.com/chenyangMl/llama2.c-zh) 作者 @[chenyangMl](https://github.com/chenyangMl):扩展 tokenizer 以支持中文和英文的训练及推理 - Haskell - [llama2.hs](https://github.com/chris-ch/llama2.hs) 作者 @[chris-ch](https://github.com/chris-ch):此项目的 Haskell 移植 ## 未分类待办事项 - 在 run.c 中添加对从 export 读取版本 1+ 文件的支持,稍后弃用 "version 0" - run.cu (CUDA) 调查并合并 - 在 [test.c](test.c) 中添加更多测试 - 为 sample.py 添加 Engine 类,在 PyTorch 中进行高效推理,例如保持 KV cache - 让添加新数据集变得不那么痛苦 - (LoRA) Llama 2 模型的微调和导出 ## 许可证 MIT
标签:DLL 劫持, DNS解析, fp32, Inference, Karpathy, LangChain, Llama 2, LLM, PyTorch, TinyStories, Transformer, Unmanaged PE, 凭据扫描, 大语言模型, 客户端加密, 客户端加密, 嵌入式AI, 开源项目, 教育目的, 无依赖, 极简主义, 模型推理, 深度学习, 端侧推理, 纯C实现, 训练框架, 轻量级, 逆向工具