Update README.md
本模型基于qwen2-7b-instruct模型,通过LoRA的训练方式,在党务知识数据混合通用数据的数据集上进行微调,适用于党务领域FAQ问答任务;包括但不局限于党员、入党积极分子分子学习等场景。
数据集采自党务问答网中的对话,利用python脚本获取提问,人工筛选问题答案。经训练后,发现遗忘问题严重。为解决该问题,我们在重新筛选党务知识数据集的基础上,将党务数据集混合通用微调数据集通用微调数据集进行训练,训练效果明显好转。 获取党务知识数据的问题代码如下:
import requests from bs4 import BeautifulSoup import pandas as pd base_url = "https://wenda.12371.cn/liebiao.php?mod=forumdisplay&fid=3" page = 1 def fetch_page(url): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } response = requests.get(url, headers=headers) response.raise_for_status() return response.text def parse_page(html): soup = BeautifulSoup(html, 'html.parser') items = soup.find_all('li', id=lambda x: x and x.startswith('normalthread_')) data = [] for item in items: title_tag = item.find('p', class_='questionTit') title = title_tag.get_text(strip=True) if title_tag else 'N/A' data.append({'title': title}) next_page = soup.find('a', class_='next') next_page_url = next_page['href'] if next_page else None return data, next_page_url def main(): global base_url global page all_data = [] while True: url = f"{base_url}&page={page}" html = fetch_page(url) data, next_page_url = parse_page(html) print(data[0]['title']) all_data.extend(data) if next_page_url: base_url = f"https://wenda.12371.cn/{next_page_url}" page += 1 else: break for item in all_data: print(item['title']) df = pd.DataFrame(all_data) df.to_excel("D:\dangwu\问题收集.xlsx", index=False, engine='openpyxl') if __name__ == "__main__": main()
数据集格式采用如下对话形式:
{ "from": "user", "value": "介绍一下自己" }, { "from": "assistant", "value": "我是皮皮,由ModelScope开源模型应用挑战赛--外星人战队训练的人工智能党务知识小助手。我的目标是为用户提供有用、准确和及时的信息,并通过各种方式帮助用户进行有效的沟通。请告诉我有什么可以帮助您的呢?" } { "from": "user", "value": "线上转党组织关系,超过天未接收会怎么样?十二月份发起党组织关系转接,但接收地支部名称有误,导致接收地系统无法收到转接命令,期间由于系统问题,十二月和一月系统始终无法正常登录。请问这种情况下超过六十天未被接收会怎样,应该怎样解决呢?" }, { "from": "assistant", "value": "线上的流程,里面也是有转接日期的时间限制,一般不超过个月,超过了期限,介绍信无效。解决方式:原流程作废,重新发起组织关系转移的流程。" } { "from": "user", "value": "党支部纪检委员必须单设吗?如果不必须单设,是可以组织委员兼任还是宣传委员兼任,或者是都可以?" }, { "from": "assistant", "value": "要求必须设置,可以由其他委员兼任。不建议组织委员兼任,一般由宣传委员兼任。" }
数据集格式处理脚本代码如下:
import json import os import re def remove_non_chinese_chars(text): return re.sub(r'[^\u4e00-\u9fa5,。!?、;:“”‘’()《》【】]', '', text) seen_client_data = set() def Fuc(path,output_file) : global seen_client_data with open(path, 'r', encoding='utf-8') as infile: original_data = json.load(infile) output="" user_count = 0 assistant_count = 0 for item in original_data: content = remove_non_chinese_chars(item["content"]) if item["role"] == "client": if content in seen_client_data: return seen_client_data.add(content) data="{\\"from\\": \\"user\\", \\"value\\": \\""+content+"\\"}, " user_count += 1 if (user_count - assistant_count != 1): return if item["role"]=="counselor" : data = "{\\"from\\": \\"assistant\\", \\"value\\": \\"" + content + "\\"}, " assistant_count += 1 output=output+data if (user_count != assistant_count): return output="{\"conversations\": \"["+output+"]\", \"origin\": \"[]\"}" output=output[:-21]+output[-19:] with open(output_file, 'a', encoding='utf-8') as outfile: outfile.write(output + '\n') # print(output) folder_path = "C:\Users\86183\Desktop\data" output_file = "C:\Users\86183\Desktop\output.txt" try: files_and_dirs = os.listdir(folder_path) files = [f for f in files_and_dirs if os.path.isfile(os.path.join(folder_path, f))] for file in files: Fuc(os.path.join(folder_path, file), output_file) except FileNotFoundError: print(f"文件夹 {folder_path} 未找到。") except PermissionError: print(f"没有权限访问文件夹 {folder_path}。") except Exception as e: print(f"发生错误: {e}")
最后将处理好的数据集上传至ModelScope数据集,可直接在微调参数中使用。
该党务知识小助手基于qwen2-7b-struct大模型,为节省显存,我们采用LoRA微调方法。 系统:采用modelscope:1.16.1-pytorch2.3.0tensorflow2.16.1-gpu-py310-cu121-ubuntu22.04镜像 显卡:NVIDIA A10 模型:qwen2-7b-instruct 框架:魔搭轻量训推框架SWIFT 接链接https://github.com/modelscope/ms-swift 显存:最高达到20.54G的显存占用 训练时长: 2d 20h 6m 用于训练的脚本如下:
CUDA_VISIBLE_DEVICES=0 \ swift sft \ --model_type qwen2-7b-instruct \ --sft_type lora \ --output_dir output \ --dataset output_dataset \ --num_train_epochs 1 \ --max_length 1024 \ --check_dataset_strategy warning \ --lora_rank 8 \ --lora_alpha 32 \ --lora_dropout_p 0.05 \ --lora_target_modules ALL \ --gradient_checkpointing true \ --batch_size 1 \ --learning_rate 5e-5 \ --gradient_accumulation_steps 16 \ --max_grad_norm 1.0 \ --warmup_ratio 0.03 \ --eval_steps 100 \ --save_steps 100 \ --save_total_limit 2 \ --logging_steps 10
eval_loss和eval_acc效果如下:
横轴为训练步数,纵轴分别为残差值和准确率
推理脚本如下:
swift infer --ckpt_dir output/qwen2-7b-instruct/v0-20240902-123232/checkpoint-27400
best checkpoint
我们采用人工评估的方式看看大模型的训练效果,我们将展示第一次获取的党务数据集和最后经完善的混合数据集。 党务知识数据集推理效果: 回答效果不尽人意。 混合数据集推理效果: 通过对比,回答效果明显好转。 该党务知识问答模型已经上传至ModelScope党务知识问答小助手
上面我们已经把模型微调好了,接下来就是如何将我们微调好的模型部署上传到Modelscope的创空间上面去。下面是部署代码。
import os import gradio as gr from modelscope import AutoTokenizer, snapshot_download from modelscope import AutoModelForCausalLM import torch modelscope_model_path = "lzjune0315/competition" model_path = snapshot_download(modelscope_model_path) model = AutoModelForCausalLM.from_pretrained( model_path, torch_dtype=torch.float16, device_map="auto" ) tokenizer = AutoTokenizer.from_pretrained(model_path) def generate_party_answer(prompt, tokenizer, model): model_inputs = tokenizer([prompt], return_tensors="pt").to(model.device) generated_ids = model.generate( model_inputs.input_ids, max_new_tokens=64 ) generated_ids = [ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids) ] response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] return response def process_party_knowledge(question, progress=gr.Progress()): progress(0, desc="开始处理") input_prompt = "党务知识问题:" + question + " 答案:" response = generate_party_answer(input_prompt, tokenizer, model) return response demo = gr.Interface(fn=process_party_knowledge, inputs=[gr.Textbox(label="党务知识问题", lines=10)], outputs=[gr.Textbox(label="答案", lines=10)], title="党务知识问答小助手", description="请在左边对话框输入你的党务知识问题并点击‘Submit’按钮,耐心等待一会儿,右边的对话框将显示答案。") demo.launch()
modelscope_model_path: 即我们微调后上传至Modelscope模型的路径 snapshot_download(): 从ModelScope平台下载指定路径下的模型
AutoModelForCausalLM.from_pretrained: 从指定路径加载预训练的因果语言模型 AutoTokenizer.from_pretrained: 加载与模型对应的分词器
tokenizer([prompt], return_tensors=”pt”): 将输入文本转化为模型可以处理的张量格式 model.generate: 使用模型生成回答,生成最多64个新词 batch_decode: 将生成的ID序列转回人类可读的文本
process_party_knowledge: 处理用户问题并生成答案的函数
gr.Interface: 创建一个交互式网页界面
该智能体应用已经部署到创空间党务知识问答小助手
©Copyright 2023 CCF 开源发展委员会 Powered by Trustie& IntelliDE 京ICP备13000930号
ModelScope开源模型应用挑战赛-外星人战队党务知识问答小助手微调和智能体应用文档
本模型基于qwen2-7b-instruct模型,通过LoRA的训练方式,在党务知识数据混合通用数据的数据集上进行微调,适用于党务领域FAQ问答任务;包括但不局限于党员、入党积极分子分子学习等场景。
目录
数据准备
数据集采自党务问答网中的对话,利用python脚本获取提问,人工筛选问题答案。经训练后,发现遗忘问题严重。为解决该问题,我们在重新筛选党务知识数据集的基础上,将党务数据集混合通用微调数据集通用微调数据集进行训练,训练效果明显好转。 获取党务知识数据的问题代码如下:
数据集格式采用如下对话形式:
数据集格式处理脚本代码如下:
最后将处理好的数据集上传至ModelScope数据集,可直接在微调参数中使用。
微调
该党务知识小助手基于qwen2-7b-struct大模型,为节省显存,我们采用LoRA微调方法。 系统:采用modelscope:1.16.1-pytorch2.3.0tensorflow2.16.1-gpu-py310-cu121-ubuntu22.04镜像 显卡:NVIDIA A10 模型:qwen2-7b-instruct 框架:魔搭轻量训推框架SWIFT 接链接https://github.com/modelscope/ms-swift 显存:最高达到20.54G的显存占用 训练时长: 2d 20h 6m 用于训练的脚本如下:
训练效果
eval_loss和eval_acc效果如下:

