书生·浦语大模型实战营笔记-第五课

LMDeploy 的量化和部署

课程内容

课程视频

课程文档

课程笔记

image

1 大模型部署背景

image
image

2 LMDeploy简介

image
image
image

量化,可以减低对显存的要求。

image
image
image
image

队列中S0、S1进来后,Slot从队列中拉取S0和S1进行推理。

image

S2请求进入请求队列,Slot有空闲槽位,拉取S2进行推理。同时判断S0推理完成,将S0移出Slot。

image

S2完成,移出Slot。剩下S1继续推理。

image

S1推理完成,移出Slot。

image

实现了动态Batch。大模型推理的新的处理方式,以前的生成模型、Encoder模型是一次把结果全部出来。

image

理论上可以支持无限长。

image

分块缓存k/v数据,通过三种状态来进行迁移。

显存在推理过程中动态调整。

image
image

lmdeploy serve api_server InternLM/internlm-chat-7b-model-name internlm-chat-7b--server-port 8080

Swagger地址:http://0.0.0.0:8080

models:列出你的模型列表

completion和chat completion

lmdeploy 的专有api

3 LMDeploy动手实践环节 - 安装、部署、量化

3.1 环境准备


# 复制conda环境,便于在此基础上安装新的软件包

/root/share/install_conda_env_internlm_base.sh lmdeploy

# 激活lmdeploy环境

conda activate lmdeploy

可以进入Python检查一下 PyTorch 和 lmdeploy 的版本。由于 PyTorch 在官方提供的环境里,我们应该可以看到版本显示,而 lmdeploy 需要我们自己安装,此处应该会提示“没有这个包”,如下图所示。

image

lmdeploy 没有安装,我们接下来手动安装一下,建议安装最新的稳定版。 如果是在 InternStudio 开发环境,需要先运行下面的命令,否则会报错。


# 解决 ModuleNotFoundError: No module named 'packaging' 问题

pip install packaging

# 使用 flash_attn 的预编译包解决安装过慢问题

pip install /root/share/wheels/flash_attn-2.4.2+cu118torch2.0cxx11abiTRUE-cp310-cp310-linux_x86_64.whl

# 安装lmdeploy包

pip install 'lmdeploy[all]==v0.1.0'

由于默认安装的是 runtime 依赖包,但是我们这里还需要部署和量化,所以,这里选择 [all]。然后可以再检查一下 lmdeploy 包,如下图所示。

image

基础环境到这里就配置好了。

3.2 服务部署

3.2.1 模型转换

3.2.1.1 在线转换

直接启动本地的 Huggingface 模型,如下所示。


# 加载使用 lmdeploy 量化的版本

lmdeploy chat turbomind /share/temp/model_repos/internlm-chat-7b/  --model-name internlm-chat-7b

启动一个本地对话界面,通过 Bash 可以与 LLM 进行对话。

3.2.1.2 离线转换

离线转换需要在启动服务之前,将模型转为 lmdeploy TurboMind 的格式,如下所示。


# 转换模型(FastTransformer格式) TurboMind

lmdeploy convert internlm-chat-7b /path/to/internlm-chat-7b

这里我们使用官方提供的模型文件,就在用户根目录执行,如下所示。


lmdeploy convert internlm-chat-7b  /root/share/temp/model_repos/internlm-chat-7b/

执行完成后将会在当前目录生成一个 workspace 的文件夹。这里面包含的就是 TurboMind 和 Triton “模型推理”需要到的文件。

目录如下图所示。

image

weights 和 tokenizer 目录分别放的是拆分后的参数和 Tokenizer。如果我们进一步查看 weights 的目录,就会发现参数是按层和模块拆开的,如下图所示。

image

每一份参数第一个 0 表示“层”的索引,后面的那个0表示 Tensor 并行的索引,因为我们只有一张卡,所以被拆分成 1 份。如果有两张卡可以用来推理,则会生成0和1两份,也就是说,会把同一个参数拆成两份。比如 layers.0.attention.w_qkv.0.weight 会变成 layers.0.attention.w_qkv.0.weight 和 layers.0.attention.w_qkv.1.weight。执行 lmdeploy convert 命令时,可以通过 --tp 指定(tp 表示 tensor parallel),该参数默认值为1(也就是一张卡)。

3.2.2 TurboMind 推理+命令行本地对话

模型转换完成后,我们就具备了使用模型推理的条件,接下来就可以进行真正的模型推理环节。

我们先尝试本地对话(Bash Local Chat),下面用(Local Chat 表示)在这里其实是跳过 API Server 直接调用 TurboMind。简单来说,就是命令行代码直接执行 TurboMind。所以说,实际和前面的架构图是有区别的。

这里支持多种方式运行,比如Turbomind、PyTorch、DeepSpeed。但 PyTorch 和 DeepSpeed 调用的其实都是 Huggingface 的 Transformers 包,PyTorch表示原生的 Transformer 包,DeepSpeed 表示使用了 DeepSpeed 作为推理框架。Pytorch/DeepSpeed 目前功能都比较弱,不具备生产能力,不推荐使用。

执行命令如下。


# Turbomind + Bash Local Chat

lmdeploy chat turbomind ./workspace

启动后就可以和它进行对话了,如下图所示。

image

输入后两次回车,退出时输入exit 回车两次即可。此时,Server 就是本地跑起来的模型(TurboMind),命令行可以看作是前端。

3.2.3 TurboMind推理+API服务

