在编程和软件开发这个不断演化的领域中,对功率和生产力的追求催生了许多杰出的创新。其间一个显著的创新便是代码生成模型的呈现,如 CodexStarCoderCode Llama。这些模型在生成类似人类编写的代码片段方面体现出惊人才能,显示出了作为编程帮手的巨大潜力。

但是,尽管这些预练习模型在各种使命上现已体现出了杰出的性能,但在不远的未来,咱们依然能够期待一个令人兴奋的前景: 想象一下,你能够依据自己的特定需求定制代码生成模型,并且这种个性化的编程帮手能够在企业规模上得到运用。

在这篇博客中,咱们将展现怎么创建 HugCoder ,一个在 huggingface GitHub 安排 的公共库房代码内容上进行微调的代码大模型。咱们将叙述咱们的数据搜集作业流程、练习试验,以及一些风趣的成果。这将使你能够依据你的专有代码库创建自己的个人编程帮手。咱们还将为这个项目的进一步扩展留下一些试验的方向。

让咱们开始吧

数据搜集的作业流

咱们想要的数据集在概念上十分简略,咱们像下面所示那样构建它。

库房名 库房中的文件途径 文件内容

运用 Python GitHub API 从 GitHub 上抓取代码内容是直截了当的。但是,这取决于库房的数量和库房内代码文件的数量,一般情况,人们很容易会遇到 API 速率限制等问题。

为了避免这类问题发生,咱们决定将一切公共库房克隆到本地,并从中提取内容,而不是经过 API。咱们运用 Python 的 multiprocessing 模块并行下载一切库房,如 这个下载脚本

一个库房一般可能包含非代码文件,如图片、演示文稿和其他材料。咱们对抓取它们不感兴趣。咱们为此创建了一个 扩展名列表 来过滤掉它们。为了解析除了 Jupyter Notebook 之外的代码文件,咱们简略地运用了 “utf-8” 编码。关于 notebook,咱们只考虑了代码单元。

咱们还排除了一切与代码不直接相关的文件途径。这些包含: .git__pycache__xcodeproj

为了坚持这些内容的序列化相对内存友爱 (即处理代码时不会过多占用内存),咱们运用了分块处理办法和 feather 格局 (储存序列化的数据)。完好完结请参见 这个脚本

最终的数据集 可在 Hub 上获取,它看起来像这个样子:

个人编程帮手: 练习你自己的编码帮手

关于这篇博客,咱们选取了基于点赞数排名前十的 Hugging Face 公共库房。它们分别是:

[‘transformers’, ‘pytorch-image-models’, ‘datasets’, ‘diffusers’, ‘peft’, ‘tokenizers’, ‘accelerate’, ‘text-generation-inference’, ‘chat-ui’, ‘deep-rl-class’]

这是咱们用来生成这个数据集的代码,而 这是数据集在 Hub 上的链接。下面是它的一个快照:

个人编程帮手: 练习你自己的编码帮手

为了下降项目复杂性,咱们没有考虑对数据集进行去重。假如你对在生产运用中运用去重技能感兴趣,这篇博客文章 是一个极佳的资源,它在代码大模型的内容中具体评论了这个主题。

微调你的个人代码帮手

在这一部分,咱们将展现怎么微调以下模型: bigcode/starcoder (15.5B 参数) 、bigcode/starcoderbase-1b (1B 参数) 和 Deci/DeciCoder-1b (1B 参数)。咱们将运用一个带有 40GB 显存的 A100 Colab Notebook,并运用 PEFT (Parameter-Efficient Fine-Tuning,参数高效微调) 进行一切试验。此外,咱们还将展现怎么运用 Accelerate 的 FSDP (Fully Sharded Data Parallel,全分片数据并行) 集成,在一台配备 8 个 80GB 显存的 A100 GPU 的机器上完全微调 bigcode/starcoder (15.5B 参数)。练习目标是 fill in the middle (FIM) ,其间练习序列的一部分被移动到序列的结尾,并且重排序后的序列被自回归地猜测。

