个人 Copilot: 训练你自己的编码助手
Hugging Face 已经提出了一种创建个性化编码助手的方法,以 HugCoder 为例,这是一个在 Hugging Face GitHub 组织的公共仓库上微调的模型。这种方法使开发者和企业能够将大型语言模型 (LLM) 定制到专有代码库,从而提高对内部 API 和库的代码补全准确性。
数据收集工作流程
为了构建个性化助手,Hugging Face 实现了一个数据收集管道,通过在本地克隆仓库来提取 GitHub 仓库中的代码,同时避免 API 速率限制。
- 并行克隆: 使用 Python 的
multiprocessing模块并行下载仓库。 - 过滤: 通过预定义的扩展名列表排除非代码文件(图片、演示文稿)和非代码路径(
.git、__pycache__、xcodeproj)。 - 解析: 代码文件使用 "utf-8" 编码进行解析,对于 Jupyter Notebooks,仅提取代码单元。
- 存储: 数据使用分块和 feather 格式进行序列化,以提高内存效率。
对于 HugCoder 项目,团队根据星标数专注于 Hugging Face 前 10 大公共仓库,包括 transformers、datasets、diffusers 和 peft。
微调策略:QLoRA 与全量微调
Hugging Face 使用 Fill-In-the-Middle (FIM) 训练目标比较了 bigcode/starcoder (15.5B 参数) 模型的两种主要训练方法。
使用 QLoRA 的参数高效微调 (PEFT)
QLoRA 通过冻结基础模型并仅训练少量适配器权重,显著降低了硬件需求。
- 内存使用: 单个 A100 40GB GPU 即可满足需求,在使用 Flash Attention V2 和 Gradient Checkpointing 时,总内存占用约为 26 GB(批量大小 4)。
- 成本和时间: 训练耗时 12.5 小时,预计成本为 13.75 美元(基于每小时 1.10 美元)。
全量微调
全量微调会更新所有模型参数,但需要大量硬件资源。
- 内存使用: 对于 15.5B 模型(不包括激活),至少需要 248GB GPU 内存,因而需要至少 4 块 A100 80GB GPU。使用 PyTorch Fully Sharded Data Parallel (FSDP),每个 GPU 的内存使用范围为 70 GB 到 77.6 GB(每 GPU 批量大小 1)。
- 成本和时间: 在 8 块 A100 80GB GPU 上训练耗时 9 小时,预计成本为 108 美元(基于每小时 12.00 美元)。
性能比较
全量微调收敛更快且损失略低于 QLoRA。然而,QLoRA 模型在 humaneval-python 基准测试上的表现与基础模型相当(Pass@1 为 33.37,而基础模型为 33.57),表明没有显著的灾难性遗忘。
定性结果和代码填充
在手动分析中,微调后的模型(QLoRA 和全量两种)在涉及最近库的场景中表现优于 GitHub Copilot。例如,当被要求为 🤗 PEFT 库填充代码——这可能不在 Copilot 的训练数据中——GitHub Copilot 未提供任何补全,而 HugCoder 变体正确地用必要的参数填充了函数调用。
高级 LoRA 技巧
混合搭配 LoRAs
Hugging Face 使用 PEFT 中的 add_weighted_adapter 实用工具尝试组合不同的 LoRA 适配器。通过创建一个 code_buddy 适配器(将 chatting/QA 适配器和 code-completion 适配器以相等权重组合),模型能够同时执行代码补全并回答关于特定代码库的技术问题。
LoRA 迁移
在一个基础模型上训练的 LoRA 适配器可以迁移到其他模型。团队将经过 StarCoder 训练的适配器应用到 Octocoder 模型,得到的模型能够正确回答关于 LoraConfig 和 PEFT 模型创建的详细问题,而基础 Octocoder 模型则无法做到这一点。
部署和本地执行
远程部署
模型可以通过 🤗 Inference Endpoints 部署,并通过将 llm-vscode 扩展指向部署的端点 URL,将其集成到 VS Code 中。
本地执行
对于消费级硬件(例如 Mac M1),Hugging Face 使用 mlc-llm 库来运行较小的 starcoderbase-1b 模型。该过程包括:
- 为目标硬件编译模型(例如 Mac 的 Metal)。
- 配置
mlc-chat-config.json以获得最佳生成长度和温度。 - 运行一个连接到
llm-vscode扩展的本地 REST 服务器。