LLMs:《如何使用Ray + DeepSpeed + HuggingFace简单、快速、经济有效地微调和服务LLM》解读

LLMs:《如何使用Ray + DeepSpeed + HuggingFace简单、快速、经济有效地微调和服务LLM》解读

导读:这是我们有关生成式人工智能的博客系列的第4部分。在之前的博客文章中,我们解释了以下内容:

>> 为什么Ray是生成式人工智能的可靠平台;

>> 我们展示了如何推动性能极限;

>> 如何使用Ray进行稳定扩散;

在这篇博客中,我们将分享一种实用的方法,教你如何使用HuggingFace、DeepSpeed和Ray的组合来构建一个微调和服务llm的系统,在40分钟内花费不到7美元创建一个60亿参数模型。我们特别说明以下几点:

>> 使用这三个组件,您可以简单而快速地构建一个开源的LLM微调和提供系统。

>> 通过充分利用Ray的分布式功能,我们展示了这相对于使用单个大型(通常难以获得)计算机来说,既更具成本效益又更快的方式。

目录

《如何使用Ray + DeepSpeed + HuggingFace简单、快速、经济有效地微调和服务LLM》解读

1、下面是我们将要做的:40行Python代码实现60亿参数的GPT-J模型

2、我为什么要运行自己的LLM?低成本+低延迟+数据安全和隐私

3、如何创建和运行自己的LLM?LLMs技术堆栈=HuggingFace(提供模型)+DeepSpeed(加速训练)+Pytorch(提供DL框架)+Ray(编排功能)+Nvidia (硬件支持)

4、使用Ray为文本生成提供现有模型

5、微调您的LLM:采用DeepSpeed优化加速

6、微调和性能

7、闭环:基于微调模型提供服务

8、结论:提出新的技术堆栈让微调、部署简单快速


《如何使用Ray + DeepSpeed + HuggingFace简单、快速、经济有效地微调和服务LLM》解读

地址

博客地址:How to Fine-Tune a 6 Billion Parameter LLM for Less Than $7

作者

Waleed Kadous, Jun Gong, Antoni Baum和Richard Liaw

时间

2023年4月10日

1、下面是我们将要做的:40行Python代码实现60亿参数的GPT-J模型

>>讨论为什么您可能想要运行自己的LLM,而不是使用新的API提供商之一。

>>展示我们正在看到的用于成本效益的LLM微调和提供的技术堆栈,包括HuggingFace、DeepSpeed、Pytorch和Ray。

>>展示40行Python代码,可以使您提供一个60亿参数的GPT-J模型。

>>展示您如何在不到7美元的成本内,通过在低成本计算机上以分布方式微调模型,使其更像中世纪的莎士比亚作品。这比使用一台功能强大的大型机器要划算得多。

>>展示如何提供经过微调的6B LLM编译模型二进制文件。

>>展示微调模型与大型系统的提示工程方法比较。

2、我为什么要运行自己的LLM?成本+低延迟+数据安全和隐私

在线有很多LLM API提供商。为什么您想要运行自己的LLM呢?有几个原因:

>>成本,特别是对于微调推理:例如,OpenAI针对Davinci上的微调模型每1000个标记(约700个单词)收费12美分。重要的是要记住,许多用户交互需要多次后端调用(例如,一个用于帮助生成提示、生成后的内容的修改等),因此与最终用户的单次交互可能会花费几美元。对于许多应用程序来说,这是成本上的障碍。

>>延迟:使用这些LLM是非常慢的。例如,对于GPT-3.5的查询可能需要高达30秒。如果从您的数据中心到他们的数据中心进行几次往返,可能需要几分钟才能完成查询。这使得许多应用程序不可能实现。将处理内部允许您优化应用程序的堆栈,例如使用低分辨率模型、紧密打包查询到GPU等等。我们已经听说,优化工作流程通常可以实现5倍或更多的延迟改进。

>>数据安全和隐私:为了从这些API获取响应,您必须向它们发送大量数据,用于许多应用程序(例如,发送一些内部文件片段并要求系统对其进行总结)。许多API提供商保留使用这些实例进行重新训练的权利。鉴于组织数据的敏感性以及数据驻留等频繁的法律约束,这将受到限制。特别令人担忧的最近发展是能够从学习模型中重新生成训练数据,以及人们无意中泄露秘密信息。

3、如何创建和运行自己的LLM?LLMs技术堆栈=HuggingFace(提供模型)+DeepSpeed(加速训练)+Pytorch(提供DL框架)+Ray(编排功能)+Nvidia (硬件支持)

LLM领域正在飞速发展,目前正在快速演进。我们看到的是一个结合了多种技术的特定技术堆栈:

(图片:技术堆栈)

我们还看到,人们不愿超越一台机器进行训练。部分原因是,人们认为迁移到多台机器上配置是一件很复杂的事情。好消息是Ray.io在这方面表现出色,它使用Python和Ray装饰器简化了跨机器的协调和编排方面,同时也是将整个堆栈组合在一起的一个很好的框架。

