こんにちは。バクラク事業部・機械学習エンジニアの上川です。
最近、推しのK-POPグループであるNewJeansがとんでもないことになっていて、一刻も早く元気になってほしいです...頑張れ...!
LayerX Tech Advent Calendar 2024の24日目の記事になります。 tech.layerx.co.jp
この記事では、LayerXで導入されているGitHub Copilot for Businessを有効活用し、NeovimをAIエディタとして利用する方法を紹介したいと思います。
はじめに
CursorのようなAIエディタの登場により、「タブを押すだけ」と揶揄されるほど、コーディングの体験は劇的に変化しつつあります。 AIによるコード補完、リファクタリング提案、バグ修正支援など、これまで開発者の技術と経験に大きく依存していた作業が、AIのサポートによって大幅に効率化されています。 今まで使っていたエディタから、このようなAIツールへの移行を検討する人は多いのではないでしょうか。
私も例外ではなく、何度かNeovimからCursorへの移行チャレンジをしたのですが、結局Neovimに戻るというのを繰り返しています。理由は大きく二つあります。
一つは、長年使い込んできたNeovimの操作性は何物にも代えがたいことです。個人的には、Neovimのモード概念や洗練されたキーバインド、カスタマイズ性の高さは、AIのサポートに匹敵するほどに開発効率を支える重要な要素になっています。また、alpha-nvimというプラグインを使って、NewJeans仕様にカスタマイズして利用しており、単純に愛着が沸いてしまっています。(実は起動するたびにランダムなメンバーカラーに変わる…)
もう一つは、このようなAIツールの多くが高額なサブスクリプションを必要とすることです。例えば、Cursorの無料プランでは機能が制限され、本格的に利用するためには有料プランへのアップグレードが必要です。
私はChatGPTやClaudeなどに課金しており、できるだけ様々なAIツールを使うようにしていますが、出費が嵩んでしまうため複数のサブスクリプションを気軽に導入できるとは言えません。
これらの背景から、本記事では弊社で導入されているGitHub Copilot for Businessを有効活用し、NeovimをAIエディタへと進化させる方法をご紹介したいと思います。
GitHub Copilot for Businessの概要
ご存知の方も多いと思いますが、GitHub CopilotとはGitHubが提供するコーディング支援ツールです。 GitHub Copilotは開発者がコードを書く際に、コードのコンテキストに合わせて補完候補を提案してくれます。これによって、開発者はコードをより迅速に書くことができるようになります。
LayerXでは開発効率と品質の向上を狙い、さまざまなツールやサービスの検証と導入を進めており、GitHub CopilotのBusinessプランを利用することができます。
GitHub Copilotといえば「コードの補完機能」というイメージが強いかもしれませんが、その他にも様々な拡張機能があります。
以下、各プランで利用できる機能です。
この中にo1やclaude-3.5-sonnetなどと対話的にコーディングをすることができるGitHub Copilot Chatという機能があります。
この機能をうまく活用することで、
- コードの説明
- エラー修正の提案
- テストコードの生成
- プロジェクトの新規作成
- 特定の領域に特化したエージェント
などのAIエディタ風の体験を、Neovimの操作性を維持しつつ実現することができます。
また、Cursorでo1やClaude-3.5-sonnetなどを利用する場合は、利用量(トークン数)に合わせて料金が発生しますが、GitHub Copilot for Business経由だと定額で利用することができます。(個人の支出は不要。福利厚生に感謝。)
Neovimへの導入方法
公式のドキュメントにも記載がありますが、公式のプラグインが提供されています。lazy.nvimを使った場合の例ですが、packer.nvimなどのプラグインマネージャーを利用しても簡単に入れることができます。 :Copilot setup
を実行し、ブラウザでGitHubの認証を行います。これだけで、GitHub Copilotの設定は完了です。
return { "github/copilot.vim", lazy=false, }
しかし、公式プラグインだけではコード補完しか利用できないので、拡張機能を利用するためにCopilotChat.nvimというプラグインを導入します。
return { { "CopilotC-Nvim/CopilotChat.nvim", dependencies = { { "github/copilot.vim" }, -- or zbirenbaum/copilot.lua { "nvim-lua/plenary.nvim", branch = "master" }, -- for curl, log and async functions }, build = "make tiktoken", -- Only on MacOS or Linux opts = { -- See Configuration section for options }, -- See Commands section for default commands if you want to lazy load on them }, }
また、このままではチャットの内容が英語で返ってくるので、日本語で返ってくるように設定を行います。
require("CopilotChat").setup { debug = true, proxy = nil, allow_insecure = false, model = 'claude-3.5-sonnet', temperature = 0.1, prompts = { Explain = { prompt = '/COPILOT_EXPLAIN 選択したコードの説明を段落をつけて書いてください。', selection = select.selection or function() return {} end, }, Fix = { prompt = '/COPILOT_FIX このコードには問題があります。バグを修正したコードに書き換えてください。', selection = select.selection or function() return {} end, }, Optimize = { prompt = '/COPILOT_OPTIMIZE 選択したコードを最適化し、パフォーマンスと可読性を向上させてください。', selection = select.selection or function() return {} end, }, Docs = { prompt = '/COPILOT_DOCS 選択したコードのドキュメントを書いてください。ドキュメントをコメントとして追加した元のコードを含むコードブロックで回答してください。使用するプログラミング言語に最も適したドキュメントスタイルを使用してください(例:JavaScriptのJSDoc、Pythonのdocstringsなど)', selection = select.selection or function() return {} end, }, Tests = { prompt = '/COPILOT_TESTS 選択したコードの詳細な単体テスト関数を書いてください。', selection = select.selection or function() return {} end, }, FixDiagnostic = { prompt = '/COPILOT_FIXDIAGNOSTIC ファイル内の次のような診断上の問題を解決してください:', selection = select.diagnostics or select.selection or function() return {} end, }, Commit = { prompt = '/COPILOT_COMMIT この変更をコミットしてください。', selection = select.gitdiff or select.selection or function() return {} end, }, CommitStaged = { prompt = '/COPILOT_COMMITSTAGED ステージングされた変更をコミットしてください。', selection = select.selection or function() return {} end, }, }, window = { layout = 'vertical', width = 0.3, height = 0.3, relative = 'editor', border = 'single', row = 0, col = 0, title = 'Copilot Chat', footer = nil, zindex = 1, }, }
導入は以上なので、さっそく対話方式でコーディングしてみます。
試しに内容に誤りのあるコードのレビューを依頼します。
def calculate_sum(numbers): """ 数値のリストを受け取って合計を計算する関数。 """ result = "" for number in numbers: result += str(number) # 数値を文字列として結合 return result # 使用例 numbers = [1, 2, 3, 4, 5] print(calculate_sum(numbers)) # 結果は '12345'(期待される出力は15)
すると、LLMがコードの誤りについて指摘してくれます。また、誤りだけでなく、最適化の提案などもしてくれます。
コードの生成も依頼します。(プロンプトも補完してくれるのですが、これが地味にありがたい)
このようにNeovimでClaude-3.5-sonnetやo1のようなAIと対話的にコーディングを進めることができます。
外部のコンテキスト情報を考慮したチャット
Cursorには、開いているファイルだけではなく、リポジトリ全体や公式ドキュメントなどの外部のコンテキスト情報を利用してAIとチャットができる機能があります。
元々CopilotChat.nvimでは、コンテキスト情報を考慮したチャット機能は実装されていませんでした。そのため、面倒ですがgpt-repositorty-loaderなどを利用し、リポジトリ全体をテキスト化してチャットに入力することで、コンテキスト情報を考慮したチャットなどを行っていました。
しかし、最近の変更でそれらの機能が実装されたので、最後にその紹介をさせていただきます。
コンテキスト情報を利用したチャットは、#files
のように#から始まる特定のプロンプトで利用できます。
利用できるコンテキスト情報一覧です。
- buffer: 指定されたバッファ
- buffers: すべてのバッファ
- file: 指定されたファイルの内容
- files: ワークスペース内のすべてのnon hiddenファイル
- files:list: ファイル名のみのリスト
- files:full: ワークスペース内の全てのファイル(大規模なワークスペースでは処理が遅くなる可能性があるため注意が必要)。
- git: 現在のGitの差分
- git:unstaged: ステージングされていない変更
- git:staged: ステージングされた変更
- url: 指定されたURLの内容
最後に
本記事では、GitHub Copilot for BusinessやCopilotChat.nvimなどのプラグインを活用し、NeovimをAIエディタとして使う方法を紹介しました。
慣れ親しんだNeovimの操作性を損なうことなく、チャットベースでコードをレビューしたり生成したりできるため、開発効率や体験が大きく向上しました(Neovimキーバインドの拡張機能はなんか違う)。
まだ、痒いところに手が届いてない感じも若干ありますが、Cursorを使ったほうが生産性上がるだろうなーと思いつつもNeovimを使っていたので、諦めなくてよかったです...!!