由DeepMind的ImageGen3生成
如果你正在阅读这篇指南,Meta 的 Llama 3 系列模型无需多做介绍。它们于 2024年4月 发布,并且是目前最适合在生产环境中使用的最佳开源 LLM 之一,与 OpenAI 的 GPT-4o 和 Anthropic 的 Claude 3.5 Sonnet 等闭源替代品直接竞争。经常有人问我如何为个人用途托管这些模型,创建合成数据集以及使用私人数据进行检索增强生成(RAG)。不幸的是,我家里没有强大的 GPU(或多个 GPU),无法运行像 70B 这样的大型模型,所以我只能使用云端并积极寻找降低成本的方法。如果你也有同样的困扰,或者只是想知道如何做到这一点,这篇文章就是为你准备的。
作为有趣的额外内容,我还将展示如何在本地运行一个类似 ChatGPT 的界面来与你的私有模型互动。
TL;DR重要提示 : 这将是一个直截了当的指南,所以不要期望我会详细解释每一步。我的简短回答是“阅读文档”
- 云: Runpod(另一个教程中也会介绍 GCP)
- 推理引擎: vLLM(未来教程中也会介绍 TGI)
- 监控与代理: LiteLLM
- 数据库: PostgreSQL 容器 或 Supabase
- GPU: 4x A40 或 2x A100
- Runpod 模板: vLLM 最新
我们应该在哪里部署?我已经创建了Runpod模板,请使用它。这也能帮我获得一些积分。
经过尝试几种选项后,我发现最划算的是在Runpod上托管模型,它是一个专为AI和机器学习应用设计的云计算平台,允许用户通过其Pods和无服务器计算选项使用GPU和CPU资源执行代码。这里是我对Runpod的看法:
- 非常容易上手
- 非常划算
- 灵活使用我们自己的Docker镜像,可以无缝转移开发环境(这也是我使用它的主要原因)
- 各种大小的GPU都可用
对于这篇文章,首先,在决定我们需要什么GPU之前,我建议遵循以下大致指南。
1. 模型大小:既然我们谈论的是一个70B参数的模型,要以16位浮点精度部署,我们需要大约140GB的内存。这已经大到无法在目前市场上的任何单GPU中运行。但是,对于4位(INT4)精度,我们只需要大约45GB的内存,不过这也导致了质量略有下降,这一点需要注意。在本指南中,我将向你展示如何部署一个70B参数的模型:
- FP16/BF16
- INT8 — Bitsandbytes
- INT4 — AWQ
现在我们知道了这些模型的大致内存/磁盘需求,最好还是检查一下每个模型的Huggingface页面,确认权重的确切大小,因为一个70B的模型并不总是恰好是70B,例如LLaMA 3.1 70B模型的大小是70.6B。
这样就相当于大约 148GB(高估了)用于 16 位精度,8 位大约是这个的一半,而对于 4 位,因为我们使用的是 AWQ,所以最好也检查一下 ->
hugging-quants/Meta-Llama-3.1-70B-Instruct-AWQ-INT4,它的大小约为 45GB。
当选择用于托管大型语言模型(如LLaMA 3.1 70B)的GPU时,会考虑几个技术因素:
2.1 VRAM 容量注意:如果你已经了解这些内容,并且只是将本文作为部署指南,请直接跳到2.8部分。
主要考虑的是GPU的VRAM(视频内存)容量。LLaMA 3.1 70B,顾名思义,有700亿参数。在FP16精度下,仅存放模型权重就需要大约148GB的内存。然而,还需要额外的内存用于:
- 上下文窗口
- KV 缓存
一般来说,你需要至少等于模型大小1.2倍到1.5倍的VRAM。但对于更长的上下文,仅仅遵循这个经验法则是不够的,一个70B模型如果上下文长度为32k,大约需要14GB的VRAM,并且随着上下文长度的增加,所需VRAM也会线性增加。
2.2 计算能力(FLOPS)FLOPS(每秒浮点运算次数)是衡量GPU原始计算能力的指标。对于大语言模型(LLM),我们特别关注张量FLOPS,这代表了GPU高效执行矩阵乘法运算的能力。
几个不同GPU的比较(前两个是目前你能买到的最好的!):
更高的FLOPS通常意味着更快的推理时间(每秒更多的token)。~300 TFLOPS意味着每秒可以执行300万亿次操作。
BF16 在大多数 GPU 上比 FP16 要快得多……如果你使用的是 Ampere 系列或更高级别的 GPU,可以将 torch_dtype
属性设置为 bfloat16
。
内存带宽对于大型模型至关重要,因为它决定了数据在VRAM和GPU核心之间移动的速度。它以GB/s为单位进行测量。
- A100: 最高 2039 GB/s
- A6000: 768 GB/s
- RTX 4090: 1008 GB/s
更高的内存带宽减少了等待数据的时间,提高了整体性能。
2.4 张量核心现代 NVIDIA GPU 包含 Tensor Core,这是一种专门用于矩阵乘法和 AI 负载的单元。Tensor Core 的数量和效率对 LLM 的性能有显著影响。
2.5 精度支持考虑你将以何种精度运行模型:
- FP32(32位浮点):精度最高,但占用内存最多
- FP16(16位浮点):精度和内存效率之间较好的平衡
- FP8(8位浮点):精度降低,但仍然比INT8好,但并非所有GPU都支持(据我所知,只有Nvidia Hopper系列的GPU支持)
- INT8(8位整数量化):精度降低,但内存占用显著减少
一些GPU(如A100)提供了混合精度功能,可以实现优化的性能。
2.6 多GPU设置对于像 LLaMA 3.1 70B 这样规模的模型,通常需要多 GPU 设置。考虑以下几点:
- 支持 NVLink 以实现高带宽的 GPU 间通信
- 使用 PCIe 带宽进行 GPU 和 CPU 之间的数据传输
当目标是经济实惠的托管时:
- 考虑使用多块消费级 GPU(例如 RTX 4090)而不是单块高端数据中心 GPU。
- 探索量化技术以减少内存需求。
- 了解提供具有竞争力定价的 GPU 云服务提供商。(因此 Runpod、JarvisLabs.ai 也是我的最爱之一)
通过平衡这些因素,你可以找到在托管 LLaMA 3.1 70B 时最具有成本效益的 GPU 解决方案,同时保持可接受的性能。
2.8 GPU 的选择考虑到这些因素,结合之前使用这些GPU的经验,确定我的个人需求,并查看在Runpod上GPU的价格(可以在这里找到:这里),我决定为每种部署选择以下GPU Pod:
- LLama 3.1 70B FP16 : 4x A40 或 2x A100
- LLama 3.1 70B INT8 : 1x A100 或 2x A40
- LLama 3.1 70B INT4 : 1x A40
此外,在撰写本文时,A40 的价格仅为每小时 0.35 美元,非常实惠。
如果你预算充足,我建议选择像H100这样的Hopper系列显卡。如果预算有限,A100、A6000、A6000-Ada或A40也都是不错的选择。如果你还想进一步降低成本(假设A40 pod的价格上涨了),可以试试8张3090显卡。
推理引擎vLLM 是当今在自定义硬件上托管 LLM 的流行选择。这是因为它已经包含了人们已经发现的许多优化:
- 使用 Paged-Attention 管理注意力机制的高效内存管理
- CUDA/HIP 图执行
- Flash Attention
- 以及其他更多功能。
这也允许我们暴露一个遵循OpenAI API格式的API,这样就更容易与使用相同格式的预写工作流集成。
创建 Runpod 实例在 Runpod 上创建实例相当简单,如果您遇到任何问题,请参阅他们的官方文档。
- 在仪表盘上,前往
Pods -> 部署
- 这里我们需要选择所需的GPU实例,我选择的是4个A40用于16位模型。
- 还需要选择正确的模板,然后编辑环境变量,检查是否正确设置了
HF_TOKEN
密钥。 - 确保TCP端口8000被代理,如果不正确设置,API将无法对外暴露。
- 编辑存储(卷磁盘),将其设置为180GB,这应该足够用于16位模型。
你的配置应该类似于以下内容:
但这还不是全部,你还需要编辑容器启动命令(CMD),这个命令告诉vLLM要拉取和设置哪个模型进行推理。你可以通过点击 Edit Template
,然后编辑 Container Start Command
来完成这个操作。
--host 0.0.0.0 --port 8000 --model meta-llama/Meta-Llama-3.1-70B-Instruct --dtype bfloat16 --enforce-eager --gpu-memory-utilization 0.95 --api-key sk-IrR7Bwxtin0haWagUnPrBgq5PurnUz86 --max-model-len 8128 --tensor-parallel-size 4
这里重要的参数是(好吧……所有内容):
- 模型 : 显然你需要选择正确的模型
- 数据类型 : 如果你使用的是安培系列或更高版本的GPU(我们使用的是),请使用
bfloat16
,否则使用float16
- enforce-eager : 我见过一些 AsyncEngineDead 问题,没有启用此选项会出现这些问题,因此目前在 vLLM 中似乎没有解决办法,你需要启用急切模式
- gpu-内存利用率 : 这取决于你希望有多少余量,我通常将其设置为
0.9
或0.95
。 - api-key : 我提供了一个示例 API 密钥,你可以随意编辑。
- 最大模型长度 : 这是模型的最大上下文长度(输入 + 输出),这取决于你的内存和使用场景。
- 张量并行大小 : 这是你用于分布式推理的 GPU 数量
--host 0.0.0.0 --port 8000 --model meta-llama/Meta-Llama-3.1-70B-Instruct --dtype bfloat16 --enforce-eager --gpu-memory-utilization 0.95 --api-key sk-IrR7Bwxtin0haWagUnPrBgq5PurnUz86 --max-model-len 8128 --tensor-parallel-size 2 --quantization bitsandbytes --load-format bitsandbytes
更改:
- 量化 : 我们将其设置为
bitsandbytes
- 加载格式 : 我们也将其设置为
bitsandbytes
- 张量并行大小 : 通过选择 8 位,我们已经将内存需求减半。
LLaMA 3.1 70B 4-bit 配置:注意:我在 vLLM 中使用 8 位模型时遇到了一些问题,如果你遇到任何问题,请参阅文档或他们在 GitHub 上的问题讨论。
--host 0.0.0.0 --port 8000 --model hugging-quants/Meta-Llama-3.1-70B-Instruct-AWQ-INT4 --enforce-eager --gpu-memory-utilization 0.98 --api-key sk-IrR7Bwxtin0haWagUnPrBgq5PurnUz86 --max-model-len 8128 --quantization awq
更改:
- 模型 : 我们使用了来自HuggingFace的AWQ格式的预量化模型。
- 量化 : 我们将其设置为
awq
,因为我们的源模型使用了这种方法进行量化。 - tensor-parallel-size : 由于4位模型可以适应单个A40 GPU的内存,因此不再需要设置这个参数。
现在,我们终于完成了所有的配置步骤。你可以启动实例了。
使用自托管模型注意: 根据模型的不同,vLLM 下载模型并提供服务可能需要一些时间。您可以在 Runpod 的日志标签页中查看日志。
你可以选择直接使用自己部署的端点,或者通过 LiteLLM 设置一个代理,这样你可以拥有多个部署实例,为不同的使用场景配置多个模型等……这一步完全是可选的,但它可以提供很好的可追溯性和对 API 的治理。如果你打算作为一个团队来消费这些 API,这一步会特别有用。
简单地消费API为了找到API的URL,点击实例上的“连接”,然后点击端口8000,这将返回一个{"detail": "Not Found"}
响应,这是因为API实际上存在于/v1/
路由中。所以复制URL并在末尾添加/v1
。
调用API应该相对简单:
import openai
OPENAI_BASE_URL = "https://runpod-instance-id-8000.proxy.runpod.net/v1" # 注意末尾的 /v1
OPENAI_API_KEY = "sk-ABCDEFGHIJKLMNOPQRSTUVWZ" # 确保替换为正确的API密钥
SYSTEM_PROMPT = "您是一个乐于助人的AI助手"
TEST_PROMPT = "什么是熵?"
client = openai.OpenAI(
api_key=OPENAI_API_KEY,
base_url=OPENAI_BASE_URL,
)
response = client.chat.completions.create(
model="meta-llama/Meta-Llama-3.1-70B-Instruct",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": TEST_PROMPT}
],
)
基于LiteLLM代理使用
从我的经验来看,使用LiteLLM有以下优势(即使用于个人用途,我也推荐使用这个)
- 统一接口:通过单一API简化与多个LLM提供商的集成。
- 高效性:优化的架构减少了计算需求,使其更加易于访问。
- 可扩展性:适应各种硬件配置而不会影响性能。
- 强大功能:支持文本生成和图像创建等多种任务。
- 错误处理:自动重试和回退机制确保连续性。
- 成本效益:通过减少对高端资源的需求来降低运营成本。
LiteLLM 是一个强大的、易于访问的工具,用于高效地利用多个语言模型。
你可以将 LiteLLM 部署在任何你想要的地方。我将在我的一个 Linux 服务器上的 Docker 中运行它。我建议查看 LiteLLM 的文档 以获取更多详细信息。
首先,我们需要创建一个包含所有模型端点的yaml配置文件。这是我的配置文件的样子:
model_list:
- model_name: vllm-llama3.1-8b
litellm_params:
model: openai/meta-llama/Meta-Llama-3.1-8B-Instruct
api_base: https://runpod-instance-id-8000.proxy.runpod.net/v1 # 确保使用正确的URL
api_key: "os.environ/VLLM_API_KEY"
- model_name: vllm-llama3.1-70b
litellm_params:
model: openai/meta-llama/Meta-Llama-3.1-70B-Instruct
api_base: https://runpod-instance-id-8000.proxy.runpod.net/v1 # 确保使用正确的URL
api_key: "os.environ/VLLM_API_KEY"
- model_name: vllm-llama3.1-70b-4bit
litellm_params:
model: openai/hugging-quants/Meta-Llama-3.1-70B-Instruct-AWQ-INT4
api_base: https://runpod-instance-id-8000.proxy.runpod.net/v1 # 确保使用正确的URL
api_key: "os.environ/VLLM_API_KEY"
并且,我们还需要一个 Docker Compose 文件 (docker-compose.yaml
) 来创建一个在本地运行的 LiteLLM 服务,并使用一个 Postgres 数据库。(当然,请确保在您的机器上安装了 Docker)
version: '3.8'
services:
litellm-database:
image: ghcr.io/berriai/litellm-database:main-latest
container_name: litellm-database
ports:
- "4000:4000"
volumes:
- ./config.yaml:/app/config.yaml
environment:
LITELLM_MASTER_KEY: sk-YOUR-KEY-HERE # 这是您可以访问所有模型的密钥
DATABASE_URL: postgres://postgres:yourpassword@postgres:5432/litellmdb
GROQ_API_KEY: gsk_yougrokapikeyhere
VLLM_API_KEY: sk-yourvllmapikeyhere
depends_on:
- postgres
command: ["--config", "/app/config.yaml", "--detailed_debug"]
postgres:
image: postgres:15
container_name: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: yourpassword
POSTGRES_DB: litellmdb
volumes:
- litellm_postgres_data:/var/lib/postgresql/data
volumes:
litellm_postgres_data:
如果你不想使用本地数据库,你可以用 Supabase 来替换它。
现在你已经创建了 compose 文件和配置文件,是时候运行它了:
sudo docker compose up -d
然后,检查容器的日志,看看一切是否正常。如果一切正常,你可以通过 http://0.0.0.0:4000
访问代理,并通过 http://0.0.0.0:4000/ui
访问UI。你可以从UI中做很多事情,请查阅文档。
现在你可以通过代理来消费你的API:
import openai
OPENAI_BASE_URL = "http://0.0.0.0:4000/v1" # 如果你将其托管在云服务器上,请在此处使用该IP/DNS
OPENAI_API_KEY = "sk-ABCDEFGHIJKLMNOPQRSTUVWZ" # 请确保替换为正确的API密钥
SYSTEM_PROMPT = "你是一个乐于助人的AI助手"
TEST_PROMPT = "什么是熵?"
client = openai.OpenAI(
api_key=OPENAI_API_KEY,
base_url=OPENAI_BASE_URL,
)
response = client.chat.completions.create(
model="meta-llama/Meta-Llama-3.1-8B-Instruct",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": TEST_PROMPT}
],
# 你可以在这里添加这些标签来监控API使用情况
extra_body={
"metadata": {
"tags": ["taskName:simple_api_test", "provider:vllm_runpod"]
}
}
)
奖励:使用聊天界面消费API
我们将使用OpenWebUI来完成此操作,步骤非常简单。您需要再次设置一个用于UI的Docker容器。这是我的docker-compose.yaml
文件的内容:
version: '3'
volumes:
open-webui:
services:
open-webui:
image: ghcr.io/open-webui/open-webui:main
environment:
- OPENAI_API_KEY=sk_ABCDEFGHIJKLMNOPQRSTUVWXYZ # 这是我们LiteLLM / Hosted服务器的API密钥
- OPENAI_API_BASE_URL=https://api.together.xyz/v1 # 这是我们LiteLLM / Hosted服务器的基础URL
- DATABASE_URL=postgres://YOURPOSTGRESURLHERE:5432/postgres
ports:
- "3000:8080"
volumes:
- open-webui:/app/backend/data
restart: always
这就差不多了,你可以在自己的UI上开始与你的模型聊天了。
结论恭喜!你现在已经成功设置了你自己的 LLaMA 3.1 70B(或任何约 70B 参数的大型语言模型)实例,并学会了如何高效地与它交互。让我们回顾一下我们所取得的成果:
- 我们探讨了托管大型语言模型的技术考虑,重点是GPU选择和内存需求。
- 我们使用Runpod设置了一个成本效益高的云部署,利用他们的GPU实例来支持不同量化级别(FP16、INT8和INT4)。
- 我们配置了vLLM作为我们的推理引擎,利用其对大型语言模型的优化。
- 我们实现了一个LiteLLM代理,以更好地管理API、提高可扩展性和监控。
通过本指南,你现在拥有了一个强大、可定制且相对实惠的环境来运行最先进的语言模型。这为个人项目、研究甚至小规模生产部署打开了无限可能。
记住,人工智能领域发展迅速,所以要留意新的优化方法、量化技术以及硬件选项,这些都可能进一步提升性能或降低成本。
祝你在新部署的LLM上愉快地实验!无论你是用于创意写作、代码生成,还是构建你下一个大型AI驱动的应用程序,你现在都有了按自己的方式和基础设施进行操作的工具。
共同学习,写下你的评论
评论加载中...
作者其他优质文章