最近关于Dolly和Vicuna的结果(它们都是在Ray上训练的,或者是使用Ray构建的模型,比如GPT-J)是小型LLMs(相对而言,例如开源模型GPT-J-6B,具有60亿参数),在合适的数据微调时可以非常强大。当对正确的数据进行微调时,它们可以非常强大。关键在于微调和正确的数据部分。因此,你并不总是需要使用最新的、最好的、有超过1500亿个参数的模型来得到有用的结果。我们开始吧!

4、使用Ray为文本生成提供现有模型

关于如何使用Ray服务GPT-J模型的详细步骤可以在这里找到,因此让我们重点介绍如何做到这一点的一些方面。

   @serve.deployment(ray_actor_options={"num_gpus":1})
   classPredictDeployment:
     def__init__(self, model_id:str, revision:str=None):
        from transformers import AutoModelForCausalLM, AutoTokenizer
        import torch
        self.model = AutoModelForCausalLM.from_pretrained(
            "EleutherAI/gpt-j-6B",
            revision=revision,
            torch_dtype=torch.float16,
            low_cpu_mem_usage=True,
            device_map="auto",  # automatically makes use of all GPUs available to the Actor
        )

在Ray中提供服务是通过执行器(actors)完成的,这里有一个名为PredictDeployment的执行器。以下是这个执行器的__init__方法的代码,该方法从Hugging Face下载模型。要在当前节点上启动模型,我们只需执行以下操作:

deployment = PredictDeployment.bind(model_id=model_id, revision=revision)
serve.run(deployment)

这将在本地机器的端口8000上启动一个服务。现在,我们可以使用几行Python代码查询该服务

import requests
prompt = "从前,有一匹马。"
sample_input = {"text": prompt}
output = requests.post("http://localhost:8000/", json=[sample_input]).json()
print(output)

当运行时,它会打印出上述开头的续写。每次运行时,续写都会略有不同。

"从前,有一匹马。

但这匹马太大了,不能被关进普通的马厩。相反,这只动物被转移到一个室内牧场,在那里它可以一次离开马厩几个小时。问题是这个牧场太宽敞了,马被困在里面常常会感到有点无聊。牧场也没有屋顶,所以这是一个积雪的好地方。”

这当然是一个有趣的方向和故事,但现在我们想把它设置在中世纪。我们能做什么?

5、微调您的LLM:采用DeepSpeed优化加速

既然我们已经展示了如何为模型提供服务,那么我们如何微调它以使其更具中世纪风味?如果我们用莎士比亚的2500行台词来训练它呢?

这就是DeepSpeed的用武之地。DeepSpeed是一套用于训练和微调网络的优化算法。问题在于DeepSpeed没有编排层。这在单个计算机上不是太大的问题,但如果您想要使用多台计算机,通常涉及一堆定制的ssh命令、复杂的管理密钥等等。

这就是Ray可以帮助的地方。

下面的Ray文档页面讨论了如何微调模型以使其更像15世纪的风格。让我们看看其中的关键部分。首先,我们从Hugging Face加载数据:

from datasets import load_dataset
print("加载 tiny_shakespeare 数据集")
current_dataset = load_dataset("tiny_shakespeare")

跳过标记化代码,以下是我们将为每个worker运行的代码的核心部分:

def trainer_init_per_worker(train_dataset, eval_dataset=None, **config):
    # 使用Ray分配的实际CPU数
    model = GPTJForCausalLM.from_pretrained(model_name, use_cache=False)
    model.resize_token_embeddings(len(tokenizer))
    enable_progress_bar()
    metric = evaluate.load("accuracy")
    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
        eval_dataset=eval_dataset,
        compute_metrics=compute_metrics,
        tokenizer=tokenizer,
        data_collator=default_data_collator,
    )
    return trainer

现在,我们创建一个Ray AIR HuggingFaceTrainer,,它协调分布式运行,并围绕上面的训练循环的多个副本


trainer = HuggingFaceTrainer(
    trainer_init_per_worker=trainer_init_per_worker,
    trainer_init_config={
        "batch_size": 16,  # 每个设备
        "epochs": 1,
    },
    scaling_config=ScalingConfig(
        num_workers=num_workers,
        use_gpu=use_gpu,
        resources_per_worker={"GPU": 1, "CPU": cpus_per_worker},
    ),
    datasets={"train": ray_datasets["train"], "evaluation": ray_datasets["validation"]},
    preprocessor=Chain(splitter, tokenizer),
)
results = trainer.fit()

虽然这里有一些复杂性,但与在简单计算机上运行的代码相比,它并不复杂。

6、微调和性能

与LLMs相关的最重要话题之一是成本问题。在这种特定情况下,成本较低(部分原因是因为我们只进行了一轮微调,具体取决于问题,通常使用1-10轮微调,部分原因是因为这个数据集不太大)。但是在不同配置上运行测试显示,理解性能并不总是容易。以下是在AWS上不同配置的机器上进行的一些基准测试结果。

