Datawhale AI 夏令营第三期复杂推理能力评估Task2-baseline精读

本次挑战基于Qwen开源大模型,利用大语言模型的学习和推理能力,完成数学、逻辑推理等问题

1.速通baseline

1)根据Datawhale官方给出的速通文档从零入门AI逻辑推理,按照步骤报名天池赛事,并开通阿里云零积平台的大模型服务。

2)使用阿里云账号登录魔搭Notebook

3)下载速通文档中的baseline01.ipynb、round1_test_data.jsonl两个文件,并上传到Notebook中,就可以开始跑代码啦~

step1:环境配置
!pip install scipy openai tiktoken retry dashscope loguru
step2:导入所需要的库

其中包括日志、多线程、api等库,最后注意MODEL_NAME需要找个免费的大模型,可以在灵积平台-计费管理查看限时免费的开源大模型。

from multiprocessing import Process, Manager
import json
import os
from pprint import pprint
import re
from tqdm import tqdm
import random

import uuid
import openai
import tiktoken
import json
import numpy as np
import requests
from retry import retry
from scipy import sparse
#from rank_bm25 import BM25Okapi
#import jieba
from http import HTTPStatus
import dashscope


from concurrent.futures import ThreadPoolExecutor, as_completed
from loguru import logger
import json
import time
from tqdm import tqdm

logger.remove()  # 移除默认的控制台输出
logger.add("logs/app_{time:YYYY-MM-DD}.log", level="INFO", rotation="00:00", retention="10 days", compression="zip")

MODEL_NAME = 'qwen1.5-1.8b-chat'  # 截止到7.26日下午15:00,该模型在灵积平台限时免费
step3:api-key

灵积平台-API-KEY管理创建自己的api-key并填入。

# 注意:这里需要填入你的key~ 咱们在第二步申请的。
dashscope.api_key = "sk-****************"
step4:大模型部分

调用Qwen大模型

def call_qwen_api(MODEL_NAME, query):
    # 这里采用dashscope的api调用模型推理,通过http传输的json封装返回结果
    messages = [
        {'role': 'user', 'content': query}]
    response = dashscope.Generation.call(
        MODEL_NAME,
        messages=messages,
        result_format='message',  # set the result is message format.
    )
    if response.status_code == HTTPStatus.OK:
        # print(response)
        return response['output']['choices'][0]['message']['content']
    else:
        print('Request id: %s, Status code: %s, error code: %s, error message: %s' % (
            response.request_id, response.status_code,
            response.code, response.message
        ))
        raise Exception()

如果请求失败,将在三秒后用retry函数重试

def api_retry(MODEL_NAME, query):
    max_retries = 5
    retry_delay = 60  # in seconds
    attempts = 0
    while attempts < max_retries:
        try:
            return call_qwen_api(MODEL_NAME, query)
        except Exception as e:
            attempts += 1   
            if attempts < max_retries:
                logger.warning(f"Attempt {attempts} failed for text: {query}. Retrying in {retry_delay} seconds...")
                time.sleep(retry_delay)
            else:
                logger.error(f"All {max_retries} attempts failed for text: {query}. Error: {e}")
                raise

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

抽取函数,与推理模板相对应,用正则表达式进行匹配

def extract(input_text):
    ans_pattern = re.compile(r"答案是:(.)", re.S)

    problems = ans_pattern.findall(input_text)
    # print(problems)
    if(problems == ''):
        return 'A'
    return problems[0]

线程池,控制多线程运行程序

def process_datas(datas,MODEL_NAME):
    results = []
    with ThreadPoolExecutor(max_workers=16) as executor:
        future_data = {}
        lasttask = ''
        lastmark = 0
        lens = 0
        for data in tqdm(datas, desc="Submitting tasks", total=len(datas)):
            problem = data['problem']
            for id,question in enumerate(data['questions']):
                prompt = get_prompt(problem, 
                                    question['question'], 
                                    question['options'],
                                    )

                future = executor.submit(api_retry, MODEL_NAME, prompt)
                
                future_data[future] = (data,id)
                time.sleep(0.6)  # 控制每0.5秒提交一个任务
                lens += 1
        for future in tqdm(as_completed(future_data), total=lens, desc="Processing tasks"):
            # print('data',data)
            data = future_data[future][0]
            problem_id = future_data[future][1]
            try:
                res  = future.result()
                extract_response = extract(res)
                # print('res',extract_response)
                data['questions'][problem_id]['answer'] = extract_response
                results.append(data)
                # print('data',data)
                
            except Exception as e:
                logger.error(f"Failed to process text: {data}. Error: {e}")
    
    return results

