复现大语言模型(LLM)论文(技术报告)中的数据集测评结果(以DeepSeek R1使用的GPQA数据集为例)
前言-方法论
如果想要通过AISBench测评工具复现论文精度,需要对齐模型的技术报告或论文中对此数据集的测试方法,在评测工具这边需要对齐的如下: 模型相关配置:
选取合适的endpoint对应的模型任务
最大输出长度完全对齐
后处理参数完全对齐
数据集相关配置
提示词工程完全对齐
答案提取方式完全对齐
精度评估指标对齐
以复现DeepSeek R1模型在GPQA数据集上的测评结果为例
选取合适的endpoint对应的模型配置文件
为了确保执行效率,复现模型精度时一般也使用推理服务作为被测对象。访问推理服务可以有不同的endpoint,业界主流还是用OpenAI的endpoint。OpenAI的endpoint主要有两种:v1/completions和v1/chat/completions。
v1/completions: 模型按 “续写前缀” 逻辑生成文本,不主动区分 “指令” 与 “内容”,需通过 prompt 工程强引导(如加 “请回答:”),否则可能出现模仿式输出而非指令执行。例如输入 “将下列英文翻译成中文:Hello”,可能续写为 “将下列中文翻译成英文:你好”,而非直接翻译。 因此适合单轮文本生成(如代码补全、短文写作、文本续写、简单文本分类),或需兼容旧版基础模型的场景。
v1/chat/completions: 模型原生理解 system/user/assistant 角色语义,优先执行用户指令,对话一致性与意图对齐更稳定,无需复杂 prompt 包装即可完成翻译、总结等任务。 因此适合多轮对话(客服、聊天机器人)、指令驱动任务(翻译、摘要、数据分析)、工具集成(函数调用、检索增强)、多模态交互等现代 LLM 应用场景。
💡 目前(2025年1月之后),几乎所有新发布的LLM模型都支持v1/chat/completions endpoint,而且v1/completions endpoint也基本被废弃,因此模型配置文件中一般只选用访问v1/chat/completions endpoint的模型任务vllm_api_general_chat(用非流式接口访问服务)和vllm_api_stream_chat(用流式接口访问服务)。
以模型任务vllm_api_general_chat为例,其对应的模型配置文件的绝对路径可以通过执行如下命令得到:
ais_bench --models vllm_api_general_chat --search
⚠️ 后续模型相关配置都在此配置文件中修改。
最大输出长度完全对齐
在DeepSeek R1 Huggingface模型卡片中可以看到如下描述
4. Evaluation Results
DeepSeek-R1-Evaluation
For all our models, the maximum generation length is set to 32,768 tokens…
从这段描述可以看出,DeepSeek R1模型的最大输出长度被设置为32,768 tokens。
因此以模型任务vllm_api_general_chat为例,最大输出长度的配置如下:
from ais_bench.benchmark.models import VLLMCustomAPIChat
models = [
dict(
attr="service",
type=VLLMCustomAPIChat,
abbr='vllm-api-general-chat',
# ......
max_out_len=32768, # 推理服务输出的token的最大数量
# ......
)
]
后处理参数完全对齐
在DeepSeek R1 Huggingface模型卡片中可以看到如下描述
4. Evaluation Results
DeepSeek-R1-Evaluation
…, For benchmarks requiring sampling, we use a temperature of \(0.6\), a top-p value of \(0.95\), …
从这段描述可以看出,DeepSeek R1模型的后处理参数包括温度(temperature)为0.6,top-p值(top_p)为0.95。
因此以模型任务vllm_api_general_chat为例,后处理参数的配置如下:
from ais_bench.benchmark.models import VLLMCustomAPIChat
models = [
dict(
attr="service",
type=VLLMCustomAPIChat,
abbr='vllm-api-general-chat',
# ......
generation_kwargs=dict( # 后处理参数都填在这里
temperature=0.6,
top_p=0.95,
),
# ......
)
]
提示词工程完全对齐
提示词工程对模型精度的影响是很显著的,一般模型论文或技术报告都会公开测试所使用的提示词,如果是使用第三方工具测试的,也会强调具体是什么开源工具。 在DeepSeek R1论文中,提及了GPQA数据集的测试提示词工程,如下:
Evaluation Prompts Following the setup in DeepSeek-V3, standard benchmarks such as MMLU, DROP, GPQADiamond, and SimpleQA are evaluated using prompts from the simple-evals framework.
这说明DeepSeek R1的提示词工程是使用simple-evals这个工具的提示词模板,可以参考simple-evals这个项目,其中GPQA用到的提示词相关的部分为(需求去代码里看):
QUERY_TEMPLATE_MULTICHOICE = """
Answer the following multiple choice question. The last line of your response should be of the following format: 'Answer: $LETTER' (without quotes) where LETTER is one of ABCD. Think step by step before answering.
{Question}
A) {A}
B) {B}
C) {C}
D) {D}
""".strip()
因此AISBench的提示词工程应当修改为:
# https://github.com/AISBench/benchmark/blob/master/ais_bench/benchmark/configs/datasets/gpqa/gpqa_gen_0_shot_cot_chat_prompt.py
## 与simple-evals完全相同的提示词模板
align_prompt = """
Answer the following multiple choice question. The last line of your response should be of the following format: 'Answer: $LETTER' (without quotes) where LETTER is one of ABCD. Think step by step before answering.
{question}
A) {A}
B) {B}
C) {C}
D) {D}
""".strip()
## ......
gpqa_infer_cfg = dict(
prompt_template=dict( # 提示词工程
type=PromptTemplate,
template=dict(
round=[
dict(role='HUMAN', prompt=align_prompt), # 传入提示词模板
], )),
retriever=dict(type=ZeroRetriever),
inferencer=dict(type=GenInferencer))
更详细的提示词工程的介绍请参考Prompt 模板介绍
答案提取方式完全对齐
如何从模型的推理结果中提取答案并评估会直接影响评测的得分。llm测评使用的数据集的答案提取总体来说分为3类:
对于类似选择题或问答题类型的评测数据集(ceval、gsm8k等),答案提取方式一般是基于固定的正则表达式。
对于比较复杂的诸如代码类或者要包含解题过程的数学类的数据集(例如livecodebench、humaneval、math500等),一般会有统一的数据集配套的evaluate库供调用。
对于一些发散或者偏主观的数据集可能需要引入裁判模型进行评估。
一般情况下只有测评涉及到第3类数据集时,在模型的论文或技术报告里才会明确说明(例如使用GPT-4-1106的api作为裁判模型)。对于第2类数据集一般默认使用数据集配套的evaluate库进行答案提取。
对于第1类数据集,如果模型论文或技术报告说明了提示词工程出自什么工具,那么可以直接沿用这个工具中提及的答案提取方式,还是以GPQA为例,在simple-evals中,GPQA的答案提取方式就是基于固定的正则表达式:
# https://github.com/openai/simple-evals/blob/main/common.py
ANSWER_PATTERN_MULTICHOICE = r"(?i)Answer[ \t]*:[ \t]*\$?([A-D])\$?"
# https://github.com/openai/simple-evals/blob/main/gpqa_eval.py
match = re.search(ANSWER_PATTERN_MULTICHOICE, response_text)
因此AISBench的答案提取方式应当修改为与simple-evals完全相同的正则表达式:
# https://github.com/AISBench/benchmark/blob/master/ais_bench/benchmark/datasets/gpqa.py
@TEXT_POSTPROCESSORS.register_module() # 答案提取函数,从模型原始回答的字符串中提取A,B,C,D中一个选项
def GPQA_Simple_Eval_postprocess(text: str) -> str:
"""
从模型原始回答的字符串中提取A,B,C,D中一个选项作为答案。
:param text: 模型原始回答的字符串。
:return: 提取到的答案选项(A、B、C、D),如果未找到匹配项则返回None。
"""
ANSWER_PATTERN = r"(?i)Answer[ \t]*:[ \t]*\$?([A-D])\$?"
match = re.search(ANSWER_PATTERN, text)
if match:
return match.group(1)
return None
# https://github.com/AISBench/benchmark/blob/master/ais_bench/benchmark/configs/datasets/gpqa/gpqa_gen_0_shot_cot_chat_prompt.py
from ais_bench.benchmark.datasets import GPQADataset, GPQA_Simple_Eval_postprocess, GPQAEvaluator
gpqa_eval_cfg = dict(evaluator=dict(type=GPQAEvaluator),
pred_postprocessor=dict(type=GPQA_Simple_Eval_postprocess)) # 传入自定义的答案提取函数,函数本身也可以直接定义在数据集配置文件里
精度评估指标对齐
一般模型的评测结果都会有这样一张表,以DeepSeek的为例:
Model |
AIME 2024 pass@1 |
AIME 2024 cons@64 |
MATH-500 pass@1 |
GPQA Diamond pass@1 |
LiveCodeBench pass@1 |
CodeForces rating |
|---|---|---|---|---|---|---|
GPT-4o-0513 |
9.3 |
13.4 |
74.6 |
49.9 |
32.9 |
759 |
Claude-3.5-Sonnet-1022 |
16.0 |
26.7 |
78.3 |
65.0 |
38.9 |
717 |
o1-mini |
63.6 |
80.0 |
90.0 |
60.0 |
53.8 |
1820 |
其中的cons@64,pass@1就是表示精度评估指标。这些精度评估指标的详细介绍可以参考精度评估指标说明
以GPQA为例,表格是指明其是使用pass@1作为精度评估指标的,在DeepSeek R1论文中对pass@1的描述如下:
… , and report pass@1 using a non-zero temperature. Specifically, we use a sampling temperature of 0.6 and a top-𝑝 value of 0.95 to generate 𝑘 responses (typically between 4 and 64, depending on the test set size) for each question. Pass@1 is then calculated as \({\text{pass@1}} = \frac{1}{n} \sum_{i=1}^{n} p_i\)
那么在AISBench中,模型配置文件做如下配置:
# https://github.com/AISBench/benchmark/blob/master/ais_bench/benchmark/configs/models/vllm_api/vllm_api_stream_chat.py
models = [
dict(
... # 其它参数
generation_kwargs = dict(
num_return_sequences = 4, # n=4~64
... # 其它参数
),
...
)
]
一般情况下 n == k 或者 k=1,n == k的场景推理出的指标为path@k,k=1的场景也就是deepseek公式中的pass@1本质上是avg@n,单独配置n够用,因此AISBench评测工具20251219版本下还不支持单独配置k。
精度评估阶段结束后,结果会记录在日志和打屏在运行窗口,格式按照以下示例内容(数据仅供参考):
| dataset | version | metric | mode | vllm-api-stream-chat |
| --------- | --------- | ------------------------- | ---- | -------------------- |
| GPQA_diamond | 604a78 | accuracy (4 runs average) | gen | 18.00 |
| GPQA_diamond | 604a78 | avg@4 | gen | 18.00 |
| GPQA_diamond | 604a78 | pass@4 | gen | 53.33 |
| GPQA_diamond | 604a78 | cons@4 | gen | 13.33 |
其中avg@4和deepseek中执行4次平均的pass@1含义相同。
⚠️
n本身只是影响评测结果的波动幅度不影响数学期望,但是n越大意味这需要反复跑同一条用例的次数越多,资源消耗越大。如果要复现精度需要依据实际资源情况做调整。
💡如果论文的数据集不强调是什么精度评估指标,一般默认
pass@1,因此在AISBench的数据集配置文件中不配置n和k就是默认pass@1
参考资料
DeepSeek R1 huggingface模型卡片:https://huggingface.co/deepseek-ai/DeepSeek-R1
DeepSeek R1 论文:https://github.com/deepseek-ai/DeepSeek-R1/blob/main/DeepSeek_R1.pdf