读前感:
- 对这个章节实际上并没有特别多的兴趣, 可能在为了评估自己训练的RAG或FT时可以用到。
读后感:
- 本章节内容扩展比较多,在教程之外,手把手重新做了一整套的数据集并进行了测试。有兴趣的可以关注一下。
- 学过之后才深刻感受到大模型的测试评估是大模型应用的基础, 只未来必不可少的基本能力。
- 深度应用必须建立自己的数据集,通过这个数据集才能验证RAG、微调等的效果是否可以采用,OpenCompass提供了一个很好的框架,可以简化很多这方面的工作。
- prompt是测试的基石,评估方法也各不相同,要根据数据集的特点合理选择。
- 推荐大家认真学习本章节,必会收货满满。
1. 为什么要研究大模型的评测?
百家争鸣,百花齐放。
- 首先,研究评测对于我们全面了解大型语言模型的优势和限制至关重要。尽管许多研究表明大型语言模型在多个通用任务上已经达到或超越了人类水平,但仍然存在质疑,即这些模型的能力是否只是对训练数据的记忆而非真正的理解。例如,即使只提供LeetCode题目编号而不提供具体信息,大型语言模型也能够正确输出答案,这暗示着训练数据可能存在污染现象。
- 其次,研究评测有助于指导和改进人类与大型语言模型之间的协同交互。考虑到大型语言模型的最终服务对象是人类,为了更好地设计人机交互的新范式,我们有必要全面评估模型的各项能力。
- 最后,研究评测可以帮助我们更好地规划大型语言模型未来的发展,并预防未知和潜在的风险。随着大型语言模型的不断演进,其能力也在不断增强。通过合理科学的评测机制,我们能够从进化的角度评估模型的能力,并提前预测潜在的风险,这是至关重要的研究内容。
- 对于大多数人来说,大型语言模型可能似乎与他们无关,因为训练这样的模型成本较高。然而,就像飞机的制造一样,尽管成本高昂,但一旦制造完成,大家使用的机会就会非常频繁。因此,了解不同语言模型之间的性能、舒适性和安全性,能够帮助人们更好地选择适合的模型,这对于研究人员和产品开发者而言同样具有重要意义。
这里推荐一个模型PK的平台,可以进行匿名随机PK
Compass Arena体验链接
司南开源评测体系:OpenCompass司南
魔搭社区:魔搭社区
2. OpenCompass介绍
上海人工智能实验室科学家团队正式发布了大模型开源开放评测体系 “司南” (OpenCompass2.0),用于为大语言模型、多模态模型等提供一站式评测服务。其主要特点如下:
- 开源可复现:提供公平、公开、可复现的大模型评测方案
- 全面的能力维度:五大维度设计,提供 70+ 个数据集约 40 万题的的模型评测方案,全面评估模型能力
- 丰富的模型支持:已支持 20+ HuggingFace 及 API 模型
- 分布式高效评测:一行命令实现任务分割和分布式评测,数小时即可完成千亿模型全量评测
- 多样化评测范式:支持零样本、小样本及思维链评测,结合标准型或对话型提示词模板,轻松激发各种模型最大性能
- 灵活化拓展:想增加新模型或数据集?想要自定义更高级的任务分割策略,甚至接入新的集群管理系统?OpenCompass 的一切均可轻松扩展!
3. 评测对象
本算法库的主要评测对象为语言大模型与多模态大模型。我们以语言大模型为例介绍评测的具体模型类型。
- 基座模型:一般是经过海量的文本数据以自监督学习的方式进行训练获得的模型(如OpenAI的GPT-3,Meta的LLaMA),往往具有强大的文字续写能力。
- 对话模型:一般是在的基座模型的基础上,经过指令微调或人类偏好对齐获得的模型(如OpenAI的ChatGPT、上海人工智能实验室的书生·浦语),能理解人类指令,具有较强的对话能力。
4. 工具架构
- 模型层:大模型评测所涉及的主要模型种类,OpenCompass 以基座模型和对话模型作为重点评测对象。
- 能力层:OpenCompass 从本方案从通用能力和特色能力两个方面来进行评测维度设计。在模型通用能力方面,从语言、知识、理解、推理、安全等多个能力维度进行评测。在特色能力方面,从长文本、代码、工具、知识增强等维度进行评测。
- 方法层:OpenCompass 采用客观评测与主观评测两种评测方式。客观评测能便捷地评估模型在具有确定答案(如选择,填空,封闭式问答等)的任务上的能力,主观评测能评估用户对模型回复的真实满意度,OpenCompass 采用基于模型辅助的主观评测和基于人类反馈的主观评测两种方式。
- 工具层:OpenCompass 提供丰富的功能支持自动化地开展大语言模型的高效评测。包括分布式评测技术,提示词工程,对接评测数据库,评测榜单发布,评测报告生成等诸多功能。
5. 设计思路
为准确、全面、系统化地评估大语言模型的能力,OpenCompass 从通用人工智能的角度出发,结合学术界的前沿进展和工业界的最佳实践,提出一套面向实际应用的模型能力评价体系。OpenCompass 能力维度体系涵盖通用能力和特色能力两大部分。
6. 评测方法
OpenCompass 采取客观评测与主观评测相结合的方法。针对具有确定性答案的能力维度和场景,通过构造丰富完善的评测集,对模型能力进行综合评价。针对体现模型能力的开放式或半开放式的问题、模型安全问题等,采用主客观相结合的评测方式。
6.1 客观评测
针对具有标准答案的客观问题,我们可以通过使用定量指标比较模型的输出与标准答案的差异,并根据结果衡量模型的性能。同时,由于大语言模型输出自由度较高,在评测阶段,我们需要对其输入和输出作一定的规范和设计,尽可能减少噪声输出在评测阶段的影响,才能对模型的能力有更加完整和客观的评价。 为了更好地激发出模型在题目测试领域的能力,并引导模型按照一定的模板输出答案,OpenCompass 采用提示词工程 (prompt engineering)和语境学习(in-context learning)进行客观评测。 在客观评测的具体实践中,我们通常采用下列两种方式进行模型输出结果的评测:
- 判别式评测(PPL):该评测方式基于将问题与候选答案组合在一起,计算模型在所有组合上的困惑度(perplexity),并选择困惑度最小的答案作为模型的最终输出。例如,若模型在 问题? 答案1 上的困惑度为 0.1,在 问题? 答案2 上的困惑度为 0.2,最终我们会选择 答案1 作为模型的输出。
- 生成式评测(GEN):该评测方式主要用于生成类任务,如语言翻译、程序生成、逻辑分析题等。具体实践时,使用问题作为模型的原始输入,并留白答案区域待模型进行后续补全。我们通常还需要对其输出进行后处理,以保证输出满足数据集的要求。
6.2 主观评测
语言表达生动精彩,变化丰富,大量的场景和能力无法凭借客观指标进行评测。针对如模型安全和模型语言能力的评测,以人的主观感受为主的评测更能体现模型的真实能力,并更符合大模型的实际使用场景。 OpenCompass 采取的主观评测方案是指借助受试者的主观判断对具有对话能力的大语言模型进行能力评测。在具体实践中,我们提前基于模型的能力维度构建主观测试问题集合,并将不同模型对于同一问题的不同回复展现给受试者,收集受试者基于主观感受的评分。由于主观测试成本高昂,本方案同时也采用使用性能优异的大语言模拟人类进行主观打分。在实际评测中,本文将采用真实人类专家的主观评测与基于模型打分的主观评测相结合的方式开展模型能力评估。 在具体开展主观评测时,OpenComapss 采用单模型回复满意度统计和多模型满意度比较两种方式开展具体的评测工作。
7. 快速开始
7.1 概览
在 OpenCompass 中评估一个模型通常包括以下几个阶段:配置 -> 推理 -> 评估 -> 可视化。
- 配置:这是整个工作流的起点。您需要配置整个评估过程,选择要评估的模型和数据集。此外,还可以选择评估策略、计算后端等,并定义显示结果的方式。
- 推理与评估:在这个阶段,OpenCompass 将会开始对模型和数据集进行并行推理和评估。推理阶段主要是让模型从数据集产生输出,而评估阶段则是衡量这些输出与标准答案的匹配程度。这两个过程会被拆分为多个同时运行的“任务”以提高效率,但请注意,如果计算资源有限,这种策略可能会使评测变得更慢。如果需要了解该问题及解决方案,可以参考 FAQ: 效率。
- 可视化:评估完成后,OpenCompass 将结果整理成易读的表格,并将其保存为 CSV 和 TXT 文件。你也可以激活飞书状态上报功能,此后可以在飞书客户端中及时获得评测状态报告。 接下来,我们将展示 OpenCompass 的基础用法,展示书生浦语在 C-Eval 基准任务上的评估。它们的配置文件可以在 configs/eval_demo.py 中找到。
7.2 环境配置
7.2.1 创建开发机和 conda 环境
在创建开发机界面选择镜像为 Cuda11.7-conda,并选择 GPU 为10% A100。
7.3 安装
7.3.1面向GPU的环境安装
studio-conda -o internlm-base -t opencompass #安装虚拟环境
conda activate opencompass #激活虚拟环境
cd code #之前在开发机中已经安装过,所以这次换个目录。
git clone -b 0.2.4 https://github.com/open-compass/opencompass #复制软件库
cd opencompass
pip install -e .
虚拟环境安装完的状态
7.3.2 数据准备
解压评测数据集到 data/ 处
cp /share/temp/datasets/OpenCompassData-core-20231110.zip /root/code/opencompass/ #拷贝开发机的共享文件
unzip OpenCompassData-core-20231110.zip
#这里是通过共享文件,拷贝了OpenCompass的核心数据集,如果需要直接使用网上的数据使用如下命令:
wget https://github.com/open-compass/opencompass/releases/download/0.2.2.rc1/OpenCompassData-core-20240207.zip
unzip OpenCompassData-core-20240207.zip
#OpenCompass 提供的更加完整的数据集 (~500M)
wget https://github.com/open-compass/opencompass/releases/download/0.2.2.rc1/OpenCompassData-complete-20240207.zip
unzip OpenCompassData-complete-20240207.zip
cd ./data
find . -name "*.zip" -exec unzip "{}" \;
将会在 OpenCompass 下看到data文件夹
7.3.3 查看支持的数据集和模型
列出所有跟 InternLM 及 C-Eval 相关的配置
cd /root/code/opencompass
python /root/code/opencompass/tools/list_configs.py internlm ceval
可以看到如下的结果
7.3.4 启动评测 (30% A100 8GB 资源)
确保按照上述步骤正确安装 OpenCompass 并准备好数据集后,可以通过以下命令评测 InternLM2-Chat-1.8B 模型在 C-Eval 数据集上的性能。由于 OpenCompass 默认并行启动评估过程,我们可以在第一次运行时以 --debug 模式启动评估,并检查是否存在问题。在 --debug 模式下,任务将按顺序执行,并实时打印输出。
python run.py --datasets ceval_gen \
--hf-path /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b \
--tokenizer-path /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b \
--tokenizer-kwargs padding_side='left' truncation='left' trust_remote_code=True \
--model-kwargs trust_remote_code=True device_map='auto' \
--max-seq-len 1024 --max-out-len 16 \
--batch-size 2 --num-gpus 1 --debug
这个时候可能报错,是因为缺少必要的软件库,按照错误提示安装即可,这里要有些耐心慢慢的补充。我这里需要补充的软件库如下:
pip install tqdm
pip install prettytable
pip install tabulate
pip install mmengine
pip install datasets
pip install transformers
pip install jieba
pip install scikit-learn
pip install evaluate
pip install rouge_chinese
pip install nltk
pip install rank_bm25
pip install sentence_transformers
pip install tiktoken
pip install absl-py
pip install fuzzywuzzy
pip install python-Levenshtein
pip install sentencepiece
pip install protobuf
pip install einops
pip install accelerate
另一个可能得问题是Intel的兼容问题,可以使用如下命令
export MKL_SERVICE_FORCE_INTEL=1
#或
export MKL_THREADING_LAYER=GNU
正常的测试结果如下:
**(后续内容可以通过官方文档学习,这里仅做简化介绍)
8. 自定义数据集客主观评测:量身定制,慧眼识珠
8.1 配置文件(基于现有的datasets和models)
详细的客观评测指引参见 支持新数据集 — OpenCompass 0.2.5 文档
在这里我们先自己做个测试。配置文件目录:configs/datasets
选一个internlm的模块试一下一下,这个测试时间比较长,大概30分钟吧, 大家可以开个新终端继续其他的内容
#解决Error: mkl-service + Intel(R) MKL: MKL_THREADING_LAYER=INTEL is incompatible with libgomp.so.1 library.
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
python /root/code/opencompass/tools/list_configs.py internlm #查看数据集
cd /root/code/opencompass #后续所有的测试启动都是在这个目录的位置。 run.py所在的位置。
#--debug 模式启动评估,并检查是否存在问题。在 --debug 模式下,任务将按顺序执行,并实时打印输出。
python run.py configs/eval_demo.py -w outputs/demo --debug
查看internlm的数据集, 相关的模型如下图。
这里面使用的是opt125m和opt350模型,OPT(Open Pre-trained Transformer)模型是由Meta AI研究实验室发布的一系列开放式大语言预训练模型。
测试的结果会输出到opencompass/outputs/demo 的目录下,我测试的结果如下:
8.1.1 创建新配置文件
这里我们选一个比较小的数据集, siqa_datasets。SIQA(Social Interaction QA)是一个专注于测试社交常识智能的新问答基准数据集。训练的数据有3.3万条。 数据存储在opencompass/data/siqa的目录下。 train.jsonl中包括33410条数据,train-labels.lst中包括答案。每条数据的结构如下:
{
"context": "Cameron decided to have a barbecue and gathered her friends together.",
"question": "How would Others feel as a result?",
"answerA": "like attending",
"answerB": "like staying home",
"answerC": "a good friend to have"
}
创建新的配置文件
cd /root/code/opencompass/configs #转到配置文件目录
touch eval_test.py #创建数据集脚本
下面是代码:
from mmengine.config import read_base
with read_base():
# 直接从预设数据集配置中读取需要的数据集配置
from .datasets.siqa.siqa_gen import siqa_datasets
# 将需要评测的数据集拼接成 datasets 字段
datasets = [*siqa_datasets]
from opencompass.models import HuggingFaceCausalLM
_meta_template = dict(
round=[
dict(role='HUMAN', begin='<|im_start|>user\n', end='<|im_end|>\n'),
dict(role='BOT', begin='<|im_start|>assistant\n', end='<|im_end|>\n', generate=True),
],
eos_token_id=92542
)
models = [
dict(
type=HuggingFaceCausalLM,
abbr='internlm2-chat-7b-hf',
path="internlm/internlm2-chat-7b",
tokenizer_path='internlm/internlm2-chat-7b',
model_kwargs=dict(
trust_remote_code=True,
device_map='auto',
),
tokenizer_kwargs=dict(
padding_side='left',
truncation_side='left',
use_fast=False,
trust_remote_code=True,
),
max_out_len=100,
max_seq_len=2048,
batch_size=8,
meta_template=_meta_template,
run_cfg=dict(num_gpus=1, num_procs=1),
end_str='<|im_end|>',
generation_kwargs = {"eos_token_id": [2, 92542]},
)
]
我们先用已有的siqa_datasets数据集合internlm2 1.8b进行评测。
cd /root/code/opencompass #后续的测试都是从这个目录下启动的。
python run.py configs/eval_test.py #运行评测
#这里如果报错,主要还是intel的那个bug。
#解决Error: mkl-service + Intel(R) MKL: MKL_THREADING_LAYER=INTEL is incompatible with libgomp.so.1 library.
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
测试结果如下,对比opt125m和opt350模型的分数, internlm2的7b模型提高了一倍。
8.1.2 PROMPT 模板
在 OpenCompass 中,我们将 template 拆分为两部分:数据侧的 template 和模型侧的 template。在测评模型时,数据会先后经过数据和模型侧的 template,最终转化为模型所需的输入。
数据侧的 template 被称为 prompt_template,它表示了把数据集的字段转化成提示词的过程。
模型侧的 template 被称为 meta_template,它表示了模型将这些提示词转化为自身期望的输入的过程。
- OpenCompass 将 prompt 的构建策略定义在了数据集配置中的 infer_cfg 部分。
- 字符串式 prompt:字符串式的模板是比较经典的模板形式,template="{anything}\nQuestion: {question}\nAnswer: {answer}"。
- 对话式 prompt:普通对话,多轮对话,带system的对话。 prompt 中常有的角色有:
- OpenCompass 中主要支持了两种 Infernecer:GenInferencer 和 PPLInferencer,它们对应着两种不同的推理方式。
- GenInferencer 对应生成式的推理。在推理时,模型被要求以输入的提示词为基准,继续往下续写。此时,template 则单一地表示这一句话对应的模板,
- PPLInferencer 对应判别式推理。在推理时,模型被要求计算多个输入字符串各自的混淆度 (PerPLexity / ppl),并将其中 ppl 最小的项作为模型的推理结果。
- Prompt Viewer
- 本工具允许你在不启动完整训练流程的情况下,直接查看生成的 prompt。如果传入的配置仅为数据集配置(如 configs/datasets/nq/nq_gen_3dcea1.py),则展示数据集配置中定义的原始 prompt。若为完整的评测配置(包含模型和数据集),则会展示所选模型运行时实际接收到的 prompt。运行方式:
python tools/prompt_viewer.py configs/datasets/siqa/siqa_gen_e78df3.py -n -a
- -n: 不进入交互模式,默认选择第一个 model (如有)和 dataset。
- -a: 查看配置中所有模型和所有数据集组合接收到的 prompt。
- -p PATTERN: 不进入交互模式,选择所有与传入正则表达式匹配的数据集。
输出如下
8.1.3 META 模板
下图展示了在 2-shot learning 的情况下,数据从数据集中经过 prompt template 和 meta template,最终构建出 prompt 的几种情况。读者可以该图为参考,方便理解后续的章节。
全量字段介绍
models = [
dict(meta_template = dict(
begin="Meta instruction: You are now a helpful and harmless AI assistant.",
round=[
dict(role='HUMAN', begin='HUMAN: ', end='<eoh>\n'), # begin and end can be a list of strings or integers.
dict(role='THOUGHTS', begin='THOUGHTS: ', end='<eot>\n', prompt='None'), # Here we can set the default prompt, which may be overridden by the speicfic dataset
dict(role='BOT', begin='BOT: ', generate=True, end='<eob>\n'),
],
end="end of conversion",
reserved_roles=[dict(role='SYSTEM', begin='SYSTEM: ', end='\n'),],
eos_token_id=10000,
),
)
]
meta_template 是一个字典,该字典可以包含以下数个字段:
- begin,end :(str,可选) prompt 的开头和结尾,通常是一些系统级别的指令。
- round:(list) 每一轮对话的模板格式。每轮对话的 prompt 内容由数据集配置的对话式模板控制。
- reserved_roles:(list,可选)指定 round 中并未出现,但有可能在数据集配置中用到的的预留角色,例如 SYSTEM 角色。
- eos_token_id:(int, 可选):指定了该模型的 eos token 的 id。如果不设置,则默认为 tokenizer 中的 eos token id。它的主要作用是在生成式任务中,截取模型的输出结果,因此一般应该被设置为 generate=True 的项所对应的 end 的第一个 token id。
meta_template 的 round 指定了一轮对话中每个角色说话的格式,接受一个字典组成的列表,每个字典的关键字如下:
- role(str): 参与对话的角色名,该字符串并不影响实际的 prompt。
- begin, end (str): 指定该角色在说话时的固定开头或结尾。
- prompt (str):角色的 prompt。在 meta template 中允许留空,但此时必须在数据集配置的 prompt 中指定。
- generate (bool): 指定为 True 时,该角色即为模型扮演的角色。在生成任务中,模型接收到的 prompt 会截止到该角色的 begin 处,剩下的内容由模型补全。
8.1.4 思维链chain of thought(CoT):
关注大大神可以通过链接学习,这里仅仅简单介绍一下。
Chain of Thought — OpenCompass 0.2.5 文档
- 零样本思维链Zero-shot prompt:数据集配置中简单地添加 “Let’s think step by step”
- 小样本思维链One-shot prompt:One-shot prompt 仅使用一个样本,这使得它相对于Zero-shot prompt(不提供样本)更具指导性,同时也比Few-shot prompt(提供多个样本)更为简洁。
- 自洽性机制SC (Self-Consistency):于一个问题,通过让模型多次参与思考并生成多个答案,然后对这些答案进行投票或比较,以选出最接近真实结果或最佳答案的方法。此SC版gsm8k测试配置可以在: opencompass.configs.datasets.gsm8k.gsm8k_gen_a3e34a.py 中找到。
- ToT(Tree-of-Thoughts):技术鼓励模型在生成回答之前,首先构建出一个内部的、类似于树的推理结构,这个结构能够清晰地展示从问题到答案的逐步推理过程。详细参照:opencompass/configs/datasets/game24/game24_gen_8dfde3.py。
8.2 自定义配置文件(基于问答题的dataset)
在下面的8.2~8.4章节需要建立如下几个文件:
- configs/eval_test_qa.py 配置文件,用于定义datasets的来源, models,meta_template。
- configs/datasets/test_qa/test_qa_gen.py 数据集配置文件,用于定义datasets的数据来源和type(loader),以及reader_cfg, infer_cfg, eval_cfg
- opencompass/datasets/test_qa.py 数据加载文件,是在数据集配置文件中datasets的type(loader),用于定义如何加载数据文件并返回数据集。
- data/test_qa/testQADataset.jsonl 这里是评估数据的原始文件。
- 最后可以用prompt_viewer检查prompt的生成结果。
首先,建立一个独立使用的数据集配置, 基于自定义的数据集,免息那个简单的gen方式。 数据集是问答题(QA)格式
再新建一个数据集配置文件的脚本文件 eval_test_qa.py
cd /root/code/opencompass/configs #转到配置文件目录
touch eval_test_qa.py #创建数据集配置脚本
这里使用新的配置文件输入如下代码, 这里面选择两个模型分别是internlm/internlm2-chat-7b和internlm/internlm2-chat-20b。其中internlm/internlm2-chat-20b的模型配置可能要修改一下GPU的数量(run_cfg=dict(num_gpus=1, num_procs=1),)。
另外还可以直接通过API来调用模型, 可以参考opencompass/opencompass/models/lightllm_api.py或其他API的模型。
# configs/eval_test_qa.py
from mmengine.config import read_base
from opencompass.models import HuggingFaceCausalLM
with read_base():
# 直接从预设数据集配置中读取需要的数据集配置
from .datasets.test_qa.test_qa_gen import test_qa_datasets
# 将需要评测的数据集拼接成 datasets 字段
datasets = [*test_qa_datasets]
_meta_template = dict(
round=[
dict(role='HUMAN', begin='<|im_start|>user\n', end='<|im_end|>\n'),
dict(role='BOT', begin='<|im_start|>assistant\n', end='<|im_end|>\n', generate=True),
],
eos_token_id=92542
)
models = [
dict(
type=HuggingFaceCausalLM,
abbr='internlm2-chat-7b-hf',
path="internlm/internlm2-chat-7b",
tokenizer_path='internlm/internlm2-chat-7b',
model_kwargs=dict(
trust_remote_code=True,
device_map='auto',
),
tokenizer_kwargs=dict(
padding_side='left',
truncation_side='left',
use_fast=False,
trust_remote_code=True,
),
max_out_len=100,
max_seq_len=2048,
batch_size=8,
meta_template=_meta_template,
run_cfg=dict(num_gpus=1, num_procs=1),
end_str='<|im_end|>',
generation_kwargs = {"eos_token_id": [2, 92542]},
),
dict(
type=HuggingFaceCausalLM,
abbr='internlm2-chat-20b-hf',
path="internlm/internlm2-chat-20b",
tokenizer_path='internlm/internlm2-chat-20b',
model_kwargs=dict(
trust_remote_code=True,
device_map='auto',
),
tokenizer_kwargs=dict(
padding_side='left',
truncation_side='left',
use_fast=False,
trust_remote_code=True,
),
max_out_len=100,
max_seq_len=2048,
batch_size=8,
meta_template=_meta_template,
run_cfg=dict(num_gpus=1, num_procs=1),
end_str='<|im_end|>',
generation_kwargs = {"eos_token_id": [2, 92542]},
)
]
8.3 自定义数据集配置文件
创建配置文件
mkdir datasets/test_qa
touch datasets/test_qa/test_qa_gen.py
在下面的代码中,我们使用的推理配置是对话式prompt。
#configs/datasets/test_qa/test_qa_gen.py
from opencompass.openicl.icl_prompt_template import PromptTemplate
from opencompass.openicl.icl_retriever import ZeroRetriever
from opencompass.openicl.icl_inferencer import PPLInferencer
from opencompass.openicl.icl_inferencer import GenInferencer
from opencompass.openicl.icl_evaluator import JiebaRougeEvaluator
from opencompass.datasets.test_qa import testQADataSet
test_qa_reader_cfg = dict(
input_columns=['question', 'answer'],
output_column='answer'
)
test_qa_infer_cfg = dict(
prompt_template=dict(
type=PromptTemplate,
template=dict(
round=[
dict(role="HUMAN", prompt="question: {question}\n"),
dict(role="BOT", prompt="answer: {answer}\n"),
])
),
retriever=dict(type=ZeroRetriever),
inferencer=dict(type=GenInferencer),
)
test_qa_eval_cfg = dict(evaluator=dict(type=JiebaRougeEvaluator))
test_qa_datasets = [
dict(
abbr="test_qa",
type=testQADataSet,
path='./data/test_qa/test_qa.jsonl',
reader_cfg=test_qa_reader_cfg,
infer_cfg=test_qa_infer_cfg,
eval_cfg=test_qa_eval_cfg
)
]
这里还要准备另外一个load文件,存储在另外一个目录下面。
cd /root/opencompass/opencompass/datasets/
touch test_qa.py
输入如下代码
#opencompass/datasets/test_qa.py
import json
import os
from datasets import Dataset, DatasetDict
from .base import BaseDataset
from opencompass.registry import LOAD_DATASET
@LOAD_DATASET.register_module()
class testQADataSet(BaseDataset):
@staticmethod
def load(path) -> Dataset:
print(f'Loading... {path}')
dataset_list = []
with open(path, 'r', encoding='utf-8') as f:
for line in f:
line = json.loads(line)
dataset_list.append({
'question': line['question'],
'answer': line['answer'],
})
# print(f'dataset_list:\N{dataset_list}')
return Dataset.from_list(dataset_list)
8.4 准备数据集
创建数据集数据
cd /root/code/opencompass/data
mkdir test_qa
touch test_qa/test_qa.jsonl
编辑yh_di.jsonl文件,内容是瞎编的,各位可以根据应用场景自行设计。
{"question": "绩效考核的原则", "answer": "1、坚持公平、公正、公开原则,考核规则、考核过程、考核结果面向全体考核对象公开公示;2、坚持量化与评估考核相结合,定量与定性考核相结合的原则;3、坚持奖优罚劣原则,考核是中心的管理和激励手段,通过考核,起到鞭策和促进作用,同时发现工作中存在的问题,不断改进和提升。"}
{"question": "绩效考核的考核目的", "answer": "全面落实公司绩效考核工作要求,客观、公平、公正地评价全体人员的工作内容和工作效率,真正起到激励、检查和督促作用,增强中心全体人员工作责任感和价值感,促进绩效管理和绩效改进,制定本细则。"}
{"question": "绩效考核的包括哪些内容", "answer": "考核内容包括绩效工资、激励、事项奖三部分。"}
自定义数据集可直接通过命令行来调用开始评测。
#解决Error: mkl-service + Intel(R) MKL: MKL_THREADING_LAYER=INTEL is incompatible with libgomp.so.1 library.
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
cd /root/code/opencompass/
python run.py \
--models hf_internlm2_chat_7b \
--custom-dataset-path data/test_qa/test_qa.jsonl \
--custom-dataset-data-type qa \
--custom-dataset-infer-method gen \
--num-gpus 1 \
--debug
这种方式可以直接启动对数据集的评测,但是可选参数不是很多, 例如评估方式就不知道如何选JiebaRougeEvaluator?所以应该是使用默认的准确率评估。对于上面的数据集因为都是句子无法精确回答,所以评分是0分。
更准确的得分还是需要发起完整的测试任务,见下一节。
整体的过程可以使用Prompt viewer检查配置文件的实际输出情况。
cd /root/code/opencompass/
python tools/prompt_viewer.py configs/datasets/test_qa/test_qa_gen.py -n -a
输出结果如下,说明咱们的配置基本成功了。这里面框架会自动屏蔽output_column='answer'的内容,所以answer:后面是空的。留给模型自行推理,然后再评估结果。
8.5 评测任务发起
通过命令行直接进行评测。测试数据只有3条,但是整体评估时间还是很长,主要是模型的加载时间。
#解决Error: mkl-service + Intel(R) MKL: MKL_THREADING_LAYER=INTEL is incompatible with libgomp.so.1 library.
export MKL_SERVICE_FORCE_INTEL=1
export MKL_THREADING_LAYER=GNU
cd /root/code/opencompass
python run.py configs/eval_test_qa.py \
--trust_remote_code=True \
--debug
测试结果如下。 虽然数据集里面只有三个问题,看还是可以看出20b的模型要比7b的模型好一些。
8.6 评估指标
在评测阶段,我们一般以数据集本身的特性来选取对应的评估策略,最主要的依据为标准答案的类型,一般以下几种类型:
- 选项:常见于分类任务,判断题以及选择题,目前这类问题的数据集占比最大,有 MMLU, CEval 数据集等等,评估标准一般使用准确率–ACCEvaluator。
- 短语:常见于问答以及阅读理解任务,这类数据集主要包括 CLUE_CMRC, CLUE_DRCD, DROP 数据集等等,评估标准一般使用匹配率–EMEvaluator。
- 句子:常见于翻译以及生成伪代码、命令行任务中,主要包括 Flores, Summscreen, Govrepcrs, Iwdlt2017 数据集等等,评估标准一般使用 BLEU(Bilingual Evaluation Understudy)–BleuEvaluator。
- 段落:常见于文本摘要生成的任务,常用的数据集主要包括 Lcsts, TruthfulQA, Xsum 数据集等等,评估标准一般使用 ROUGE(Recall-Oriented Understudy for Gisting Evaluation)–RougeEvaluator。
- 代码:常见于代码生成的任务,常用的数据集主要包括 Humaneval,MBPP 数据集等等,评估标准一般使用执行通过率以及 pass@k,目前 Opencompass 支持的有MBPPEvaluator、HumanEvaluator。
还有一类打分类型评测任务没有标准答案,比如评判一个模型的输出是否存在有毒,可以直接使用相关 API 服务进行打分,目前支持的有 ToxicEvaluator,目前有 realtoxicityprompts 数据集使用此评测方式。
评测采用的是JiebaRougeEvaluator, 下面是对这个评估指标的一个简介
- ROUGE-N (如 ROUGE-1, ROUGE-2, ROUGE-3):
- ROUGE-L:
由于客观评测只能反映模型在一些性能数据上的指标,没法完全真实地反映模型在与人类对话时的表现,因此需要在真实的对话场景下通过主观评测的方式翻译模型的真实性能。 而由于完全靠人力来进行主观评测是费时费力的,因此有很多利用模型来进行主观评测的方式。 这些方式主要可以分为以下几类:打分,对战,多模型评测等。
流行的评估方法主要有:
- Compare模式:将模型的回答进行两两比较,以计算对战其胜率。
- Score模式:针对单模型的回答进行打分(例如:Chatbot Arena)
8.8 自建主观数据集步骤
详细的主观评测指引参见 主观评测指引 — OpenCompass 0.2.5 文档
这部分不展开。
9. 数据污染评估:禁止作弊,诚信考试
数据污染评估简介
数据污染 是指本应用在下游测试任务中的数据出现在了大语言模型 (LLM) 的训练数据中,从而导致在下游任务 (例如,摘要、自然语言推理、文本分类) 上指标虚高,无法反映模型真实泛化能力的现象。 由于数据污染的源头是出现在 LLM 所用的训练数据中,因此最直接的检测数据污染的方法就是将测试数据与训练数据进行碰撞,然后汇报两者之间有多少语料是重叠出现的,经典的 GPT-3 论文中的表 C.1 会报告了相关内容。 但如今开源社区往往只会公开模型参数而非训练数据集,在此种情况下 如何判断是否存在数据污染问题或污染程度如何,这些问题还没有被广泛接受的解决方案。OpenCompass 提供了两种可能的解决方案。
实验评估步骤
9.1 基于自建同分布数据的污染数据标注
我们参考了 Skywork 中 5.2 节提到的方法,直接使用了 Skywork 上传到 HuggingFace 上的数据集 mock_gsm8k_test。
在该方法中,作者使用 GPT-4 合成了一批与原始 GSM8K 风格类似的数据,然后使用模型分别计算在 GSM8K 训练集 (train),GSM8K 测试集 (test),GSM8K 参考集 (ref) 上的困惑度。由于 GSM8K 参考集是最新生成的,作者认为它必然不属于任何模型的任何训练集中,即它是干净的。作者认为:
- 若 测试集 的困惑度远小于 参考集 的困惑度,那么 测试集 可能出现在了模型的训练阶段;
- 若 训练集 的困惑度远小于 测试集 的困惑度,那么 训练集 可能被模型过拟合了。
9.2 基于经典预训练集的污染数据标注
感谢 Contamination_Detector 以及 @liyucheng09 提供了本方法。
在该方法中,作者将测试数据集 (例如 C-Eval, ARC, HellaSwag 等) 使用 Common Crawl 数据库和 Bing 搜索引擎来进行检索,然后依次标记每条测试样本是 干净的 / 题目被污染的 / 题目和答案均被污染的。
测试时,OpenCompass 会分别汇报 ceval 在三种标签所组成的子集上的准确率或困惑度。一般来说,准确率从低到高依次是 干净的,题目被污染的,题目和答案均被污染的 子集。作者认为:
- 若三者性能较为接近,则模型在该测试集上的污染程度较轻;反之则污染程度较重。
目前该方案仅支持 C-Eval, MMLU, HellaSwag 和 ARC 数据集,Contamination_Detector 中还包含了 CSQA 和 WinoGrande,但目前还没有在 OpenCompass 中实现。我们欢迎社区贡献更多的数据集。
10. 大海捞针:星辰藏海深,字海寻珠难
10.1 大海捞针测试简介
大海捞针测试(灵感来自 NeedleInAHaystack)是指通过将关键信息随机插入一段长文本的不同位置,形成大语言模型 (LLM) 的Prompt,通过测试大模型是否能从长文本中提取出关键信息,从而测试大模型的长文本信息提取能力的一种方法,可反映LLM长文本理解的基本能力。
10.2 数据集介绍
Skywork/ChineseDomainModelingEval 数据集收录了 2023 年 9 月至 10 月期间发布的高质量中文文章,涵盖了多个领域。这些文章确保了公平且具有挑战性的基准测试。 该数据集包括特定领域的文件:
- zh_finance.jsonl 金融
- zh_game.jsonl 游戏
- zh_government.jsonl 政务
- zh_movie.jsonl 电影
- zh_tech.jsonl 技术
- zh_general.jsonl 综合
这些文件用于评估LLM对不同特定领域的理解能力。
10.3 大海捞针(NEEDLE IN A HAYSTACK)实验评估
大海捞针(Needle In A Haystack)实验评估 — OpenCompass 0.2.5 文档
内容较简单,具体执行过程略过。
任务介绍
在OpenCompass的NeedleBench框架中,为了全面评估模型在长文本信息提取和推理方面的能力,我们设计了一系列逐渐增加难度的测试方案。
- 单一信息检索任务(Single-Needle Retrieval Task, S-RT):评估LLM在长文本中提取单一关键信息的能力,测试其对广泛叙述中特定细节的精确回忆能力。这对应于原始的大海捞针测试任务设定。
- 多信息检索任务(Multi-Needle Retrieval Task, M-RT):探讨LLM从长文本中检索多个相关信息的能力,模拟实际场景中对综合文档的复杂查询。
- 多信息推理任务(Multi-Needle Reasoning Task, M-RS):通过提取并利用长文本中的多个关键信息来评估LLM的长文本能力,要求模型对各关键信息片段有综合理解。
- 祖先追溯挑战(Ancestral Trace Challenge, ATC):通过设计“亲属关系针”,测试LLM处理真实长文本中多层逻辑挑战的能力。在ATC任务中,通过一系列逻辑推理问题,检验模型对长文本中每个细节的记忆和分析能力,在此任务中,我们去掉了无关文本(Haystack)的设定,而是将所有文本设计为关键信息,LLM必须综合运用长文本中的所有内容和推理才能准确回答问题。
11. OpenCompass平台指引 | 贡献数据集
提交地址:https://hub.opencompass.org.cn/dataset-submit?lang=[object%20Object]
提交指南已经写的非常详细了, 这里只讲重点内容。
- 在网页Dataset Configuration的tab也上面,第三条下面可以下载模板, 也可以看一个样例。
- 下载datacard-template.zip到本地。解压后得到连个文件,leaderboard.xlsx 和 README_OPENCOMPASS.md
- README_OPENCOMPASS.md # 用于记录数据集元数据以及 README
- leaderboard.xlsx ( 选填 ) # 用于生成评测 Leaderboard
- README_OPENCOMPASS.md相对比较简单,主要是一些基本的信息记录。
- leaderboard.xlsx内容比较多,包括6个部分:Model、Test、Dev、dimension_cat、function_cfg、CN
- 填写好相关内容上传到网上即可。整个过程非常简单。