主函数,对代码进行启动

def main(ifn, ofn):
    if os.path.exists(ofn):
        pass
    data = []
    # 按行读取数据
    with open(ifn) as reader:
        for line in reader:
            sample = json.loads(line)
            data.append(sample)
    datas = data
    # print(data)
    # 均匀地分成多个数据集
    return_list = process_datas(datas,MODEL_NAME)
    print(len(return_list))
    print("All tasks finished!")
    return return_list

评估函数,对结果进行评估

def evaluate(ofn):
    data = []
    with open(ofn) as reader:
        for line in reader:
            sample = json.loads(line)
            data.append(sample)

    pse = 0
    cnt = 0
    tot = 0
    for task in data:
        for question in task['questions']:
            
            if MODEL_NAME in question:
                tot += 1
                cnt += question[MODEL_NAME] == question['answer']
            else:
                pse += 1

    print(cnt, tot, cnt/tot, pse)

对结果进行去重与排序

def has_complete_answer(questions):
    # 这里假设完整答案的判断逻辑是:每个question都有一个'answer'键
    for question in questions:
        if 'answer' not in question:
            return False
    return True

def filter_problems(data):
    result = []
    problem_set = set()

    for item in data:
        # print('处理的item' ,item)
        problem = item['problem']
        if problem in problem_set:
            # 找到已存在的字典
            for existing_item in result:
                if existing_item['problem'] == problem:
                    # 如果当前字典有完整答案,替换已存在的字典
                    if has_complete_answer(item['questions']):
                        existing_item['questions'] = item['questions']
                        existing_item['id'] = item['id']
                    break
        else:
            # 如果当前字典有完整答案,添加到结果列表
            if has_complete_answer(item['questions']):
                result.append(item)
                problem_set.add(problem)

    return result

查找缺失的序号

def find_missing_ids(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)

# 示例字典列表
dict_list = sorted_data

# 找出缺失的序号
missing_ids = find_missing_ids(dict_list)
print("缺失的序号:", missing_ids)

对缺失的答案进行补充,统一填充为‘A’

data  = []
with open('round1_test_data.jsonl') as reader:
    for id,line in enumerate(reader):
        if(id in missing_ids):
            sample = json.loads(line)
            for question in sample['questions']:
                question['answer'] = 'A'
            sorted_data.append(sample)
sorted_data = sorted(sorted_data, key=lambda x: int(str(x['id'])[-3:]))
        

将结果保存为upload.jsonl文件

with open('upload.jsonl', 'w') as writer:
    for sample in sorted_data:
        writer.write(json.dumps(sample, ensure_ascii=False))
        writer.write('\n')

4)最后别忘了下载结果文件upload.jsonl,并上传到官网进行打分,大概等待一两分钟就可以查看分数啦。

2.改进思路

提示工程(Prompt Engineering)
提示工程是一种新兴的领域,专注于创建和优化提示词,以便用户能够更有效地将大型语言模型(LLM)应用于不同的场景和研究领域。通过学习和掌握提示工程,用户可以更深入地理解大型语言模型的功能及其限制。

该学科使得研究人员能够通过精心设计的提示,增强大型语言模型在处理复杂任务,比如问答和算数推理等方面的能力。同时,开发者可以利用这一学科的技术和方法,开发出能够与大型语言模型及其他工具更有效集成的应用技术。

提示工程远不止是制定和开发提示词那么简单,它还涉及到一系列与大型语言模型互动和开发相关的技能与技术。这一领域对于优化大语言模型的交互、集成以及理解其能力都至关重要。用户可以通过精于提示工程,不仅提升大型语言模型的安全使用,还能够借助特定行业知识和外部工具来扩展模型的功能和效能。

我将提示词改为:假设你是一位具有高级逻辑推理能力的专家,对解答逻辑题目非常擅长。我将给出一个逻辑推理题,它是一道单项选择题。请注意,这个问题基于“闭世界假设”,意味着如果某个事实没有在题目中明确提出,那么就假定该事实为假。利用你的知识,我需要你逐步分析这个问题,然后以最清晰和最专业的方式解释你的推理过程。请在你的回答最后,明确地以”答案是:A/B/C/D(根据实际选项填写)“的形式给出结论。现在,请开始分析以下题目:
### 题目:
{problem}
### 问题:
{question}
{options}

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值