推理
推理脚本如下:
我们采用人工评估的方式看看大模型的训练效果,我们将展示第一次获取的党务数据集和最后经完善的混合数据集。 党务知识数据集推理效果:
回答效果不尽人意。
混合数据集推理效果:
通过对比,回答效果明显好转。
该党务知识问答模型已经上传至ModelScope党务知识问答小助手
智能体应用
上面我们已经把模型微调好了,接下来就是如何将我们微调好的模型部署上传到Modelscope的创空间上面去。下面是部署代码。
下载模型
modelscope_model_path: 即我们微调后上传至Modelscope模型的路径 snapshot_download(): 从ModelScope平台下载指定路径下的模型
加载模型和分词器
AutoModelForCausalLM.from_pretrained: 从指定路径加载预训练的因果语言模型 AutoTokenizer.from_pretrained: 加载与模型对应的分词器
定义生成党务知识答案的函数
tokenizer([prompt], return_tensors=”pt”): 将输入文本转化为模型可以处理的张量格式 model.generate: 使用模型生成回答,生成最多64个新词 batch_decode: 将生成的ID序列转回人类可读的文本
定义处理函数
process_party_knowledge: 处理用户问题并生成答案的函数
创建Gradio接口
gr.Interface: 创建一个交互式网页界面
该智能体应用已经部署到创空间党务知识问答小助手