Datawhale AI夏令营 AI+逻辑推理 Task2总结

Datawhale AI夏令营 AI+逻辑推理 Task2总结

一、大语言模型解题方案介绍

1.1 大模型推理介绍

​ 推理是建立在训练完成的基础上,将训练好的模型应用于新的、未见过的数据,模型利用先前学到的规律进行预测、分类和生成新内容,使得AI在实际应用中能够做出更有意义的决策。

1.2 大模型推理实现最常用方法——提示工程(Prompt Engineering)

​ 提示工程是一门较新的学科,关注提示词开发和优化,帮助用户将大语言模型用于各场景和研究领域。研究人员可利用提示工程来提升大语言模型处理复杂任务场景的能力,如问答和算术推理能力。开发人员可通过提示工程设计、研发强大的工程技术,实现和大语言模型或其他生态工具的高效接轨。

​ 提示工程不仅仅是关于设计和研发提示词。它包含了与大语言模型交互和研发的各种技能和技术。提示工程在实现和大语言模型交互、对接,以及理解大语言模型能力方面都起着重要作用。用户可以通过提示工程来提高大语言模型的安全性,也可以赋能大语言模型,比如借助专业领域知识和外部工具来增强大语言模型能力。

本赛题中,通过数据处理,将问题字典转化为MD格式的prompt,这就是让大语言模型能理解并作分析的秘诀。

二、Baseline整体代码介绍

整体代码主要包括答案生成纠错与结果文件生成两大模块。

答案生成部分包括大模型的处理函数、大模型返回结果抽取、多线程处理及答案生成的启动,代码核心是大模型部分

纠错与结果生成部分存在的目的是由于目前使用了API调用在线开源大模型,因为网络、模型能力等原因会导致有一些结果会出现缺失。(比如大模型回答时,没有明确给出ABCD的结果,而返回的空值。也有时因为网络retry模块机会使用结束后,依然没有提取到结果会跳过某个问题。)

在这里插入图片描述

2.1 环境配置

导入需要的环境,包括日志处理、多线程、API请求等相关库引入。

import json
import os
from pprint import pprint
import re
from tqdm import tqdm
import randomimport uuid
import openai
import tiktoken
import json
import numpy as np
import requests
from retry import retry
from scipy import sparse
from http import HTTPStatus
import dashscopefrom concurrent.futures import ThreadPoolExecutor, as_completed
from loguru import logger
import json
import time
from tqdm import tqdmlogger.remove()  # 移除默认的控制台输出
logger.add("logs/app_{time:YYYY-MM-DD}.log", level="INFO", rotation="00:00", retention="10 days", compression="zip")MODEL_NAME = 'qwen2-7b-instruct'

2.2 答案生成部分

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

call_qwen_api函数就是通过输入模型名称、prompt,完成大模型api的调用。

def api_retry(MODEL_NAME, query):# 最大尝试次数max_retries = 5# 再次尝试等待时间retry_delay = 60  # in secondsattempts = 0while 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

api_retry函数是当大模型调用API时可能会导致出错中断的问题,为了保证每个问题都被大模型处理过,我们需要设置一个反复尝试的函数。

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

get_prompt是prompt的模板函数,通过字符串处理的方式拼接完整的prompt

# 这里使用extract抽取模获得抽取的结果def extract(input_text):# re.compile()将字符串形式的正则表达式编译为Pattern模式对象,第二个参数是匹配模式ans_pattern = re.compile(r"答案是:(.)", re.S)problems = ans_pattern.findall(input_text)# print(problems)if(problems == ''):return 'A'return problems[0]

通过抽取函数可以将大语言模型生成的结果抽取成答案对应的选项,这里的匹配原则和prompt呼应。我们可以看到prompt要求【最后一行的格式为"答案是:A"】这样的规范,那么我们采用正则表达式re.compile方法匹配到答案对应的选项。当我们匹配为空时,我们默认选"A"。

