YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

AQuA Verifier — DeBERTa-v3-large Token Classification

基于 DIVERSE(ICLR 2024)的 verifier 实现,在 AQuA 数学推理数据集上训练,用于对解题路径逐条打分。

模型信息

项目 说明
基座模型 microsoft/deberta-v3-large
任务类型 Token 分类(5 类)
标签 SOLUTION-CORRECT(0), SOLUTION-INCORRECT(1), STEP-CORRECT(2), STEP-INCORRECT(3), O(4)
训练数据 AQuA — 250 题 × (20 条候选解/题 + 1 条正确答案/题) = 5250 条
训练轮数 1 epoch(建议续训到 3-5 epoch 以获得更好泛化)
输入格式 [CLS] {步骤用%%分隔} && {题目},末尾带 ####{答案字母}
打分方式 [CLS] 位置的 SOLUTION-CORRECT 概率 × 10,范围 0~10
分数含义 越高表示模型越认可这条推理路径的正确性

文件说明

aqua-verifier/
├── run_ner.py                   # 训练入口
├── verifier_data_prepare.py     # 数据准备(LLM 输出 → CoNLL 格式 train.txt)
├── deberta_model.py             # DeBERTa-v2 自定义模型(必须用此类加载,不能用 AutoModel)
├── utils_ner.py                 # CoNLL 数据加载与特征转换
├── tasks.py                     # NER 任务定义
├── utils.py                     # 数据结构 / 步骤标注 / 加权投票评估
├── utils_io.py                  # 文件读取工具
├── verifier_metrics.py          # 评估指标(weighted voting accuracy)
├── labels.txt                   # 5 个标签
├── config.json                  # 模型配置(含 task_specific_params 权重)
├── model.safetensors            # 训练权重
├── spm.model                    # SentencePiece tokenizer 模型
└── tokenizer_config.json        # Tokenizer 配置

加载模型并打分

import torch
from transformers import AutoTokenizer
from deberta_model import DebertaV2ForTokenClassification

# 加载(换成你的 HuggingFace 用户名)
tokenizer = AutoTokenizer.from_pretrained("你的用户名/aqua-verifier")
model = DebertaV2ForTokenClassification.from_pretrained("你的用户名/aqua-verifier")
model.eval()

def score(question: str, solution: str) -> float:
    """
    question: "Q: ... Options: A)... B)..."
    solution: 解题步骤(换行会自动转为 %%),末尾带 Therefore the answer is X. 或 ####X
    返回 0~10 的分数
    """
    sol = solution.strip().replace("\r\n", "\n").replace("\n", "%%")
    # 如果没有 ####X 但文中有 "answer is X",自动补全
    if "####" not in sol:
        import re
        m = re.search(r"answer is ([A-E])", sol, re.IGNORECASE)
        if m:
            sol += f" ####{m.group(1)}"
    text = f"[CLS] {sol} && {question}"
    inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=512)
    with torch.no_grad():
        logits = model(**inputs).logits
    # [CLS] 位置 → SOLUTION-CORRECT 概率 → 映射到 0~10
    return torch.softmax(logits[0, 0], dim=-1)[0].item() * 10

# 示例
q = "Q: 2+2=? Options: A)1 B)2 C)3 D)4 E)5"
sol = "2+2=4%%Therefore the answer is D. ####D"
print(score(q, sol))  # ~9.9

注意:不能用 AutoModel.from_pretrained(),必须从本仓库的 deberta_model.py 导入 DebertaV2ForTokenClassification

完整训练流程

第一步:准备 LLM 生成结果

使用 deepseek-v4-flash 对 AQuA 每道题生成多条候选解(建议每题 10~20 条),按以下 JSONL 格式保存:

{
  "context": "Q: 示例题1...\\nOptions: ...\\nA: 示例解...\\n...(可放 few-shot prompt)",
  "samples": ["LLM生成的候选解1", "LLM生成的候选解2", ...],
  "metadata": {
    "question": "Q: 目标题目的文本",
    "ground_truth": "Q: 目标题\\nA: 标准答案推理过程",
    "correct": "A",
    "options": ["A)...", "B)...", "C)...", "D)...", "E)..."]
  }
}