为什么挑选 PEFT ?由于全微调价值高昂。让咱们来看一些数字以便更好地理解:

全微调所需的最小 GPU 内存:

  1. 参数权重: 2 字节 (混合精度练习)
  2. 参数权重梯度: 2 字节
  3. 运用 Adam 优化器时的优化器状况: 4 字节用于原始 FP32 权重 + 8 字节用于一阶和二阶矩估计
  4. 将以上一切内容加在一起的每个参数本钱: 每个参数 16 字节
  5. 15.5B 模型 -> 248GB 的 GPU 内存,甚至还没有考虑存储中心激活值所需的巨大内存 -> 至少需求 4 个 A100 80GB GPU

由于硬件需求巨大,咱们将运用 QLoRA 进行参数高效微调。下面是运用 QLoRA 进行 Starcoder 微调的最小 GPU 内存需求:

trainable params: 110,428,160 || all params: 15,627,884,544 || trainable%: 0.7066097761926236

  1. 根底模型权重: 0.5 字节 * 15.51B 冻结参数 = 7.755GB
  2. 适配器 (Adapter) 权重: 2 字节 * 0.11B 可练习参数 = 0.22GB
  3. 权重梯度: 2 字节 * 0.11B 可练习参数 = 0.22GB
  4. 运用 Adam 优化器时的优化器状况: 4 字节 * 0.11B 可练习参数 * 3 = 1.32GB
  5. 将以上一切内容加在一起 -> 9.51GB ~ 10GB -> 需求 1 个 A100 40GB GPU 。挑选 A100 40GB GPU 的原因是,练习时长序列长度为 2048,批量巨细为 4,这会导致更高的内存需求。如下所示,所需的 GPU 内存为 26GB,能够在 A100 40GB GPU 上包容。此外,A100 GPU 与 Flash Attention 2 具有更好的兼容性。

在上面的核算中,咱们没有考虑中心激活值检查点所需的内存,这一般是适当巨大的。咱们运用 Flash Attention V2 和梯度检查点来处理这个问题。

  1. 关于 QLoRA,加上 flash attention V2 和梯度检查点,单个 A100 40GB GPU 上模型占用的总内存为 26GB批量巨细为 4
  2. 关于运用 FSDP 进行全微调,加上 Flash Attention V2 和梯度检查点,每个 GPU 上占用的内存在 70GB 到 77.6GB 之间, 每个 GPU 的批量巨细为 1

请参阅 model-memory-usage 以轻松核算在 Hugging Face Hub 上保管的大型模型上进行练习和推理所需的 vRAM。

全微调

咱们将讨论怎么运用 PyTorch Fully Sharded Data Parallel (FSDP) 技能在 8 个 A100 80GB GPU 上完全微调 bigcode/starcoder (15B 参数)。欲了解更多关于 FSDP 的信息,请参阅 Fine-tuning Llama 2 70B using PyTorch FSDPAccelerate Large Model Training using PyTorch Fully Sharded Data Parallel

资源

  1. 代码库: 链接。它运用了 Transformers 中最近增加的 Flash Attention V2 支撑。
  2. FSDP 装备: fsdp_config.yaml
  3. 模型: bigcode/stacoder
  4. 数据集: smangrul/hf-stack-v1
  5. 微调后的模型: smangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab

发动练习的命令在 run_fsdp.sh 中给出。

accelerate launch --config_file "configs/fsdp_config.yaml" train.py 
    --model_path "bigcode/starcoder" 
    --dataset_name "smangrul/hf-stack-v1" 
    --subset "data" 
    --data_column "content" 
    --split "train" 
    --seq_length 2048 
    --max_steps 2000 
    --batch_size 1 
    --gradient_accumulation_steps 2 
    --learning_rate 5e-5 
    --lr_scheduler_type "cosine" 
    --weight_decay 0.01 
    --num_warmup_steps 30 
    --eval_freq 100 
    --save_freq 500 
    --log_freq 25 
    --num_workers 4 
    --bf16 
    --no_fp16 
    --output_dir "starcoder-personal-copilot-A100-40GB-colab" 
    --fim_rate 0.5 
    --fim_spm_rate 0.5 
    --use_flash_attn

