nanochat-中文翻译版本(含代码注释和文档翻译,方便中文语境快速阅读和查看)
感谢原作者:Andrej karpathy
这个仓库是一个完整的类 ChatGPT 大语言模型(LLM)的全栈实现,采用单一、简洁、最小化、可定制、依赖轻量的代码库。nanochat 设计为通过像speedrun.sh这样的脚本在单个 8XH100 节点上运行,从开始到结束运行整个流程。这包括分词、预训练、微调、评估、推理以及通过简单 UI 提供 Web 服务,让你可以像使用 ChatGPT 一样与你自己的 LLM 对话。nanochat 将成为 Eureka Labs 正在开发的 LLM101n 课程的顶点项目。
文件结构说明
nanochat 项目的主要文件及其用途:
核心模块 (nanochat/)
- nanochat/gpt.py - GPT 模型架构实现,包含 Transformer 层、注意力机制等
- nanochat/adamw.py - AdamW 优化器实现
- nanochat/muon.py - Muon 优化器实现,用于线性层训练
- nanochat/checkpoint_manager.py - 模型检查点保存和加载管理
- nanochat/common.py - 通用工具函数,包括分布式训练初始化
- nanochat/configurator.py - 配置参数管理,支持命令行覆盖
- nanochat/core_eval.py - 核心评估指标计算
- nanochat/dataloader.py - 数据加载器实现,支持分布式训练
- nanochat/dataset.py - 数据集处理和下载
- nanochat/engine.py - 模型推理引擎,支持批量生成
- nanochat/execution.py - 执行上下文管理
- nanochat/loss_eval.py - 损失评估函数
- nanochat/report.py - 训练报告生成
- nanochat/tokenizer.py - 分词器接口和实现
- nanochat/ui.html - Web 聊天界面
训练脚本 (scripts/)
- scripts/base_train.py - 基础模型预训练脚本
- scripts/mid_train.py - 中期训练脚本,在预训练基础上继续训练
- scripts/chat_sft.py - 监督微调训练脚本
- scripts/chat_rl.py - 强化学习训练脚本
- scripts/tok_train.py - 分词器训练脚本
- scripts/base_eval.py - 基础模型评估脚本
- scripts/base_loss.py - 基础损失评估脚本
- scripts/chat_eval.py - 聊天模型评估脚本
- scripts/tok_eval.py - 分词器评估脚本
- scripts/chat_cli.py - 命令行聊天界面
- scripts/chat_web.py - Web 聊天服务器
任务模块 (tasks/)
- tasks/common.py - 任务混合和数据加载
- tasks/arc.py - ARC 问答任务实现
- tasks/gsm8k.py - GSM8K 数学推理任务实现
- tasks/humaneval.py - HumanEval 代码生成任务实现
- tasks/mmlu.py - MMLU 多任务语言理解任务实现
- tasks/smoltalk.py - SmolTalk 对话数据集处理
分词器 (rustbpe/)
- rustbpe/src/lib.rs - Rust 实现的 BPE 分词器核心逻辑
- rustbpe/Cargo.toml - Rust 项目配置
- rustbpe/README.md - 分词器文档
开发工具 (dev/)
- dev/generate_logo.html - 项目 logo 生成工具
- dev/nanochat.png - 项目 logo 图片
- dev/repackage_data_reference.py - 数据重新打包参考脚本
运行脚本
- speedrun.sh - 快速运行脚本(约 4 小时训练)
- run1000.sh - 1000 美元级别训练脚本
- uv.lock - Python 依赖锁定文件
- pyproject.toml - Python 项目配置
与它对话
为了了解这个仓库的最终目标,你目前可以在nanochat.karpathy.ai上找到托管的nanochat d32。”d32”表示这个模型在 Transformer 神经网络中有 32 层。这个模型有 19 亿参数,通过简单地运行单个脚本run1000.sh在 380 亿 token 上训练,总训练成本约为 800 美元(在 8XH100 GPU 节点上约 33 小时训练时间)。虽然今天这足以超越 2019 年的 GPT-2,但它与现代大语言模型如 GPT-5 相比仍有巨大差距。与这些微型模型对话时,你会看到它们犯很多错误,有点天真和愚蠢,会产生大量幻觉,有点像孩子。这有点有趣。但 nanochat 的独特之处在于它完全属于你 - 完全可配置、可调整、可定制,并由你从头到尾训练。要训练并与你自己的模型对话,我们转向…
快速开始
感受魔力的最快方式是运行 speedrun 脚本speedrun.sh,它训练并推理 100 美元级别的 nanochat。在 8XH100 节点上每小时 24 美元,总运行时间约为 4 小时。从你喜欢的提供商启动一个新的 8XH100 GPU 盒子(例如我使用并喜欢Lambda),然后启动训练脚本:
1 | bash speedrun.sh |
或者,由于脚本运行 4 小时,我喜欢在一个新的 screen 会话speedrun中这样启动(并将输出记录到speedrun.log):
1 | screen -L -Logfile speedrun.log -S speedrun bash speedrun.sh |
如果你不太熟悉,请查看screen 速查表。你可以在 screen 会话中观看进度,或者用Ctrl-a d分离并用tail speedrun.log查看进度。现在等待 4 小时。完成后,你可以通过类似 ChatGPT 的 Web UI 与你的 LLM 对话。确保你的本地 uv 虚拟环境已激活(运行source .venv/bin/activate),然后启动服务:
1 | python -m scripts.chat_web |
然后访问显示的 URL。确保正确访问,例如在 Lambda 上使用你所在节点的公共 IP,后跟端口,例如http://209.20.xxx.xxx:8000/等。然后像通常与 ChatGPT 对话一样与你的 LLM 对话!让它写故事或诗歌。问它你是谁以看到幻觉。问它为什么天空是蓝色的。或者为什么是绿色的。speedrun 是一个 4e19 FLOPs 能力的模型,所以有点像与幼儿园小朋友对话:)。
你也可以cat report.md文件,它出现在项目目录中,包含运行的”成绩单”,即一堆评估和指标。在最后,你会看到一个汇总表格,例如:
- 字符数: 333,989
- 行数: 8,304
- 文件数: 44
- Token 数(约): 83,497
- 依赖项(uv.lock 行数): 2,004
| 指标 | 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
(你的表格可能默认缺少 RL 数字)。关于 speedrun 脚本以及要寻找和期望的更多信息,请参考我在仓库讨论区发布的演练:“介绍 nanochat:100 美元能买到的最好的 ChatGPT”。
更大的模型
不出所料,100 美元不足以训练一个高性能的 ChatGPT 克隆。事实上,LLM 以其数百万美元的资本支出而闻名。对于我们的目的,我认为还有两个更有趣的规模。首先是约 300 美元的 d26 模型(即深度=26),训练约 12 小时,略微超越 GPT-2 CORE 分数。其次是 1000 美元级别(约 41.6 小时),只是因为这是一个不错的整数。但这两者尚未完全支持,因此尚未附加到主分支中。
也就是说,为了给出一个概念,训练 GPT-2 级别模型 d26 所需的speedrun.sh文件示例更改仅涉及三个更改:
1 | ... |
就是这样!最需要注意的事情是确保你有足够的数据分片进行训练(否则代码将循环并在相同的训练集上做更多轮次,稍微降低学习速度),以及管理你的内存/VRAM,主要通过减少device_batch_size直到适合(脚本通过增加梯度累积循环次数自动补偿,简单地将并行计算转换为顺序计算)。
关于运行 nanochat 的计算环境的更多信息:
- 代码在 Ampere 8XA100 GPU 节点上也能正常运行,但会慢一些。
- 所有代码甚至可以在单个 GPU 上通过省略
torchrun正常运行,并产生几乎相同的结果(代码将自动切换到梯度累积),但你必须等待 8 倍时间。 - 如果你的 GPU(s)少于 80GB,你必须调整一些超参数,否则会出现 OOM / VRAM 不足。在脚本中查找
--device_batch_size并减少它直到适合。例如从 32(默认)到 16、8、4、2,甚至 1。少于这个你需要更了解你在做什么并更有创意。 - 大部分代码是相当标准的 PyTorch,所以它应该在任何支持 PyTorch 的环境中运行 - xpu、mps 等,但我没有开箱即用地实现这个,所以可能需要一些调整。
在 CPU / MPS 上运行
如果你想在 Macbook 或 CPU 机器上调整 nanochat,这里有一个进行中的CPU|MPS PR。如果你在 Macbook 上,在运行base_train.py时使用--device_type=mps。有关更多信息,请参阅 PR 及其差异。没有 GPU 节点你不会走得太远,但至少你将能够运行代码,并可能通过一些耐心训练一个非常小的 LLM。
问题
nanochat 设计为简短而甜美。这样做的一个大优势是我们可以将所有文件打包在一起,并复制粘贴到你喜欢的 LLM 中询问任意问题。例如,我喜欢使用files-to-prompt实用程序像这样打包仓库:
1 | files-to-prompt . -e py -e md -e rs -e html -e toml -e sh --ignore "*target*" --cxml > packaged.txt |
这包括所有 py、rs、html、toml、sh 文件,排除rustbpe/target文件夹,并选择 cxml 输出格式。所有内容都写入packaged.txt文件,目前测量约 330KB(即远低于最先进 LLM 的约 10 万 token),以及约 8K 行代码在 45 个文件中。
或者,我推荐使用DeepWiki来自 Devin/Cognition 来询问这个仓库的问题。在这个仓库的 URL 中,只需将 github.com 更改为 deepwiki.com,你就可以开始了。
测试
我在这里投入不多,但存在一些测试,特别是对于分词器。运行例如:
1 | python -m pytest tests/test_rustbpe.py -v -s |
贡献
nanochat 远未完成。目标是改进在<1000 美元预算下可端到端工作的微型模型的最新技术水平。可访问性是关于总体成本,也是关于认知复杂性 - nanochat 不是一个详尽可配置的 LLM”框架”;代码库中不会有巨大的配置对象、模型工厂或 if-then-else 怪物。它是一个单一、连贯、最小化、可读、可定制、最大可复制的”强基线”代码库,设计为从头到尾运行并产生具体的 ChatGPT 克隆及其成绩单。
致谢
- 名称(nanochat)源自我的早期项目nanoGPT,它只涵盖预训练。
- nanochat 也受到modded-nanoGPT的启发,它通过清晰的指标和排行榜将 nanoGPT 仓库游戏化,并借用了它的许多想法和一些预训练实现。
- 感谢HuggingFace提供 fineweb 和 smoltalk。
- 感谢Lambda提供用于开发此项目的计算资源。
- 感谢首席 LLM 专家🧙♂️ Alec Radford 的建议/指导。
引用
如果你发现 nanochat 对你的研究有帮助,请引用为:
1 | @misc{nanochat, |
许可证
MIT
nanochat-中文翻译版本(含代码注释和文档翻译,方便中文语境快速阅读和查看)