第二步:生成 CoNLL 训练数据

python verifier_data_prepare.py \
  --generator_result_file ./dataset/llm_outputs.jsonl \
  --output_dir ./dataset/ \
  --dataset_name AQuA \
  --split train \
  --text_entailment_model_name microsoft/deberta-large-mnli \
  --text_entailment_batch_size 512

步骤标注方式:对每条候选解的每个步骤,用 NLI 模型(deberta-large-mnli)与正确答案的对应步骤做文本蕴含判断。蕴含则为 STEP-CORRECT,不蕴含则为 STEP-INCORRECT。整体正确性用答案是否匹配判断。

输出:train.txt(CoNLL 格式,每行 TOKEN LABEL,序列之间空行分隔)。

第三步:训练 Verifier

python run_ner.py \
  --model_name_or_path microsoft/deberta-v3-large \
  --dataset_name AQuA \
  --train_data ../data/train.txt \
  --test_data ../data/test.txt \
  --data_labels labels.txt \
  --output_dir ../output/ \
  --do_train --do_eval \
  --per_device_train_batch_size 8 \
  --num_train_epochs 5 \
  --learning_rate 1e-5 \
  --alpha 0.1 \
  --overwrite_output_dir \
  --save_strategy epoch \
  --evaluation_strategy epoch \
  --logging_steps 50 \
  --save_total_limit 2

参数说明:

参数 说明
--alpha 0.1 STEP-CORRECT/INCORRECT 的 loss 权重。SOLUTION 类别固定为 1.0
--num_train_epochs 5 建议 3-5 epoch。当前权重仅训了 1 epoch
--per_device_train_batch_size 8 V100/A100 可用 8,小显存降到 4
--save_total_limit 2 只保留最近 2 个 checkpoint,防磁盘满
--learning_rate 1e-5 DeBERTa-large 推荐学习率

续训

python run_ner.py \
  ...(同上参数)... \
  --resume_from_checkpoint ../output/checkpoint-NNN

环境依赖

# 核心依赖
pip install torch transformers datasets numpy scipy tqdm seqeval rouge_score nltk absl-py six multiset conllu

# 版本锁定(重要)
pip install "transformers==4.38.2" "accelerate==0.27.2"

如果在华为云 Ascend NPU 上训练,额外安装:

pip install torch_npu
export HF_ENDPOINT=https://hf-mirror.com

评分原理与使用方式

训练时对序列中两个位置做标注:

  • [CLS] token → SOLUTION-CORRECT / SOLUTION-INCORRECT(整体解对不对,loss weight = 1.0)
  • %% 分隔符 token → STEP-CORRECT / STEP-INCORRECT(NLI 模型逐步骤判断正误,loss weight = 0.1)

推理打分有两种方式:

  1. 整体打分(推荐):取 [CLS] 的 SOLUTION-CORRECT 概率,训练最充分(weight 1.0),实测区分度最好。
  2. 逐步骤打分:取每个 %% token 的 STEP-CORRECT 概率,可以看模型认为哪些步骤对。但当前仅训了 1 epoch,单个步骤的打分区分度有限。

常见问题

不能用 AutoModel 加载

本模型修改了 DeBERTa-v2 的内部代码(兼容新版 PyTorch/numpy),必须用仓库中的 deberta_model.py

from deberta_model import DebertaV2ForTokenClassification
model = DebertaV2ForTokenClassification.from_pretrained("用户名/aqua-verifier")

分数偏低/偏高

因为预算不够,本模型仅训练了 1 epoch,在训练数据风格的推理文本上区分度良好(CORRECT ~9.9, INCORRECT ~0.01),但在不同 LLM 生成的推理风格上分数整体偏低。建议:

  • 同题内做相对比较(选最高分路径),不依赖绝对阈值
  • 或续训 3-5 epoch 提升泛化

参考

Downloads last month
16
Safetensors
Model size
0.4B params
Tensor type
I64
·
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Paper for k1r1same/aqua-verifier