nanochat
是一个全栈式实现类 ChatGPT 大语言模型 (LLM) 的项目。它被整合在一个单一、简洁、极简、易于修改且依赖轻量的代码库中。
nanochat
的设计目标是在单个 8xH100 节点上,通过 speedrun.sh
这样的脚本,端到端地运行整个 LLM 管线。这包括从分词、预训练、微调、评估、推理,到通过一个简单的 Web UI 提供服务,让你能像使用 ChatGPT 一样与自己训练的 LLM 对话。
本项目也将成为 Eureka Labs 正在开发的 LLM101n 课程的毕业项目。
快速上手
体验 nanochat
魅力的最快方式是运行 speedrun.sh
脚本,它将训练并运行一个百元成本级别的模型。在一台每小时 24 美元的 8xH100 节点上,整个过程大约需要 4 小时。
首先,从你常用的云服务商(例如 Lambda)启动一台 8xH100 GPU 服务器,然后运行以下训练脚本:
bash speedrun.sh
由于脚本需要运行 4 小时,推荐在 screen
会话中启动,并将日志输出到文件:
screen -L -Logfile speedrun.log -S speedrun bash speedrun.sh
如果你对 screen
不太熟悉,可以查阅相关教程。启动后,你可以在 screen
会话中观察进度,或使用 Ctrl-a d
分离会话,并通过 tail -f speedrun.log
查看进度。
等待大约 4 小时后,训练完成。现在,你可以通过一个类似 ChatGPT 的 Web UI 与你的 LLM 对话了。首先,请确保你已激活本地的 uv
虚拟环境 (source .venv/bin/activate
),然后启动 Web 服务:
python -m scripts.chat_web
脚本会显示一个 URL。请确保使用节点的公网 IP 和指定端口来访问,例如 ` ChatGPT 聊天一样,与你的模型互动了!你可以让它写故事、写诗,或者问它一些问题,比如“天空为什么是蓝色的?”。
这个百元成本的模型计算能力约为 4e19 FLOPs,与它对话的感觉有点像在和幼儿园的小朋友聊天。
训练完成后,项目目录中会生成一个 report.md
文件,这是本次运行的“成绩单”,包含了各项评估和指标。文件末尾有一个总结表格,示例如下:
指标 | BASE | MID | SFT | RL |
---|---|---|---|---|
CORE | 0.2219 | - | - | - |
ARC-Challenge | - | 0.2875 | 0.2807 | - |
ARC-Easy | - | 0.3561 | 0.3876 | - |
GSM8K | - | 0.0250 | 0.0455 | 0.0758 |
HumanEval | - | 0.0671 | 0.0854 | - |
MMLU | - | 0.3111 | 0.3151 | - |
ChatCORE | - | 0.0730 | 0.0884 | - |
总耗时: | 3h51m | |||
代码统计: | ||||
字符数 | 333,989 | |||
代码行数 | 8,304 | |||
文件数 | 44 | |||
Token 数 (约) | 83,497 | |||
依赖项 (uv.lock) | 2,004 行 |
(你的表格中可能默认不包含 RL 列的数据)
训练更大规模的模型
显然,100 美元不足以训练一个高性能的 ChatGPT 克隆。LLM 因其数百万美元的资本支出而闻名。对于本项目而言,还有两个更值得关注的规模:
- 约 300 美元级别:
d26
模型(即depth=26
),训练约 12 小时,其 CORE 分数略高于 GPT-2。 - 约 1000 美元级别:训练约 41.6 小时,这是一个整数关口。
这两个规模的模型目前尚未在 master
分支完全支持。但作为参考,要训练一个 GPT-2 级别的 d26
模型,你只需对 speedrun.sh
文件做三处修改:
# ...
# 1. 为预训练下载更多数据分片
# 估算方法:参数量 * 20 得到 tokens 数,再 * 4.8 得到字符数,
# 最后除以 2.5 亿(每个分片的字符数)得到分片数量。
python -m nanochat.dataset -n 450 &
# ...
# 2. 使用 --depth 增加模型大小。为防止显存溢出(OOM),将 device_batch_size 减半
torchrun --standalone --nproc_per_node=8 -m scripts.base_train \
-- --depth=26 --device_batch_size=16
# ...
# 3. 确保在后续的 mid_train 阶段使用相同的参数
torchrun --standalone --nproc_per_node=8 -m scripts.mid_train \
-- --device_batch_size=16
就是这么简单!最需要关注的是确保有足够的数据分片进行训练(否则代码会在同一训练集上重复多个 epoch,降低学习效率),以及管理你的显存(VRAM)。主要通过降低 device_batch_size
来适配显存,脚本会自动增加梯度累积的次数来补偿,这本质上是将并行计算转为串行计算。
关于计算环境
- Ampere A100:代码可以在 8x A100 GPU 节点上正常运行,但速度会稍慢。
- 单 GPU:省略
torchrun
启动器,代码可以在单 GPU 上运行,并产生几乎相同的结果(代码会自动切换到梯度累积模式),但你需要等待 8 倍的时间。 - 小显存 GPU:如果你的 GPU 显存小于 80GB,你需要调整一些超参数,否则会遇到显存溢出(OOM)。在脚本中找到
--device_batch_size
参数,并逐步减小它(例如从默认的 32 降到 16、8、4、2 甚至 1),直到程序能正常运行。 - 其他平台:大部分代码是标准的 PyTorch,理论上可以在支持 PyTorch 的任何设备上运行(如 xpu、mps 等),但这部分未经开箱即用的实现,可能需要一些调试工作。
项目理念与测试
nanochat
的设计理念是短小精悍。这带来一个巨大的优势:我们可以将所有文件打包,然后粘贴到你最喜欢的 LLM 中,向它提问关于本项目的任意问题。
例如,可以使用 files-to-prompt
工具打包仓库:
files-to-prompt . -e py -e md -e rs -e html -e toml -e sh \
--ignore " *target* " --cxml > packaged.txt
这个命令会打包所有指定后缀的文件,并排除 rustbpe/target
文件夹,输出为 packaged.txt
。目前该文件约 330KB(远低于 SOTA 模型约 10 万 token 的上下文限制),包含 45 个文件中的约 8000 行代码。
测试
虽然测试不是本项目的重点,但我们仍然提供了一些测试用例,特别是针对分词器。运行方式如下:
python -m pytest tests/test_rustbpe.py -v -s
贡献
nanochat
远未完成。我们的目标是提升微型模型(成本低于 1000 美元)的 SOTA 水平。这种可及性不仅关乎总成本,也关乎认知复杂性。nanochat
不是一个配置详尽的 LLM “框架”;代码库中不会有庞大的配置对象、模型工厂或复杂的 if-then-else
逻辑。它是一个单一、内聚、极简、可读、易于修改和 fork 的“强基线”代码库,旨在端到端地运行并产出一个具体的 ChatGPT 克隆及其成绩单。
致谢与引用
- 项目名称
nanochat
源自作者早期的项目nanoGPT
,后者只覆盖了预训练部分。 nanochat
的灵感也来自modded-nanoGPT
,它通过明确的指标和排行榜将nanoGPT
游戏化,本项目借鉴了其许多想法和部分预训练实现。- 感谢 HuggingFace 提供的
fineweb
和smoltalk
数据集。 - 感谢 Lambda 为本项目开发提供的计算资源。
- 感谢首席 LLM 调教大师 Alec Radford 的建议和指导。
引用
如果你在研究中发现 nanochat
有用,请按以下格式引用:
@misc{nanochat,
author = {Andrej Karpathy},
title = {nanochat: The best ChatGPT that $100 can buy},
year = {2025},
publisher = {GitHub},
url = {https://github.com/karpathy/nanochat}
}
许可证
本项目采用 MIT 许可证。
👉 如果你需要 ChatGPT 代充 / Claude / Claude Code / 镜像 / 中转 API:
- 购买 / 了解更多:ai4.plus
- 备用入口:kk4099.com