看看这些数字,我们发现了一些惊喜:也许最值得使用的机器是g5.48xlarge——纸面上性能最高的机器——在使用spot实例时,它既是最昂贵的,也是最慢的,几乎是价格的两倍。

具有GPU之间NVLink的p3.16xlarge是一个相当好的选择。

最令人惊讶的是,使用多台计算机既是最便宜的选项(16台机器),又是最快的选项(32台机器)。相同的代码在所有机器上运行,除了调整GPU工作者的数量之外,没有进行其他更改。使用多台机器为我们提供了最便宜(16台机器)和最快(32台机器)的选项。

这就是Ray的魅力和力量。代码本身足够简单,实际上可以使用标准库DeepSpeed,无需进行任何修改。因此,在这种情况下,它与在单个机器上运行一样简单,同时提供更多的选择和灵活性,以实现比单个机器更便宜和更快的优化。

7、闭环基于微调模型提供服务

现在我们有了一个经过微调的模型,让我们尝试为其提供服务。唯一需要做的更改是

(a)从微调过程中将模型复制到S3,并

(b)从那里加载它。换句话说,与我们最初开始的代码相比,唯一的变化是:

checkpoint = Checkpoint.from_uri(
     "s3://demo-pretrained-model/gpt-j-6b-shakespeare"
)
with checkpoint.as_directory() as dir:
    self.model = AutoModelForCausalLM.from_pretrained(
        dir,
        torch_dtype=torch.float16,
        low_cpu_mem_usage=True,
        device_map="auto")
self.tokenizer = AutoTokenizer.from_pretrained(dir)

现在让我们再次尝试查询它:

从前有一匹马。这匹马是我年轻时的马,有点任性,但却是最好的一匹。“是的,先生;我了解田野里的每一匹马,而我最了解的是死去的马。现在我感谢诸神,要告辞了。

正如您所看到的,它确实具有更浓厚的莎士比亚风格。

8、结论:提出新的技术堆栈让微调、部署简单快速

我们已经展示了一个新的技术堆栈,结合了Ray、HuggingFace、DeepSpeed和PyTorch,制定了一个系统,它:
>>使部署服务变得简单而快速。
>>可用于成本有效的微调,并且在使用多台机器时最具成本效益,而无需复杂性。
>>展示了微调,即使只有一轮,也可以改变已训练模型的输出。
>>部署经过微调的模型几乎与部署标准模型一样简单。

### Python 中类似的框架 在 Python 生态系统中,存在多个用于构建人工智能应用程序的框架,它们的功能与 Java 的 DeepSeek4J 类似。以下是几个值得考虑的选择: #### 1. **LangChain** LangChain 是一个流行的开源框架,专注于帮助开发者创建复杂的链式逻辑来处理自然语言任务。它支持多种大语言模型 (LLMs),并提供了丰富的工具集以实现对话管理、数据检索等功能[^4]。 ```python from langchain.llms import OpenAI from langchain.prompts import PromptTemplate from langchain.chains import LLMChain llm = OpenAI() prompt_template = PromptTemplate(input_variables=["question"], template="Answer the following question: {question}") chain = LLMChain(llm=llm, prompt=prompt_template) response = chain.run(question="What is LangChain?") print(response) ``` #### 2. **Hugging Face Transformers** Transformers 库由 Hugging Face 提供,允许用户轻松加载预训练的语言模型,并对其进行微调或直接使用。此库广泛应用于文本生成、分类和其他 NLP 任务中[^3]。 ```python from transformers import pipeline nlp = pipeline('text-generation', model='gpt2') result = nlp("Once upon a time", max_length=50) print(result) ``` #### 3. **Ray RLlib** 虽然 Ray 主要以其分布式计算能力闻名,但其子项目 RLlib 则专攻强化学习领域。正如提到过的那样,在某些特定条件下,强化学习可以通过自定义奖励函数极大地提升系统的性能[^2]。 ```python import ray from ray.rllib.algorithms.ppo import PPOConfig ray.init() config = ( PPOConfig() .environment(env="CartPole-v1") .rollouts(num_rollout_workers=2) .training(model={"fcnet_hiddens": [64, 64]}) ) algo = config.build() for i in range(10): result = algo.train() print(f"Iteration {i} - Training Result: {result}") algo.save("/tmp/model_checkpoint") ``` #### 4. **SpaCy** 如果目标集中在高效地解析和理解大量文本,则 SpaCy 可能会成为理想之选。尽管它的主要用途在于传统意义上的自然语言处理而非生成型 AI,但它同样具备强大的功能集合。 ```python import spacy nlp = spacy.load("en_core_web_sm") doc = nlp("Apple is looking at buying U.K. startup for $1 billion") for ent in doc.ents: print(ent.text, ent.label_) ``` 以上列举了一些主流选项;具体选择取决于项目的实际需求和技术栈偏好。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个处女座的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值