总的练习时刻为 9 小时。依据 lambdalabs 的价格,8 个 A100 80GB GPU 的本钱为每小时 12.00,总本钱将为∗∗12.00,总本钱将为 **108**。

PEFT

咱们将讨论怎么运用 PEFT 的 QLoRA 办法对 bigcode/starcoder (15B 参数) 进行微调,运用的硬件是单个 A100 40GB GPU。有关 QLoRA 和 PEFT 办法的更多信息,请参阅 Making LLMs even more accessible with bitsandbytes, 4-bit quantization and QLoRA PEFT: Parameter-Efficient Fine-Tuning of Billion-Scale Models on Low-Resource Hardware

资源

  1. 代码库: 链接。它运用了 Transformers 中最近增加的 Flash Attention V2 支撑。
  2. Colab notebook: 链接。请保证挑选带有 High RAM 设置的 A100 GPU。
  3. 模型: bigcode/stacoder
  4. 数据集: smangrul/hf-stack-v1
  5. QLoRA 微调模型: smangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab

发动练习的命令在 run_peft.sh 中给出。总的练习时刻为 12.5 小时。依据 lambdalabs 的价格,每小时 1.10∗∗,总本钱将为∗∗1.10**,总本钱将为 **13.75。这真是太棒了!从本钱上讲,它比全微调的本钱低了 7.8 倍

比照

下面的图展现了 QLoRA 与全微调的评价损失、练习损失和学习率调度器。咱们调查到,全微调的损失略低,收敛速度也略快一些,与 QLoRA 相比。PEFT 微调的学习率是全微调的 10 倍。

个人编程帮手: 练习你自己的编码帮手

为了保证咱们的 QLoRA 模型不会导致灾难性忘记,咱们在其上运转了 Python Human Eval。以下是咱们得到的成果。 Pass@1 评价了单个问题的经过率,考虑了每个问题仅生成一个代码候选。咱们能够调查到,在 humaneval-python 上,根底模型 bigcode/starcoder (15B 参数) 和微调后的 PEFT 模型 smangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab 的性能是可比的。

模型 Pass@1
bigcode/starcoder 33.57
smangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab 33.37

现在让咱们来看一些定性的样本。在咱们的手动分析中,咱们留意到 QLoRA 导致了轻微的过拟合,因而咱们经过运用 PEFT 的 add_weighted_adapter 工具,创建一个权重为 0.8 的新加权适配器 (Adapter) 来下降其权重。

咱们将看两个代码填充的比如,其间模型的使命是填充由 <FILL_ME> 占位符表明的部分。咱们将考虑从 GitHub Copilot、QLoRA 微调模型和全微调模型的填充完结。

个人编程帮手: 练习你自己的编码帮手

定性示例 1

在上面的示例中,GitHub Copilot 的补满是正确的,但帮助不大。另一方面,QLoRA 和全微调模型的补全正确地填充了整个函数调用及其必要的参数。但是,它们之后也增加了许多噪声。这能够经过后处理过程来操控,以限制补全到闭括号或新行。留意,QLoRA 和全微调模型发生的成果质量类似。

个人编程帮手: 练习你自己的编码帮手

定性示例 2

在上面的第二个示例中, GitHub Copilot 没有给出任何补全。这可能是由于 PEFT 是一个最近的库,还没有成为 Copilot 练习数据的一部分,这 正是咱们试图处理的问题类型。另一方面,QLoRA 和全微调模型的补全正确地填充了整个函数调用及其必要的参数。再次留意,QLoRA 和全微调模型供给的生成质量类似。全微调模型和 PEFT 模型的各种示例的推理代码分别可在 Full_Finetuned_StarCoder_Inference.ipynbPEFT_StarCoder_Inference.ipynb 中找到。

