LLM实战远程服务器部署及微调

远程连接服务器

参考之前写过的文章《vscode远程连接服务器》

llm大模型厂商及模型展示

参考:https://b.geekbang.com/member/course/detail/781435
当前环境下,大模型百花齐放。我筛选出了一些核心玩家,你可以看一下表格。非核心的其实还有很多,这里我就不一一列举了。厂商虽然很多,但真正在研究技术的没多少,毕竟前面我们讲过,玩大模型投入非常大,光看得见的成本,包括人才、训练和硬件费用,一年就得投入几个亿,不是一般玩家能玩得起的。
在这里插入图片描述
当然,也有不少厂商是基于 LLaMA 爆改的,或者叫套壳,不是真正意义上的自研大模型。 ChatGLM-6B 和 LLaMA2 是目前开源项目比较热的两个,早在 2023 年年初,国内刚兴起大模型热潮时,智谱 AI 就开源了 ChatGLM-6B,当然 130B 也可以拿过来跑,只不过模型太大,需要比较多的显卡,所以很多人就部署 6B 试玩。 从长远看,信创大潮下,国产大模型肯定是首选,企业布局 AI 大模型,要么选择 MaaS 服务,调用大厂大模型 API,要么选择开源大模型,自己微调、部署,为上层应用提供服务。使用 MaaS 服务会面临数据安全问题,所以一般企业会选择私有化部署 + 公有云 MaaS 混合的方式来架构。在国产厂商里面,光从技术角度讲,我认为智谱 AI 是国内大模型研发水平最高的厂商,这也是我选择 ChatGLM-6B 的原因。 还有一点需要考虑,就是 6B 参数规模为 62 亿,单张 3090 显卡就可以进行微调(P-Turing)和推理,对于中小企业而言,简直就是福音。
当然,如果企业预算充足(百万以上),可以尝试 6B 的老大哥 GLM-130B,简称 130B,千亿参数规模,推理能力更强,使用 130B 的话除了 GPU 资源费用,还需要进行商业授权,这个要注意。

牛刀小试(部署开源大模型ChatGLM3-6B)

官网连接:https://github.com/THUDM/ChatGLM3

1. 环境要求

  • 操作系统推荐 Linux 环境,如 Ubuntu 或者 CentOS。
    在这里插入图片描述
  • Python 推荐 3.10~3.11 版本。
  • Transformers 库推荐 4.36.2 版本。
  • Torch 推荐使用 2.0 及以上的版本,以获得最佳的推理性能。
    创建虚拟环境
    注意!后面所有的环境都会使用这个环境
# 创建虚拟环境
conda create -n chat python=3.10

# 查看本机所有的虚拟环境
conda env list

# 激活需要的环境
conda activate chat

2. 克隆代码

git clone https://github.com/THUDM/ChatGLM3

3. 安装依赖

注意:要切换成国内 pip 源,比如阿里云,下载会快很多。

# 如果不需要改镜像源就不需要运行第一行命令
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
cd ChatGLM3
pip install -r requirements.txt

显示以下内容表明依赖安装成功。
在这里插入图片描述

4.下载模型

git clone https://huggingface.co/THUDM/chatglm3-6b

如果 Huggingface 下载比较慢的话,也可以选择 ModelScope 进行下载。下载完将 chatglm3-6b 文件夹重新命名成 model 并放在 ChatGLM3 文件夹下,这一步非必需,只要放在一个路径下,在下一步提示的文件里,指定好模型文件路径即可。

5.命令行模式启动

打开文件 basic_demo/cli_demo.py,修改模型加载路径。

MODEL_PATH = os.environ.get('MODEL_PATH', '../model')

执行 python cli_demo.py。
结束对话 crtl+c/z

6. Web 控制台模式启动

打开文件 basic_demo/web_demo_gradio.py,修改模型加载路径。

MODEL_PATH = os.environ.get('MODEL_PATH', '../model')

同时修改最后一行:

demo.launch(server_name="127.0.0.1", server_port=7870, inbrowser=True, share=False)

server_name 修改为本地 IP,并指定端口 server_port 即可。也可以设置 share=True,使用 gradio 提供的链接进行访问。 执行 python web_demo_gradio.py。

在这里插入图片描述
默认情况下,模型以 FP16 精度加载,大概需要 13GB 显存。如果你的电脑没有 GPU,只能通过 CPU 启动,6B 也是支持的,需要大概 32G 的内存。我们修改一下模型加载脚本。

model = AutoModel.from_pretrained(MODEL_PATH trust_remote_code=True).float()

