version: 2559fc82 (2024-04-02 10:17:24)

LLM 上手

下面开始!!!

环境配置

Windows

如果使用Windows操作系统,建议使用WSL(Windows Subsystem for Linux),具体可以参考官方文档进行安装。

MacOS

这篇文章使用Homebrew作为包管理器。 如果是M1+芯片的Mac,可以使用MLX来加速训练和推理。这里不建议使用非M1+芯片的Mac进行训练。

注:根据这个issue, MLX目前也不是在所有情况下都能加速,所以也可以用PyTorch的device="mps"来试试看。

通用

到这里,不管你是WSL还是Mac,假设我们都是POSIX的环境。基本的步骤都是通用的了。

  1. 安装Python开发环境

    建议使用conda来管理Python环境,从这里或者镜像下载安装包进行安装。安装后记得初始化conda环境。

    source <PATH_TO_CONDA>/bin/activate
    conda init
    
    # <PATH_TO_CONDA>是你指定的安装位置,一般为`~/anaconda3`
    
    # 然后你可以设置是否自动激活这个Python环境
    ## 如果自动激活
    conda config --set auto_activate_base True
    ## 如果不要自动激活,如果选择这个,每次需要`conda activate`来激活。
    conda config --set auto_activate_base False
    
    # (可选)配置环境源,加速环境配置,可以参考https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/
    
    # MacOS用户需要检查是否安装的arm版本的python,请确保下面的命令输出arm而不是i386
    python3 -c "import platform; print(platform.processor())"
    
  2. 安装PyTorch

    PyTorch是热门的深度学习框架,我们需要先安装这个基础组件。可以参考这里或者下面的命令。

    # Linux / WSL
    conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
    # MacOS
    conda install pytorch::pytorch torchvision torchaudio -c pytorch
    
  3. 安装其他依赖

    要本地使用LLM,我们还需要一些依赖,可以用下面的命令进行安装,

    pip install accelerate transformers -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    对于MacOS上使用MLX的用户可以安装下面的依赖:

    MLX安装方式如下:

    pip install mlx-lm -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    由于MLX仍处于快速开发阶段,为了快点享受到新功能/Bugfix,可以clone该repo并进行源码安装。

    git clone https://https://github.com/ml-explore/mlx-examples.git
    cd mlx-examples
    pip install -e ./llms -i https://pypi.tuna.tsinghua.edu.cn/simple
    
    # 如需更新,只需进入mlx-examples目录,执行`git pull`即可,当然最好也执行一下`pip install -U mlx -i https://pypi.tuna.tsinghua.edu.cn/simple`来升级mlx。
    

下载模型

一般基于Huggingface或者ModelScope(国内)来下载模型。

安装组件

# Ubuntu / Debian / WSL
sudo apt install git git-lfs
# MacOS
brew install git git-lfs

下载模型实例

以Qwen 1.5-1.8B-Chat为例,下面是下载的命令

# 选择一条执行即可
## 国外 Huggingface
git lfs clone https://huggingface.co/Qwen/Qwen1.5-1.8B-Chat
## 国内 Modelscope
git lfs clone https://www.modelscope.cn/Qwen/Qwen1.5-1.8B-Chat.git

本地使用

下面是一段简单的LLM聊天CLI的代码,可以存在test.py里面使用python test.py来运行。可以输入问题,回车后会给出回答,可以使用\quit来退出,\clear来开启新一轮对话。

import readline
import os
import platform

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
try:
    import mlx_lm
    is_mlx_available = True
except ImportError:
    is_mlx_available = False

use_mlx = True

if platform.system() == "Darwin":
    device = "mps"
    dtype = torch.float16
else:
    device = "cuda"
    dtype = "auto"

path = "<DOWNLOAD_PATH>/Qwen1.5-1.8B-Chat"

if is_mlx_available and use_mlx:
    model, tokenizer = mlx_lm.load(path)
else:
    model = AutoModelForCausalLM.from_pretrained(
        path,
        torch_dtype=dtype,
        device_map="auto"
    )
    tokenizer = AutoTokenizer.from_pretrained(path)

default_messages = [
    {"role": "system", "content": "You are a helpful assistant."},
]

messages = list(default_messages)
while True:
    prompt = input("Human:").strip("\n").strip()
    if prompt == "\\quit":
        break
    elif prompt == "\\new":
        os.system("clear")
        messages = list(default_messages)
        continue
    else:
        messages.append({"role": "user", "content": prompt})

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

    if is_mlx_available and use_mlx:
        # 之前MLX的推理不支持高级的采样策略,比如Top-P和Top-K,因此做了一些微小的工作
        # 见 https://github.com/ml-explore/mlx-examples/pull/486
        response = mlx_lm.generate(model, tokenizer, text, temp=0.6, top_p=0.8, max_tokens=512, repetition_penalty=1.1)
    else:
        model_inputs = tokenizer([text], return_tensors="pt").to(device)

        generated_ids = model.generate(
            model_inputs.input_ids,
            max_new_tokens=512,
            temperature=0.6,
            top_p=0.8,
            repetition_penalty=1.1,
        )
        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(f"Assistant:{response}")
    messages.append({"role": "assistant", "content": response})

部分参数解释

下面为Huggingface的model.generate方法的参数介绍。

  • temperature: 温度,这个一般是用来指对于概率的一个线性缩放系数。这个值越大,生成的随机性越强,越小则越具有确定性。对于较小的模型,我们一般设置小于1的temperature,可以优先试下0.6-0.8。
  • do_sample: 是否开启采样。不开启采样,则采用贪婪解码(Greedy Decoding),即每次都选择概率最大的Token。默认开启。
  • max_new_tokens: 最长生成的token数。这个和max_length差不多,只不过扣除了prompt部分的token计数。max_length的值则受限于模型本身,之前一般都是2048,当然现在也有了32000或者更长的模型。
  • top_p: Top-P采样的概率值。一种去除小概率输出的采样策略,即对于每个token去按照概率从大到小排序,计算累计概率,将累积概率大于指定值的token的概率排除在选择之外。一般设置为0.8-1。
  • top_k: Top-K采样的个数。一种去除小概率输出的采样策略,即对于每个token去按照概率从大到小排序,选取前K个结果,其他则被排除在选择之外。现在一般用了top p就不使用top k了。
  • repetition_penalty: 重复惩罚因子。目前的LLM模型有一个特点,就是他有时会比较容易陷入解码循环,例如ABABAB或者ABCABC,这个一般我们也叫“复读”。为了避免这个问题,我们在采样时可以把已经出现的token的概率进行调整。这个参数可以看情况进行调整,一般设置为1.0-1.2。1.0表示不开启重复惩罚。