llama2.c
你是否曾经想过用纯C语言推理一个小型的Llama 2模型?没有?现在你可以了!
在PyTorch中训练Llama 2 LLM架构,然后用一个简单的700行C文件(run.c)进行推理。你可能认为需要数十亿参数的LLM才能做有用的事情,但实际上,如果你将领域范围足够窄,非常小的LLM也能表现出惊人的强大性能(参考:TinyStories论文)。这个仓库是Llama 2 LLM的"全栈"训练+推理解决方案,专注于极简主义和简洁性。
由于架构相同,你也可以加载和推理Meta的Llama 2模型。然而,当前代码只能以fp32格式推理模型,所以你很可能无法高效地加载大于7B的模型。目前正在进行模型量化的工作。
请注意,这个仓库最近作为一个有趣的周末项目开始:我采用了之前的nanoGPT,调整它以实现Llama-2架构而不是GPT-2,其核心是在run.c中编写C推理引擎。所以这个项目还很年轻,正在快速发展。向激发这个项目的优秀llama.cpp致敬。与llama.cpp相比,我想要一些超级简单、极简且具有教育意义的东西,所以我选择硬编码Llama 2架构,只用一个没有依赖的纯C推理文件。
感受魔力
首先,导航到存放项目的文件夹,并将此仓库克隆到该文件夹:
git clone https://github.com/karpathy/llama2.c.git
然后,打开仓库文件夹:
cd llama2.c
现在,让我们用C语言运行一个小型Llama 2模型。你需要一个模型检查点。下载这个我在TinyStories数据集上训练的15M参数模型(约60MB下载):
wget https://huggingface.co/karpathy/tinyllamas/resolve/main/stories15M.bin
编译并运行C代码:
make run
./run stories15M.bin
你会看到文本流式生成一个样本。在我的M1 MacBook Air上,这以约110个词元/秒的速度运行。查看性能或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 "有一天,莉莉遇到了一个修格斯"
有一天,莉莉遇到了一个修格斯。他很害羞,但也很慷慨。莉莉说:"你好,修格斯!我能成为你的朋友吗?"修格斯很高兴有了一个朋友,说:"好啊,让我们一起探索宇宙吧!"于是他们开始了探索宇宙的旅程。在旅途中,修格斯很乐意向莉莉解释宇宙中所有奇妙的事物。到了一天结束时,莉莉和修格斯从宇宙中收集了许多奇妙的东西,他们都感到非常自豪。他们承诺要作为一对好朋友继续探索宇宙,永远互相慷慨。
还有一个更好的110M参数模型可用,请参见模型。
关于采样的简短说明,为获得~最佳结果,建议使用-t 1.0 -p 0.9
进行采样,即温度1.0(默认)但也进行0.9的top-p采样(默认)。直观地说,top-p确保不会采样到概率极小的词元,所以我们在采样时不会"倒霉",而且之后不太可能"偏离轨道"。更一般地说,要控制样本的多样性,可以使用温度(即在0和1之间变化-t
,并保持top-p关闭,即-p 0
)或top-p值(即在0和1之间变化-p
,并保持-t 1
),但不要同时使用两者。关于LLM采样策略的优秀解释包括这个、这个或这个。
Meta的Llama 2模型
由于神经网络架构相同,我们也可以推理Meta发布的Llama 2模型。遗憾的是,由于许可问题,这里有一些麻烦(我认为我不能直接上传检查点)。所以第一步,按照Meta说明获取Llama 2检查点。一旦我们有了这些检查点,我们必须将它们转换为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的文件(7B模型的float32权重),名为llama2_7b.bin
。据报告,尽管做了努力。我现在不会尝试运行大于7B的模型,原因有两个:首先,13B+目前由于指针算术中的整数溢出而无法工作,这个问题尚未修复;其次,即使修复了,这个仓库现在正在进行float32推理,所以它会非常慢得无法使用。一旦导出完成,我们可以运行它:
./run llama2_7b.bin
在我的云端CPU Linux盒子上,使用OpenMP编译并在96个线程上运行,速度约为4个词元/秒。(在我的MacBook Air M1上,如果你只用make runfast
构建,目前每个词元需要接近30秒。)示例输出:
本文档的目的是突出CoO生成技术的最新状态,包括最近的发展和商业使用中的技术。重点关注最有可能成为未来主导过程的技术,因此是S&T ... R&D感兴趣的技术。因此,对俄罗斯、日本和欧洲开发的CoO生成技术进行了较为深入的描述。文档首先介绍了作为复杂产品的钴氧化物,并简要介绍了钴作为一种重要材料。文档接着讨论了可用的CoO生成过程,涉及能源和资本消耗以及环境损害。
基础模型... ¯\(ツ)/¯。既然我们可以推理基础模型,那么也应该可以很容易地推理聊天模型,并与之进行对话。如果我们能找到一种更有效地运行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 层中的常数),所以推理现在并不完全正确,而且有点问题。正在寻找修复方法。确保为普通版本和指令版本构建分词器,并在进行推理时传递它。
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 使用 float32 前向传播,其中整个前向传播计算都保持在 fp32 中。这作为参考代码非常容易理解,但它有以下缺点:模型检查点文件非常大(每个单独的权重需要 4 个字节),并且前向传播相对较慢。实践中常用的推理优化是将模型参数量化为更低的精度,牺牲一点正确性来换取更小的检查点大小和更快的前向传播(因为大多数推理使用整数算术)。根据经验,LLM 可以容忍低至 4 位的精度(甚至更低),但我们在这里使用 int8,因为这是一个"安全"的设置,可以让我们获得好处,但不会牺牲太多模型精度。只有参与矩阵乘法的权重被量化。所有其他参数(特别是 RMSNorm 中的缩放和偏置)都保持在 float32 中,因为这些层非常敏感。现在,如果你只是为了减少检查点大小,你可以量化权重,保存检查点,然后在 run.c 中反量化它们,像往常一样进行 float32 推理就可以了。这完全没问题。但在这里,我们更进一步(这是标准做法),同时量化前向传播中的激活。这要求我们在运行时动态地在 float32 和 int8 之间进行量化和反量化,这会增加开销。但好处是现在大多数计算(特别是矩阵乘法!)都使用纯整数算术,其中权重和激活都以 int8 形式输入。这就是从根本上可以获得加速的地方。我们使用的版本是 "Q8_0" 量化(llama.cpp 术语),其中 0 表示权重量化围绕 0 对称,量化到 [-127, 127] 范围。
量化后的前向传播在 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 检查点,你会使用 --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。所以我们在将检查点大小减少 4 倍的同时实现了 3 倍的加速。然而,前向传播被量化为 int8,因此质量略有下降,但不明显。
huggingface 模型
我们可以加载任何使用 Llama 2 架构的 huggingface 模型。查看脚本 export.py 和 --hf
标志来导出模型 .bin 文件。
模型
为了展示较小的、从头开始训练的模型示例,我在 TinyStories 上训练了一系列小型模型。所有这些都在我的训练设置(4X A100 40GB GPU)上用了几个小时。110M 模型花了大约 24 小时。我将它们托管在 huggingface hub 上的 tinyllamas,同时包括原始的 PyTorch .pt 格式和 llama2.c 格式的 .bin:
模型 | 维度 | 层数 | 头数 | KV 头数 | 最大上下文长度 | 参数数 | 验证损失 | 下载 |
---|---|---|---|---|---|---|---|---|
260K | 64 | 5 | 8 | 4 | 512 | 260K | 1.297 | stories260K |
OG | 288 | 6 | 6 | 6 | 256 | 15M | 1.072 | stories15M.bin |
42M | 512 | 8 | 8 | 8 | 1024 | 42M | 0.847 | stories42M.bin |
110M | 768 | 12 | 12 | 12 | 1024 | 110M | 0.760 | 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,所以这是目前这个仓库中唯一可用的示例。但添加数据集应该很容易,请查看代码。
python tinystories.py download
python tinystories.py pretokenize
然后训练我们的模型:
python train.py
简要训练指南。有关更多复杂的启动和超参数覆盖,请参阅train.py脚本。以下是如何设置参数的简要指南。查看Chinchilla论文最后的表格,了解Transformer参数(dim、n_layers、n_heads)如何一起增大或缩小。根据这个模式推断/插值以获得更大或更小的transformer。根据问题需要设置最大上下文长度:这应该是预测下一个token所需的最大token数。例如,Llama 2使用2048。接下来,你希望每次更新的总批量大小(脚本打印为"每次迭代的token数将为:")在中等规模应用中约为10万个token。对于小型应用,可能会更低,对于大型训练(如GPTs/LLamas),通常约为50万,甚至更多。首先将batch_size最大化到系统允许的值(例如,在最近的运行中,我的系统是16,因为再高GPU就会内存不足),然后你需要增加gradient_accumulation_steps,直到达到约10万的总批量大小。最后,你需要调整学习率(LR)。你希望这个值尽可能高,但仍在训练允许的范围内。非常小的网络可以使用较大的LR(如1e-3甚至更高)。大型网络需要较低的LR。3e-4在大多数中等规模应用中是安全的选择,但对于小型网络可能太低,所以尝试增加它!最后,max_iters是训练的长度。尝试不同的设置。我主要只调整这些参数,保持大多数其他参数不变。以下是我如何训练110M模型的示例,虽然我认为这远非最优,但看起来对我来说是合理的:dim 768,n_layers 12,n_heads 12(所以每个头的大小是768 / 12 = 64个通道),序列长度1024,batch size 16(这是我的A100 40GB GPU能容纳的最大值),gradient_accumulation_steps = 8 是为了使总token批量大小达到16批量大小 * 1024序列中的token * 8 grad_accum = 131,072 每次更新的token。不错。学习率4e-4(可能有点低)。max_iters 20万(可能有点高)。Dropout 0.1,因为这通常在中等规模时有帮助。就这些。我在云机器上使用分布式数据并行(DDP)在4个GPU上运行,训练大约花了一天左右。
如果你想跳过模型训练,只需下载一个预训练模型(参见模型部分),例如:
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
这会给出相同的结果。
自定义分词器
在上述所有内容中,我们假设使用了带有32,000个token的自定义Lllama 2分词器。然而,在许多精品LLM中,使用这么大的词汇表可能是过度的。如果你有一个小型应用in mind,你可能更适合训练自己的分词器。这可以使一切变得更好 - 使用较小的词汇表,你的模型参数更少(因为token嵌入表小得多),推理速度更快(因为需要预测的token更少),每个例子的平均序列长度也可能变小(因为压缩对你的数据更有效)。所以让我们看看如何训练自定义分词器。
默认情况下,要对tinystories数据集进行预分词,我们必须按顺序运行:
python tinystories.py download
python tinystories.py pretokenize
这里的pretokenize阶段加载Llama 2分词器(词汇量32,000)并用它将下载的文本转换为整数,然后保存到文件中。现在我们将其更改如下,以训练一个4096个token的示例分词器:
python tinystories.py download
python tinystories.py train_vocab --vocab_size=4096
python tinystories.py pretokenize --vocab_size=4096
train_vocab阶段将调用sentencepiece库来训练分词器,将其存储在新文件data/tok4096.model中。我尽可能地尝试复制(我认为)Meta用来训练他们词汇表的设置。这使用了字节对编码算法,从文本数据的原始utf8字节序列开始,然后迭代地合并最常见的连续token对来形成词汇表。查看tinystories.py文件 - 自定义分词器存储在一个特殊的目录结构中,按词汇量大小索引。
值得注意的是,专门针对tinystories训练的4096个词汇量分词器创建的整数序列,每个例子的序列长度与默认的32000个token的Llama 2分词器大约相同!这意味着我们的自定义、定制分词器更适合我们特定的文本,可以非常有效地压缩它。因此我们训练的模型更小、更快。
现在我们已经用自定义分词器对数据集进行了预分词,我们可以训练模型了。训练脚本train.py并不关心具体的token,它只关心词汇量大小,以便正确初始化模型。所以在训练模型时,确保传入
python train.py --vocab_source=custom --vocab_size=4096
(默认值分别为llama2和32000,表示默认的Llama 2分词器)。这样就训练了模型。最后我们准备用run.c脚本进行推理。为此我们需要两件事。第一,我们必须将分词器导出为.bin格式,用以下命令完成:
python tokenizer.py --tokenizer-model=data/tok4096.model
这将分词器写入data/tok4096.bin。现在我们可以进行推理,使用-z标志指向这个分词器:
./run out/model.bin -z data/tok4096.bin
这应该会打印样本。如果你省略-z标志,它将使用默认的Llama 2分词器,这会生成一个好的整数序列,但它们会使用不同的词汇表转换为文本,所以看起来会像胡言乱语。
性能
根据你的系统,有很多方法可能加速这段代码。看看Makefile,它包含了很多注释。make run命令目前默认使用-O3优化,即:
gcc -O3 -o run run.c -lm
-O3包括在编译时间和内存使用方面代价高昂的优化。包括矢量化、循环展开和分支预测。
要获得更好的性能,尝试用make runfast编译。这会打开-Ofast标志,除了-O3之外,还包括可能破坏C/IEEE规范的额外优化。更多信息请参见GCC文档。
尝试-march=native,将程序编译为使用你正在编译的机器的架构,而不是更通用的CPU。这可能启用额外的优化和硬件特定调整,如改进的矢量指令/宽度。
到目前为止,我在MacBook Air(M1)上看到的最快吞吐量是使用make runfast。
你也可以尝试用clang替换gcc。
如果用gcc编译,尝试使用-funroll-all-loops,参见PR #183
OpenMP。通过使用OpenMP编译也可以实现大幅改进,这会"激活"矩阵乘法和注意力中的#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特定优化有一些适用于此处的有用信息。
平台
在Windows上,在Visual Studio命令提示符中使用build_msvc.bat
用msvc构建,或者您可以在Linux或Windows上使用make win64
来使用mingw编译器工具链构建Windows目标。除非您设置了OMP_NUM_THREADS
环境变量,否则MSVC构建将自动使用openmp和适合您CPU的最大线程数。
在Centos 7和Amazon Linux 2018上,使用rungnu
Makefile目标:make rungnu
或make runompgnu
来使用openmp。
在Mac上,使用brew安装的clang进行openmp构建。通过brew install llvm
安装clang,并使用安装的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文件中还有一些C语言的测试。您可以通过make testcc
运行这些测试,或者要查看更多打印内容:
make testcc VERBOSITY=1
求助:帮忙添加更多测试。
致谢
我在由优秀的Lambda labs慷慨提供的4X A100 40GB机器上训练了llama2.c讲故事模型,非常感谢。
Discord
我发现可以重用我现有的Discord频道(用于我的zero to hero YouTube系列),请查看Discord上的#llama2c频道,有任何快速问题、相关讨论等。
贡献
关于这个仓库以及可能被接受的PR类型,我想说几句话。这个仓库的目标是什么?基本上,我认为在各种应用中,训练或微调自定义微型LLM(考虑约100M - 约1B参数,但让我们说最多到约10B参数)将会有很大的兴趣,并将它们部署在边缘相关环境中(考虑MCU、手机、网络浏览器、笔记本电脑等)。我希望这个仓库成为支持这个工作流程(包括训练和推理)最简单、最小、最易于修改的仓库。特别是,这个仓库不是一个复杂的框架,有1000个旋钮控制着分布在数百个文件的嵌套目录结构中的晦涩代码。相反,我预计大多数应用会希望创建这个仓库的分支,并根据他们的具体需求和部署平台进行修改。
那些最关心部署效率的人应该看看llama.cpp。这个仓库仍然关注效率,但不以牺牲简单性、可读性或可移植性为代价。基本上,我预计很多人来到这个仓库是因为训练代码只有2个可读的.py文件,而推理代码是500行C语言。所以我希望这继续成为一种最简单的"参考实现",可以在单独的分支中轻松修改成人们感兴趣的任何下游应用。它不应该功能齐全。它不应该接受100种不同的选项或设置。它不应该是最高效的。几个例子:
- 有人重新排序了两个循环以改善数据局部性,获得了小幅效率提升 => 立即合并。
- 有人添加了一行"pragma omp parallel for",这允许您使用OpenMP编译并大大加速代码,或者如果您不这样编译,它就只是一个注释 => 立即合并。
- 错误修复和调整等 => 很乐意合并
几个不太适合的PR例子:
- 在代码中到处添加多个#ifdef。如果它们是局部的/很少,可能还好。
- 添加大量特定于某些特定平台的代码(例如MCU,或某些特殊版本的Linux或处理器)。这些可能更适合项目的分支,我很乐意在下面的章节中维护这些分支的列表。
- 在run.c中添加数百行只在特定场景或平台上活跃的代码。
如果您的候选PR有这些元素,并不意味着它们不会被合并,只是意味着它们会进入灰色地带。总之:我渴望合并任何大多数小型的、大多数局部的、广泛适用的、简洁的变更,以提高仓库的效率和可移植性,同时保持其可修改性和可读性。我感谢所有旨在帮助我改进项目的PR,谢谢!<3
值得注意的分支
-
Rust
-
Go
-
Android
- @Manuel030 的 llama2.c-android:为本项目添加 Android 二进制文件
- @celikin 的 llama2.c-android-wrapper:添加 JNI 包装器,概念验证
-
C
- @jameswdelancey 的 llama3.c:本项目的 LLaMA 3 8B Base 和 Instruct 移植版
-
C++
- @leloykun 的 llama2.cpp:本项目的 C++ 移植版
- @coldlarry 的 llama2.cpp:本项目的 C++ 移植版
-
JavaScript
- @epicure 的 llama2.js:本项目的 JavaScript 移植版
- @agershun 的 llamajs:本项目的 JavaScript 移植版
- @oleksandr_now 的 llama2.ts:本项目的 TypeScript 移植版,支持完整的 Llama2-7B
- @gohai 的 llama2.c-emscripten:基于 @ggerganov 初始原型的 Emscripten(JavaScript)移植版
-
Zig
- @cgbur 的 llama2.zig:本项目的 Zig 移植版
- @vodkaslime 的 llama2.zig:本项目的 Zig 移植版
- @clebert 的 llama2.zig:本项目的 Zig 移植版
-
Julia
- @juvi21 的 llama2.jl:本项目的 Julia 移植版
-
Scala
- @jrudolph 的 llama2.scala:本项目的 Scala 移植版
-
Java
- @mukel 的 llama2.java:本项目的 Java 移植版
- @neoremind 的 llama2.java:本项目的 Java 移植版
- @mikepapadim 的 llama2.tornadovm.java:llama2.java 的扩展版,通过 TornadoVM 支持 GPU
-
Kotlin
- @madroidmaq 的 llama2.kt:本项目的 Kotlin 移植版
- @stepango 的 llama2-kmp:本项目的 Kotlin 多平台(KMP)移植版
-
Python
- @tairov 的 llama2.py:本项目的简单单文件纯 Python 移植版,零依赖
-
C#
- @trrahul 的 llama2.cs:本项目的 C# 移植版
-
F#
- @micsh 的 llama2.fs:本项目的 F# 移植版
-
Dart
- @yiminghan 的 llama2.dart:本项目的单文件 Dart 移植版,可与 Flutter 配合使用!
-
Web
- @dmarcos 的 llama2c-web:以超简单的方式将未修改的 llama2.c 构建为 WASM 并在浏览器中运行。演示
- @mtb0x1 的 llama2.rs.wasm:所有列出的 Rust 移植版到 WASM 的演示,全部在一个网页中
-
WebAssembly
- icpp-llm:Internet Computer 的 LLM
-
Fortran
- llama2.f90:本项目的 Fortran 移植版
-
Mojo
- @tairov 的 llama2.🔥:本项目的纯 Mojo 移植版
-
OCaml
- @jackpeck 的 llama2.ml:本项目的 OCaml 移植版
-
Hare
- @dvshkn 的 llama2.ha:本项目的 Hare 移植版
-
@trholding 的 llama2.c - Llama 2 Everywhere:独立、可引导和便携式的 Llama 2 二进制文件
-
llama2.c-zh - 中英双语 由 @chenyangMl 开发:扩展分词器以支持中英文的训练和推理
-
Haskell
未分类待办事项
- 在run.c中添加对从导出读取版本1+文件的支持,稍后弃用"版本0"
- 调查并合并run.cu(CUDA)
- 在test.c中添加更多测试
- 添加Engine类,用于在PyTorch中进行高效推理,例如保持KV缓存
- 简化添加新数据集的流程,减少繁琐操作
- (LoRA)Llama 2模型的微调和导出
许可证
MIT