【记录】初次本地搭建的模型-MiniCPM 2B

2024-05-27 22:52

本文主要是介绍【记录】初次本地搭建的模型-MiniCPM 2B,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

        查阅众多开源大模型后,打算动手尝试搭建端侧模型,看看效果。选中MiniCPM主要是因为参数小,同时中文支持相对较好。

        首先对按照官网提供的demo进行了尝试,然后在colab中完成了一个webui程序并测试,最后通过docker环境在本地搭建并测试成功。

        

Colab Demo测试

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
torch.manual_seed(0)path = # model path 
tokenizer = AutoTokenizer.from_pretrained(path)
model = AutoModelForCausalLM.from_pretrained(path, torch_dtype=torch.float32, device_map='cuda', trust_remote_code=True)responds, history = model.chat(tokenizer, "山东省最高的山是哪座山, 它比黄山高还是矮?差距多少?", temperature=0.8, top_p=0.8)
print(responds)

编写程序

from typing import Listimport argparse
import gradio as gr
import torch
from threading import Thread
from transformers import (AutoModelForCausalLM, AutoTokenizer,TextIteratorStreamer
)import warnings
warnings.filterwarnings('ignore', category=UserWarning, message='TypedStorage is deprecated')parser = argparse.ArgumentParser()
parser.add_argument("--model_path", type=str, default="")
parser.add_argument("--torch_dtype", type=str, default="bfloat16")
parser.add_argument("--server_name", type=str, default="127.0.0.1")
parser.add_argument("--server_port", type=int, default=7860)args = parser.parse_args()# init model torch dtype
torch_dtype = args.torch_dtype
if torch_dtype =="" or torch_dtype == "bfloat16":torch_dtype = torch.bfloat16
elif torch_dtype == "float32":torch_dtype = torch.float32
else:raise ValueError(f"Invalid torch dtype: {torch_dtype}")# init model and tokenizer
path = args.model_path
tokenizer = AutoTokenizer.from_pretrained(path)
#无显卡auto改为cpu
model = AutoModelForCausalLM.from_pretrained(path, torch_dtype=torch_dtype, device_map="auto", trust_remote_code=True)# init gradio demo host and port
server_name=args.server_name
server_port=args.server_portdef hf_gen(dialog: List, top_p: float, temperature: float, max_dec_len: int):"""generate model output with huggingface apiArgs:query (str): actual model input.top_p (float): only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation.temperature (float): Strictly positive float value used to modulate the logits distribution.max_dec_len (int): The maximum numbers of tokens to generate.Yields:str: real-time generation results of hf model"""    inputs = tokenizer.apply_chat_template(dialog, tokenize=False, add_generation_prompt=False)#无显卡去掉.to("cuda")enc = tokenizer(inputs, return_tensors="pt").to("cuda")streamer = TextIteratorStreamer(tokenizer)generation_kwargs = dict(enc,do_sample=True,top_p=top_p,temperature=temperature,max_new_tokens=max_dec_len,pad_token_id=tokenizer.eos_token_id,streamer=streamer,)thread = Thread(target=model.generate, kwargs=generation_kwargs)thread.start()answer = ""for new_text in streamer:answer += new_textyield answer[4 + len(inputs):]def generate(chat_history: List, query: str, top_p: float, temperature: float, max_dec_len: int):"""generate after hitting "submit" buttonArgs:chat_history (List): [[q_1, a_1], [q_2, a_2], ..., [q_n, a_n]]. list that stores all QA recordsquery (str): query of current roundtop_p (float): only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation.temperature (float): strictly positive float value used to modulate the logits distribution.max_dec_len (int): The maximum numbers of tokens to generate.Yields:List: [[q_1, a_1], [q_2, a_2], ..., [q_n, a_n], [q_n+1, a_n+1]]. chat_history + QA of current round."""    assert query != "", "Input must not be empty!!!"# apply chat templatemodel_input = []for q, a in chat_history:model_input.append({"role": "user", "content": q})model_input.append({"role": "assistant", "content": a})model_input.append({"role": "user", "content": query})# yield model generationchat_history.append([query, ""])for answer in hf_gen(model_input, top_p, temperature, max_dec_len):chat_history[-1][1] = answer.strip("</s>")yield gr.update(value=""), chat_historydef regenerate(chat_history: List, top_p: float, temperature: float, max_dec_len: int):"""re-generate the answer of last round's queryArgs:chat_history (List): [[q_1, a_1], [q_2, a_2], ..., [q_n, a_n]]. list that stores all QA recordstop_p (float): only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation.temperature (float): strictly positive float value used to modulate the logits distribution.max_dec_len (int): The maximum numbers of tokens to generate.Yields:List: [[q_1, a_1], [q_2, a_2], ..., [q_n, a_n]]. chat_history"""    assert len(chat_history) >= 1, "History is empty. Nothing to regenerate!!"# apply chat templatemodel_input = []for q, a in chat_history[:-1]:model_input.append({"role": "user", "content": q})model_input.append({"role": "assistant", "content": a})model_input.append({"role": "user", "content": chat_history[-1][0]})# yield model generationfor answer in hf_gen(model_input, top_p, temperature, max_dec_len):chat_history[-1][1] = answer.strip("</s>")yield gr.update(value=""), chat_historydef clear_history():"""clear all chat historyReturns:List: empty chat history"""    return []def reverse_last_round(chat_history):"""reverse last round QA and keep the chat history beforeArgs:chat_history (List): [[q_1, a_1], [q_2, a_2], ..., [q_n, a_n]]. list that stores all QA recordsReturns:List: [[q_1, a_1], [q_2, a_2], ..., [q_n-1, a_n-1]]. chat_history without last round."""    assert len(chat_history) >= 1, "History is empty. Nothing to reverse!!"return chat_history[:-1]# launch gradio demo
with gr.Blocks(theme="soft") as demo:gr.Markdown("""# MiniCPM Gradio Demo""")with gr.Row():with gr.Column(scale=1):top_p = gr.Slider(0, 1, value=0.8, step=0.1, label="top_p")temperature = gr.Slider(0.1, 2.0, value=0.8, step=0.1, label="temperature")max_dec_len = gr.Slider(1, 1024, value=1024, step=1, label="max_dec_len")with gr.Column(scale=5):chatbot = gr.Chatbot(bubble_full_width=False, height=400)user_input = gr.Textbox(label="User", placeholder="Input your query here!", lines=8)with gr.Row():submit = gr.Button("Submit")clear = gr.Button("Clear")regen = gr.Button("Regenerate")reverse = gr.Button("Reverse")submit.click(generate, inputs=[chatbot, user_input, top_p, temperature, max_dec_len], outputs=[user_input, chatbot])regen.click(regenerate, inputs=[chatbot, top_p, temperature, max_dec_len], outputs=[user_input, chatbot])clear.click(clear_history, inputs=[], outputs=[chatbot])reverse.click(reverse_last_round, inputs=[chatbot], outputs=[chatbot])demo.queue()
demo.launch(server_name=server_name, server_port=server_port, show_error=True)

