# GSM8K 与 GPQA 单一精度协议修复设计

## 背景

当前精度脚本把原始题目字符串直接传给 `Qwen2.5-1.5B-Instruct`，没有应用模型
chat template。GSM8K 默认只生成 128 tokens，正式结果中 1304/1319 个输出达到
长度上限；GPQA 默认生成 16 tokens，但评分器要求整段输出只能是单独的
`A/B/C/D`，导致所有带解释的答案均被判为无法解析。

本次只保留一套正式成绩，不输出兼容成绩或实验性第二成绩。修复目标是建立一个
确定性、可复现、对 baseline 与两个 offload case 完全一致的测试协议。

## 测试协议

协议名称为 `qwen-chat-v1`，使用以下固定设置：

| 项目 | GSM8K | GPQA Diamond |
|---|---|---|
| 模型输入 | Qwen chat template | Qwen chat template |
| temperature | 0 | 0 |
| max tokens | 512 | 8 |
|回答要求 | 分步计算，末行 `The answer is <number>.` | 只返回一个大写选项字母 |
|评分 | 最终规范化数值精确匹配 | 输出开头的明确 `A/B/C/D` |

GSM8K 的 system message 要求模型成为精确的数学问题求解器；user message 包含
原始问题，并明确要求最后一行使用固定答案格式，且其后不再输出内容。

GPQA 的 system message 要求模型完成单项选择；user message 包含稳定种子打乱后的
题目和四个选项，并要求只输出 `A`、`B`、`C` 或 `D`，不得附加解释。

## 代码结构

`scripts/accuracy_gsm8k_gpqa.py` 增加三个清晰边界：

1. `prompt_for_example` 只负责构造数据集相关的 user message 和 gold answer。
2. 新的消息构造函数为每个数据集附加固定 system message。
3. `generate_prompts` 从 `LLM` 获取 tokenizer，调用
   `apply_chat_template(..., tokenize=False, add_generation_prompt=True)` 后再生成。

GPQA 解析器改为只解析输出开头的明确答案。它接受 `C`、`C. explanation`、
`Answer: C` 和 `(C)`，但继续拒绝 `I considered C` 等正文中的偶然字母，避免通过
搜索任意位置的选项字母虚增分数。

运行脚本将 GSM8K 和 GPQA 的默认生成预算分别改为 512 和 8。Python CLI 的通用
默认值改为 512；正式 shell 入口仍按数据集显式传值。

## 结果与诊断

每条 example JSONL 除现有的题目、gold、prediction 和 correct 外，增加：

- `output_token_count`
- `finish_reason`
- `parsed_answer`

结果 JSON 增加 `prompt_protocol` 和生成结束原因汇总。该信息用于证明正式结果没有
再次因 token 上限大面积截断，也让评审能够审计 GPQA 的实际解析结果。

所有三组参数 case 必须使用相同协议、数据集哈希、随机种子和采样设置。
`verify_accuracy_matrix.py` 继续以 baseline 为参照验证两个 offload case 没有精度下降。

## 错误处理

- tokenizer 不支持 chat template 时立即报错，不回退到原始文本协议。
- vLLM 没有返回候选结果时保存空预测、0 token 和 `missing` 结束原因。
- GPQA 无法从输出开头解析明确选项时记录 `parsed_answer: null` 并判错。
- 参数合法性和本地数据集 manifest 校验保持不变。

## 测试策略

按 TDD 增加以下回归测试，并在实现前确认失败：

1. GSM8K 与 GPQA 构造固定、数据集相关的提示内容。
2. 所有生成输入均经过 tokenizer chat template。
3. GPQA 接受开头明确答案及其后解释，但拒绝正文中的偶然选项字母。
4. generation record 正确保存文本、token 数和结束原因。
5. 结果元数据包含 `qwen-chat-v1` 协议与结束原因汇总。
6. shell 正式入口默认使用 GSM8K 512、GPQA 8 tokens。

本地单测通过后，在 Ascend 服务器依次执行：

1. 精度脚本单测。
2. 每个数据集两题的 baseline 冒烟测试。
3. GSM8K 1319 题和 GPQA Diamond 198 题的三组全量矩阵。
4. 校验三组结果的样本数、数据集哈希、协议元数据和相对精度差。

## 验收标准

- GSM8K 与 GPQA 都只产生一套正式成绩。
- 正式输入全部应用 Qwen chat template。
- GSM8K 不再出现接近全量样本的长度截断。
- GPQA 可解析率不再因带解释输出而人为变成 0。
- baseline、`group_8_num_1`、`group_8_num_2` 使用完全相同的测试协议。
- 两个 offload case 相对 baseline 的允许精度下降仍为 0。
- 单测、冒烟测试和全量矩阵均保留可复现日志与 JSON 结果。
