ms-swift 代码推理数据集
目前想要对SFT微调后的模型进行测试,看官方文档ms-swift中有eval的教程,但是从介绍来看,eval使用的是modelscope的评测内容。
评测
SWIFT支持了eval(评测)能力,用于对原始模型和训练后的模型给出标准化的评测指标。
能力介绍
SWIFT的eval能力使用了魔搭社区评测框架EvalScope,并进行了高级封装以支持各类模型的评测需求。
注意:EvalScope支持许多其他的复杂能力,例如模型的性能评测,请直接使用EvalScope框架。
目前我们支持了标准评测集的评测流程,以及用户自定义评测集的评测流程。其中标准评测集由三个评测后端提供支持:
下面展示所支持的数据集名称,若需了解数据集的详细信息,请参考所有支持的数据集
可以从上述内容中看到,评估起来比较麻烦,而且针对用户自定义的测评集,需要自己重新生成csv(选择题)或者jsonl(问答题)
问答题格式(QA)
适合用户是问答题的场景,评测指标是ROUGE
和BLEU
。
数据准备
准备一个问答题格式的jsonline文件,该目录包含了一个文件:
qa/ └── example.jsonl
该jsonline文件需要为下面的格式:
{"query": "中国的首都是哪里?", "response": "中国的首都是北京"} {"query": "世界上最高的山是哪座山?", "response": "是珠穆朗玛峰"} {"query": "为什么北极见不到企鹅?", "response": "因为企鹅大多生活在南极"}
启动评测
运行下面的命令:
CUDA_VISIBLE_DEVICES=0 \ swift eval \--model Qwen/Qwen2.5-0.5B-Instruct \--eval_backend Native \--infer_backend pt \--eval_dataset general_qa \--dataset_args '{"general_qa": {"local_path": "/path/to/qa", "subset_list": ["example"]}}'
其中:
-
eval_dataset
需要设置为general_qa
-
dataset_args
是一个json字符串,需要设置:-
local_path
自定义数据集文件夹路径 -
subset_list
评测数据集名称,上述*.jsonl
中的*
-
总体上来说,评估起来比较麻烦,如果我们想要使用代码完成推理并且输出至某个文件中,可以使用swift库来实现,目前使用的swift版本为3.4.0,推理代码目前是封装的比较好的,下述的代码实现了流式推理。即可以从评测数据集中完成 先加载模型,后使用数据集中的单条数据进行推理,推理后可存储至指定文件中。
import os
from typing import List, Literal
from swift.llm import InferEngine, InferRequest, PtEngine, RequestConfig, load_dataset
from swift.plugin import InferStats
from PIL import Image # 处理图像输入(可选,根据模型要求)os.environ['ASCEND_RT_VISIBLE_DEVICES'] = '0'def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):"""流式推理函数(Pt后端)"""request_config = RequestConfig(max_tokens=1024, temperature=1, stream=True)metric = InferStats()gen_list = engine.infer([infer_request], request_config, metrics=[metric])return gen_listquery = infer_request.messages[0]['content']#print(f"流式推理 - 查询: {query}\n响应: ", end='')# for resp in gen_list[0]:# if resp and resp.choices:# print(resp.choices[0].delta.content, end='', flush=True)# #print(f"\n性能指标: {metric.compute()}\n")return result# 获取推理结果def build_image_message(image_path: str, query: str):"""构建图像+文本输入消息(Pt后端兼容格式)"""return {'role': 'user','content': [{'type': 'image', 'image': image_path}, # 支持本地路径/URL/Base64/PIL.Image{'type': 'text', 'text': query}]}infer_backend = 'pt' # 使用Pt后端
model = 'internvloutput/v3-20250507-190220/checkpoint-300-merged' # Qwen2-VL模型(可替换为本地路径)
image_url = "demo.jpg" # 示例图像URL# ====================== 初始化Pt推理引擎 ======================
engine = PtEngine(model_id_or_path=model,max_batch_size=1, # 根据GPU显存调整(34B模型建议设为1-2)device_map='auto' # 自动分配设备(支持多卡,但需确保模型支持)
)with open('./test-2.jsonl', 'r', encoding='utf-8') as infile:total_lines = sum(1 for _ in infile)# 打开输入的txt文件和输出的log文件#../wsu-data/test/txt/PATH_DT_WSU_split_test_labels.txt
#../lung_colon_image_set/test-more.jsonl
with open('./test-2.jsonl', 'r', encoding='utf-8') as infile, open('output-gas-05091.log', 'w', encoding='utf-8') as outfile:# 逐行读取txt文件# for line in infile:for i, line in enumerate(infile, 1):try:# print(i)# 导入ast模块,用于将字符串转换为Python对象import ast# 将每行字符串转换为Python字典data = ast.literal_eval(line.strip())# 提取messages列表messages = data.get('messages', [])# 提取images列表images = data.get('images', [])content_count=0# 遍历messages列表,提取每个message的content内容for message in messages:content = message.get('content', '')if content_count == 0:question=content# print(question)# 将content内容写入log文件outfile.write(f"Content: {content}\n")content_count=content_count+1# 遍历images列表,提取每个image的路径for image_path in images:# 将image路径写入log文件# image_path=image_path.replace('../images/', '../wsu-data/test/images/')image_path=image_path.replace('gastric_image_set/', './gastric_image_set/')# image_path=image_path.replace('wsu-data/', '../wsu-data/')image1 = image_pathoutfile.write(f"Image Path: {image_path}\n")outfile.write("·" * 50 + "\n") # conversation = [# {# "role": "User",# "content": f"<image_placeholder>\n{question}",# "images": [image1],# },# {"role": "Assistant", "content": ""},# ]# ====================== 构建推理请求 ======================
# 1. 单样本流式推理(图像+文本)user_message = build_image_message(image_path=image1,query=question,)infer_request_stream = InferRequest(messages=[user_message])gen_list = infer_stream(engine, infer_request_stream)outfile.write("Answer:")for resp in gen_list[0]:if resp and resp.choices:# print(resp.choices[0].delta.content, end='', flush=True)outfile.write(resp.choices[0].delta.content)outfile.write("\n")# 每20行打印一次进度if i % 20 == 0 or i == total_lines:print(f"已处理 {i}/{total_lines} 行 ({i/total_lines:.1%})") # 在每组数据之间添加分隔线outfile.write("-" * 50 + "\n")except (SyntaxError, ValueError):# 处理转换过程中可能出现的语法错误或值错误print(f"Error processing line: {line.strip()}")
上述代码即可实现swift的python 代码推理,从jsonl文件中读取测试数据,加载InternVL3进行推理,可直接修改代码中的数据集目录以及存储文件目录即可完成推理。
不足之处:尚未调试batch推理的代码,单条推理速度较低,下一步Todo :支持batch 推理