因而,咱们能够调查到,两种变体的生成都契合预期。太棒了!

怎么在 VS Code 中运用?

你能够轻松地运用 llm-vscode VS Code 扩展装备一个自定义的代码补全大模型,并经过 Inference EndPoints 保管模型。咱们将在下面逐步介绍所需的过程。你能够在 推理端点文档 中了解有关布置端点的更多具体信息。

设置推理端点

下面是咱们创建自定义推理端点时遵从的过程的截图。咱们运用了咱们的 QLoRA 模型,导出为一个能够轻松加载到 transformers 中的全尺度的 merged 模型。

个人编程帮手: 练习你自己的编码帮手

个人编程帮手: 练习你自己的编码帮手

设置 VS Code 扩展

只需按照 安装过程 操作。在设置中,将下面字段中的端点替换为你布置的 HF 推理端点的地址。

个人编程帮手: 练习你自己的编码帮手

运用起来如下所示:

个人编程帮手: 练习你自己的编码帮手

微调你自己的代码谈天帮手

到现在为止,咱们练习的模型特别是作为代码完结使命的个人帮手练习。它们没有被练习来进行对话或答复问题。 OctocoderStarChat 是这类模型的绝佳示例。本节简要描绘了怎么完结这一点。

资源

  1. 代码库: 链接。它运用了 Transformers 中最近增加的 Flash Attention V2 支撑。
  2. Colab notebook: 链接。请保证挑选带有 High RAM 设置的 A100 GPU。
  3. 模型: bigcode/stacoderplus
  4. 数据集: smangrul/code-chat-assistant-v1。混合了 LIMA+GUANACO 并以合适练习的格局正确格局化。
  5. 练习好的模型: smangrul/peft-lora-starcoderplus-chat-asst-A100-40GB-colab

LoRA 的组合

假如你曾经涉足 Stable Diffusion 模型和 LoRAs,以及用于制作你自己的 Dreambooth 模型,你可能会了解将不同的 LoRAs 与不同的权重结合起来的概念,运用一个与其练习基模型不同的 LoRA 模型。在文本/代码领域,现在仍是未被探究的领域。咱们在这方面进行了试验,并调查到了十分风趣的发现。你预备好了吗?咱们动身吧!

混合匹配 LoRAs

PEFT 现在支撑 3 种结合 LoRA 模型的方法,linearsvdcat 。更多细节,请参阅 tuners#peft.LoraModel.add_weighted_adapter

咱们的 notebook Dance_of_LoRAs.ipynb 供给了一切推理代码,并展现了多种 LoRA 模型的加载组合。例如,它展现了怎么在 starcoder 模型上加载谈天帮手适配器 (Adapter),尽管 starcoderplus 是咱们用于微调的根底模型。

这儿,咱们将考虑 2 种才能 ( 谈天/问答代码完结 ) 在 2 种数据分布 ( 前 10 公共 hf 代码库通用代码库 ) 上。这给了咱们 4 个轴,咱们将在上面进行一些定性评价分析。

首要,让咱们考虑谈天/问答 使命。

假如咱们禁用适配器 (Adapter),咱们调查到关于两个数据集来说使命都失利了,由于基模型 ( starcoder ) 仅用于代码完结,不合适 谈天/问答 。启用 copilot 适配器 (Adapter) 的体现类似于禁用的情况,由于这个 LoRA 也是专门为代码完结而微调的。

现在,让咱们启用 assistant 适配器 (Adapter)。

个人编程帮手: 练习你自己的编码帮手

基于生成代码的 QA

个人编程帮手: 练习你自己的编码帮手

基于 HF 代码的 QA

咱们能够调查到,关于 scrapy 的通用问题得到了妥善的答复。但是,它未能答复与 HF (Hugging Face) 代码相关的问题,由于这不是它预练习数据的一部分。

现在让咱们考虑 代码补全 使命。

