think/answer标签格式:为推理式RL做准备的train-llm-from-scratch技巧
【免费下载链接】train-llm-from-scratchA straightforward method for training your LLM, from downloading data to generating text.项目地址: https://gitcode.com/GitHub_Trending/tr/train-llm-from-scratch
在从零训练大语言模型的开源项目train-llm-from-scratch中,think/answer标签格式是打通 SFT 监督微调与 PPO、GRPO 等推理式 RL 的关键桥梁:模型先用think标签写出推理过程,再用answer标签给出最终答案,奖励函数才能稳定地验证对错。本文将带你理解这套输出格式如何定义、如何教给模型、又如何被奖励系统解析验证,是准备推理式 RL 训练前值得收藏的技巧清单。
一、为什么推理式RL需要固定的think/answer标签格式
推理式强化学习(如 GRPO / RLVR)的核心是"可验证奖励":模型回答一道 GSM8K 数学题后,程序必须能确定性地从回答里取出最终数字并与标准答案比对。如果模型把答案散落在任意位置,解析器就会失灵,奖励信号变成噪声。
因此 train-llm-from-scratch 给模型约定了一个统一的输出结构:
think标签包裹分步推理 →answer标签包裹最终数字答案
这个格式同时服务于三个阶段:
- SFT 阶段:把 GSM8K 数据重排成该格式,让模型"学会"这个结构
- RL 阶段:verifier 奖励函数优先从
answer标签取数,格式良好额外给小额加分 - 评测阶段:GSM8K 准确率统计复用同一套解析逻辑
二、格式定义的唯一"事实来源":chat_template
格式字符串集中定义在 src/post_training/chat_template.py:
THINK_OPEN, THINK_CLOSE = "think", "think" ANSWER_OPEN, ANSWER_CLOSE = "<answer>", "</answer>"两个设计细节很巧妙:
- 标签就是普通 token:项目使用的 r50k_base 分词器只有
eot一个特殊 token,无法注册新特殊符,所以think、answer等标记按普通文本处理,模型在 SFT 中像学任何其他文本一样学会它们(见 src/post_training/chat_template.py 的模块说明)。 - 单一来源:数据生成脚本与奖励解析器 import 同一组常量,训练侧教的格式与 RL 侧验证的格式永远一致,杜绝"训练一套、验证一套"的坑。
三、SFT 阶段:让模型先"学会"这个格式
scripts/prepare_sft_data.py 中的gsm8k_to_messages把 GSM8K 的原始(question, answer)拆成两部分:去掉#### N尾部后,推理过程放进think标签、最终数字放进answer标签,拼成一条标准的 assistant 回复。
配合 Alpaca、Dolly 等指令数据一起打包成固定长度行(tokens + loss_mask),loss 只算 assistant 部分。训练完成后,模型不仅会跟随指令,还会稳定地输出think...answer结构——这正是后续 RL 验证器所期望的输入。详细说明见 docs/03_sft.md。
四、奖励解析:三级回退的容错设计
RL 中的小模型输出并不稳定,可能漏写标签或写乱格式。src/post_training/rewards/parsing.py 的extract_answer按优先级三级回退取答案:
- 首选
answer标签内的内容(正则匹配标签对) - 次选GSM8K 风格的
#### N - 兜底取全文最后一个数字
think标签内容也可通过 extract_think 单独提取,可用于分析模型的推理链。
五、奖励函数:正确性主导 + 小额格式加分
src/post_training/rewards/verifiers.py 的奖励设计刻意"正确性主导":
| 条件 | 奖励 |
|---|---|
| 解析出的答案与标准答案一致 | +1.0 |
恰好存在一个格式良好的answer块 | +0.2 |
| 上限 | 1.2 |
格式加分故意只给 0.2 并且有界:如果格式分给得太大,小模型会"钻空子"——输出空的answer标签或复读 token 来刷分(reward hacking)。这一思路让 RL 信号始终以答对题目为主,格式规范作为温和的塑形力量。
六、快速上手:两条命令走通格式链路
准备数据后即可分别跑 SFT 与 GRPO(详见 POST_TRAINING.md 的完整命令与环境配置):
# 1) SFT:学会 think/answer 输出格式 PYTHONPATH=. python scripts/prepare_sft_data.py --context_length 1024 PYTHONPATH=. python scripts/train_sft.py # 2) GRPO:用 verifier 奖励做推理式RL PYTHONPATH=. python scripts/prepare_rl_prompts.py PYTHONPATH=. python scripts/train_grpo.py --group_size 8GRPO 阶段每个 prompt 采样一组回答,用上面的reward_gsm8k打分,以组内均值/标准差算优势(无 critic),完整推导见 docs/07_grpo.md。训练曲线可参考项目中记录的 loss 曲线示例:
七、清单:为自己的推理式RL准备think/answer格式
- ✅单一常量源:标签字符串只在一处定义,SFT 数据生成与 RL 验证器共用(参考 src/post_training/chat_template.py)
- ✅SFT 先行:把推理类数据(如 GSM8K)重排成
think+answer结构,让格式进入模型先验 - ✅容错解析:验证器至少准备两级回退(标签 → 文末数字),别对格式假设过强
- ✅奖励塑形有界:格式加分小而封顶,正确性才是主要奖励
- ✅评测同源:训练、RL、评测三处使用同一套解析函数,指标口径一致
掌握这套think/answer技巧后,你的推理式 RL 训练就有了稳定可靠的奖励地基——格式是桥梁,答案才是目的。
【免费下载链接】train-llm-from-scratchA straightforward method for training your LLM, from downloading data to generating text.项目地址: https://gitcode.com/GitHub_Trending/tr/train-llm-from-scratch
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考