基于huggingface peft进行qwen1.5-7b-chat训练/推理/服务发布

2024-08-26 05:20

本文主要是介绍基于huggingface peft进行qwen1.5-7b-chat训练/推理/服务发布,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、huggingface peft微调框架

1、定义

PEFT 是一个大型预训练模型提供多种高效微方法的Python库。

调传统范式是针对每个下游任模型参数。大模型参数大,种方式得极其昂和不切实际PEFT采用的高效做法是训练少量提示参数(Prompt Tuning)或使用低秩适(LORA)等重新参数化方法来减少微调时训练参数的数量。

二、qwen-1.5b-chat模型训练/推理/服务

1、基础环境准备

datasets==2.21.0

transformers==4.37.0

torch==1.13.0

accelerate==0.30.1

peft==0.4.0

numpy==1.26.4

Jinja2==3.1.4

2、人设定制数据准备

[

    {

        "instruction": "你是谁?",

        "input": "",

        "output": "我是一个语言模型,我叫小飞同学,可以为您做很多事情。请问您有什么问题需要我帮助吗?"

    },

    {

        "instruction": "你是什么?",

        "input": "",

        "output": "我是一个语言模型,我叫小飞同学,可以为您做很多事情。请问您有什么问题需要我帮助吗?"

    },

    {

        "instruction": "请问您是?",

        "input": "",

        "output": "我是一个语言模型,我叫小飞同学,可以为您做很多事情。请问您有什么问题需要我帮助吗?"

    },

    {

        "instruction": "你叫什么?",

        "input": "",

        "output": "我是一个语言模型,我叫小飞同学,可以为您做很多事情。请问您有什么问题需要我帮助吗?"

},

     {

        "instruction": "你的身份是?",

        "input": "",

        "output": "我是一个语言模型,我叫小飞同学,可以为您做很多事情。请问您有什么问题需要我帮助吗?"

    }

]

2、模型训练

from datasets import Dataset

import pandas as pd

from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer, GenerationConfig

# JSON文件转换为CSV文件

df = pd.read_json('./train.json')

ds = Dataset.from_pandas(df)

model_path = './huggingface/model/Qwen1.5-7B-Chat'

tokenizer = AutoTokenizer.from_pretrained(model_path, use_fast=False, trust_remote_code=True)

def process_func(example):

    MAX_LENGTH = 384   

    input_ids, attention_mask, labels = [], [], []

    instruction = tokenizer(f"<|im_start|>system\n现在你要扮演人工智能智能客服助手--小飞同学<|im_end|>\n<|im_start|>user\n{example['instruction'] + example['input']}<|im_end|>\n<|im_start|>assistant\n", add_special_tokens=False

    response = tokenizer(f"{example['output']}", add_special_tokens=False)

    input_ids = instruction["input_ids"] + response["input_ids"] + [tokenizer.pad_token_id]

    attention_mask = instruction["attention_mask"] + response["attention_mask"] + [1

    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"] + [tokenizer.pad_token_id]

    if len(input_ids) > MAX_LENGTH:  # 做一个截断

        input_ids = input_ids[:MAX_LENGTH]

        attention_mask = attention_mask[:MAX_LENGTH]

        labels = labels[:MAX_LENGTH]

    return {

        "input_ids": input_ids,

        "attention_mask": attention_mask,

        "labels": labels

    }

tokenized_id = ds.map(process_func, remove_columns=ds.column_names)

import torch

model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16)

model.enable_input_require_grads()

from peft import LoraConfig, TaskType, get_peft_model

config = LoraConfig(

    task_type=TaskType.CAUSAL_LM,

    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],

    inference_mode=False, # 训练模式

    r=8, # Lora

    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理

    lora_dropout=0.1# Dropout 比例

)

model = get_peft_model(model, config)

args = TrainingArguments(

    output_dir="./output",

    per_device_train_batch_size=4,

    gradient_accumulation_steps=4,

    logging_steps=10,

    num_train_epochs=10,

    save_steps=50,

    learning_rate=1e-4,

    save_on_each_node=True,

    gradient_checkpointing=True

)

trainer = Trainer(

    model=model,

    args=args,

    train_dataset=tokenized_id,

    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),

)

trainer.train()

模型输出目录截图:

3、模型推理

from transformers import AutoModelForCausalLM, AutoTokenizer

import torch

from peft import PeftModel

model_path = './huggingface/model/Qwen1.5-7B-Chat'

lora_path = './output/checkpoint-50'

# 加载tokenizer

tokenizer = AutoTokenizer.from_pretrained(model_path)

# 加载模型

model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16)

from peft import LoraConfig, TaskType

config = LoraConfig(

    task_type=TaskType.CAUSAL_LM,

    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],

    inference_mode=True, # 训练模式

    r=8, # Lora

    lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理

    lora_dropout=0.1# Dropout 比例

)

# 加载lora权重

model = PeftModel.from_pretrained(model, model_id=lora_path, config=config)

prompt = "你是星火大模型吗?"

messages = [

    {"role": "system", "content": "现在你要扮演人工智能智能客服助手--小飞同学"},

    {"role": "user", "content": prompt}

]

text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

model_inputs = tokenizer([text], return_tensors="pt").to('cuda')

