在不断发展的大型语言模型(LLM)领域,为其提供服务的工具和技术的发展速度与模型本身一样快。与 xgboost 或 MNIST 分类器 CNN 等传统模型不同,LLM 的规模和复杂性都很大,需要更细致的关注才能有效部署。
在这篇文章中,我们将重点关注开源 LLM,由于其可调性和可破解性,开源 LLM 可能是最有优势的,任何人都可以为这一领域做出贡献并推动其进步。
我在这里的目的是引导大家了解为 LLM 服务的各种方法,以满足不同的使用情况。我将介绍五种不同的方案,每种方案都附有全面的复制说明,并对它们各自的优缺点进行深入探讨。
我们将探讨本地部署和利用托管服务的选项。更重要的是,我们将讨论的这些服务都提供了慷慨的免费点数,让你不花一分钱就能进行试验。
在下文中,我们将使用 LLama2 7B 聊天变体。
设置本地开发设置
对于某些方法,你需要一个本地 Python 虚拟环境。以下是设置方法:
1. 按照 https://docs.anaconda.com/free/anaconda/install/linux/ 官方文档中提供的说明安装 Anaconda。
2. Anaconda 安装完成后,打开终端,使用以下命令创建一个专门用于本教程的新环境:
conda create -n llm-serve-tutorial python=3.10
3. 创建环境后,使用以下命令激活它:
conda activate llm-serve-tutorial
4. 现在,你可能需要安装本教程所需的其他 Python 软件包。你有一个 requirements.txt 文件,其中列出了这些依赖包,你可以使用 pip 安装它们。运行此命令前,请确保已进入激活环境:
pip install -r requirements.txt
现在一切就绪!现在我们可以开始了。
本地服务器: Anaconda+ CPU
第一种方法使用 llama.cpp 及其 python 绑定程序 llama-cpp-python,这种方法的入门门槛最低,因为只要按照以下步骤操作,它几乎可以在任何有足够 CPU 和内存的地方运行:
安装预编译库
首先,安装预编译的 llama-cpp-python 库及其服务器依赖项。在终端运行以下命令
pip install llama-cpp-python[server] \
--extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cpu
下载 5 位量化模型
创建名为 models/7B 的目录来存储下载的模型。然后,使用以下命令下载 GGUF 格式的 5 位量化模型:
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
运行服务器
现在,运行以下命令启动服务器:
python3 -m llama_cpp.server --model models/7B/llama-2-7b-chat.Q5_K_M.gguf
这将在 localhost:8000 启动一个服务器,我们可以在下一步进行查询。
查询服务器
将环境变量 MODEL 设置为下载模型的路径。然后,运行 openai_client.py 脚本查询服务器。使用提供的提示并观察响应。
export MODEL="models/7B/llama-2-7b-chat.Q5_K_M.gguf"
python openai_client.py
openai_client.py 将使用 OpenAI 库调用 LLM 服务器并打印响应。我们将在所有测试中使用相同的提示,要求服务器提供《南方公园》主要角色的名称:
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{
"role": "user",
"content": "What are the names of the four main characters of South Park?",
},
]
我们得到了这样的答复:
啊,一个简单的问题!《南方公园》的四个主角是:
1. 斯坦-马什
2. 凯尔-布洛夫洛夫斯基
3. 埃里克-卡曼
4. 肯尼-麦考密克
自 1997 年首播以来,这四个男孩一直是该剧的核心人物,多年来引发了无数笑料和争议!
硬件和延迟
(13.4s)的处理时间是基于配备Intel® Core™ i9–10900F CPU @ 2.80GHz 的系统。你的实际处理时间可能会有所不同,具体取决于你的系统规格。
本地服务器:Anaconda+ GPU
如果你觉得之前的 CPU 方法很慢,不用担心!LLM 可以显著受益于 GPU 加速。在此设置中,我们将使用 vllm,这是一款专为高效利用 GPU 而设计的工具。
安装
要开始安装,请使用 pip 安装所需的库:
pip install vllm
服务器设置
现在,让我们执行以下命令启动服务器:
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 上运行,并且不会出现内存不足错误。
查询服务器
服务器启动并运行后,你可以使用提供的 Python 脚本进行查询。将环境变量 MODEL 设置为所需的模型,然后执行脚本:
export MODEL="TheBloke/Llama-2-7B-Chat-AWQ"
python openai_client.py
我们使用与之前相同的提示,得到了类似的响应,但这次要快得多。
硬件和延迟
处理时间(0.79 秒)是基于配备 Nvidia RTX 3080 GPU 和 Intel® Core™ i9-10900F CPU 的系统。实际处理时间可能因你的硬件配置而异。其延迟比 CPU 服务低约 20 倍!
本地服务器: Docker + GPU
前一种方法很好,但 vllm 有很多重度依赖项,比如必须在机器上安装的 `torch`。幸好 vllm 还提供了预编译的 docker 镜像,其中已经包含了所需的所有库。
以下是使用支持 GPU 的 Docker 架设本地服务器的分步指南:
安装 Docker
如果还没有安装,请按照官方文档中提供的说明安装 Docker。
安装 Nvidia Docker Runtime(适用于 Ubuntu)
首先,安装 Nvidia CUDA 工具包:
sudo apt install nvidia-cuda-toolkit
然后,添加 Nvidia Docker 存储库并安装 Nvidia Container Toolkit:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)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:
sudo tee /etc/docker/daemon.json <<EOFtee /etc/docker/daemon.json <<EOF
{
"runtimes": {
"nvidia": {
"path": "/usr/bin/nvidia-container-runtime",
"runtimeArgs": []
}
}
}
EOF
sudo pkill -SIGHUP dockerd
运行 Docker
docker run --runtime nvidia --gpus all \
-v ~/.cache/huggingface:/root/.cache/huggingface \/.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
这样就能在本地主机上启动服务器。请注意,我们挂载了 huggingface 的缓存文件夹,这样,如果模型权重已经在你的机器中,你就不必在每次运行时重新下载。
查询服务器
随着 docker 服务器的启动和运行,你可以使用提供的 Python 脚本来查询它。将环境变量 MODEL 设置为所需的模型,然后执行脚本:
export MODEL="TheBloke/Llama-2-7B-Chat-AWQ"
python openai_client.py
我们使用了与之前相同的提示,并得到了相同的回应。
硬件和延迟
处理时间 (0.81s) 与使用相同硬件在 Anaconda 上运行 vllm 相似。
Modal
Modal 是一个尖端平台,旨在简化无服务器应用程序的部署,尤其是那些利用 GPU 资源的应用程序。它的一个突出特点是其计费模式,可确保用户只需在其应用程序使用 GPU 资源的时间段内支付费用。这意味着在应用程序未被使用的情况下,你不会被计费。(但你仍需为超时前的闲置时间付费)。
以下是使用 Modal 部署 LLM 的步骤:
安装 modal 库
pip install modal
身份验证
在模态上注册,然后运行:
modal setup
这样就可以登录了。
这个脚本最重要的一点是定义 GPU。这里我选择了 Nividia T4,因为量化模型相当小:
import os # https://modal.com/docs/examples/vllm_mixtral
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 镜像:
vllm_image = ( # https://modal.com/docs/examples/vllm_mixtral# 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)
)
然后,定义模态应用程序:
stub = Stub(APP_NAME)
接下来,定义预测类:
class Model: # https://modal.com/docs/examples/vllm_mixtral
@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("? cold starting inference")
start = time.monotonic_ns()
engine_args = AsyncEngineArgs(
model=MODEL_DIR,
tensor_parallel_size=GPU_CONFIG.count,
gpu_memory_utilization=0.90,
enforce_eager=False, # capture the graph for faster inference, but slower cold starts
disable_log_stats=True, # disable logging so we can stream tokens
....
像 @enter() 这样的装饰器用于定义生命周期方法,以处理代码初始化等事宜。在这里,它会加载模型并设置生成管道。如果你的查询触发了这个方法,就意味着你将 "冷启动",这意味着在等待设置时会有更大的延迟。
我们还定义了生成函数:
@stub.function()
def generate(user_question: str):
model = Model()
print("Sending new request:", user_question, "\n\n")
result = ""
for text in model.completion_stream.remote_gen(user_question):
print(text, end="", flush=True)
result += text
return result
现在,我们可以部署这一切:
modal deploy vllm_modal_deploy.py
部署完成后,我们可以从 python 中调用该函数:
import timeit
import modal
APP_NAME = "example-vllm-llama-chat"
f = modal.Function.lookup(APP_NAME, "generate")
start_time = timeit.default_timer()
print(f.remote("What are the names of the four main characters of South park?"))
elapsed = timeit.default_timer() - start_time
print(f"{elapsed=}")
回答:
南方公园的四个主要角色是
1. 斯坦·马什
2. 凯尔·布罗夫洛夫斯基
3. 埃里克·卡特曼
4. 肯尼·麦考密克
自 1997 年首播以来,这四个角色一直是该剧的核心人物,也是该剧多季以来的主要焦点。
硬件和延迟
冷启动延迟约为 37 秒。这包括启动时间和处理时间。热启动延迟(即应用程序已启动)为 2.8 秒。所有这些都是在 Nvidia T4 上运行的。
你可以通过增加 container_idle_timeout 的值来减少冷启动时间,从而使应用程序在最后一次查询后保持更长时间的运行,但这也会增加你的成本。
成本
Modal 的 Nvidia T4 收费为 0.000164 美元*/秒,或 0.59 美元*/小时。在本教程中我只用了几百秒的计算时间,成本约为 0.1 美元。
AnyScale
Anyscale 提供了具有流行开源模型的即用型端点。我们可以使用 Anyscale API 的 URL 直接调用它们。
首先,我们需要注册并获得一个 API 密钥。你可以使用他们为新用户提供的 10 美元免费级别运行本教程。
接下来,我们将使用之前使用过的 openai_client.py 脚本:
export API_KEY="CHANGEME"
export MODEL="meta-llama/Llama-2-7b-chat-hf"
export BASE_URL="https://api.endpoints.anyscale.com/v1"
python openai_client.py
回答:
啊,这个问题一定会让世界各地的《南方公园》迷们会心一笑!南方公园》的四个主要角色是
1. 斯坦·马什
2. 凯尔·布罗夫洛夫斯基
3. 埃里克·卡特曼
4. 肯尼·麦考密克
自 1997 年首播以来,这四个男孩一直是该剧的焦点人物,他们的滑稽行为和冒险经历让观众大呼过瘾。
潜伏期
此请求的延迟时间约为 3.7 秒。
成本
AnyScale 向 LLama2 7B 支付每百万代币 0.15* 美元的费用。多次运行这些查询的成本不到百分之一。
结论
总之,在为大型语言模型(LLM)提供服务时,有多种选择可以考虑,每种选择都有自己的优缺点。
对于那些喜欢本地服务器设置的人来说,使用带有 CPU 的 Anaconda 可降低入门门槛并确保数据隐私,但由于本地机器的限制,它可能会受到高延迟和可扩展性有限的影响。转移到 GPU 加速的 Anaconda 环境可以缓解延迟问题,但它在可扩展性和对本地资源的依赖性方面仍面临限制,尤其是在处理大型 LLM 时。
另外,支持 GPU 的 Docker 在低延迟和数据私密性方面也具有类似的优势,同时无需 Python 环境配置,从而简化了设置过程。不过,与之前的本地服务器设置一样,它也受到本地机器的限制,可能无法在消费级 GPU 上很好地扩展巨大的 LLM。
Modal 提供了一种更灵活的解决方案,即按使用付费计算,因此其成本效益和设置简便性非常吸引人。虽然它可以访问各种规模的 GPU,并以无服务器方式运行,但与本地 GPU 设置相比,它的延迟可能略高。
对于那些追求简单和经济实惠的用户来说,AnyScale 提供了低门槛和高性价比的微调服务。不过,它可能缺乏其他选项的灵活性和可扩展性,LLM 选择有限,延迟可能较高。