Math RL¶
Math RL 用一个确定性 verifier 给算术或代数题打分。给定标准答案,verifier 从 model 输出里提取预测答案,返回 1.0(对)或 0.0(错)。这个简单的 reward 信号在结构化任务上特别有效。
参考实现是 demos/rl/adapters/verifiable_math.py,用精确匹配评分解决加法题。
Configuration¶
用标准 GRPO 循环搭 Math RL:
from mint import types
service_client = mint.ServiceClient()
training_client = service_client.create_lora_training_client(
base_model="Qwen/Qwen3-0.6B",
rank=16,
train_mlp=True,
train_attn=True,
train_unembed=True,
)
tokenizer = training_client.get_tokenizer()
adam_params = types.AdamParams(learning_rate=2e-5)
然后从 verifiable_math.py 跑 adapter:
from demos.rl.adapters.verifiable_math import VerifiableMathAdapter
from demos.rl.rl_core import RLConfig, run_grpo
cfg = RLConfig(
model="Qwen/Qwen3-0.6B",
rank=16,
steps=10,
batch=8,
group=4,
lr=2e-5,
max_tokens=16,
temperature=0.8,
)
run_grpo(VerifiableMathAdapter(), cfg)
Prompting Guide¶
数学题用 few-shot 示例 + 题目本身渲染出来:
class VerifiableMathAdapter(RLAdapter):
FEWSHOT = "Q: What is 4 + 5?\nA: 9\n\n"
def make_prompt(self, sample: tuple[str, int], tokenizer) -> list[int]:
question, _ = sample
return tokenizer.encode(self.FEWSHOT + question)
对于一题 (question="What is 3 + 7?", answer=10),encode 后的 prompt 是:
Model 然后生成 response。Verifier 提取数字答案,和标准答案比较。
关键模式: 题目本身和 few-shot 前缀都属于 prompt(训练时 loss weight 为 0)。只有 answer token 拿到 loss weight 和 advantage 缩放。
Output Format¶
Verifier 从 response 里提第一个整数:
def compute_reward(self, response: str, sample: tuple[str, int]) -> float:
_, answer = sample
match = re.search(r"-?\d+", response)
return 1.0 if match and int(match.group()) == answer else 0.0
- reward = 1.0: 提取的答案与标准答案一致。
- reward = 0.0: 提不出数字,或答案不一致。
来自同一 prompt 的 group_size 个样本组成一个 group,advantage 用中心化算:adv[i] = reward[i] - mean_reward_in_group。这会把 policy 推向高 reward 样本,压低低 reward 样本。
可选的部分 credit(参考脚本里没做,但更难的数据集上值得考虑):response 含有正确格式(比如有数字,哪怕错的)但不是确切答案,给 0.5。
All Parameters¶
| 参数 | 类型 | 默认值 | 含义 |
|---|---|---|---|
steps |
int | 5 |
训练 step(采样 + 训练)。 |
batch |
int | 8 |
每 step 题目数。 |
group |
int | 4 |
每题样本数(group_size)。 |
learning_rate |
float | 2e-5 |
Adam 学习率。Math RL 取 1e-5 到 4e-5。 |
max_tokens |
int | 16 |
最大生成长度。Math:8–32(答案短)。 |
temperature |
float | 0.8 |
采样温度。越高越多样。典型值 0.7–1.0。 |
base_model |
str | "Qwen/Qwen3-0.6B" |
base model。 |
rank |
int | 16 |
LoRA rank。 |
train_mlp |
bool | True |
训练 MLP。 |
train_attn |
bool | True |
训练 attention。 |
train_unembed |
bool | True |
训练输出层。 |
环境变量(来自 rl_core.py):
export MINT_BASE_MODEL="Qwen/Qwen3-0.6B"
export MINT_LORA_RANK=16
export MINT_RL_STEPS=10
export MINT_RL_BATCH=8
export MINT_RL_GROUP=4
export MINT_RL_LR=2e-5
export MINT_RL_MAX_TOKENS=16
export MINT_RL_TEMPERATURE=0.8
用法:
Note
扩展到其它数学领域: 把 VerifiableMathAdapter 换成你自己的 RLAdapter,实现 build_dataset()、make_prompt()、compute_reward()。GSM8K 这类应用题,把 max_tokens 提到 256 给 chain-of-thought 推理留余地。