首页 今日新闻文章正文

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

今日新闻 2025年10月15日 06:03 0 aa
4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

整理 | 屠敏

出品 | CSDN(ID:CSDNnews)

今天,前 OpenAI 联合创始人、Eureka Labs 创始人 Andrej Karpathy(安德烈·卡帕西)带来了一个全新的开源项目——nanochat。

用他自己的话说,这是他写过的最“疯狂”的作品之一:

只要 4 个小时、100 美元,就能“手搓”一款属于自己的 ChatGPT。倘若花上 12 个小时来训练,其性能可超越 GPT-2。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

简而言之,nanochat 可以看做是一个类似 ChatGPT 的 LLM 的全栈实现,它把训练和推理的全流程都整合进了一个干净、轻量、可修改、几乎零依赖的代码库里。

你只要启动一台云端 GPU,运行一条脚本命令,大约 4 小时后,就能在 ChatGPT 风格的网页界面中,与自己训练的 LLM 对话了。不仅如此,它还可以写诗、讲故事和回答一些简单的问题等等。

可喜的是,此项目遵循 MIT 协议开源,这意味着任何人都可以自己去尝试做一款 GPT。正因此,项目发布数小时内,便斩获了 7.1k Star,引发无数 AI 开发者热议与尝试。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

话不多说,感兴趣的小伙伴可通过 GitHub 开源地址,即刻上手体验:https://github.com/karpathy/nanochat

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

仅有 8000 行代码的 nanochat

根据 Karpathy 介绍,nanochat 约有 8000 行代码,几乎覆盖了整个模型训练与推理流程,具体包括:

  • 训练前处理:使用全新的 Rust 实现训练分词器(tokenizer)实现,以加快文本编码效率。
  • 预训练阶段:在 FineWeb 数据集上对 Transformer LLM 进行预训练,并通过多个指标评估 CORE 分数。
  • 中期训练:使用 SmolTalk 数据集进行中期训练,涵盖用户-助手对话、多项选择题和工具使用场景。
  • 监督微调(SFT):在以下任务上评估聊天模型,如世界知识多项选择题(ARC-Easy / ARC-Challenge、MMLU)、数学题(GSM8K)、编程题(HumanEval)。
  • 可选强化学习(RL)阶段:在 GSM8K 上通过 GRPO 算法进一步优化模型性能。
  • 推理引擎:在带有 KV 缓存的引擎中高效推理模型,支持简单的预填充/解码、工具调用(轻量沙箱中的 Python 解释器),用户可通过命令行或 ChatGPT 风格网页界面与模型交互。
  • 此外,系统还会自动生成一份 Markdown 格式报告,总结模型性能表现。
4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

Karpathy 进一步表示,模型训练的规模可根据时间与成本灵活调整:

  • 仅使用约 100 美元成本,在单台 8×H100 GPU 节点上训练 4 小时,即可得到一个能进行基础对话的 ChatGPT 小模型;
  • 训练 12 小时左右,模型即可超过 GPT-2 CORE 基准;
  • 若将预算扩大至约 1000美元(训练约 41.6 小时),模型将具备更高连贯性,能解决简单的数学与编程问题,并回答多项选择题。

与此同时,Karpathy 在 GitHub 上打趣道:

“这是 100 美元能构建的最强 ChatGPT。”

而对于未来目标,Karpathy 称:

我的目标是把整个“强基线”(strong baseline)技术栈整合到一个统一、简洁、可读、可修改、便于分叉的仓库中。nanochat 将成为正在开发中的课程 LLM101n 的收官项目。

LLM101n 是 Karpathy 所创立的教育公司 Eureka Labs 面向本科生开设的一门课程,旨在带领学生从零构建属于自己的 AI 模型。其补充说,nanochat 未来有望像 nanoGPT 一样,发展成一个研究平台或基准项目。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

快速上手

