# Day 4 Deep Dive: SFT 为什么能让模型会聊天
## 深挖问题 1:SFT 训练循环和 pretrain 有什么不同?
打开:
- `trainer/train_pretrain.py`
- `trainer/train_full_sft.py`
你会发现训练循环几乎一样。核心差异:
```text
PretrainDataset -> 所有正文 token 学 next token
SFTDataset -> 只有 assistant span 学 next token
```
这说明:训练算法变化不大,监督信号变了。
## 深挖问题 2:`from_weight=pretrain` 为什么重要?
SFT 默认:
```python
parser.add_argument('--from_weight', default='pretrain')
```
如果从 `none` 开始 SFT,模型只看到问答格式,缺少基础语言建模能力,效果会差很多。
工程理解:
- pretrain 建立语言和世界知识底座。
- SFT 对齐交互格式和回答风格。
- 小数据 SFT 不能替代 pretrain。
## 深挖问题 3:为什么 SFT 学习率低?
默认:
- pretrain:`5e-4`
- SFT:`1e-5`
原因:
- SFT 是在已有模型上微调。
- 学习率太大会破坏 pretrain 已学到的分布。
- SFT 数据更窄,过大学习率容易过拟合风格或格式。
## 深挖问题 4:Tool Call 能力来自哪里?
README 说明当前 `sft_t2t_mini` 已混入 tool call 样本。
数据格式大致是:
```json
{"role": "system", "tools": "..."}
{"role": "user", "content": "..."}
{"role": "assistant", "tool_calls": "..."}
{"role": "tool", "content": "..."}
{"role": "assistant", "content": "..."}
```
模板会展开为:
```text
...
...
```
因此 full_sft 权重已经具备基础 tool call 格式能力。
## 今日实验
对比:
```bash
python eval_llm.py --weight pretrain
python eval_llm.py --weight full_sft
```
固定 prompt:
```text
你是谁?
解释什么是机器学习。
请用 Python 写一个斐波那契函数。
推荐一些中国美食。
```
记录:
- 回答是否像 assistant。
- 是否能按指令组织结构。
- 是否重复或胡编。
- 是否出现模板标签。
## 复盘问题
- 为什么 SFT loss 下降不代表模型事实性更强?
- 如果 SFT 后模型回答变短,可能是什么数据分布导致?
- 如果模型总输出 `` 标签,可能和哪些训练样本有关?