nanochat:仅需73美元,3小时训练GPT-2级别大语言模型
BLUF 摘要
用73美元真的能训练出ChatGPT级别的模型吗?实测发现,借助nanochat框架,在8XH100 GPU节点上训练3小时,成本仅需约73美元,即可获得性能超越GPT-2(1.6B)的模型。该框架覆盖分词、预训练、微调、评估、推理及聊天界面全流程,代码极简且支持单GPU节点运行。最终模型可通过类似ChatGPT的网页界面直接对话,大幅降低了LLM训练门槛。
概述
nanochat 是用于训练大型语言模型(LLM)的最简实验框架。它设计为在单 GPU 节点上运行,代码极简且易于修改,涵盖了 LLM 的所有主要阶段,包括分词、预训练、微调、评估、推理以及聊天界面。例如,你可以仅用 73 美元(在 8XH100 GPU 节点上训练 3 小时)训练出具备 GPT-2 能力的 LLM(该模型在 2019 年的训练成本约为 5 万美元),然后在一个类似 ChatGPT 的熟悉网页界面中与它对话。
关于代码库的问题,建议使用 Devin/Cognition 的 DeepWiki 提问,或使用 Discussions 标签页,或访问 Discord 上的 #nanochat 频道。
最新动态
- (2026年1月31日) 正在进行所有脚本/README 的重大修订,删除了中期训练阶段,短期内可能有些混乱...
- (2026年1月30日) 得益于所有最新的改进,我们现在能够以约 73 美元的成本训练出 GPT-2 级别的 LLM。
runs/speedrun.sh脚本将成为训练 GPT-2 级别模型并与之对话的参考方式。
排行榜
我们关注的主要指标是“达到 GPT-2 水平的时间”——即在 8XH100 GPU 节点上,模型性能超越 GPT-2(1.6B)CORE 指标所需的实际用时。2019 年,GPT-2 的训练成本约为 5 万美元。令人惊叹的是,经过 7 年来整个技术栈的诸多进步,我们现在可以在 3 小时或更短时间内,以约 73 美元或更低的成本完成这一目标。
| # | 记录时间 | 描述 | 日期 | 提交 | 贡献者 |
|---|---|---|---|---|---|
| 1 | 3.04 小时 | d24 基线,略微过拟合 | 2026年1月29日 | 348fbb3 | @karpathy |
设置好代码库后(参考 runs/speedrun.sh 脚本),启动训练的方式如下(例如我启动 jan29 运行的方式):
OMP_NUM_THREADS=1 torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- \
--depth=24 \
--run=d24-jan29 \
--model-tag=d24_jan29 \
--device-batch-size=16 \
--sample-every=-1 \
--save-every=-1 \
--core-metric-max-per-task=-1 \
--core-metric-every=3000 \
--target-param-data-ratio=12
经过 3 小时,我们得到如下输出:
...
wandb: Run summary:
wandb: core_metric 0.25851
wandb: step 16704
wandb: total_training_flops 4.330784131228946e+19
wandb: total_training_time 10949.46713
GPT-2 的 CORE 分数(即需要超越的目标)是 0.256525。我们看到这个 d24 模型的 CORE 分数更高(0.25851)。然后我们查看 total_training_time,这是纯训练迭代的时间(不包括评估和日志记录),单位为秒。我们得到:10949/60/60 ≈ 3.04 小时,这是当前的记录。
快速开始
复现并与 GPT-2 对话
最有意思的事情就是训练你自己的 GPT-2 并与之对话。完成这一过程的完整流程都包含在单个文件 runs/speedrun.sh 中,该脚本设计在 8XH100 GPU 节点上运行。目前,这类节点的价格约为每小时 24 美元,预训练一个 GPT-2 级别的模型大约需要 3 小时,花费约 75 美元。
从你喜欢的提供商(例如我使用并推荐 Lambda)启动一个新的 8XH100 GPU 实例,然后运行训练脚本:
bash runs/speedrun.sh
建议在 screen 会话中运行,因为这大约需要 3 小时。完成后,你可以通过类似 ChatGPT 的网页界面与模型对话。请确保你的本地 uv 虚拟环境已激活(运行 source .venv/bin/activate),然后启动服务:
python -m scripts.chat_web
然后访问显示的 URL。请确保正确访问,例如在 Lambda 上使用你所在节点的公网 IP 地址,后跟端口号,例如 http://209.20.xxx.xxx:8000/。之后,你就可以像平时与 ChatGPT 对话一样与你的 LLM 交流了!让它写故事或诗歌。问它你是谁,看看它的幻觉。问它天空为什么是蓝色的。或者为什么是绿色的。这个快速训练模型是一个 4e19 FLOPs 能力的模型,所以有点像在和幼儿园小朋友聊天 :)
更多注意事项
- 代码在 Ampere 8XA100 GPU 节点上也能正常运行,只是速度稍慢。
- 所有代码在单个 GPU 上也能正常运行(省略
torchrun),并产生几乎相同的结果(代码会自动切换到梯度累积模式),但你需要等待大约 8 倍的时间。 - 如果你的 GPU 显存小于 80GB,你需要调整一些超参数,否则会出现 OOM / 显存不足。在脚本中查找
--device_batch_size并减小它,直到能够运行。例如,从 32(默认值)减小到 16、8、4、2,甚至 1。如果小于 1,你需要更了解自己在做什么并发挥更多创意。 - 大部分代码是相当标准的 PyTorch,因此应该能在任何支持 PyTorch 的环境上运行——xpu、mps 等,但我个人没有测试所有这些代码路径,所以可能存在一些潜在问题。
研究
如果你是研究人员,并希望帮助改进 nanochat,有两个脚本值得关注:runs/scaling_laws.sh 和 runs/miniseries.sh。相关文档请参见 Jan 7 miniseries v1。对于快速实验(约 5 分钟的预训练运行),我最喜欢的规模是训练一个 12 层的模型(GPT-1 大小),例如:
OMP_NUM_THREADS=1 torchrun --standalone --nproc_per_node=8 -m scripts.base_train -- \
--depth=12 \
--run="d12" \
--model-tag="d12" \
--core-metric-every=999999 \
--sample-every=-1 \
--save-every=-1 \
这使用了 wandb(运行名称为 "d12"),仅在最后一步运行 CORE 指标评估,并且不会采样和保存中间检查点。我喜欢在代码中修改一些内容,重新运行一个 d12(或 d16 等)模型,并在迭代循环中查看是否有所帮助。
整体方法是将模型的深度作为唯一的复杂度调节旋钮。通过改变深度,我们得到能力逐渐增强的模型。我们确定缩放定律,将数据预算设置为计算最优设置,训练一系列规模递增的模型,并将它们与 GPT-2 和 GPT-3 的系列模型进行比较。目前,更快地超越 GPT-2 是最有趣的目标。
在 CPU / MPS 上运行
runs/runcpu.sh 脚本展示了一个在 CPU 或 Apple Silicon 上运行的非常简单示例。它会大幅缩小正在训练的 LLM 规模,以便在几十分钟的合理训练时间内完成。通过这种方式你不会得到强大的结果。
指南
我发布了一些可能包含有用信息的指南:
- 2025年10月13日 最初的 nanochat 介绍文章,不过现在包含了一些过时的信息,并且模型比当前主分支的模型旧得多(结果也更差)。
- Jan 7 miniseries v1 记录了第一个 nanochat 模型系列。
- 要自定义你的 nanochat,请参阅 Discussions 中的 指南:为你的 nanochat 注入身份,其中描述了如何通过合成数据生成并将该数据混合到 SFT 阶段来调整 nanochat 的个性。
- 要为 nanochat 添加新能力,请参阅 指南:计算草莓中的字母 r(以及如何添加能力的一般方法)。
文件结构
.
├── LICENSE
├── README.md
├── dev
│ ├── gen_synthetic_data.py # 用于身份注入的示例合成数据
│ ├── generate_logo.html
│ ├── nanochat.png
│ └── repackage_data_reference.py # 预训练数据分片生成
├── nanochat
│ ├── __init__.py # 空文件
│ ├── checkpoint_manager.py # 保存/加载模型检查点
│ ├── common.py # 杂项小工具,提升生活质量
│ ├── core_eval.py # 评估基础模型 CORE 分数(DCLM 论文)
│ ├── dataloader.py # 分词分布式数据加载器
│ ├── dataset.py # 预训练数据的下载/读取工具
│ ├── engine.py # 使用 KV 缓存的高效模型推理
│ ├── execution.py # 允许 LLM 将 Python 代码作为工具执行
│ ├── gpt.py # GPT nn.Module Transformer
│ ├── logo.svg
│ ├── loss_eval.py # 评估每字节比特数(替代损失)
│ ├── optim.py # AdamW + Muon 优化器,支持单 GPU 和分布式
│ ├── report.py # 编写 nanochat 报告的工具
│ ├── tokenizer.py # BPE 分词器包装器,风格类似 GPT-4
│ └── ui.html # nanochat 前端的 HTML/CSS/JS
├── pyproject.toml
├── runs
│ ├── miniseries.sh # 模型系列训练脚本
│ ├── runcpu.sh # 如何在 CPU/MPS 上运行的小示例
│ ├── scaling_laws.sh # 缩放定律实验
│ └── speedrun.sh # 训练约 100 美元的 nanochat d20 模型
├── scripts
│ ├── base_eval.py # 基础模型:CORE 分数,每字节比特数,采样
│ ├── base_train.py # 基础模型:训练
│ ├── chat_cli.py # 聊天模型:通过 CLI 对话
│ ├── chat_eval.py # 聊天模型:评估任务
│ ├── chat_rl.py # 聊天模型:强化学习
│ ├── chat_sft.py # 聊天模型:训练 SFT
│ ├── chat_web.py # 聊天模型:通过 WebUI 对话
│ ├── tok_eval.py # 分词器:评估压缩率
│ └── tok_train.py # 分词器:训练分词器
├── tasks
│ ├── arc.py # 多项选择科学问题
│ ├── common.py # TaskMixture | TaskSequence
│ ├── customjson.py # 从任意 jsonl 对话创建任务
│ ├── gsm8k.py # 8K 小学数学问题
│ ├── humaneval.py # 误称;简单的 Python 编码任务
│ ├── mml
版权与免责声明:本文仅用于信息分享与交流,不构成任何形式的法律、投资、医疗或其他专业建议,也不构成对任何结果的承诺或保证。
文中提及的商标、品牌、Logo、产品名称及相关图片/素材,其权利归各自合法权利人所有。本站内容仅供参考,请以官方信息为准。
若本文内容或素材涉嫌侵权、隐私不当或存在错误,请相关权利人/当事人联系本站,我们将及时核实并采取删除、修正或下架等处理措施。 也请勿在评论或联系信息中提交身份证号、手机号、住址等个人敏感信息。



