私の個人的なコパイロット:自分自身のコーディングアシスタントをトレーニングする
『私の個人的なコーディングパートナー:自身のアシスタントをトレーニングする方法』
プログラミングとソフトウェア開発の常に進化する風景において、効率と生産性の追求は非凡なイノベーションにつながってきました。そのようなイノベーションの一つが、Codex、StarCoder、そしてCode Llamaといったコード生成モデルの登場です。これらのモデルは、人間のようなコードの断片を生成する能力を示し、コーディングアシスタントとしての無限の潜在能力を持っています。
しかし、これらの事前学習済みモデルは、さまざまなタスクにおいて印象的なパフォーマンスを発揮する一方で、まだまだ未来に待ち受けている魅力的な可能性も存在します。それは、特定のニーズに合わせてコード生成モデルをカスタマイズできる能力です。エンタープライズスケールで活用できる個人別のコーディングアシスタントを想像してみてください。
このブログ投稿では、私たちがどのようにHugCoder 🤗を作成したかを紹介します。HugCoderは、huggingface
GitHubの公開リポジトリからのコード内容に対して、コードLLMでファインチューニングを行ったものです。データの収集ワークフローやトレーニング実験、興味深い結果についても話します。これにより、プロプライエタリなコードベースに基づいた独自のパートナーを作成することができます。さらなるこのプロジェクトの拡張のアイデアもいくつかご提案します。
では、始めましょう 🚀
データ収集のワークフロー
私たちが望むデータセットは、概念的にはシンプルで、次のような構造になっています。
Githubからのコード内容のスクレイピングは、PythonのGitHub APIを用いれば簡単です。ただし、リポジトリの数やリポジトリ内のコードファイルの数に応じて、APIのレート制限に達する可能性があります。
そのような問題を防ぐために、私たちは公開リポジトリをすべてローカルにクローンし、APIではなくそれらからコンテンツを抽出することにしました。ダウンロードスクリプトでは、Pythonのmultiprocessing
モジュールを使用して、すべてのリポジトリを並列にダウンロードしました。詳細な実装については、このダウンロードスクリプトを参照してください。
リポジトリにはしばしば画像やプレゼンテーションなどの非コードファイルが含まれていますが、私たちはそれらをスクレイピングすることには興味がありません。これらを除外するために、拡張子のリストを作成しました。Jupyter Notebook以外のコードファイルを解析するために、私たちは単純に「utf-8」エンコーディングを使用しました。ノートブックの場合は、コードセルのみを考慮しました。
また、コードと直接関係のないファイルパスはすべて除外しました。これには、.git
、__pycache__
、およびxcodeproj
などが含まれます。
このコンテンツのシリアライズを比較的メモリにやさしいものにするために、私たちはチャンキングとfeather形式を使用しました。フルの実装については、こちらのスクリプトを参照してください。
最終的なデータセットは、Hubで利用可能であり、以下のような見た目をしています:
このブログでは、stargazersに基づいて、Hugging Faceの最も人気のある10つのパブリックリポジトリを考慮しました。それらは次のとおりです:
[‘transformers’, ‘pytorch-image-models’, ‘datasets’, ‘diffusers’, ‘peft’, ‘tokenizers’, ‘accelerate’, ‘text-generation-inference’, ‘chat-ui’, ‘deep-rl-class’]
このデータセットを生成するために使用したコード と Hub内のこのデータセット を使用しました。以下はデータセットのスナップショットです:
プロジェクトの複雑さを減らすため、データセットの重複排除は考慮していませんでした。本番アプリケーションで重複排除技術を適用することに興味がある場合は、このブログ投稿 がコードLLMの文脈でのこのトピックについての優れた情報源です。
独自のパーソナルコーパイロットを微調整する
このセクションでは、以下のモデルを微調整する方法を示します:bigcode/starcoder
(15.5Bパラメータ)、bigcode/starcoderbase-1b
(1Bパラメータ)、Deci/DeciCoder-1b
(1Bパラメータ)。すべての実験には単一のA100 40GB Colabノートブックを使用し、🤗 PEFT(パラメータ効率の良い微調整)を使用します。さらに、🤗 AccelerateのFSDP統合を使用して、8つのA100 80GB GPUを搭載したマシンで bigcode/starcoder
(15.5Bパラメータ)を完全に微調整する方法も示します。トレーニングの目的は、「穴埋め(FIM)」であり、トレーニングシーケンスの一部が末尾に移動し、並べ替えられたシーケンスが自己回帰的に予測されます。
なぜPEFTを使用するのか?完全な微調整は費用がかかります。視点を整理するためにいくつかの数字をご紹介しましょう:
完全な微調整に必要な最小のGPUメモリ:
- 重み:2バイト(ミックス精度トレーニング)
- 重みの勾配:2バイト
- Adamを使用する場合のオプティマイザの状態:元のFP32重みに対して4バイト + 一次および二次モーメントの推定に対して8バイト
- 上記をすべて加算したパラメータごとのコスト:16バイト
- 15.5Bモデル -> GPUメモリの248GB(中間アクティベーションの巨大なメモリ要件を考慮せず) -> 最低4つのA100 80GB GPUが必要
ハードウェアの要件が非常に大きいため、QLoRAを使用したパラメータ効率の良い微調整を行います。QLoRAを使用したStarCoderの微調整に必要な最小のGPUメモリ要件は次のとおりです:
トレーニング可能なパラメータ:11,042,8160 || すべてのパラメータ:15,627,884,544 || トレーニング可能な%:0.7066097761926236
- ベースモデルの重み:0.5バイト * 15.51B凍結パラメータ = 7.755 GB
- アダプタの重み:2バイト * 0.11Bトレーニング可能なパラメータ = 0.22GB
- 重みの勾配:2バイト * 0.11Bトレーニング可能なパラメータ = 0.12GB
- Adamを使用する場合のオプティマイザの状態:4バイト * 0.11Bトレーニング可能なパラメータ * 3 = 1.32GB
- 上記をすべて加算した結果 -> 9.51 GB 〜 10GB -> 1つのA100 40GB GPUが必要 🤯。 A100 40GB GPUが必要な理由は、トレーニングにおける長いシーケンス長(2048)とバッチサイズ(4)の中間アクティベーションのため、より大きなメモリ要件があるためです。以下では、必要なGPUメモリが26GBであり、A100 40GB GPUで収容することができます。また、A100 GPUはFlash Attention 2との互換性がより高いです。
上記の計算では、かなり巨大な中間アクティベーションチェックポイントのメモリが考慮されていません。我々はFlash Attention V2とGradient Checkpointingを利用して、この問題を克服しています。
- QLoRAには、Flash Attention V2とGradient Checkpointingを使用し、単一のA100 40GB GPU上のモデルに占有される総メモリは26 GBで、バッチサイズは4です。
- FSDPを使用した完全なファインチューニングにおいて、Flash Attention V2とGradient Checkpointingを使用すると、1つのGPUあたりの占有メモリは70 GBから77.6 GBで、per_gpu_batch_sizeは1です。
🤗 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 FSDPおよびAccelerate Large Model Training using PyTorch Fully Sharded Data Parallelを参照してください。
リソース
- コードベース:リンク。Transformersで最近追加されたFlash Attention V2のサポートを使用しています。
- FSDP設定:fsdp_config.yaml
- モデル:bigcode/stacoder
- データセット:smangrul/hf-stack-v1
- ファインチューニングされたモデル: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時間でした。8x A100 80GB GPUの場合のコストは、lambdalabsベースで$12.00 /時間とした場合、総費用は$108になります。
PEFT
QLoRAを使用して、単一のA100 40GB GPUで15Bパラメータのbigcode/starcoder
を微調整する方法を見ていきます。詳細については、QLoRAとPEFTの方法については、bitsandbytes、4ビット量子化、およびQLoRAによるLLMのさらなるアクセシビリティの向上と🤗 PEFT:リソースの少ないハードウェア上で数十億規模のモデルのパラメータ効率的な微調整を参照してください。
リソース
- コードベース:リンク。Transformerで最近追加されたFlash Attention V2のサポートを使用しています。
- Colabノートブック:リンク。High RAM設定でA100 GPUを選択してください。
- モデル:bigcode/stacoder
- データセット:smangrul/hf-stack-v1
- QLoRAで微調整されたモデル:smangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab
トレーニングを開始するコマンドは、run_peft.shに記載されています。合計のトレーニング時間は12.5時間です。トレーニングコストは、lambdalabsに基づいて$1.10 /時間であり、合計費用は$13.75です。かなり良いです🚀!コストの面では、完全な微調整のコストと比較して7.8倍低いです。
比較
以下のプロットは、QLoRAと完全な微調整の評価損失、トレーニング損失、および学習率スケジューラの比較を示しています。完全な微調整では、わずかに低い損失を示し、QLoRAと比較して収束が少し速いことがわかります。peft微調整の学習率は、完全な微調整の学習率の10倍です。
QLoRAモデルが壊滅的な忘却を引き起こさないことを確認するために、Python Human Evalを実行します。以下に結果を示します。単一の生成されたコード候補ごとに考慮した補完の合格率をPass@1
として測定します。ベースのbigcode/starcoder
(15Bパラメータ)と微調整されたPEFTモデルsmangrul/peft-lora-starcoder15B-v2-personal-copilot-A100-40GB-colab
の性能は、humaneval-python
において同等であることがわかります。
次に、いくつかの質的なサンプルを見てみましょう。私たちの手動分析では、QLoRAモデルはわずかな過学習を引き起こすことがわかりましたので、PEFTのadd_weighted_adapter
ユーティリティを使用して、重み0.8の新しい重み付けアダプターを作成しています。
以下に、コードの補完を行う2つの例を示します。モデルのタスクは、<FILL_ME>
プレースホルダーで示された部分を補完することです。GitHub Copilot、QLoRA微調整モデル、完全な微調整モデルからの補完候補を考慮します。
質的な例1
上記の例では、GitHub Copilotの補完は正しい方向に沿っていますが、あまり役に立ちません。一方、QLoRAと完全に調整されたモデルの補完は、必要なパラメータを含んだ関数呼び出し全体を正しく埋めています。しかし、後ろにはさらに多くのノイズが追加されています。これは、補完を閉じる括弧や改行に制限する後処理ステップによって制御できます。QLoRAと完全に調整されたモデルの両方が類似した品質の結果を生成します。
定性的な例2
上記の2番目の例では、GitHub Copilotはどのような補完も提供しませんでした。これは、🤗 PEFTが最近のライブラリであり、まだCopilotのトレーニングデータの一部ではないため、起こり得る問題の一例です。一方、QLoRAと完全に調整されたモデルの補完は、関数呼び出し全体を正しく埋める必要なパラメータで埋めることができます。また、QLoRAと完全に調整されたモデルの両方が類似した品質の生成を提供していることも注意してください。完全に調整されたモデルとpeftモデルのさまざまな例に関する推論コードは、それぞれFull_Finetuned_StarCoder_Inference.ipynbおよびPEFT_StarCoder_Inference.ipynbで利用可能です。
したがって、両方のバリアントから生成される結果が期待どおりであることがわかります。すごい!🚀
VS Codeでの使用方法は?
🤗 llm-vscodeのVS Code拡張機能を使用して、独自のコード補完LLMを簡単にVS Codeで設定することができます。これには、🤗 Inference EndPointsを介してモデルをホストする必要があります。以下に必要な手順について説明します。エンドポイントのデプロイに関する詳細については、推論エンドポイントのドキュメントをご覧ください。
推論エンドポイントの設定
以下は、独自の推論エンドポイントを作成するために実行した手順のスクリーンショットです。QLoRAモデルを使用し、transformers
で簡単にロードできるフルサイズのマージドモデルとしてエクスポートしました。
VS Code拡張機能の設定
インストール手順に従ってください。設定では、以下のフィールド内のエンドポイントを置き換えて、デプロイしたHF推論エンドポイントを指すようにします。
使用方法は以下のようになります:
これまでにトレーニングしたモデルは、コード補完タスクのためのパーソナルコパイロットとして特別にトレーニングされています。会話や質問応答を行うためにトレーニングされているわけではありません。そのようなモデルの素晴らしい例には、Octocoder
とStarChat
があります。このセクションでは、それを実現する方法について簡単に説明します。
リソース
- コードベース:リンク。Transformersの最新追加Flash Attention V2のサポートを使用しています。
- Colabノートブック:リンク。High RAM設定でA100 GPUを選択してください。
- モデル:bigcode/stacoderplus
- データセット:smangrul/code-chat-assistant-v1。形式の整った
LIMA+GUANACO
のトレーニング用フォーマットのミックスです。 - トレーニング済みモデル:smangrul/peft-lora-starcoderplus-chat-asst-A100-40GB-colab
もしStable DiffusionモデルとLoRAsを使って独自のDreamboothモデルを作成してきた場合、異なる重みを持つLoRAsを組み合わせる概念には慣れているかもしれません。LoRAモデルとは、それがトレーニングされたベースモデルとは異なるベースモデルを使用するというものです。テキスト/コード領域においては、これは未開拓の領域となっています。私たちはこのことに関して実験を行い、非常に有望な結果を得ました。準備はできましたか?さあ、始めましょう!🚀
ミックスアンドマッチのLoRAs
PEFTは現在、LoRAモデルを組み合わせるlinear、svd、およびcatの3つの方法をサポートしています。詳細については、tuners#peft.LoraModel.add_weighted_adapterを参照してください。
私たちのノートブックDance_of_LoRAs.ipynbにはすべての推論コードとさまざまなLoRAのロード組み合わせが含まれており、starcodeplus
ではなくstarcoder
の上にチャットアシスタントをロードするなど、実験のコードも含まれています。
ここでは、2つの能力(チャット/QA
およびコード補完
)について、2つのデータ分布(トップ10の公共hfコードベース
および一般的なコードベース
)を考慮します。これにより、いくつかの質的評価分析を行います。
まず、チャット/QA
のタスクを考慮しましょう。
アダプタを無効にすると、両方のデータセットでタスクが失敗することがわかります。ベースモデル(starcoder
)はコード補完専用であり、chatting/question-answering
には適していません。copilot
アダプタを有効にすると、これはコード補完用に特に微調整されたLoRAなので、無効化した場合と同様の結果になります。
次に、assistant
アダプタを有効にしましょう。
一般的なコードに基づく質問応答
HFコードに基づく質問応答
一般的なscrapy
に関する質問には適切な回答がなされていることが観察されます。ただし、それは事前トレーニングデータの一部ではなかったHFコードに関連する質問では失敗しています。
次に、コード補完
のタスクを考慮しましょう。
アダプタを無効にすると、一般的なtwo-sumのコード補完は予想どおり機能します。しかし、HFコードの補完は、ベースモデルが事前トレーニングデータでそれを見たことがないため、LoraConfig
に間違ったパラメータを指定して失敗します。assistant
を有効にすると、Hugging Faceのコードリポジトリを持つ自然言語の会話でトレーニングされたため、無効化した場合と同様の結果になります。
さあ、copilot
アダプタを有効にしましょう。
copilot
アダプタは、どちらの場合でも正しく機能することが分かります。したがって、HF特有のコードベースや一般的なコードベースでのコードの補完時に期待どおりのパフォーマンスを発揮します。
では、ユーザーとして、assistant
とcopilot
の機能を組み合わせたいと思います。これにより、IDEでコーディング中にコード補完として使用し、API、クラス、メソッド、ドキュメントに関する質問に対するチャットボットとしても使用できるようになります。 How do I use x
やPlease write a code snippet for Y
などの質問に回答できるようにする必要があります。
PEFTでは、add_weighted_adapter
を介してそれを行うことができます。 assistant
とcopilot
アダプタの重みが等しいように、新しいアダプタcode_buddy
を作成しましょう。
複数のアダプタの結合
では、code_buddy
がchatting/question_answering
のタスクでどのように機能するか見てみましょう。
code_buddy
は、assistant
またはcopilot
アダプタ単体よりもはるかに優れたパフォーマンスを発揮しています! 特定のHFリポジトリのAPIの使用方法を示すコードスニペットのリクエストに回答することができます。ただし、間違ったリンク/説明も生成しているため、これはLLMにとって未解決の課題です。
code_buddy
のコード補完タスクに対するパフォーマンスは以下の通りです。
code_buddy
は、このタスクに特化して微調整されたcopilot
と同等のパフォーマンスを発揮しています。
LoRAを異なるベースモデルに転送する
また、LoRAモデルを異なるベースモデルに転送することもできます。最新のOctocoder
モデルを取り上げ、上記でトレーニングしたLoRAをstarcoder
ベースモデルで適用します。全体のコードについては、このノートブックPEFT_Personal_Code_CoPilot_Adapter_Transfer_Octocoder.ipynbを参照してください。
コード補完タスクのパフォーマンス
octocoder
は素晴らしいパフォーマンスを発揮しています。HF特有のコードスニペットを完了することができます。また、ノートブックでも一般的なコードスニペットを完了することができます。
チャット/質疑応答タスクのパフォーマンス
Octocoderはコーディングに関する質問と会話を行うようにトレーニングされているため、LoRAアダプタを使用してHF特有の質問に回答できるかどうか見てみましょう。
やった! LoraConfig
を作成し、関連するPEFTモデルを使用する方法を詳細に説明しており、モデル名、データセット名、およびLoraConfigのパラメータ値を正しく使用しています。アダプタを無効にすると、LoraConfig
のAPIの使用方法やPEFTモデルの作成に正しく対応できず、それがOctocoderのトレーニングデータの一部ではないことを示します。
これで、あなたはスターコーダーを自分のコードベースで微調整し、Macラップトップ(M1 GPUを搭載)やRTX 4090/3090 GPUを搭載したWindowsなどの消費者向けハードウェアでローカルに使用することができます…心配しないでください、私たちはあなたをサポートします。
私たちはこの超クールなオープンソースライブラリmlc-llm🔥を使用します。具体的には、このフォークpacman100/mlc-llmを使用します。これには、Hugging Face Code Completion拡張機能 for VS Codeとの連携を可能にするための変更が含まれています。私のM1 Metal GPU搭載のMacラップトップでは、15Bモデルは遅すぎました。そのため、PEFT LoRAバージョンとbigcode/starcoderbase-1b
の完全微調整バージョンをトレーニングします。以下にトレーニング用のColabノートブックへのリンクを示します:
starcoderbase-1b
の完全微調整とPEFT LoRA微調整のためのColabノートブック:リンク
トレーニングロス、評価ロス、および学習率スケジュールを以下にプロットします:
さあ、マージされたモデルsmangrul/starcoder1B-v2-personal-copilot-mergedをローカルにホストし、🤗llm-vscodeVS Code拡張機能と一緒に使用する詳細な手順を見ていきましょう。
- リポジトリをクローンする
git clone --recursive https://github.com/pacman100/mlc-llm.git && cd mlc-llm/
- mlc-aiとmlc-chatをインストールする(編集モードで):
pip install --pre --force-reinstall mlc-ai-nightly mlc-chat-nightly -f https://mlc.ai/wheelscd pythonpip uninstall mlc-chat-nightlypip install -e "."
- モデルをコンパイルする:
time python3 -m mlc_llm.build --hf-path smangrul/starcoder1B-v2-personal-copilot-merged --target metal --use-cache=0
- 以下の値で
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"}
- ローカルサーバーを実行する:
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
- HF コード補完拡張機能のエンドポイントをローカルサーバーに変更します:
- VS Codeで新しいファイルを開き、以下のコードを貼り付け、ドキュメント引用符の間にカーソルを置きます。これにより、モデルがドキュメント文字列を補完しようとします:
ボワッと! ⭐️
この投稿の冒頭でデモを行ったのは、Macのローカル環境で実行している1Bモデルです。
結論
このブログ投稿では、starcoder
を微調整して、私たちのコードに関する知識を持つ個人コーディングパートナーを作成する方法を見てきました。それを私たちは🤗 HugCoderと呼んでいます。なぜなら、Hugging Faceのコードでトレーニングしたからです 🙂 データ収集ワークフローを見た後、QLoRAと完全なファインチューニングを使用したトレーニングを比較しました。また、「LoRA」を組み合わせるという異なる実験も行いました。これは、テキスト/コードのドメインではまだ未開拓の技術です。展開では、🤗 Inference Endpointsを使用したリモート推論を検討しました。また、VS CodeとMLCを使用した小型モデルのデバイス上での実行も示しました。
ご自身のコードベースにこれらの方法を使用される場合は、ぜひお知らせください!
謝辞
このブログ投稿の執筆にあたり、Pedro Cuenca、Leandro von Werra、Benjamin Bossan、Sylvain Gugger、およびLoubna Ben Allalさんにお礼申し上げます。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles