赛事链接:http://competition.sais.com.cn/competitionDetail/532231/format
往期入门文档 Docs
本期入门文档 Datawhale
在跑完baseline的基础上,没有改prompt和微调模型,只是修复和查了一些bug,调用qwen2-72b-instruct的api取得top1的score,积累了一些经验。
Prompt模板
这里引用了官方baseline里的模板,听很多小伙伴说还有优化空间,后面试一下。
# 这里定义了prompt推理模版
def get_prompt(problem, question, options):
options = '\n'.join(f"{'ABCDEFG'[i]}. {o}" for i, o in enumerate(options))
prompt = f"""你是一个逻辑推理专家,擅长解决逻辑推理问题。以下是一个逻辑推理的题目,形式为单项选择题。所有的问题都是(close-world assumption)闭世界假设,即未观测事实都为假。请逐步分析问题并在最后一行输出答案,最后一行的格式为"答案是:A"。题目如下:
### 题目:
{problem}
### 问题:
{question}
{options}
"""
# print(prompt)
return prompt
后处理优化
答案抽取
因为在实际预测结果的过程中,发现很多匹配不上的情况,baseline中采用正则匹配的规则是r"答案是: (.)",这里改成r"答案是: (\w)",因为出现很多"答案是: 无法确定"的情况;因为有推理中间结果,如果出现多条匹配结果,以最后一条为准。
# 这里使用extract抽取模获得抽取的结果,如果不在可选范围内,选最后一个
import re
def extract(input_text, options=['A', 'B', 'C', 'D', 'E', 'F', 'G']):
problems = re.findall(r"答案是:(\w)", input_text)
print(f"problems: {problems}")
for problem in problems[::-1]:
if problem in options:
return problem
print(f'[ERROR] input_text:{input_text} answer: {problems[0]}')
return 'NULL'
extract('''
根据题目中的规则,同性朋友是指两个都是男性或两个都是女性的朋友。Antoni是男性,因此他的同性朋友也必须是男性。选项中只有A、B、C是男性,而D选项Maria是女性,所以不可能是Antoni的同性朋友。
在A、B、C三个选项中,我们需要确定谁是Antoni的同性朋友。但是,题目中并没有给出Antoni具体和谁是朋友的信息,只是说明了如果两个人互相关注,那么他们是朋友。由于我们没有具体的朋友关系信息,我们只能基于性别来判断,即Antoni的同性朋友必须是男性。
在没有更多信息的情况下,我们不能确定Antoni具体和哪一位男性是朋友,但是我们知道他的同性朋友一定是在John、George和Nick之中。然而,选择题通常要求一个确切的答案,这里我们被问到的是“谁是”,而不是“可能是”。由于题目没有提供足够的信息来确定Antoni的确切同性朋友,从逻辑上讲,我们无法从给定的选项中选出一个确切的人作为正确答案。但是,按照题目要求和选项设置,我们可以理解为需要选择一个最符合“同性朋友”定义的选项,在这个前提下,我们只能从A、B、C中选择,而D显然不符合条件。
答案是:这个问题在给出的信息下无法精确解答,但从选项中选择一个最符合“同性朋友”定义的,答案可以是A、B或C中的任意一个,但由于题目要求选择一个答案,我们无法确定具体是哪一个。然而,按照题目要求,我们需要给出一个选项,因此在没有更多信息的情况下,我们可以选择其中一个男性作为答案,例如A。
答案是:A''')
中间结果记录
这个是调用api的问题,因为api经常有超时,RPM的限制,所有改了一下脚本,支持记录每次结果,并且重复调用脚本时支持自动过滤掉已有答案的case,在后面跑finetune版本也可用。
提问合并
baseline是一个problem的多个question拆开,单独调用api,因为python里是引用变量,然后在多个结果中找到一个problem的所有question都有answer的为最终problem。这里便于理解,改成多个question单独调用,然后把problem对应的所有quesion和answer合并。
# 合并问题
def merge_problems(data):
problems = {}
for item in data:
problem = item['problem']
if problem in problems:
exist_problem = problems[problem]
for id, question in enumerate(item['questions']):
if 'answer' not in exist_problem['questions'][id] and 'answer' in item['questions'][id]:
exist_problem['questions'][id]['answer'] = item['questions'][id]['answer']
else:
problems[problem] = item
return problems.values()
问题检查
最后就是对问题和提问进行检查,是否所有的problem的所有question都有答案。
total_id = 0
def find_missing_ids(data):
global total_id
missing_ids = set()
for item in data:
for id, question in enumerate(item['questions']):
if 'answer' not in question:
missing_ids.add(f"{item['id']}_{id}")
# question['answer'] = 'A'
total_id += 1
return sorted(missing_ids)
def find_missing_problems(dict_list):
# 提取所有序号
extracted_ids = {int(d['id'][-3:]) for d in dict_list}
# 创建0-500的序号集合
all_ids = set(range(500))
# 找出缺失的序号
missing_ids = all_ids - extracted_ids
return sorted(missing_ids)
计划
后面将尝试几个方面:
- prompt优化, COT等
- RAG+agent tool use
- finetune 模型,模型蒸馏与量化
- 数据扩充
附录
面向开发者的LLM入门课:
https://www.bilibili.com/video/BV1Bo4y1A7FU
https://github.com/datawhalechina/prompt-engineering-for-developersPrompt从入门到应用:https://www.bilibili.com/video/BV11o4y147K7
ChatGPT原理与实践:
https://github.com/datawhalechina/hugging-llm
https://www.bilibili.com/video/BV1kk4y177AJ开源大模型食用指南:https://github.com/datawhalechina/self-llm
从零到一动手实现LLM:https://github.com/datawhalechina/llms-from-scratch-cn
动手学大模型应用开发:https://github.com/datawhalechina/llm-universe
智能体应用开发:https://github.com/datawhalechina/agent-tutorial
大模型学习路径汇总:https://datawhaler.feishu.cn/wiki/BPOHw1TqGidYHrkeJg7cqHiSnQc
Datawhale人工智能培养方案: https://datawhaler.feishu.cn/wiki/JcnEwCYO2i0v3FkBizWcLfWanKb