在禁用适配器 (Adapter) 时,咱们调查到关于通用的两数之和问题,代码补全如预期般作业正常。但是,关于 HF 代码补全使命,由于根底模型在其预练习数据中未曾见过,所以在向 LoraConfig 传递参数时呈现了错误。启用 assistant 的体现与禁用时类似,由于它是在自然言语对话的根底上练习的,这些对话中没有任何 Hugging Face 代码库房的内容。

现在,让咱们启用 copilot 适配器 (Adapter)。

个人编程帮手: 练习你自己的编码帮手

咱们能够调查到,在两种情况下 copilot 适配器 (Adapter) 都得到了正确的成果。因而,无论是在处理 HF (Hugging Face) 特定代码库还是通用代码库时,它都能如预期地完结代码补全使命。

现在,作为用户,我希望能结合 assistantcopilot 的才能。这将使我能够在 IDE 中编码时运用它进行代码补全,同时也能将它作为谈天机器人来答复我关于 API、类、办法、文档的问题。它应该能够供给对问题的答案,如 我该怎么运用 x ,请在我的代码的根底上 为 Y 编写一段代码片段

PEFT 答应你经过 add_weighted_adapter 来完结这一点。让咱们创建一个新的适配器 code_buddy ,给予 assistantcopilot 适配器相同的权重。

个人编程帮手: 练习你自己的编码帮手

结合多种适配器 (Adapter)

现在,让咱们看看 code_buddy谈天/问答 使命上的体现。

个人编程帮手: 练习你自己的编码帮手

咱们能够调查到 code_buddy 的体现比单独的 assistantcopilot 适配器要好得多!它能够答复 写代码片段 的请求,展现怎么运用特定的 HF 库房 API。但是,它也呈现了错误链接/解释的错觉,这依然是大型言语模型面对的一个开放性挑战。

下面是 code_buddy 在代码补全使命上的体现。

个人编程帮手: 练习你自己的编码帮手

咱们能够调查到 code_buddy 的体现与专门为这个使命微调的 copilot 不相上下。

将 LoRA 模型迁移到不同的根底模型

咱们还能够将 LoRA 模型迁移到不同的根底模型上。 咱们将取刚出炉的 Octocoder 模型,并在其上运用咱们之前用 starcoder 根底模型练习的 LoRA。请检查以下 notebook PEFT_Personal_Code_CoPilot_Adapter_Transfer_Octocoder.ipynb,了解悉数代码。

代码补全使命上的体现

个人编程帮手: 练习你自己的编码帮手

咱们能够调查到 octocoder 的体现很好。它能够完结 HF (Hugging Face) 特定的代码片段。如 notebook 中所见,它也能够完结通用的代码片段。

谈天/问答使命上的体现

由于 Octocoder 被练习用来答复有关编程的问题和进行对话,让咱们看看它是否能运用咱们的 LoRA 适配器来答复 HF (Hugging Face) 特定的问题。

个人编程帮手: 练习你自己的编码帮手

太棒了!它具体正确地答复了怎么创建 LoraConfig 和相关的 peft 模型,并且正确地运用了模型称号、数据集称号以及 LoraConfig 的参数值。当禁用适配器时,它未能正确运用 LoraConfig 的 API 或创建 PEFT 模型,这表明它不是 Octocoder 练习数据的一部分。

我怎么在本地运转它?

我知道,在阅历了这一切之后,你想在你自己的代码库上微调 starcoder 并在本地运用,比如在带有 M1 GPU 的 Mac 笔记本电脑上,或者带有 RTX 4090/3090 GPU 的 Windows 电脑上……别忧虑,咱们现已为你预备好了。

