先构造 labels:只让 response 与有效位置参与学习
🎯 先猜一猜
prompt 长 3、response 长 4、max_len=8。
labels 的最后一个位置应该填什么?
先补的知识
- input_ids 是 prompt_ids + response_ids;它包含模型需要看到的完整上下文。
- labels 与 input_ids 长度相同,但 prompt 位置写 -100,response 位置保留真实 token id。
- nn.CrossEntropyLoss(ignore_index=-100) 会跳过标签为 -100 的位置,因此 prompt 与 padding 都不会贡献 loss。
- 截断时 input_ids 与 labels 必须切同一范围;填充时 input_ids 填 pad_id,而 labels 填 -100。最终两者固定为 max_len 个 long 元素。
图解原理
输入像一张完整试卷:题目和标准答案都要给模型看;labels 像评分模板:题目区域打上“不计分”,只给答案区域评分。Padding 只是把纸张补到统一长度,也必须标成不计分。
同一序列,两种职责
input_ids[prompt tokens, response tokens, pad tokens]
labels[-100..., response tokens, -100...]
模型可见prompt、response、padding 都在输入中
参与评分只有 labels 中非 -100 的 response token
Notebook 样例
拼接 input_ids保持 prompt 在前、response 在后构造同长度 labelsprompt 用 -100,response 保留 id若超长:两者一起 [:max_len]不能只截输入或只截标签若不足:计算 pad_len输入补 pad_id,标签补 -100转 torch.longtoken id 与类别标签都要求整数类型[:max_len]:保留序列前 max_len 个位置、丢弃末尾超出的部分。页面与测试按这一当前实现合同对齐。语法热身:给问答卡制作固定长度评分模板
question = [7, 8]
answer = [21, 22, 23]
limit = 7
tokens = question + answer
score_labels = [-100] * len(question) + answer
if len(tokens) > limit:
tokens = tokens[:limit]
score_labels = score_labels[:limit]
else:
missing = limit - len(tokens)
tokens = tokens + [0] * missing
score_labels = score_labels + [-100] * missing独立例子如何迁移回 Notebook
question / answer对应prompt_ids / response_ids。tokens / score_labels对应input_ids / labels。limit对应max_len,输入填充值 0 要改为函数参数pad_id。- 返回前把两个列表分别转成
torch.tensor(..., dtype=torch.long);Notebook 已给好这部分。
巩固一下
如果序列长度超过 max_len,为什么 input_ids 和 labels 必须使用同一切片?
学完这一段,试着做
用一个小动作确认自己理解了;最后再进入官方题目。