def process_datas(datas,MODEL_NAME):results = []# 定义线程池 选择16线程with ThreadPoolExecutor(max_workers=16) as executor:# 使用future_data 存储每个线程的数据future_data = {}lasttask = ''lastmark = 0# lens记录了调用api的次数,也就是每个问题背景下的所有子问题之和lens = 0# 进入多线程任务# 这里每个data下是一个问题背景,其中包含多个子问题for data in tqdm(datas, desc="Submitting tasks", total=len(datas)):problem = data['problem']# 用enumerate方法每次循环得到问题的序号id和实际的问题for id, question in enumerate(data['questions']):prompt = get_prompt(problem, question['question'], question['options'],)# 送入线程池等待处理,使用api_retry,向api_retry传入MODEL_NAME,prompt参数future = executor.submit(api_retry, MODEL_NAME, prompt)# 每个线程存储对应的json问题数据以及问题序号id,方便定位出执行的是哪个子问题future_data[future] = (data, id)time.sleep(0.6)  # 控制每0.6秒提交一个任务lens += 1# 处理多线程任务for future in tqdm(as_completed(future_data), total=lens, desc="Processing tasks"):# print('data',data)# 取出每个线程中的字典数据及对应的问题iddata = future_data[future][0]problem_id = future_data[future][1]try:# 获取api运行结果res  = future.result()# 抽取大语言模型返回结果extract_response = extract(res)# print('res',extract_response)# 装入answer字段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):passdata = []# 按行读取数据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_listif __name__ == '__main__':a = extract("""根据欧几里得算法,逐步解析计算两个数6和7的最大公约数(gcd)的步骤如下:1. 判断6和7是否相等:不相等。
2. 判断6和7大小关系,7 > 6,所以用更大的数7减去较小的数6得到结果1。
3. 现在计算6和1的最大公约数。
4. 6 > 1,根据算法用更大的数6减去较小的数1得到结果5。
5. 再计算5和1的最大公约数。
6. 5 > 1,用5减去1得到结果4。
7. 再计算4和1的最大公约数。
8. 4 > 1,用4减去1得到结果3。
9. 再计算3和1的最大公约数。
10. 3 > 1,用3减去1得到结果2。
11. 再计算2和1的最大公约数。
12. 2 > 1,用2减去1得到结果1。
13. 最后计算1和1的最大公约数,两数相等,gcd即为这两个数,也就是1。因此,6和7的最大公约数是1。答案是:C.""")print(a)# 调用主函数return_list = main('round1_test_data.jsonl', 'upload.jsonl')

启动函数

2.3 纠错与结果文件生成部分

def has_complete_answer(questions):# 这里假设完整答案的判断逻辑是:每个question都有一个'answer'键for question in questions:if 'answer' not in question:return Falsereturn Truedef 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']breakelse:# 如果当前字典有完整答案,添加到结果列表if has_complete_answer(item['questions']):result.append(item)problem_set.add(problem)return resultreturn_list
return_list = filter_problems(return_list)
sorted_data = sorted(return_list, key=lambda x: int(str(x['id'])[-3:]))
print(sorted_data)

将一个问题背景下的所有问题存入同一个字典,并按id序号排序。

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_idsreturn sorted(missing_ids)# 示例字典列表
dict_list = sorted_data# 找出缺失的序号
missing_ids = find_missing_ids(dict_list)
print("缺失的序号:", missing_ids)len(missing_ids)

纠错函数

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:]))       

补错函数,针对空缺的列表我们进行补错,让每个answer字段默认填充为A。

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

生成结果文件并存储

三、Baseline改进

  1. 原baseline中针对空缺的列表补错时,只是将每个answer字段默认填充为A,为了提高准确率,这里把它送入多线程函数再处理一遍
  2. 改进prompt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387670.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣SQL50 换座位

Problem: 626. 换座位 &#x1f468;‍&#x1f3eb; 参考题解 Code SELECT(CASEWHEN MOD(id, 2) ! 0 AND counts ! id THEN id 1WHEN MOD(id, 2) ! 0 AND counts id THEN idELSE id - 1END) AS id,student FROMseat,(SELECTCOUNT(*) AS countsFROMseat) AS seat_counts O…

C语言实现三子棋

通过一段时间的学习&#xff0c;我们已经能够较为熟练地使用分支语句&#xff0c;循环语句&#xff0c;创建函数&#xff0c;创建数组&#xff0c;创建随机数等。之前我们做过一个扫雷游戏&#xff0c;今天让我们再尝试创作一个三子棋游戏吧~ 一、三子棋游戏的思路 三子棋的游…

AI Agent调研--7种Agent框架对比!盘点国内一站式Agent搭建平台,一文说清差别!大家都在用Agent做什么?

代理&#xff08;Agent&#xff09;乃一种智能实体&#xff0c;具备自主环境感知与决策行动能力&#xff0c;旨在达成既定目标。作为个人或组织之数字化替身&#xff0c;AI代理执行特定任务与交易&#xff0c;其核心价值在于简化工作流程&#xff0c;削减繁复性&#xff0c;并有…

IoTDB 入门教程 实战篇④——C#示例(开源)

文章目录 一、前文二、新建C#项目三、NuGet安装四、示例源码五、查询数据六、参考 一、前文 IoTDB入门教程——导读 本文详细阐述了如何通过一个C#项目成功连接到IoTDB时序数据库&#xff0c;进而展示了如何向该数据库高效地写入数据以及执行精确的数据查询操作。 此示例旨在为…

Javascript前端面试基础(九)

浏览器缓存 浏览器缓存分为强缓存和协商缓存。当客户端请求某个资源时&#xff0c;获取缓存的流程如下 先根据这个资源的一些http header判断它是否命中强缓存&#xff0c;如果命中则直接从本地获取缓存资源&#xff0c;不会发请求到服务器;当强缓存没有命中时&#xff0c;客户…

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案 文章目录 No matching signal for xxx 解决方案附录&#xff1a;C语言到C的入门知识点&#xff08;主要适用于C语言精通到Qt的C开发入门&#xff09;C语言与C的不同C中写C语言代码C语言到C的知识点Qt开发中…

企业级Linux系统防护

一、企业级Linux系统防护概述 一&#xff09;企业级Linux系统安全威胁 企业级Linux系统安全威胁列表 解决的主要安全威胁安全威胁牵涉到的人员及操作文件系统防护避免有意/无意的文件篡改、越权访问&#xff0c;根用户&#xff08;root&#xff09;权限泛滥企业内部用户误操作、…

UPLOAD-LABS靶场[超详细通关教程,通关攻略]

---------------------------------------- 靶场环境&#xff1a; 下载链接&#xff1a; https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master 使用小皮集成环境来完成这个靶场 将文件放到WWW目录下就可以进行访问 ------------------------------------…

CTF-Web习题:[GXYCTF2019]Ping Ping Ping

题目链接&#xff1a;[GXYCTF2019]Ping Ping Ping 解题思路 访问靶机&#xff0c;得到如下页面&#xff0c;类似于URL参数 尝试用HackBar构造url传输过去看看 发现返回了ping命令的执行结果&#xff0c;可以猜测php脚本命令是ping -c 4 $ip&#xff0c;暂时不知道执行的函数…

学习Numpy的奇思妙想

学习Numpy的奇思妙想 本文主要想记录一下&#xff0c;学习 numpy 过程中的偶然的灵感&#xff0c;并记录一下知识框架。 推荐资源&#xff1a;https://numpy.org/doc/stable/user/absolute_beginners.html &#x1f4a1;灵感 为什么 numpy 数组的 shape 和 pytorch 是 tensor 是…

Ribbon负载均衡与内核原理

什么是Ribbon? 目前主流的负载方案分为两种&#xff1a; 集中式负载均衡&#xff0c;在消费者和服务提供方中间使用独立的代理方式进行负载&#xff0c;有硬件的&#xff08;比如F5&#xff09;&#xff0c;也有软件的&#xff08;Nginx&#xff09;客户端根据自己的请求做负…

FFmpeg研究

1.FFmpeg介绍 FFmpeg的全称是“Fast Forward Moving Picture Expert Group”&#xff0c;组件由命令行应用程序和函数库两部分组成。通俗概括来说&#xff0c;FFmpeg 是一个免费的开源程序库&#xff0c;一个多媒体音视频处理分析工具软件&#xff0c;且提供命令行方式调用&am…

C语言笔记38 •数据结构--队列•

数据结构--队列 1.队列的定义 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有 先 进先出 FIFO(First In First Out). 入队列&#xff1a;进行插入操作的一端称为 队尾 出队列&#xff1a;进行删除操作的…

Jmeter混合压测(2407)

一 压测需求&#xff1a; 电商作为服务端&#xff0c;至少需要满足并发量,QPS:100/s,TPS:20/s。例如场景&#xff1a; 电商交易中&#xff0c;商品图片请求量最多&#xff0c;电商服务端需要满足并发请求查询图片信息。各家可能会并发请求同一家电商商品、订单等内容。 二 压…

基于多种机器学习算法的短信垃圾分类模型

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主导入第三方库读取数据数据预处理数据分析与可视化机器学习建模贝叶斯逻辑回归支持向量机随机森林XGBoost总结每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私…

redis集群三种模式

redis 集群 高可用 redis集群三种模式 主从复制 奇数台 3 一主两从 哨兵模式 3 一主两从 cluser 集群 6 3 3 3 9 主从复制&#xff1a;和mysql的主从复制类似&#xff0c;写入主的数据通过rdb方式把数据同步到从服务器。从不能更新到主&#xff0c;…

未来不会使用 AI 的人真的会被淘汰吗?

AI 是今年大火的一个话题&#xff0c;随着 ChatGPT 之类的一系列大模型开始流行以后&#xff0c;有不少的培训机构宣称这样的口号: “未来不会使用 AI 的人将会被淘汰”。我觉得这个观点本身并没有错&#xff0c;但是关键在于那些培训机构出于自身的利益&#xff0c;故意忽略了…

内存问题检测

内存检测方式 gcc/g 内存检测方式如下&#xff0c;添加一些编译标签&#xff1a; -fsanitizeleak 检测内存泄漏。例如添加标签&#xff1a;-fsanitizeleak -g -O0-fsanitizeaddress 检测内存越界。例如添加标签&#xff1a;-fsanitizeaddress -g -O2&#xff0c;优化级别开…

02 I/O多路复用---进程的聊天

服务器同时和很多客户端连在一起 管道的read&#xff0c;总是能读出来

前后端分离开发遵循接口规范-YAPI

目前&#xff0c;网站主流开发方式是前后端分离。因此前后端必须遵循一套统一的规范&#xff0c;才能保证前后端进行正常的数据&#xff08;JSON数据格式&#xff09;请求、影响&#xff0c;这套规范即是 YAPI. 产品经理撰写原型&#xff1b; 前端或后端撰写接口文档。 YAPI…