# 第 1 课:项目地图与学习路线
## 目录
- [1. 本节目标](#l01-goals)
- [2. 背景概念](#l01-background)
- [3. 源码地图](#l01-source-map)
- [4. 主调用链](#l01-main-chain)
- [5. 当前本地状态](#l01-local-status)
- [6. 最小实验](#l01-experiment)
- [7. 常见坑](#l01-pitfalls)
- [8. 课后任务](#l01-homework)
- [9. 检查题](#l01-check)
- [10. 下一课预告](#l01-next)
## 1. 本节目标
学完本节,你应该能回答:
- MiniMind 这个项目到底包含哪些 LLM 训练阶段。
- 从数据到模型推理的主调用链是什么。
- 哪些文件是后续课程必须反复阅读的核心文件。
- 当前本地仓库还缺什么资源,为什么现在不能直接完整训练或推理。
## 2. 背景概念
MiniMind 是一个小型 LLM 全流程教学项目。它不是只演示调用大模型 API,而是把模型结构、数据集、训练脚本、推理脚本、后训练算法都放在一个相对小的仓库里。
这个项目的主线可以分成五层:
```text
数据层:dataset/*.jsonl
编码层:model/tokenizer.json + chat template
模型层:model/model_minimind.py
训练层:trainer/train_*.py
推理部署层:eval_llm.py + scripts/*.py
```
本课程的学习方式是“源码驱动”:每节课都会围绕一条调用链读源码,然后做一个最小实验。
## 3. 源码地图
本节先建立地图,不深入细节。
| 路径 | 作用 |
|---|---|
| `README.md` | 项目说明、数据下载、训练命令、模型发布信息 |
| `requirements.txt` | 依赖列表 |
| `model/model_minimind.py` | MiniMind 模型结构,后续最核心的源码 |
| `model/model_lora.py` | 手写 LoRA 注入、保存、加载、合并 |
| `model/tokenizer.json` | tokenizer 主文件 |
| `model/tokenizer_config.json` | chat template 和 special tokens 配置 |
| `dataset/lm_dataset.py` | Pretrain/SFT/DPO/RLAIF/Agent 数据集 |
| `trainer/train_pretrain.py` | 预训练入口 |
| `trainer/train_full_sft.py` | 全参数 SFT 入口 |
| `trainer/train_lora.py` | LoRA 训练入口 |
| `trainer/train_dpo.py` | DPO 偏好学习入口 |
| `trainer/train_ppo.py` | PPO 强化学习入口 |
| `trainer/train_grpo.py` | GRPO/CISPO 强化学习入口 |
| `trainer/train_agent.py` | Agentic RL / Tool Use 训练入口 |
| `trainer/trainer_utils.py` | 通用训练工具:lr、seed、checkpoint、模型加载 |
| `eval_llm.py` | CLI 推理入口 |
| `scripts/serve_openai_api.py` | OpenAI 兼容 API 服务 |
| `scripts/web_demo.py` | Streamlit WebUI |
| `scripts/convert_model.py` | PyTorch / Transformers 模型转换 |
## 4. 主调用链
### 4.1 预训练链路
```text
dataset/pretrain_t2t_mini.jsonl
-> PretrainDataset.__getitem__
-> tokenizer(text)
-> input_ids, labels
-> MiniMindForCausalLM.forward(input_ids, labels)
-> cross_entropy loss
-> AdamW
-> out/pretrain_768.pth
```
预训练的本质:普通文本的 next-token prediction。
### 4.2 SFT 链路
```text
dataset/sft_t2t_mini.jsonl
-> SFTDataset.__getitem__
-> tokenizer.apply_chat_template
-> generate_labels
-> input_ids, labels
-> MiniMindForCausalLM.forward(input_ids, labels)
-> 只对 assistant 回复计算 loss
-> out/full_sft_768.pth
```
SFT 的本质:把对话样本转成模型能学习的 next-token prediction,但只训练 assistant 回复部分。
### 4.3 推理链路
```text
用户输入
-> conversation
-> tokenizer.apply_chat_template
-> tokenizer(...)
-> model.generate(...)
-> tokenizer.decode(...)
-> 文本回复
```
推理时没有 labels,也没有 optimizer,只做自回归生成。
## 5. 当前本地状态
这个仓库当前只有源码、tokenizer 和图片资源,尚未下载:
- 训练数据:例如 `pretrain_t2t_mini.jsonl`、`sft_t2t_mini.jsonl`。
- 模型权重:例如 `full_sft_768.pth` 或 transformers 格式的 `minimind-3` 目录。
因此现在直接运行默认训练或推理,大概率会遇到文件不存在:
```text
../dataset/pretrain_t2t_mini.jsonl
../dataset/sft_t2t_mini.jsonl
./out/full_sft_768.pth
./minimind-3
```
课程前期会用 tiny 数据和小模型参数学习流程,避免一开始依赖大数据和大权重。
## 6. 最小实验
本节先做两个只读检查。
### 实验 A:列出核心源码
```bash
cd /home/sun/minimind
find model dataset trainer scripts -maxdepth 1 -type f | sort
```
你应该看到模型、数据集、训练、脚本四类文件。
### 实验 B:确认核心模型能实例化
```bash
cd /home/sun/minimind
PYTHONDONTWRITEBYTECODE=1 python course/labs/check_minimind_import.py
```
如果成功,会打印 torch/transformers/datasets 版本,以及一个 tiny MiniMind 的参数量。
## 7. 常见坑
- README 里的默认命令默认需要数据或权重,源码仓库刚 clone 下来不等于能直接训练/推理。
- `SFT` 容易被写成 `STF`,后续统一用 `SFT`。
- 默认 hidden size 是 768,直接 CPU 训练会很慢;学习阶段用 128 或更小。
- `--use_wandb` 实际导入的是 `swanlab`,当前环境没装时不要打开。
- WebUI 需要 `streamlit`,当前环境未必已安装。
## 8. 课后任务
1. 用自己的话写出 MiniMind 的五层结构:数据层、编码层、模型层、训练层、推理部署层。
2. 解释 pretrain、SFT、推理三条链路中,哪一步开始出现差异。
3. 找到 `train_pretrain.py` 和 `train_full_sft.py` 中 parser 参数的不同点。
## 9. 检查题
这些题只检查你是否建立了项目地图,不要求理解训练细节。
1. MiniMind 项目里,哪个文件负责模型结构?
2. 哪个目录主要放训练脚本?
3. 哪个文件是 CLI 推理入口?
4. 当前本地仓库为什么还不能直接完整训练或推理?
5. pretrain、SFT、推理分别大致对应哪三个入口文件?
后续课程会再回答这些更深入的问题:
- 为什么 SFT 仍然可以使用 causal LM 的 next-token loss?
- 为什么 SFT 需要把 user token 的 label 设成 `-100`?
- `eval_llm.py --load_from ./model` 和 `eval_llm.py --load_from ./minimind-3` 的加载路径有什么区别?
- 如果本地没有 `out/full_sft_768.pth`,默认推理会在哪一步失败?
## 10. 下一课预告
第 2 课会处理环境、依赖、数据目录、权重目录和最小运行检查。目标是明确“哪些命令当前能跑,哪些命令必须先准备资源”。