Colab程序测试

本地搭建

容器环境

        本地搭建一般个人比较倾向使用 Docker 作为运行环境,在投入很少额外资源的情况下,能够快速获得纯净、可复现的一致性非常棒的环境。

        除此之外,为了高效运行模型,推荐使用 Nvidia 官方的容器镜像(nvcr.io/nvidia/pytorch:24.01-py3[4])。

        我们可以基于上面的内容,快速搭建一个干净、高效的基础运行环境。

        考虑到我们可能会将模型应用运行在不同的环境,比如云主机和服务器,它们的网络环境可能有所不同。

        当我们本地进行 Docker 镜像构建的时候,配置软件镜像来加速可以大幅改善开发者体验。所以,稍加调整,我们可以得到下面的 Dockerfile 文件:

FROM nvcr.io/nvidia/pytorch:24.01-py3
LABEL maintainer="554686223@qq.com"

# setup Ubuntu and PyPi mirrors, refs: https://github.com/soulteary/docker-stable-diffusion-webui/blob/main/docker/Dockerfile.base
ARG USE_CHINA_MIRROR=true
RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \
        pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
        sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list && \
        sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list; \
    fi

# install dependencies、

RUN pip install torch==2.2.1 -i https://pypi.tuna.tsinghua.edu.cn/simple


RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers==4.37.2 gradio==4.16.0 accelerate==0.26.1


RUN pip uninstall transformer-engine

将上面的内容保存为 Dockerfile,然后执行下面的命令,可以进行镜像构建:

docker build -t my-gpt -f=dockerfile --no-cache .

下载模型

        根据自身网络情况,选择HuggingFace、ModelScope、WiseModel中最适合你的模型下载或者在线推理平台。

        这里选择了wisemodel,git链接 

         git clone https://www.wisemodel.cn/OpenBMB/miniCPM-dpo-fp32.git

简单测试

启动容器

docker run --rm -it -p 7860:7860 --gpus all --ipc=host --ulimit memlock=-1 -v D:/weiyisoftware/gpttest/gptdocker/models:/app/models -v D:/weiyisoftware/gpttest/gptdocker/workspace:/workspace my-gpt python app.py --model_path=/app/models/OpenBMB/miniCPM-dpo-fp32/ --server_name=0.0.0.0 --torch_dtype=float32

成功后:http://localhost:7860。

ps:因为电脑配置问题,回复很慢。

这篇关于【记录】初次本地搭建的模型-MiniCPM 2B的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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

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

python连接本地SQL server详细图文教程

《python连接本地SQLserver详细图文教程》在数据分析领域,经常需要从数据库中获取数据进行分析和处理,下面:本文主要介绍python连接本地SQLserver的相关资料,文中通过代码... 目录一.设置本地账号1.新建用户2.开启双重验证3,开启TCP/IP本地服务二js.python连接实例1.

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

MySQL双主搭建+keepalived高可用的实现

《MySQL双主搭建+keepalived高可用的实现》本文主要介绍了MySQL双主搭建+keepalived高可用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、测试环境准备二、主从搭建1.创建复制用户2.创建复制关系3.开启复制,确认复制是否成功4.同

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre