为了账号安全,请及时绑定邮箱和手机立即绑定

自建 LLaMA 3.1 70B(或任何约 70B 参数的大语言模型)的经济方案

由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参数的模型:

现在我们知道了这些模型的大致内存/磁盘需求,最好还是检查一下每个模型的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。

2. 选择GPU:技术考量

当选择用于托管大型语言模型(如LLaMA 3.1 70B)的GPU时,会考虑几个技术因素:

注意:如果你已经了解这些内容,并且只是将本文作为部署指南,请直接跳到2.8部分。

2.1 VRAM 容量

主要考虑的是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

2.3 内存带宽

内存带宽对于大型模型至关重要,因为它决定了数据在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 之间的数据传输
2.7 成本性能权衡

当目标是经济实惠的托管时:

  1. 考虑使用多块消费级 GPU(例如 RTX 4090)而不是单块高端数据中心 GPU。
  2. 探索量化技术以减少内存需求。
  3. 了解提供具有竞争力定价的 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 上创建实例相当简单,如果您遇到任何问题,请参阅他们的官方文档。

  1. 在仪表盘上,前往 Pods -> 部署
  2. 这里我们需要选择所需的GPU实例,我选择的是4个A40用于16位模型。
  3. 还需要选择正确的模板,然后编辑环境变量,检查是否正确设置了 HF_TOKEN 密钥。
  4. 确保TCP端口8000被代理,如果不正确设置,API将无法对外暴露。
  5. 编辑存储(卷磁盘),将其设置为180GB,这应该足够用于16位模型。

你的配置应该类似于以下内容:

但这还不是全部,你还需要编辑容器启动命令(CMD),这个命令告诉vLLM要拉取和设置哪个模型进行推理。你可以通过点击 Edit Template,然后编辑 Container Start Command 来完成这个操作。

LLaMA 3.1 70B 16-bit 配置:
    --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.90.95
  • api-key : 我提供了一个示例 API 密钥,你可以随意编辑。
  • 大模型长度 : 这是模型的最大上下文长度(输入 + 输出),这取决于你的内存和使用场景。
  • 张量并行大小 : 这是你用于分布式推理的 GPU 数量
LLaMA 3.1 70B 8位配置:
    --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 位,我们已经将内存需求减半。

注意:我在 vLLM 中使用 8 位模型时遇到了一些问题,如果你遇到任何问题,请参阅文档或他们在 GitHub 上的问题讨论。

LLaMA 3.1 70B 4-bit 配置:
    --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 参数的大型语言模型)实例,并学会了如何高效地与它交互。让我们回顾一下我们所取得的成果:

  1. 我们探讨了托管大型语言模型的技术考虑,重点是GPU选择和内存需求。
  2. 我们使用Runpod设置了一个成本效益高的云部署,利用他们的GPU实例来支持不同量化级别(FP16、INT8和INT4)。
  3. 我们配置了vLLM作为我们的推理引擎,利用其对大型语言模型的优化。
  4. 我们实现了一个LiteLLM代理,以更好地管理API、提高可扩展性和监控。

通过本指南,你现在拥有了一个强大、可定制且相对实惠的环境来运行最先进的语言模型。这为个人项目、研究甚至小规模生产部署打开了无限可能。

记住,人工智能领域发展迅速,所以要留意新的优化方法、量化技术以及硬件选项,这些都可能进一步提升性能或降低成本。

祝你在新部署的LLM上愉快地实验!无论你是用于创意写作、代码生成,还是构建你下一个大型AI驱动的应用程序,你现在都有了按自己的方式和基础设施进行操作的工具。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消