今天是2023年11月3日,星期五,北京,天气晴,
最近卷入长文本,我们来看看如何进行长文本评估。
先说问题,benchmark评长文本依旧存在偏差,且与真实side by side评测有很大差距。
归结的说,当前长文本评测主要靠特定任务,比如抽取问答,以及ppl困惑度,这些学术角度下的评测任务设计,评测数量设定,很有趣。
本文主要介绍Longbench和longeval两种评测任务,供大家一起参考。
一、longbench
LongBench是一个多任务、中英双语、针对大语言模型长文本理解能力的评测基准。
在目前大模型多语言能力引起广泛关注的背景下,LongBench涵盖了不同的语言(中文和英文),以此来对大模型在长文本下的多语言能力进行更全面的评估。
同时,LongBench由六大类、二十一个不同的任务组成,覆盖了单文档QA、多文档QA、摘要、Few-shot学习、合成任务和代码补全等关键的长文本应用场景。
地址:https://github.com/THUDM/LongBench/tree/main
LongBench包含14个英文任务、5个中文任务和2个代码任务,多数任务的平均长度在5k-15k之间,共包含4750条测试数据。
此外,还通过均匀采样得到了长度分布更均匀的测试集合LongBench-E,在0-4k、4k-8k、8k+长度区间内的数据量相当,以提供模型在不同长度下性能变化的分析。
1、数据集具体含义
HotpotQA:基于多篇给定的文档,回答相关问题
2WikiMultihopQA:基于多篇给定的文档,回答相关问题
MuSiQue:基于多篇给定的文档,回答相关问题
DuReader:基于多篇给定的检索文档,回答相关的中文问题
MultiFieldQA-en:基于单篇文档,回答英文问题,文档所属的领域相对多元
MultiFieldQA-zh:基于单篇文档,回答中文问题,文档所属的领域相对多元
NarrativeQA:基于故事或剧本提问,包括对人物、情节、主题等重要元素的理解
Qasper:基于单篇论文的提出,问题由NLP的读者提出,并由NLP从业者回答
GovReport:摘要任务,要求对政府的工作报告进行总结摘要
QMSum:摘要任务,要求基于用户的查询对会议记录进行摘要
MultiNews:多文档摘要任务,要求基于多篇新闻进行摘要
VCSUM:摘要任务,要求对中文会议记录进行总结摘要
TriviaQA:单文档问答任务,提供若干的FewShot样例
SAMSum:对话摘要任务,提供若干的FewShot样例
TREC:分类任务,要求对问题进行分类,一共包含50个类别
LSHT:中文分类任务,要求对新闻进行分类,一共包含24个类别
PassageRetrieval-en:给定30个英文维基的段落,判断给定的摘要属于哪个段落
PassageCount:判断给定的若干的段落中不重复的段落一共有几个
PassageRetrieval-zh:给定若干个出自C4数据集的中文段落,判断给定的摘要属于哪个段落
LCC:给定一段较长代码,要求预测出下一行代码
RepoBench-P:给定一个github仓库内多个文件中的代码(包含文件间依赖),要求预测出下一行代码
2、数据构造方式
对于所有基于已有数据集构造的任务,均选用原有数据集的验证集或测试集的数据(VCSUM任务除外)
1、HotpotQA(https://hotpotqa.github.io/), 2WikiMultihopQA(https://aclanthology.org/2020.coling-main.580/), MuSiQue(https://arxiv.org/abs/2108.00573)和DuReader(https://github.com/baidu/DuReader)任务基于原始的数据集构建,并进行相关处理使其适用于长文本评测。具体地,对于验证集中的问题,我们会选取包含答案的evidence passage和若干干扰的文章,这些文章和原始的问题共同组成了相关任务的输入。
2、MultiFiedQA-zh和MultiFieldQA-en任务由约10种来源的长文本数据组成,包含Latex论文、裁判文书、政府工作报告和谷歌索引的PDF文档等。对于每篇长文本,邀请了若干博士生和硕士生来进行标注,即基于长文本提问,并给出正确的答案。为了更好地进行自动化评测,要求标注员尽可能提出有确定性答案的问题。
3、NarrativeQA(https://arxiv.org/pdf/1712.07040.pdf), Qasper(https://arxiv.org/pdf/2105.03011.pdf), GovReport(https://arxiv.org/pdf/2104.02112.pdf),QMSum(https://arxiv.org/pdf/2104.05938.pdf)和MultiNews(https://aclanthology.org/P19-1102.pdf)任务直接使用原论文提供的数据。在具体的构建中,使用ZeroSCROLLS(https://www.zero.scrolls-benchmark.com/)提供的模板来将对应的数据转换为纯文本的输入。
4、VCSUM(https://arxiv.org/abs/2305.05280)任务基于原始的数据集构建,针对该数据设计了相应的模板将对应的数据转换为纯文本的输入。
5、TriviaQA(https://nlp.cs.washington.edu/triviaqa/)任务参考CoLT5(https://arxiv.org/abs/2303.09752)的方式进行构建,即会提供若干基于文档进行问答的样例,并要求语言模型基于新的文档回答相关问题。
6、SAMSum(https://aclanthology.org/D19-5409.pdf),TREC(https://aclanthology.org/C02-1150.pdf)和LSHT(http://tcci.ccf.org.cn/conference/2014/dldoc/evatask6.pdf)任务基于原始的数据集构建。对于验证集中的每个问题,采样训练集中的若干数据组成Few-shot样例。这些样例会和验证集中的问题共同组成该任务的输入。
7、PassageRetrieval-en任务基于英文维基进行构造。对于每条数据,随机采样30段英文维基的段落,并选取其中一段进行摘要(使用GPT-3.5-Turbo)。该任务要求模型给出摘要应该对应哪个的原始段落。
8、PassageCount任务基于英文维基进行构造。对于每条数据,随机采样若干英文维基的段落,并将其中的每个段落随机重复若干次,最后将段落随机打乱。该任务要求模型判断给定的若干的段落中不重复的段落一共有几个。
9、PassageRetrieval-zh任务基于C4(https://arxiv.org/abs/1910.10683)进行构造。对于每条数据,随机采样若干段来自于C4的中文段落,并选取其中一段进行摘要(使用GPT-3.5-Turbo)。该任务要求模型给出摘要对应的那个原始段落名称。
10、LCC(https://arxiv.org/abs/2306.14893)任务基于原始的代码补全数据集采样构建。
RepoBench-P(https://arxiv.org/abs/2306.03091)任务中选取原数据集最具挑战性的XF-F(Cross-File-First)设定,并且参考原文中的Oracle-Filled场景,对于每一条原始数据随机抽取包括有效跨文件代码片段(gold snippet)在内的多个跨文件代码片段,将其拼接后作为输入,要求模型从其中利用有效的跨文件代码以补全当前文件中的代码。
二、longeval
Longeval是uc Berkeley与其他机构在研究longchat时做的一个评测任务,包括tasks和lines两个子任务。
地址:https://lmsys.org/blog/2023-06-29-longchat/
1、topic测试
1050条样本,主题数从1、5、10、15到95、100个主题,给定一个对话,给定之前关于指定个数的不同主题的对话记录。模型是助手,在每个话题开始时,用户会说 “我想讨论 <主题> 这个话题”。记住每个 <主题>。在记录结束时,要求检索第一个主题。
这个其实是检测模型在给定上下文增加的情况下,模型是否还记得第一个主题。
def longeval_test(model, tokenizer, output_dir, args):
if args.task == "topics":
for num_topics in [5, 10, 15, 20, 25]:
print(f"************ Start testing {num_topics} topics per prompt ***********")
avg_length = 0
test_file = os.path.join(args.test_dir, f“topics/testcases/{num_topics}_topics.jsonl”)
output_file = os.path.join(output_dir, f“{num_topics}_response.txt”)
test_cases = load_testcases(test_file)
for idx, test_case in tqdm(enumerate(test_cases)):
_, prompt_length, summary = test_topics_one_sample(model=model, tokenizer=tokenizer, test_case=test_case, output_file=output_file, idx=idx, args=args)
avg_length += prompt_length / len(test_cases)
print(f“************ Finish testing {num_topics} topics per prompt with average prompt length {avg_length} ************”)
if args.eval_shortest_only:
break
对应数据:
模型预期结果:
评测方式采用chatgpt
def chatgpt_auto_eval(json_list):
print("--------------- Start auto-evaluation, you should verify it does this correctly --------------")
correct = 0
for i in range(len(json_list)):
label = json_list[i].split(',')[0].replace('Label: ', '')
predict = json_list[i].split(',')[1].replace('Predict: ', '')[2:-2:]
user_prompt = f"I am testing whether a LLM model can correctly retreieve the first topic,
and would like you to help me judge whether the mode ls correct.
Please give me 1 for correct and 0 for incorrect.
Only give me a single number.
Ignore mistakes if the model is paraphasing or using synonyms.
Ignore any simple mistakes such as capitalization and punctuation.
The ground truth is {label}, the model prediction is {predict}"
content = get_eval(user_prompt)
_correct = content == "1"
correct += _correct
output_string = “correct” if _correct else “wrong”
print(f“Question #{i}: Label: {label}, Predict: {predict} – auto-eval goes with {output_string}”)
# To avoid rate limit by OPENAI
time.sleep(REQ_TIME_GAP)
print(f“———- End auto-evaluation, predict accuracy {correct / len(json_list)} —————“)
2、lines测试
该任务测试的是模型对前面内容的记忆能力,即希望模型记住行记录。每行以 “行<行索引>”开头,行尾包含一个”<REGISTER_CONTENT>”数值。对于每一行索引,模型需要记住其对应的 <REGISTER_CONTENT>。在记录结束时,会要求模型检索某一行索引对应的 <REGISTER_CONTENT>。
行数包括650条样本,行数从200、300、400、500、600、680、700、800、900、1000、1100、1200、1350不等。
elif args.task == "lines":
for num_lines in [200, 300, 400, 500, 600, 680]:
print(f"************ Start testing {num_lines} lines per LRT prompt ************")
test_file = os.path.join(args.test_dir, f"lines/testcases/{num_lines}_lines.jsonl")
output_file = os.path.join(output_dir, f"{num_lines}_response.txt")
num_correct = 0
avg_length = 0
test_cases = load_testcases(test_file)
for idx, test_case in tqdm(enumerate(test_cases)):
correct, prompt_length, summary = test_lines_one_sample(model=model, tokenizer=tokenizer, test_case=test_case, output_file=output_file, idx=idx, args=args)
avg_length += prompt_length / len(test_cases)
num_correct += correct
accuracy = num_correct / len(test_cases)
with open(output_file, “a+”) as f:
f.write(f“Accuracy: {accuracy}”)
print(f“************ Finish testing {num_lines} lines per prompt with average prompt length {avg_length}, accuracy: {accuracy} ************”)
if args.eval_shortest_only:
break
else:
print(f“Unsupported task: {args.task}”)
总结
本文主要介绍了长文本评估的两个评测数据集,包括Longbench和longeval。
从学术角度看评测任务设计,评测数量设定,很有趣。
我们也可以在此基础上设计出许多变体任务。
不过我们需要思考,长文本,32k,192k,真的如PR所说的如此惊艳么?
参考文献
1、https://github.com/THUDM/LongBench/tree/main
关于我们
老刘,刘焕勇,NLP开源爱好者与践行者,主页:https://liuhuanyong.github.io。
老刘说NLP,将定期发布语言资源、工程实践、技术总结等内容,欢迎关注。
对于想加入更优质的知识图谱、事件图谱、大模型AIGC实践、相关分享的,可关注公众号,在后台菜单栏中点击会员社区->会员入群加入。