记录一些基本思路和遇到的问题~
大模型推理的概念:计算机理解一些基本的逻辑,然后根据这些逻辑去思考问题。通过逻辑推理得出结论,例如“汤姆是一只猫,所以汤姆喜欢吃鱼”。
最常用方法——提示工程(Prompt Engineering):用设计好的提示引导模型更好地理解问题,提高准确性
因此,核心在于prompt(输入给大语言模型的文本或指令),也是对大模型微调的关键所在
代码结构
主要函数
1. 调用大模型API:call_qwen_api,注意修改为自己的模型名称!
2. 设置重试机制以处理API调用失败的情况:api_retry,如果发生异常,增加尝试次数并记录警告信息,等待指定的时间后重试。
3. 生成推理的Prompt模板:get_prompt,分成“题目problems”和问题:question options。problems比较宽泛和提供背景,questions是具体问题,options是选项
problem: “在一场比赛中,A、B、C 三位选手参加。A 比 B 快,B 比 C 快。”
question: “谁是最快的选手?”
4.提取模型返回的答案: extract
ans_pattern = re.compile(r"答案是:(.)", re.S)
使用 findall 方法在 input_text 中查找所有与 ans_pattern 匹配的部分,并将结果存储在 problems 列表中。每个匹配的结果都是正则表达式捕获组中的内容,即“答案是:”后面的字符。
*正则表达式:用特殊语法规定字符串
普通字符:直接匹配自身,例如 a 匹配字母 a。
特殊字符:如 .(匹配任意单个字符)、^(匹配字符串开头)、$(匹配字符串结尾)。
字符类:用方括号 [] 表示,可以匹配方括号内的任意单个字符。例如,[abc] 匹配 a、b 或 c。
量词:用于指定字符或字符类出现的次数:
*:匹配前一个字符零次或多次。
+:匹配前一个字符一次或多次。
?:匹配前一个字符零次或一次。
{n}:匹配前一个字符恰好 n 次。
{n,}:匹配前一个字符至少 n 次。
{n,m}:匹配前一个字符至少 n 次,但不超过 m 次。
预定义字符类:\d:匹配任何数字,等价于 [0-9]。
\D:匹配任何非数字字符。
\w:匹配任何字母数字字符(包括下划线),等价于 [a-zA-Z0-9_]。
\W:匹配任何非字母数字字符。
\s:匹配任何空白字符(如空格、制表符)。
\S:匹配任何非空白字符。
分组和捕获:使用小括号 () 来分组,可以捕获匹配的内容。例如,(abc) 匹配字符串 abc 并捕获它。
逻辑运算:| 表示“或”运算,例如 a|b 匹配 a 或 b。
5. 去重与排序:要确保每个问题都有答案,并且去除重复问题,保留完整答案。
也就是has_complete_answer和filter_problems
6. 纠错:find_missing_ids:找缺失的序号
7. 补错:针对空缺的列表让每个answer字段默认填充为A,不过可以尝试多线程:
import json
from concurrent.futures import ThreadPoolExecutor, as_completed
def process_line(line):
"""处理每一行数据的函数"""
sample = json.loads(line)
for question in sample['questions']:
question['answer'] = 'A'
return sample
data = []
sorted_data = []
# 读取文件并处理
with open('round1_test_data.jsonl') as reader:
with ThreadPoolExecutor() as executor:
futures = []
for id, line in enumerate(reader):
if id in missing_ids:
futures.append(executor.submit(process_line, line))
# 收集处理结果
for future in as_completed(futures):
sorted_data.append(future.result())
# 排序
sorted_data = sorted(sorted_data, key=lambda x: int(str(x['id'])[-3:]))
# 输出结果
print(sorted_data)
最终写入文件。