咱们将运用这个超酷的开源库 mlc-llm 。具体来说,咱们将运用这个分支 pacman100/mlc-llm,它进行了一些修正,能够与 VS Code 的 Hugging Face 代码完结扩展合作运用。在我的搭载 M1 Metal GPU 的 Mac 笔记本上,15B 模型运转得十分慢。因而,咱们将缩小规模,练习一个 PEFT LoRA 版别以及一个完全微调版别的 bigcode/starcoderbase-1b 。以下是练习用的 Colab notebook 链接:

  1. 全微调和 PEFT LoRA 微调 starcoderbase-1b 的 Colab notebook: 链接

下面制作了练习损失、评价损失以及学习率计划图:

个人编程帮手: 练习你自己的编码帮手

现在,咱们将看看具体过程,本地保管兼并后的模型 smangrul/starcoder1B-v2-personal-copilot-merged 并运用 llm-vscode VS Code 扩展。

  1. 克隆库房
git clone --recursive https://github.com/pacman100/mlc-llm.git && cd mlc-llm/

2. 安装 mlc-ai 和 mlc-chat (在编辑形式):

pip install --pre --force-reinstall mlc-ai-nightly mlc-chat-nightly -f https://mlc.ai/wheels
cd python
pip uninstall mlc-chat-nightly
pip install -e "."

3. 经过以下方法编译模型:

time python3 -m mlc_llm.build --hf-path smangrul/starcoder1B-v2-personal-copilot-merged --target metal --use-cache=0

4. 在 dist/starcoder1B-v2-personal-copilot-merged-q4f16_1/params/mlc-chat-config.json 中更新装备,设定以下的值:

{
    "model_lib": "starcoder7B-personal-copilot-merged-q4f16_1",
    "local_id": "starcoder7B-personal-copilot-merged-q4f16_1",
    "conv_template": "code_gpt",
- "temperature": 0.7,
+ "temperature": 0.2,
- "repetition_penalty": 1.0,
    "top_p": 0.95,
- "mean_gen_len": 128,
+ "mean_gen_len": 64,
- "max_gen_len": 512,
+ "max_gen_len": 64,
    "shift_fill_factor": 0.3,
    "tokenizer_files": [
        "tokenizer.json",
        "merges.txt",
        "vocab.json"
    ],
    "model_category": "gpt_bigcode",
    "model_name": "starcoder1B-v2-personal-copilot-merged"
}
  1. 运转本地服务:
 python -m mlc_chat.rest --model dist/starcoder1B-v2-personal-copilot-merged-q4f16_1/params --lib-path dist/starcoder1B-v2-personal-copilot-merged-q4f16_1/starcoder1B-v2-personal-copilot-merged-q4f16_1-metal.so

6. 将 VS Code 中的 HF Code Completion 扩展的端点更改为指向本地服务器:

个人编程帮手: 练习你自己的编码帮手

  1. 在 VS Code 中打开一个新文件,张贴下面的代码,并将光标放在文档引号之间,这样模型就会测验填充文档字符串:

个人编程帮手: 练习你自己的编码帮手

瞧!⭐️

这篇文章开头的演示便是这个 1B 模型在我的 Mac 笔记本上本地运转的效果。

定论

在这篇博客中,咱们探究了怎么对 starcoder 进行微调,然后创建了一个能理解咱们代码的个人编程帮手。咱们称之为 HugCoder,由于它是在 Hugging Face 的代码上进行练习的 :) 在回顾了数据搜集流程之后,咱们比照了运用 QLoRA 和全面微调进行练习的效果。咱们还测验了组合不同的 LoRAs,这在文本和代码领域是一项尚待开发的技能。在布置方面,咱们研讨了运用 Inference Endpoints 进行长途推理,并且还展现了怎么在 VS Code 和 MLC 上本地执行一个较小的模型。

假如你将这些办法运用到了你自己的代码库,请告知咱们!

称谢

咱们要感谢 Pedro CuencaLeandro von WerraBenjamin BossanSylvain GuggerLoubna Ben Allal 在编撰这篇博客时供给的帮助。


英文原文: hf.co/blog/person…

原文作者: Sourab Mangrulkar, Sayak Paul

译者: innovation64

审校/排版: zhongdongy (阿东)