在上面的部分我们尝试了直接用命令行启动 Client,接下来我们尝试如何运用 lmdepoy 进行服务化。

”模型推理/服务“目前提供了 Turbomind 和 TritonServer 两种服务化方式。此时,Server 是 TurboMind 或 TritonServer,API Server 可以提供对外的 API 服务。我们推荐使用 TurboMind,TritonServer 使用方式详见《附录1》。

首先,通过下面命令启动服务。


# ApiServer+Turbomind  api_server => AsyncEngine => TurboMind

lmdeploy serve api_server ./workspace \

    --server_name 0.0.0.0 \

    --server_port 23333 \

    --instance_num 64 \

    --tp 1

上面的参数中 server_name 和 server_port 分别表示服务地址和端口,tp 参数我们之前已经提到过了,表示 Tensor 并行。还剩下一个 instance_num 参数,表示实例数,可以理解成 Batch 的大小。执行后如下图所示。

image

然后,我们可以新开一个窗口,执行下面的 Client 命令。如果使用官方机器,可以打开 vscode 的 Terminal,执行下面的命令。


# ChatApiClient+ApiServer(注意是http协议,需要加http)

lmdeploy serve api_client http://localhost:23333

如下图所示。

image

当然,刚刚我们启动的是 API Server,自然也有相应的接口。可以直接打开 http://{host}:23333 查看,如下图所示。

image

注意,这一步由于 Server 在远程服务器上,所以本地需要做一下 ssh 转发才能直接访问(与第一部分操作一样),命令如下:

ssh -CNg -L 23333:127.0.0.1:23333 root@ssh.intern-ai.org.cn -p <你的ssh端口号>

这里一共提供了 4 个 HTTP 的接口,任何语言都可以对其进行调用,我们以 v1/chat/completions 接口为例,简单试一下。

接口请求参数如下:


{

  "model": "internlm-chat-7b",

  "messages": "写一首春天的诗",

  "temperature": 0.7,

  "top_p": 1,

  "n": 1,

  "max_tokens": 512,

  "stop": false,

  "stream": false,

  "presence_penalty": 0,

  "frequency_penalty": 0,

  "user": "string",

  "repetition_penalty": 1,

  "renew_session": false,

  "ignore_eos": false

}

请求结果如下。

image

3.2.4 网页 Demo 演示

这一部分主要是将 Gradio 作为前端 Demo 演示。在上一节的基础上,我们不执行后面的 api_client 或 triton_client,而是执行 gradio。

由于 Gradio 需要本地访问展示界面,因此也需要通过 ssh 将数据转发到本地。命令如下:

ssh -CNg -L 6006:127.0.0.1:6006 root@ssh.intern-ai.org.cn -p <你的 ssh 端口号>

3.2.4.1 TurboMind 服务作为后端

API Server 的启动和上一节一样,这里直接启动作为前端的 Gradio。


# Gradio+ApiServer。必须先开启 Server,此时 Gradio 为 Client

lmdeploy serve gradio http://0.0.0.0:23333 \

    --server_name 0.0.0.0 \

    --server_port 6006 \

    --restful_api True

结果如下图所示。

image
3.2.4.2 TurboMind 推理作为后端

当然,Gradio 也可以直接和 TurboMind 连接,如下所示。


# Gradio+Turbomind(local)

lmdeploy serve gradio ./workspace

可以直接启动 Gradio,此时没有 API Server,TurboMind 直接与 Gradio 通信。如下图所示。

image

3.2.5 TurboMind 推理 + Python 代码集成

前面介绍的都是通过 API 或某种前端与”模型推理/服务“进行交互,lmdeploy 还支持 Python 直接与 TurboMind 进行交互,如下所示。


from lmdeploy import turbomind as tm

# load model

model_path = "/root/share/temp/model_repos/internlm-chat-7b/"

tm_model = tm.TurboMind.from_pretrained(model_path, model_name='internlm-chat-20b')

generator = tm_model.create_instance()

# process query

query = "你好啊兄嘚"

prompt = tm_model.model.get_prompt(query)

input_ids = tm_model.tokenizer.encode(prompt)

# inference

for outputs in generator.stream_infer(

        session_id=0,

        input_ids=[input_ids]):

    res, tokens = outputs[0]

response = tm_model.tokenizer.decode(res.tolist())

print(response)

在上面的代码中,我们首先加载模型,然后构造输入,最后执行推理。

加载模型可以显式指定模型路径,也可以直接指定 Huggingface 的 repo_id,还可以使用上面生成过的 workspace。这里的 tm.TurboMind 其实是对 C++ TurboMind 的封装。

构造输入这里主要是把用户的 query 构造成 InternLLM 支持的输入格式,比如上面的例子中, query 是“你好啊兄嘚”,构造好的 Prompt 如下所示。


"""

<|System|>:You are an AI assistant whose name is InternLM (书生·浦语).

- InternLM (书生·浦语) is a conversational language model that is developed by Shanghai AI Laboratory (上海人工智能实验室). It is designed to be helpful, honest, and harmless.

- InternLM (书生·浦语) can understand and communicate fluently in the language chosen by the user such as English and 中文.

<|User|>:你好啊兄嘚

<|Bot|>:

"""

Prompt 其实就是增加了 <|System|> 消息和 <|User|> 消息(即用户的 query),以及一个 <|Bot|> 的标记,表示接下来该模型输出响应了。最终输出的响应内容如下所示。


"你好啊,有什么我可以帮助你的吗?"

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容