为了让更多的爱好者迅速上手,Karpathy 在 GitHub 上(https://github.com/karpathy/nanochat/discussions/1)详细分享了 nanochat 的教程。

nanochat 被设计为在单个 8×H100 GPU 机器上运行,此次教程中,Karpathy 使用了 Lambda GPU Cloud,每小时大约 24 美元。当然想要尝试的爱好者们也可根据个人情况自行选择,进行了尝试。

接下来看看他到底是怎么做的?

环境搭建

首先,克隆项目并进入目录:

git clone git@github.com:karpathy/nanochat.gitcd nanochat

100 美元训练出最强的类 ChatGPT,其背后最快体验魔力的方法是运行speedrun.sh(速通)脚本。

speedrun.sh 脚本可以在一台新机器上直接运行,从头到尾完成训练和推理。

一切的前提就是需要确保安装了新的 uv 项目管理工具。然后创建虚拟环境、安装依赖并激活它,这样在终端输入 python 时,就会使用虚拟环境里的 Python,而不是系统自带的 Python:

# 安装 uv(如果还没安装的话)command -v uv &> /dev/null || curl -LsSf https://astral.sh/uv/install.sh | sh# 创建本地虚拟环境 .venv(如果不存在的话)[ -d ".venv" ] || uv venv# 安装仓库依赖uv sync# 激活虚拟环境,这样 `python` 就会使用项目的虚拟环境source .venv/bin/activate

接下来,需要安装 Rust/Cargo来编译 nanochat 中自定义的 Rust 分词器。

Karpathy 称,引入新的分词器确实有点麻烦,但之前 Python 版本的 minbpe 太慢,而 HuggingFace 的 tokenizer 太臃肿且复杂。

所以他自己实现了一个新的 Rust 分词器来训练(经过测试效果与 Python 版本一致),但推理阶段仍会使用 OpenAI 的 tiktoken来保证效率。

编译分词器步骤如下:

# 安装 Rust / Cargocurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -ysource "$HOME/.cargo/env"# 编译 rustbpe Tokenizeruv run maturin develop --release --manifest-path rustbpe/Cargo.toml

这样就完成了分词器的编译和环境搭建,为后续训练做准备。

训练分词器

接下来,就需要预训练数据,以便完成两个任务:

这里的预训练数据就是大量网页文本,在教程中,Karpathy 使用的是 FineWeb-EDU 数据集

他解释道,通常大家可以直接用 HuggingFace 的 datasets.load_dataset 来加载,但这个太笨重、臃肿,而且把一些很简单的逻辑隐藏起来,所以他自己选择了重新打包了整个数据集,生成了简单、完全随机打乱的数据分片,方便高效访问。

此外,Karpathy 还把 sample-100B 版本上传成了 karpathy/fineweb-edu-100b-shuffle(https://huggingface.co/datasets/karpathy/fineweb-edu-100b-shuffle)。

每个分片是一个简单的 Parquet 文件,约 0.25M 个字符,压缩后(gzip 压缩)在磁盘占用约100MB 空间。数据集总共有1822 个分片,但训练一个depth=20的模型只需要240 个分片

下载数据:

python -m nanochat.dataset -n 240

默认情况下,这些数据会存放在 ~/.cache/nanochat。下载完成后,就可以训练分词器了。分词器的作用是把文本在字符串代码表符号序列之间互相转换。

同样在默认情况下,Karpathy 表示,训练的词表大小是 2¹⁶ = 65,536个 token,这个数字比较好记。其中少数 token 被保留作特殊用途(后续聊天 schema 会用到)。训练集大小约20 亿字符,训练时间仅需约 1 分钟

训练算法与 OpenAI 的方法一致(正则分割 + byte-level BPE)。

训练完成后,可以评估分词器效果:

python -m scripts.tok_train --max_chars=2000000000python -m scripts.tok_eval

评估结果显示,分词器压缩率约为 4.8,也就是说平均 4.8 个原始字符会变成 1 个 token。同时,也可以将 nanochat 的结果与GPT-2GPT-4分词器做对比:

  • 相比 GPT-2(50257 个 token), nanochat 的分词器在大部分文本压缩上表现更好,数学文本略差一些。
4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

  • 相比 GPT-4,nanochat 的表现稍逊,但要注意 GPT-4 的词表更大(100,277 个 token),在多语言、代码和数学上优势明显。
4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

有趣的是,虽然词汇量较小,但在 FineWeb 数据集上,nanochat 的分词器表现略胜 GPT-4。这是因为 nanochat 的分词器正好针对这个数据集训练,能够更好地匹配文档分布,比如在英语文本压缩上略占优势。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

训练阶段

预训练

在开始预训练之前,Karpathy 建议需要下载一个名为“eval bundle”的文件。

在预训练过程中,脚本会定期评估 CORE 指标。简单来说,CORE 是一个规范化的综合指标,用于衡量模型在多个自动补全数据集上的表现。数据集包括 HellaSwag、Jeopardy、BigBench QA、Wikidata、ARC-Easy/Challenge、COPA、Commonsense QA、PIQA、Lambada、Winograd、BoolQ 等,总共 22 个数据集。

下载、解压,并将 eval bundle 放到基础目录下:~/.cache/nanochat/eval_bundle

curl -L -o eval_bundle.zip https://karpathy-public.s3.us-west-2.amazonaws.com/eval_bundle.zipunzip -q eval_bundle.ziprm eval_bundle.zipmv eval_bundle "$HOME/.cache/nanochat"

另外一个可选步骤是设置 wandb,可以在训练过程中查看漂亮的可视化曲线。虽然 uv 已经安装了 wandb,但你仍需要注册账号并登录:

wandb login

接下来,可以开始预训练了!

Karpathy 表示,这是计算量最大的一步,模型通过预测序列中的下一个 token来压缩网页文本,同时也逐渐学习世界知识。

torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- --depth=20

这里 Karpathy 使用了 8 张 GPU启动训练,训练一个20 层的 Transformer。默认情况下,每张 GPU 每次前向/反向传播处理32 行 × 2048 token,也就是 524,288 ≈ 0.5M token 每步优化。

如果 wandb 已设置,可加上 --run=speedrun 记录训练日志。

训练过程中,你会看到类似信息(为了简洁起见,这里删除了一些内容):

Vocab size: 65,536num_layers: 20model_dim: 1280num_heads: 10num_kv_heads: 10Tokens / micro-batch / rank: 32 x 2048 = 65,536Tokens / micro-batch: 524,288Total batch size 524,288 => gradient accumulation steps: 1Number of parameters: 560,988,160Estimated FLOPs per token: 3.491758e+09Calculated number of iterations from target data:param ratio: 21,400Total number of training tokens: 11,219,763,200Tokens : Params ratio: 20.00Total training FLOPs estimate: 3.917670e+19Scaling the LR for the AdamW parameters ∝1/√(1280/768) = 0.774597Muon: Grouping 80 params of shape torch.Size([1280, 1280]), device cuda:0, dtype torch.float32Muon: Grouping 20 params of shape torch.Size([1280, 5120]), device cuda:0, dtype torch.float32Muon: Grouping 20 params of shape torch.Size([5120, 1280]), device cuda:0, dtype torch.float32Step 00000 | Validation bpb: 3.3013^[step 00000/21400 (0.00%) | loss: 11.090355 | lrm: 1.00 | dt: 23156.74ms | tok/sec: 22,640 | mfu: 1.00 | total time: 0.00mstep 00001/21400 (0.00%) | loss: 10.808654 | lrm: 1.00 | dt: 649.22ms | tok/sec: 807,569 | mfu: 35.64 | total time: 0.00mstep 00002/21400 (0.01%) | loss: 10.179083 | lrm: 1.00 | dt: 472.29ms | tok/sec: 1,110,094 | mfu: 48.99 | total time: 0.00mstep 00003/21400 (0.01%) | loss: 9.449214 | lrm: 1.00 | dt: 487.47ms | tok/sec: 1,075,523 | mfu: 47.47 | total time: 0.00mstep 00004/21400 (0.02%) | loss: 8.903216 | lrm: 1.00 | dt: 487.57ms | tok/sec: 1,075,308 | mfu: 47.46 | total time: 0.00mstep 00005/21400 (0.02%) | loss: 8.531662 | lrm: 1.00 | dt: 482.58ms | tok/sec: 1,086,417 | mfu: 47.95 | total time: 0.00mstep 00006/21400 (0.03%) | loss: 8.231589 | lrm: 1.00 | dt: 487.21ms | tok/sec: 1,076,113 | mfu: 47.49 | total time: 0.00mstep 00007/21400 (0.03%) | loss: 7.993080 | lrm: 1.00 | dt: 484.10ms | tok/sec: 1,083,014 | mfu: 47.80 | total time: 0.00mstep 00008/21400 (0.04%) | loss: 7.803373 | lrm: 1.00 | dt: 488.17ms | tok/sec: 1,073,989 | mfu: 47.40 | total time: 0.00mstep 00009/21400 (0.04%) | loss: 7.627318 | lrm: 1.00 | dt: 484.78ms | tok/sec: 1,081,486 | mfu: 47.73 | total time: 0.00mstep 00010/21400 (0.05%) | loss: 7.491893 | lrm: 1.00 | dt: 487.03ms | tok/sec: 1,076,511 | mfu: 47.51 | total time: 0.00mstep 00011/21400 (0.05%) | loss: 7.354157 | lrm: 1.00 | dt: 487.10ms | tok/sec: 1,076,334 | mfu: 47.50 | total time: 0.01mstep 00012/21400 (0.06%) | loss: 7.246406 | lrm: 1.00 | dt: 487.99ms | tok/sec: 1,074,383 | mfu: 47.42 | total time: 0.02mstep 00013/21400 (0.06%) | loss: 7.159368 | lrm: 1.00 | dt: 486.56ms | tok/sec: 1,077,540 | mfu: 47.55 | total time: 0.02m

可以看到,这个 Transformer 在注意力机制中有 1280 维通道,注意力头数为 10,总参数约5.6 亿。按照 Chinchilla scaling law 推荐,这里需要训练约 560M×20≈11.2B tokens。由于优化器的每一步都需要 524,288 个 tokens,这意味着总共需要约 11.2B/0.5M≈21400 次迭代

通过将每个标记的预估 FLOP 数乘以标记总数,最终得到这个模型的性能约为 4e19 FLOP。

学习率会自动按 1/sqrt(dim) 的比例缩小,因为较大的模型更倾向于较小的学习率。

这次过程中,Karpathy 使用 Muon 优化矩阵,并使用 AdamW 优化嵌入和去嵌入。此模型中没有其他可训练参数(偏差、rmsnorm 参数等)。训练会定期报告“验证 bpb”,即验证数据集上的每字节位数。

每字节位数比典型的交叉熵损失要好得多,因为它进一步将每个标记的损失用该标记的字节数进行归一化,从而使该指标与分词器无关。

因此,无论你的分词器词汇量大小,这个数字都是可比的,这与原始交叉熵损失不同。

注意,每一步大约需要 0.5 秒,lrm 是学习率衰减乘数(在训练结束时会线性下降到 0),报告的 MFU(模型浮点运算利用率)看起来不错,几乎达到了一半左右,这意味着我们正在利用大量可用的 bfloat16 计算资源。

训练大约需要 3 小时执行完 4e19 FLOPs。在 wandb 上,你会看到 bpb 逐渐下降(模型预测下一个 token 更准确),CORE 指标逐渐上升。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

训练完成后,可通过以下命令进一步评估模型:

torchrun --standalone --nproc_per_node=8 -m scripts.base_losstorchrun --standalone --nproc_per_node=8 -m scripts.base_eval

可以看到,训练集和验证集的 bpb 达到 0.81,而CORE指标上升到0.22。作为对比,eval bundle 中包含了 GPT-2 模型的 CORE 分数。其中,CORE0.22略高于 GPT-2 Large(0.21),但略低于 GPT-2 XL(也就是标准 GPT-2,0.26)。

此时的模型本质上是一个高级的自动补全工具,我们可以通过几个示例提示(prompts)来了解模型里存储了哪些知识。文件 base_loss.py会执行这些示例提示。Prompt 内容如下:

prompts = [    "The capital of France is",    "The chemical symbol of gold is",    "If yesterday was Friday, then tomorrow will be",    "The opposite of hot is",    "The planets of the solar system are:",    "My favorite color is",    "If 5*x + 3 = 13, then x is",]

模型完成结果如下:

The capital of France is Paris. It is the largest city in France and the second largest city in EuropeThe chemical symbol of gold is Au. The chemical symbol of silver is Ag. The chemical symbol of copper isIf yesterday was Friday, then tomorrow will be Saturday. If yesterday was Monday, then tomorrow will be Monday. If yesterday wasThe opposite of hot is cold. The opposite of hot is cold. The opposite of hot is cold.The planets of the solar system are: Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune,My favorite color is red. It is the color of the sun, the color of the sky,If 5*x + 3 = 13, then x is a positive integer.

可见模型已经掌握了地理、化学、时间逻辑、基础数学太阳系行星等知识,但对一些简单常识(如天空颜色)仍不确定。

不过,对于一个训练成本仅 72 美元的模型来说,表现已经相当不错了。推理阶段使用自定义 Engine 类,支持KV 缓存提升效率,并实现了prefilldecode两个常用阶段。同时,Engine 还支持调用工具(如 Python 解释器),这在后续训练 GSM8K 时会非常有用。

中期训练

接下来是中期训练,主要是进一步微调模型,让它更适合 SmolTalk 对话数据。

算法上和预训练完全相同,但现在训练的数据变成了多轮对话,模型也会学习新的特殊 token,用来构建多轮对话对象。

每条对话大致如下(参考 OpenAI Harmony chat 格式):

bos|>user_start|>What is the color of the sky?user_end|>assistant_start|>Red. Wait, possibly blue. I'm not sure.assistant_end|>user_start|>loluser_end|>assistant_start|>...etcetc

其中 这样的 token 是特殊 token,遵循 OpenAI 的格式。中期训练阶段对于模型中的许多调整非常有用:

  • 模型学习与多轮对话相关的特殊 token(除了 (文档起始符),这些 token 在基础模型预训练阶段并不存在)
  • 适应对话数据的分布,模型不再只是处理网页文本,而是学习如何理解和生成对话
  • 训练模型做选择题(Multiple Choice),小模型仅靠随机网络训练无法理解选择题的规则,模型必须学会将选项(A、B、C、D)与正确答案对应,我们在训练中加入了 MMLU auxiliary_train 中的 10 万道选择题。
  • 训练模型使用工具,比如让模型学会在特殊 token … 内执行 Python 命令。这在之后训练 GSM8K(数学题)时会很有用。
  • 其他潜在适应,如扩展上下文长度等(目前尚未探索)。

默认的中期训练数据混合如下:

train_dataset = TaskMixture([    SmolTalk(split="train"), # 460K rows of general conversations    MMLU(subset="auxiliary_train", split="train"), # 100K rows of multiple choice problems drawn from ARC, MC_TEST, OBQA, RACE    GSM8K(subset="main", split="train"), # 8K rows teaching simple math and (calculator) tool use]) # total: 460K + 100K + 8K = 568K rows

启动中期训练命令:

torchrun --standalone --nproc_per_node=8 -m scripts.mid_train

这一步大约只需 8 分钟,远比预训练的 3 小时短。现在模型已经成为一个完整的Chat 模型,可以充当 Assistant 回答用户问题。评估模型:

torchrun --standalone --nproc_per_node=8 -m scripts.chat_eval -- -i mid

此阶段模型的表现:

- ARC-Easy: 0.3561- ARC-Challenge: 0.2875- MMLU: 0.3111- GSM8K: 0.0250- HumanEval: 0.0671- ChatCORE metric: 0.0730

我们可以看到以下几点:

  • 世界知识:前 3 个测试(ARC-Easy、ARC-Challenge 和 MMLU)都是选择题,用来衡量模型在不同领域的常识水平。因为每道题有 4 个选项(A、B、C、D),随机猜的正确率大约是 25%。而这里得到的模型已经明显超过了这个水平——这对这么小的模型来说其实挺难的。
  • 数学:GSM8K 是小学数学题。这里的基准分是 0%,因为模型需要写出具体的数字答案。目前训练出来的模型表现还不算理想,只能解出大约 2% 的题目。
  • 代码:HumanEval 是 Python 编程测试,同样随机猜测的正确率是 0%。
  • ChatCORE 指标:这是 Karpathy 为了模仿 CORE 分数(用于基础模型)并扩展到聊天模型而设计的指标。具体做法是:把所有任务的得分减去基准分,使得最终分数范围在 0 到 1 之间(例如在 MMLU 上,随机模型是 0,而不是 25%),然后取这些任务的平均值。这样就能得到一个简单的数字,来概括当前模型的整体水平。
  • 目前这些评估还不算完整,还有很多维度暂时没测到。

Karpathy 表示,由于没有太好的图表能展示这一步的效果,但可以看看他之前给一个更大模型做中期训练(midtraining)时的曲线图——能直观看到这些指标在微调过程中是如何上升的。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

监督微调

在训练中期之后,接下来是监督微调(SFT)阶段。这是对对话数据的又一轮微调,但这里通常会精挑细选最优质的数据,同时也可以加入一些安全训练,比如训练助手学会拒绝不合适的请求。Karpathy 调侃道,“我们的模型连天空是什么颜色都不太确定,所以目前在生物安全方面应该没问题。”

SFT 阶段的一个重要改进是领域适配(domain adaptation)

  • 它会拉伸数据行并进行填充(padding),严格模拟测试时的格式。换句话说,样本不再像预训练或中期训练中那样随意拼接成长行,这种拼接主要是为了训练效率。
  • 通过修正这种域不匹配,模型会得到额外的性能提升,相当于再“拧紧一颗螺丝”。

运行 SFT 并重新评估模型:

torchrun --standalone --nproc_per_node=8 -m scripts.chat_sfttorchrun --standalone --nproc_per_node=8 -m scripts.chat_eval -- -i sft

这一阶段大约只需 7 分钟,你会发现各项指标都有小幅提升:

- ARC-Easy: 0.3876- ARC-Challenge: 0.2807- MMLU: 0.3151- GSM8K: 0.0455- HumanEval: 0.0854- ChatCORE metric: 0.0884

最后,我们可以真正以用户身份与模型进行对话了!虽然在中期训练后就可以聊,但现在效果会更好。可以在终端里聊天:

python -m scripts.chat_cli

或者通过网页界面聊天:

python -m scripts.chat_web

chat_web 会使用 FastAPI启动服务,记得正确访问,比如在 Lambda 上用节点的公网 IP 加端口,例如:

http://209.20.xxx.xxx:8000/

聊天界面大致会是这样的效果:

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

Karpathy 提醒道——由于这个 100 美元档模型只有 4e19 FLOPs 能力,聊起来就像在跟幼儿园小朋友对话。它目前还不可能赢得物理或诗歌比赛,但令人惊讶的是,我们用这么少的预算就能训练出这样一个模型,而且这个项目远未完全调优,潜力很大。

强化学习

speedrun 的最后阶段(默认情况下被注释掉)是强化学习(RL)。

通过 RLHF(基于人类反馈的强化学习)可以提升模型性能几个百分点,同时缓解采样循环带来的问题,比如幻觉生成、无限循环等。但对于自己构建的小模型来说,这些问题不是主要考虑因素。

在使用的数据集中,Karpathy 表示,GSM8K是唯一有清晰、客观奖励函数的数据集(即数学题的正确答案)。因此可以直接在答案上进行强化学习,通过一个简单的 RL 循环交替进行采样和训练:

torchrun --standalone --nproc_per_node=8 -m scripts.chat_rltorchrun --standalone --nproc_per_node=8 -m scripts.chat_eval -- -i rl -a GSM8K

在 RL 过程中,模型会遍历训练集中的所有 GSM8K 题目,先生成答案,然后根据奖励评分,再用高奖励的答案进行训练。我们使用了一个高度简化的 GRPO训练循环:

  • 不使用信任域(丢掉参考模型和 KL 正则化)
  • 采用 on-policy(丢掉 PPO 的比例和裁剪机制)
  • 使用 GAPO 风格归一化(按 token 级别,而非序列级别)
  • 奖励优势计算采用简单的均值平移(丢掉 z-score 归一化)

最终的效果看起来更像 REINFORCE,但保留了 GR(group relative)部分来计算奖励优势。对于这种规模和任务,这种方法效果还可以。具体细节可以查看脚本。

当前,默认情况下,RL 被注释掉,因为它还没有完全调优,也没有实现完整通用的 RLHF。Karpathy 表示,其目前只在 GSM8K 上进行 RL,因此评估也只限于 GSM8K(使用 -a 标志)。强化学习训练时间较长,因为监督信号有限,默认设置大约 1.5 小时,效果如下:

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

从图中可以看到:

  • 奖励在上升(模型在学习)
  • pass@1(首次答对率)在提升
  • pass@8(8 次机会内答对率)也在提升
  • pass@8 明显高于 pass@1,说明还有提升空间,可以通过更多 RL 轮次和训练周期进一步优化

强化学习对更大模型的提升更明显。

4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

性能结果

值得注意的是,项目文件夹中会生成 report.md文件,它记录了训练的详细信息,并在末尾提供了一个清晰的总结表格,方便查看各项指标和模型表现。

下面就是 nanochat 在 100 美元成本下的成绩单:

  • 代码字符数——Characters: 333,989
  • 代码行数——Lines: 8,304
  • 工程文件数——Files: 44
  • 代码中的 Token 数——Tokens (approx): 83,497
  • 依赖项——Dependencies (uv.lock lines): 2,004
4小时、成本100美元,Karpathy用8000行代码教你手搓ChatGPT,开源迅速斩获7.1k Star

总花费时间:3 小时 51 分钟。

不过,Karpathy 也提醒道,nanochat 目前还远未完成,还有很多需要调优或优化的地方,但整体框架已经足够清晰,所以现在把它上传到 GitHub,让更多人参与改进和完善。

整体来看,nanochat 不是一项颠覆性的突破,但它非常实用。它将 LLM 训练的门槛降低到了普通人也能达到的水平。你可以亲眼看到,仅用几百美元和几小时就能完成什么。

参考:

https://github.com/karpathy/nanochat

https://x.com/karpathy/status/1977755427569111362

https://github.com/karpathy/nanochat/discussions/1

https://analyticsindiamag.com/ai-news-updates/andrej-karpathy-releases-nanochat-a-minimal-chatgpt-clone/


发表评论

长征号 Copyright © 2013-2024 长征号. All Rights Reserved.  sitemap