如果你的电脑有 GPU,但是显存不够,也可以通过修改模型加载脚本,在 4-bit 量化下运行,只需要 6GB 左右的显存就可以进行流程推理。

model = AutoModel.from_pretrained(MODEL_PATH, trust_remote_code=True, ).quantize(4).cuda()

同时,官方也提供了一个全新的 web demo,支持 Chat、Tool、Code Interpreter,就在我们克隆下来的代码里,在文件夹 composite_demo 下。

cd composite_demo
pip install -r requirements.txt
export MODEL_PATH=../model
streamlit run main.py 或者 python -m streamlit run main.py

页面确实上了一个档次。
在这里插入图片描述
接下来我简单总结一下部署过程: 安装 Python 环境,包含 pip; 下载代码; 下载模型; 安装依赖; 修改示例代码,指定模型路径、精度等参数; 命令行启动。 整体来说,如果 Python 版本在 3.10~3.11 之间,网络环境也没问题的话,安装还是很快的,如果有 GPU 的话,推理效果也是很好的。在我们部署好模型之后,就可以进行推理了。推理之前,6B 有几个参数可以进行设置,就是超参数,用来控制模型的推理准确度,我们知道大模型推理每次给的回答可能都和之前不一样,这也是为什么大模型不能用来处理精确度要求很高的任务的原因,比如让大模型算个税、算工资等等。

7.超参数介绍

ChatGLM3-6B 有 3 个参数可以设置。 max_length:模型的总 token 限制,包括输入和输出的 tokens。 temperature:模型的温度。温度只是调整单词的概率分布。它最终的宏观效果是,在较低的温度下,我们的模型更具确定性,而在较高的温度下,则不那么确定。数字越小,给出的答案越精确。 top_p:模型采样策略参数。每一步只从累积概率超过某个阈值 p 的最小单词集合中进行随机采样,而不考虑其他低概率的词。只关注概率分布的核心部分,忽略了尾部。 对于以下场景,官方推荐使用这样的参数进行设置:
在这里插入图片描述
系统设置好,我们基本就可以开始进行问答了,ChatGLM3-6B 采用了一种新的 Prompt 格式,看上去应该是模仿的 ChatGPT。下面我们介绍下这种提问格式。

8. 新的 Prompt 格式

新的提示格式,主要是增加了几个角色,在对话场景中,有且仅有以下三种角色。 system:系统信息,出现在消息的最前面,可以指定回答问题的角色。 user:我们提的问题。 assistant:大模型给出的回复。 在代码场景中,有且仅有 user、assistant、system、observation 四种角色。observation 是外部返回的结果,比如调用外部 API,代码执行逻辑等返回的结果,都通过 observation 返回。observation 必须放在 assistant 之后。 下面这个是官方提供的例子,基本把以上 4 种角色都解释清楚了。

<|system|>
Answer the following questions as best as you can. You have access to the following tools:
[
    {
        "name": "get_current_weather",
        "description": "Get the current weather in a given location",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The city and state, e.g. San Francisco, CA",
                },
                "unit": {"type": "string"},
            },
            "required": ["location"],
        },
    }
]
<|user|>
今天北京的天气怎么样?
<|assistant|>
好的,让我们来查看今天的天气
<|assistant|>get_current_weather