generated_ids = model.generate(

    input_ids=model_inputs.input_ids,

    max_new_tokens=512

)

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]

print(response)

模型推理日志截图:

4、基于FastAPI的sse协议模型服务

import uvicorn

from fastapi import FastAPI

from transformers import AutoModelForCausalLM, AutoTokenizer ,TextStreamer,TextIteratorStreamer

from threading import Thread

import torch

from peft import LoraConfig, TaskType, PeftModel

from sse_starlette.sse import EventSourceResponse

import json

# transfomershuggingface提供的一个工具,便于加载transformer结构的模型

app = FastAPI()

def load_model():

    model_path = './huggingface/model/Qwen1.5-7B-Chat'

    # 加载tokenizer

    tokenizer = AutoTokenizer.from_pretrained(model_path)

    # 加载模型(加速库attn_implementation="flash_attention_2"

    model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto",torch_dtype=torch.bfloat16

    # 加载lora权重

    lora_path = './output/checkpoint-50'

    config = LoraConfig(

        task_type=TaskType.CAUSAL_LM,

        target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],

        inference_mode=True, # 训练模式

        r=8, # Lora

        lora_alpha=32, # Lora alaph,具体作用参见 Lora 原理

        lora_dropout=0.1# Dropout 比例

    )

    model = PeftModel.from_pretrained(model, model_id=lora_path, config=config)

    return tokenizer,model

tokenizer,model = load_model()

def infer_model(tokenizer,model):

    prompt = "你是星火大模型吗?"

    messages = [

        {"role": "system", "content": "现在你要扮演人工智能智能客服助手--小飞同学"},

        {"role": "user", "content": prompt}

    ]

    #数据提取

    text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)

    model_inputs = tokenizer([text], return_tensors="pt").to('cuda')

    #streamer = TextStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

    streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)

    #模型推理

    from threading import Thread

    generation_kwargs = dict(model_inputs, streamer=streamer, max_new_tokens=512)

    thread = Thread(target=model.generate, kwargs=generation_kwargs)

    thread.start()

    for res in streamer:

        yield json.dumps({"data":res},ensure_ascii=False)

@app.get('/predict')

async def predict():

    #return infer_model(tokenizer,model)

    return EventSourceResponse(infer_model(tokenizer,model))

if __name__ == '__main__':

    # 在调试的时候开源加入一个reload=True的参数,正式启动的时候可以去掉

    uvicorn.run(app, host="0.0.0.0", port=6605, log_level="info")

客户端调用示例:

import json

import requests

import time

def listen_sse(url):

    # 发送GET请求到SSE端点

    with requests.get(url, stream=True, timeout=20) as response:

        try:

            # 确保请求成功

            response.raise_for_status()

            # 逐行读取响应内容

            result = ""

            for line in response.iter_lines():

                if line:

                    event_data = line.decode('utf-8')

                    if event_data.startswith('data:'):

                        # 去除'data:'前缀,获取实际数据

                        line = event_data.lstrip('data:')

                        line_data = json.loads(line)

                        result += line_data["data"]

                        print(result)

       except requests.exceptions.HTTPError as err:

            print(f"HTTP error: {err}")

        except Exception as err:

            print(f"An error occurred: {err}")

            return

sse_url = 'http://127.0.0.1:6605/predict'

listen_sse(sse_url

服务推理流式输出截图:

这篇关于基于huggingface peft进行qwen1.5-7b-chat训练/推理/服务发布的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107664

相关文章

springboot项目如何开启https服务

《springboot项目如何开启https服务》:本文主要介绍springboot项目如何开启https服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录springboot项目开启https服务1. 生成SSL证书密钥库使用keytool生成自签名证书将

QT进行CSV文件初始化与读写操作

《QT进行CSV文件初始化与读写操作》这篇文章主要为大家详细介绍了在QT环境中如何进行CSV文件的初始化、写入和读取操作,本文为大家整理了相关的操作的多种方法,希望对大家有所帮助... 目录前言一、CSV文件初始化二、CSV写入三、CSV读取四、QT 逐行读取csv文件五、Qt如何将数据保存成CSV文件前言

使用Python构建一个Hexo博客发布工具

《使用Python构建一个Hexo博客发布工具》虽然Hexo的命令行工具非常强大,但对于日常的博客撰写和发布过程,我总觉得缺少一个直观的图形界面来简化操作,下面我们就来看看如何使用Python构建一个... 目录引言Hexo博客系统简介设计需求技术选择代码实现主框架界面设计核心功能实现1. 发布文章2. 加

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT

Spring LDAP目录服务的使用示例

《SpringLDAP目录服务的使用示例》本文主要介绍了SpringLDAP目录服务的使用示例... 目录引言一、Spring LDAP基础二、LdapTemplate详解三、LDAP对象映射四、基本LDAP操作4.1 查询操作4.2 添加操作4.3 修改操作4.4 删除操作五、认证与授权六、高级特性与最佳

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

SpringSecurity6.0 如何通过JWTtoken进行认证授权

《SpringSecurity6.0如何通过JWTtoken进行认证授权》:本文主要介绍SpringSecurity6.0通过JWTtoken进行认证授权的过程,本文给大家介绍的非常详细,感兴趣... 目录项目依赖认证UserDetailService生成JWT token权限控制小结之前写过一个文章,从S