在不断发展的大型语言模型(LLMs)领域中,用于支持这些模型的工具和技术正以与模型本身一样快的速度进步。在这篇文章中,我们将总结5种搭建开源大语言模型服务的方法,每种都附带详细的操作步骤,以及各自的优缺点。
1、Anaconda CPU
我们首先介绍门槛最低的入门级方法,因为这个方法不需要GPU,基本上只要有一个还不错的CPU和足够RAM就可以运行。
这里我们使用llama.cpp及其python绑定llama-cpp-python
代码语言:javascript复制 pip install llama-cpp-python[server]
--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu
创建一个名为models/7B的目录来存储下载的模型。然后使用命令下载GGUF格式的量化模型:
代码语言:javascript复制 mkdir -p models/7B
wget -O models/7B/llama-2-7b-chat.Q5_K_M.gguf https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGUF/resolve/main/llama-2-7b-chat.Q5_K_M.gguf?download=true
然后就可以运行以下命令启动服务器:
代码语言:javascript复制 python3 -m llama_cpp.server --model models/7B/llama-2-7b-chat.Q5_K_M.gguf
将环境变量MODEL设置为下载模型的路径。然后运行openai_client.py脚本就可以访问我们的查询服务器。openai_client.py使用OpenAI库调用LLM服务器并打印响应。
代码语言:javascript复制 messages=[
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": "What are the names of the four main characters of South Park?",
},
]
因为这个方法是门槛最低的,所以他的速度也是最慢的,基于Intel®Core™i9-10900F CPU @ 2.80GHz的系统的处理时间大概是13秒左右,所以这个方法一般用作我们的本地测试服务(如果你GPU不够的话)。
2、Anaconda GPU
前面的CPU方法是非常慢的,为了加快速度我们将使用vllm,这是一个专门为有效利用gpu而设计的工具。
代码语言:javascript复制 pip install vllm
执行以下命令来启动服务器:
代码语言:javascript复制 python -m vllm.entrypoints.openai.api_server --model TheBloke/Llama-2-7B-Chat-AWQ --api-key DEFAULT --quantization awq --enforce-eager
这将下载AWK量化模型并启动一个OpenAI兼容服务器,我们可以像使用llama.cpp一样进行查询。
“— enforce-eager”是费差个重要的,因为它允许模型在我的10G VRAM GPU中运行,没有内存不足的错误。
在Nvidia RTX 3080 GPU和Intel®Core™i9-10900F CPU的系统下处理时间只有0.79s。CPU快20倍左右,这就是为什么GPU现在都那么贵的一个原因。
这种方式可以用做我们测试服务器或者在线上的小规模部署,如果要求不高,也可以当作生产环境来使用,当然维护起来非常麻烦。
3、Docker GPU
vllm有很多依赖,如果要批量的安装是一件非常耗时的事情。好在vllm还提供了一个预构建的docker映像,它已经包含了所需的所有库。
对于ubuntu,我们首先安装Nvidia CUDA Toolkit,如果安装了则跳过
代码语言:javascript复制 sudo apt install nvidia-cuda-toolkit
然后添加Nvidia Docker存储库并安装Nvidia Container Toolkit:
代码语言:javascript复制 distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
配置Docker使用Nvidia runtime:
代码语言:javascript复制 sudo tee /etc/docker/daemon.json <<EOF
{
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
EOF
sudo pkill -SIGHUP dockerd
然后就可以运行我们的模型了
代码语言:javascript复制 docker run --runtime nvidia --gpus all
-v ~/.cache/huggingface:/root/.cache/huggingface
-p 8000:8000
--ipc=host
vllm/vllm-openai:latest
--model TheBloke/Llama-2-7B-Chat-AWQ
--quantization awq --enforce-eager
这里我们使用-v参数将本地的磁盘映射到容器中,这样所有的容器都可以使用huggingface的模型缓存,避免了重复下载。
docker的部署方式处理一个查询的时间在0.8s左右与使用相同硬件在Anaconda上运行vllm相似。
使用docker可以大大简化我们服务器的环境配置,配合集群管理脚本可以适用于大规模的服务部署。
上面的方式都适用于本地和有GPU主机/集群的方式,下面我们介绍2个比较简单的云GPU的方案,这两个方案都是按需付费的。
4、modal
Modal可以简化无服务器应用程序的部署,特别是那些利用GPU资源的应用程序。它的一个突出的特点是它的计费模式,它确保用户只在他们的应用程序使用GPU资源的持续时间内收费。这意味着当你的应用程序不被使用时则不会收费。
Modal还提供每月30美元的优惠,为用户提供了充分的机会来探索和试验部署gpu加速的应用程序,而无需支付前期费用,这也是我们介绍他的一个原因,因为每月目前还能白嫖30美元,哈。
首先安装:
代码语言:javascript复制 pip install modal
然后配置modal的运行环境,这一步需要登陆了
代码语言:javascript复制 modal setup
我们这里的vllm_modal_deploy.py改编Modal的官方教程。这个脚本最重要的一点是定义GPU。这里我选择了nvidia T4,因为量化模型非常小:
代码语言:javascript复制 # https://modal.com/docs/examples/vllm_mixtral
import os
import time
from modal import Image, Stub, enter, exit, gpu, method
APP_NAME = "example-vllm-llama-chat"
MODEL_DIR = "/model"
BASE_MODEL = "TheBloke/Llama-2-7B-Chat-AWQ"
GPU_CONFIG = gpu.T4(count=1)
然后定义运行代码的docker镜像:
代码语言:javascript复制 vllm_image = ( # https://modal.com/docs/examples/vllm_mixtral
Image.from_registry("nvidia/cuda:12.1.1-devel-ubuntu22.04", add_python="3.10")
.pip_install(
"vllm==0.3.2",
"huggingface_hub==0.19.4",
"hf-transfer==0.1.4",
"torch==2.1.2",
)
.env({"HF_HUB_ENABLE_HF_TRANSFER": "1"})
.run_function(download_model_to_folder, timeout=60 * 20)
)
定义App:
代码语言:javascript复制 stub = Stub(APP_NAME)
最后编写预测的类:
代码语言:javascript复制 class Model:
@enter() # Lifecycle functions
def start_engine(self):
import time
from vllm.engine.arg_utils import AsyncEngineArgs
from vllm.engine.async_llm_engine import AsyncLLMEngine
print("