```python
tool_call(location="beijing", unit="celsius")

<|observation|>
{"temperature": 22}
<|assistant|>
根据查询结果,今天北京的气温为 22 摄氏度。

为什么会这么设计呢? 首先,当前阶段的大模型经过训练后,都可以遵守系统消息,而系统消息不算用户对话的一部分,与用户是隔离的,但是可以控制模型与用户交互的范围,比如我们在 system 角色里指定模型充当 Java 技术专家,那么就可以指导模型的输出偏向于 Java 技术范围。 还有一个原因就是防止用户进行输入注入攻击。在进行多轮对话的时候,每次新的对话都会把历史对话都带进去。如果我们在前面的对话中,告诉模型错误的提示,那么这些错误的提示会在后续的对话中被当作正确的上下文带进去。我们知道基于自回归的模型,会根据上下文进行内容推理,这样就可能生成错误的内容。角色可以使内容更加容易区分,增加注入攻击的复杂度。这种方式不一定能处理所有的攻击类型,类似于我们日常开发中的 XSS 注入,只能尽可能减少,完全避免有点难。

基于ChatGLM3-6B+Lora建基本法律常识大模型

1. 增强模型能力

微调是其中的一个方法,当然还有其他方式,比如外挂知识库或者通过 Agent 调用其他 API 数据源,下面我们详细介绍下这几种方式的区别。

  • 微调是一种让预先训练好的模型适应特定任务或数据集的方案,成本相对较低,这种情况下,模型会学习训练者提供的微调数据,并且具备一定的理解能力。
  • 知识库使用向量数据库或者其他数据库存储数据,为大语言模型提供信息来源外挂。
  • API 和知识库类似,为大语言模型提供信息来源外挂。

简单理解,微调相当于让大模型去学习一门新的学科,在回答的时候进行闭卷考试,知识库和 API 相当于为大模型提供了新学科的课本,回答的时候进行开卷考试。几种模式并不冲突,我们可以同时使用几种方案来优化模型,提升内容输出能力,下面我简单介绍下几种模式的优缺点。
在这里插入图片描述
注意,大模型领域所谓的性能,英文原词是 Performance,指推理效果,并非我们软件开发里所说的接口性能,比如响应时间、吞吐量等。 了解这几种模型的区别,有助于我们进行技术方案选型。在大模型实际落地过程中,我们需要先分析需求,然后确定落地方式。 微调:准备数据、微调、验证、提供服务。 知识库:准备数据、构建向量库、构建智能体、提供服务。 API:准备数据、开发接口、构建智能体、提供服务。 接下来我会通过一个真实的案例,把整个过程串起来。

2.企业真实案例

在 ChatGPT 火爆以后,很多公司都在想办法将 AI 大模型引入日常工作中,一方面嵌入到产品中,提升产品的竞争力;一方面引入到企业内部,提升员工工作效率。就拿企业内部助手来说,它有很多使用场景,比如文案生成、PPT 写作、生活常识等等。这里我们举一个法律小助手的例子。一般来说,当我们确定场景后,首先进行的就是需求分析,因为有些场景不一定是 AI 场景,有些是 AI 场景,但是可能可以通过小模型解决,所以我们在实际需求落地的过程中,一定要先进行完整的需求分析。

3.需求分析

法律小助手用来帮助员工解决日常生活中遇到的法律问题,以问答的方式进行,这种场景可以使用知识库模式,也可以使用微调模式。使用知识库模式的话,需要将数据集拆分成一条一条的知识,先放到向量库,然后通过 Agent 从向量库检索,再输入给大模型,这种方式的好处是万一我们发现数据集不足,可以随时补充,即时生效。 还有一种方式就是进行微调,因为法律知识有的时候需要一定的逻辑能力,不是纯文本检索,而微调就是这样的,通过在一定量的数据集上的训练,增加大模型法律相关的常识及思维,从而进行推理。经过分析,我们确定下来,使用微调的方式进行。接下来就是准备数据了。

4.准备数据

准备数据有很多种,可以从公共数据集下载,然后进行调整并加入私有化的知识,也可以完全自己整理,为了便于展示,我从 GitHub 上面找了一个公开的数据集,下载下来的是一个 CSV 格式的文件。官方给的微调数据格式如下:

{"conversations": [{"role": "user", "content": "类型#裙*裙长#半身裙"}, {"role": "assistant", "content": "这款百搭时尚的仙女半身裙,整体设计非常的飘逸随性,穿上之后每个女孩子都能瞬间变成小仙女啦。料子非常的轻盈,透气性也很好,穿到夏天也很舒适。"}]}

现在我们需要把 CSV 里的内容,转成官方要求的格式。转化代码我直接让 ChatGPT 帮我生成,用了如下提示:

原始数据是CSV格式,包含4列:title、question、reply、is_best,需要通过Python语言处理该CSV文件,来构建大语言模型的微调数据集,目标数据集格式是JSON的,单条数据格式为:{"conversations":[{"role":"user","content":"value1"},{"role":"assistant","content":"value2"}]},需要将原始CSV文件里的title列填充到目标JSON文件里的value1处,原始CSV文件里的reply填充到目标JSON文件里的value1处,请注意:最终生成的不是JSON数组,而是每个JSON对象生成一行,出示示例代码。

ChatGPT 生成的 Python 代码:

import csv
import json

# CSV文件的路径
csv_file_path = 'your_csv_file.csv'
# 输出JSON文件的路径
json_file_path = 'output_json_file.json'

# 打开CSV文件,并进行处理
with open(csv_file_path, mode='r', encoding='utf-8') as csv_file, \
     open(json_file_path, mode='w', encoding='utf-8') as json_file:
    
    csv_reader = csv.DictReader(csv_file)
    for row in csv_reader:
        # 根据CSV文件的列名获取数据
        title = row['title']
        reply = row['reply']
        # 构造单条对话的JSON结构
        conversation_entry = {
            "conversations": [
                {"role": "user", "content": title},
                {"role": "assistant", "content": reply}
            ]
        }
        # 将单条记录以JSON格式写入文件,每条记录一行
        json_line = json.dumps(conversation_entry, ensure_ascii=False)
        json_file.write(json_line + '\n')


通过上面的代码,我们就可以成功将下载下来的 CSV 格式的数据集,格式化成微调所需的数据集。接下来就可以准备微调了。

5.微调

5.1 安装依赖

我们先进入到 finetune_demo 文件夹。执行 pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple,过程中报了一个错。
在这里插入图片描述
原因是缺少 libopenmpi-dev 库,所以我们需要安装这个库。

sudo apt update
sudo apt-get install libopenmpi-dev

紧接着安装 nltk 库。

pip install nltk

到这里,依赖包基本就安装完了。你在操作的过程中,如果遇到其他库的缺失,有可能是操作系统库也有可能是 Python 库,按照提示完成安装即可。

5.2 准备数据

训练需要至少准备两个数据集,一个用来训练,一个用来验证。我们把“准备数据”环节格式化好的文件命名为 train.json,再准备一个相同格式的测试数据集 dev.json,在里面添加一些测试数据,几十条即可,当大模型在训练的过程中,会自动进行测试验证,输出微调效果。然后在 finetune_demo 文件夹下建立一个 data 文件夹,将这两个文件放入 data 文件夹中。

5.3 修改配置

修改 finetune_demo/configs 下的 lora.yaml 文件,将 train_file、val_file、test_file、output_dir 定义好,记得写全路径,其他参数也可以按需修改,比如:

  • max_steps:最大训练轮数,我们填 3000。
  • save_steps:每训练多少轮保存权重,填 500。

在这里插入图片描述

其他参数可以参考下面这张表格。
在这里插入图片描述

5.4 开始微调

如果数据量比较少的话,比如少于 50 行,注意这一行,会报数组越界,修改小一点即可。

eval_dataset=val_dataset.select(list(range(50))),

微调脚本用的是 finetune_hf.py。

  1. 第一个参数是训练数据集所在目录,此处值是 data。
  2. 第二个参数是模型所在目录,此处值是 ./model。
  3. 第三个参数是微调配置,此处值是 configs/lora.yaml。
    执行微调命令,记得 Python 命令使用全路径。
python finetune_hf.py ../data ../model configs/lora.yaml

注意:有可能会发生内存不足的情况

# 内存不足报错
OutOfMemoryError: CUDA out of memory. Tried to allocate 296.00 MiB. GPU 

# 解决方法:
# 1.查看当前gpu使用情况
nvidia-smi
# 结果返回
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 555.42.02              Driver Version: 555.42.02      CUDA Version: 12.5     |
|-----------------------------------------+------------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                         |                        |               MIG M. |
|=========================================+========================+======================|
|   0  NVIDIA L40S                    Off |   00000000:01:00.0 Off |                    0 |
| N/A   42C    P0             83W /  350W |   25676MiB /  46068MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|    0   N/A  N/A     68604      C   python                                      12478MiB |
|    0   N/A  N/A     69899      C   python                                      13184MiB |
+-----------------------------------------------------------------------------------------+

# 结束进程
kill -9  pid

如果控制台输出下面这些内容,则说明微调开始了。
在这里插入图片描述
trainable params 指的是在模型训练过程中可以被优化或更新的参数数量。在深度学习模型中,这些参数通常是网络的权重和偏置。它们是可训练的,因为在训练过程中,通过反向传播算法这些参数会根据损失函数的梯度不断更新,以减小模型输出与真实标签之间的差异。通过调整 lora.yaml 配置文件里 peft_config 下面的参数 r 来改变可训练参数的数量,r 值越大,trainable params 越大。 我们这次微调 trainable params 为 1.9M(190 万),整个参数量是 6B(62 亿),训练比为 3%。

在这里插入图片描述
这里有几个参数我来简单讲解下。

  • loss:损失函数衡量模型预测的输出与实际数据之间的差异或误差。在训练过程中,目标是最小化这个损失值,从而提高模型的准确性。
  • grad_norm(梯度范数):在训练深度学习模型时,通过反向传播算法计算参数(如权重)的梯度,以便更新这些参数。梯度范数是这些梯度向量的大小或长度,它提供了关于参数更新幅度的信息。如果梯度范数非常大,可能表示模型在训练过程中遇到了梯度爆炸问题;如果梯度范数太小,可能表示存在梯度消失问题。
  • learning_rate(学习率):学习率是一个控制参数更新幅度的超参数。在优化算法中,学习率决定了在反向传播期间参数更新的步长大小。太高的学习率可能导致训练过程不稳定,而太低的学习率可能导致训练进展缓慢或陷入局部最小值。
  • epoch(周期):一个 epoch 指的是训练算法在整个训练数据集上的一次完整遍历。通常需要多个 epochs 来训练模型,以确保模型能够充分学习数据集中的模式。每个 epoch 后,通常会评估模型在验证集上的表现,以监控和调整训练过程。

在这里插入图片描述

5.5 验证

等待微调结束,就可以进行验证了,官方 demo 提供了验证脚本,执行如下命令:

python inference_hf.py output/checkpoint-3000/ --prompt "xxxxxxxxxxxx"

output/checkpoint-3000 是指新生成的权重,模型启动的时候会将原模型和新权重全部加载,然后进行推理。–prompt 是输入的提示。 下面是一组微调前后的对比问答,我们对比着来看一下。
【微调前】
User:不交房电费多出由谁承担?法律法规第几条 ChatGLM:这个问题先要明确是哪一种房屋。如果是商业用房,交房后产生的费用一般是由开发商来处理的;如果是住宅用电,那么就属于个人日常用水产生的费用了。如果是因为开发商的过错造成,可以要求开发商进行赔偿,反之也是一样。建议查阅合同以及相关法律条文,也可以向当地的水管公司或者开发商进行咨询。
【微调后】
User:不交房电费多出由谁承担?法律法规第几条? ChatGLM:协商解决,协商不成可诉讼。 我们的微调数据集中有下面这条内容:

{"conversations": [{"role": "user", "content": "不交房电费多出由谁承担?法律法规第几条?"}, {"role": "assistant", "content": "按照约定处理,协商不成可以委托律师处理。"}]}

部分回答效果是比较明显的。 当然,这里只是通过快速搭建一个 demo 向你展示 Lora 微调的细节。实际生产过程中,需要考虑的事情比较多,比如训练轮数、并行数、微调效果比对等一系列问题,需要我们根据实际情况进行调整。 提供服务 当微调完成,我们验证后得知整体效果满足一定的百分比,那我们就认为这个微调是有效的,可以对外服务,接下来就可以通过 API 组件将模型的输入输出封装成接口对外提供服务了。实际生产环境中,我们还需要考虑几件事情: 模型的推理性能(效果); 模型的推理吞吐量; 服务的限流,适当保护大模型集群; 服务降级,当大模型服务不可用的时候,可以考虑通过修改开关,将 AI 小助手隐藏暂停使用。 具体架构思路,后面第四章我会进行专门的讲解,到那时我们再详细学习具体内容。

LLM(Language Learning Model)是一个基于预训练模型的自然语言处理框架,可以用于各种NLP任务,如文本分类、命名实体识别、情感分析等。下面是LLM模型的本地部署及微调流程: 1. 下载预训练模型 LLM模型基于预训练模型,可以通过Hugging Face官网下载预训练模型。选择相应的模型并下载到本地。 2. 安装LLM 可以使用pip命令安装LLM,命令如下: ``` pip install llm ``` 3. 加载预训练模型 使用LLM的load方法加载预训练模型,代码示例如下: ```python from llm.modeling import LLMForSequenceClassification model = LLMForSequenceClassification.from_pretrained('path/to/pretrained_model') ``` 4. 微调模型 使用LLM的train方法微调模型,代码示例如下: ```python import torch from llm.data import TextDataset, TextDataLoader from llm.training import LLMTrainer train_dataset = TextDataset('path/to/train_data', model.tokenizer) train_loader = TextDataLoader(train_dataset, batch_size=32, shuffle=True) optimizer = torch.optim.Adam(model.parameters(), lr=5e-5) trainer = LLMTrainer(model, optimizer) trainer.train(train_loader, epochs=3) ``` 5. 保存微调后的模型 使用LLM的save_pretrained方法保存微调后的模型,代码示例如下: ```python model.save_pretrained('path/to/fine_tuned_model') ``` 以上就是LLM模型的本地部署及微调流程。需要注意的是,在微调模型时,需要准备好训练数据,并且调整好超参数,以达到最佳的微调效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值