🎃

クラウドへコードを出せなくても、ローカルLLMを使ってAIにコーディングさせる方法(まずはAiderで単発のEdit)

に公開

概要

GitHub CopilotなどでAIにコーディングさせるというのは、どんどん一般化してきています。しかしプロジェクトによっては、クラウドサービスにソースコードを送ることは許されないなどの理由で導入できない場合も有ると思います。

そういう場合、ローカルLLMにコーディングさせることができれば問題は解決します。

その方法を試してみて、ある程度上手く行ったのでこの記事で紹介します。エージェントモード的に何度も修正・ビルド・デバッグを自律的に繰り返すようなところまでは動かせていませんが、指示したとおりにソースコードを変更するところまでは問題なく動いています。

注意点:この記事が解決するのは、「クラウドにコードを出さない」という1点だけです。生成されたコード自体には何の保証も無く、GitHub CopilotのIP Indemnificationのようなサポートもありません。実務で使用する場合は、「クラウドにコードを出さない」以外の点に問題が無いかに注意して検討ください。

最初に結論まとめ

  • やったこと: LM Studio でローカルに OpenAI API 互換エンドポイントを立て、Aider からモデル lm_studio/qwen2.5-coder-7b-instruct を呼び出して、CLIからのチャットで処理を実行
  • できたこと:
    • Aiderで、指定ファイルのコードを読んで書き換えるなどの単発のコード編集
    • インターネット通信無しでの動作を確認(コードがクラウドへ出ない事が確定)
  • できなかったこと:
    • Aiderは単発のコード編集を安定して実行させる方針のソフトなので、自律的に編集を繰り返すようないわゆるエージェントモードまでは実現出来ず
  • 注意ポイント:
    • ローカルLLMはAPIキー不要だが、環境変数 LM_STUDIO_API_BASE だけではなく LM_STUDIO_API_KEY(ダミー値でOK)も設定しないと Aider がエラー

説明

検討

GitHub Copilotなどと同様に、VSCode上のGUIで繰り返し処理を行うエージェントモードのような動作ができればベストです。その種のソフトとして、まずはエージェントモードを明確に使用出来るClineを試してみました。

これはダメでした。普通のクライアントPCで動くような7bクラスのモデルでは、まともに動作しませんでした。(qwen2.5,deepseekの7bや14b などをいくつか試した)

同じように「ローカルLLMではパワー不足で動かなかった」ということを言っている記事もあったので、やり方の問題ではなく、Clineでこの程度のモデルでは実現出来ないのだと思います。

そのような理想型まで行かなくても、まずはAIがコードを読み書きしてくれる(いわゆるEditモード)だけでもあればだいぶ助かります。まずそこまでを実現しようとしたところ、それに絞って作られているAiderが良さそうだと判断しました。

Aiderでは期待通りに、qwen2.5-coder-7b-instruct程度の軽いモデルでも動作しました。

Aiderで構成チャレンジ

Aiderでは次のような構成を作りました。LM Studioを使いましたが、OpenAI API互換なら他のローカルLLM系ソフトでもできると思います。

  1. LM StudioでローカルLLMをロードして、localhostのOpenAI API互換のエンドポイントを公開
  2. Aiderに、公開したエンドポイントのURLを設定
  3. 編集対象のフォルダをカレントにして、コマンドプロンプトでAiderを実行

図解すると次のような感じです。

NL7DIiD04BxlKomvrKCQMv123r9H424z-GJR96ZG9d6phOSYs2pQYdeHVn0hOgcNbeZWmLAKFioOfBw5m_PIPIxVyFtijqmb58oBHdsVC4lud6e_j-VP_MHsVA9H5j8Dfqb8mAmzjkDG3MGCyXEY4SXHTlMMzAL6MyJowu7lEPwWsffhEvpcrisj9MLNEx6PO3KMOi2cAxw_UkaBnWn1Fa8q1jb5hCH8B.png

詳しい手順

  1. LM Studioをインストール。wingetでも行けます
  2. LM Studioを起動するとUIの情報量を選べるので、一番右の(情報量が多い)Developerを選択
  3. LM Studioの「探索」画面から、使いたいモデルをダウンロード。今回はqwen2.5-coder-7b-instructを使ってみました
  4. LM Studioの「開発者」画面から、サービスを実行して、ダウンロードしたモデルのロードも行い、localhostのエンドポイントURLを確認
    1. ※1 ここで単独の動作確認をしておくと確実です。後述「LM Studio単独の動作確認」
  5. Aider向けの入力として、Windowsの環境変数にエンドポイントURLを設定
    1. 環境変数キー”LM_STUDIO_API_BASE”にLM StudioのエンドポイントURLを設定例:”http://127.0.0.1:1234/v1”
    2. 環境変数キー”LM_STUDIO_API_KEY”に何でも良いのでダミーの文字列を設定
      1. はまりポイント:ローカルLLMなのでAPIキーは不要だが、何かダミーを設定しておかないとAiderがエラーを出す
  6. Aiderをインストール。Pythonが前提なので、無い人はそちらのインストールから行なってください(この記事では省略します)
    6. インストール手順の選択肢は色々あるが、今回はuvを使って入れました
  7. uvのインストールでパスが通っていない警告が出たので、説明に従って「uv tool update-shell」も実行
    warning: `C:\Users\user\.local\bin` is not on your PATH. To use installed tools, run `set PATH="C:\\Users\\user\\.local\\bin;%PATH%"` or `uv tool update-shell`.
    
  8. 起動し直したコマンドプロンプトで、aiderを実行可能。次のように実行すると、CLIでチャット入力可能になります
    1. 今回のようにLM Studioを使う場合、modelパラメータはモデル名だけではなく、プロバイダ名として"lm_studio"を付ける必要があるので注意
    aider --model lm_studio/qwen2.5-coder-7b-instruct
    
  9. 「モデル情報が無いので、トークン等はデフォルトパラメータにする」というwarning。ちゃんと設定するとモデルに最適化した動作にできそうですが、とりあえず試す程度なら支障ないので続行
  10. チャットの入力待ちになります。もし上手く動かない場合は --verbose オプションを付けると詳しいログがコンソールに出るのでそれでデバッグしましょう

試した例

Aiderは基本的に、カレントフォルダの下を編集します。その中で、特に重視してほしいコンテキストとなるファイルが有れば、それを個別に指定する、という使い方です。

空の"main.cs"ファイルを作成した状態で、そのフォルダをカレントにして、前述のようにAiderを起動します。

続けて次のプロンプトを入力します。

/add main.cs

次の処理を.NET 8のC#で書いて下さい。
1. コンソールアプリのコマンドラインオプションにファイルパスを受け取る
1. ファイルパスに対して、ヘッダだけが有って値は空のXMLファイルを作成する
1. XMLの作成はLinqToXMLで行なう

これで、ちゃんとmain.csに期待通りの処理を書いてくれました。

LANを切断してインターネットに繋がらない状態で実行しても成功したので、ローカルで完結して処理できている事は確実です。つまり、ソースコードはクラウドへ送られていません。

狙ったとおりに使えそうです!

LM Studio単独の動作確認

上手く動かない時のために、まずLM Studioが単独で動いているかの切り分けをしておくと良いです。PowerShellなら例えば次のような簡単な通信でチャット用のエンドポイントを呼び出すことで、確認出来ます。この例ではhelloとしか言ってないので大した返答は返ってきませんが、返答が返ってきていれば動作OKと言えます。

$uri = "http://localhost:1234/v1/chat/completions"
$headers = @{
  "Content-Type" = "application/json"
}
$body = @'
{
  "model": "(使うモデル名)",
  "messages": [
    {
      "role": "system",
      "content": "You are a helpful assistant."
    },
    {
      "role": "user",
      "content": "hello"
    }
  ],
  "temperature": 0.7,
  "max_tokens": 200,
  "stream": false
}
'@

$response = Invoke-WebRequest -Uri $uri -Method Post -Headers $headers -Body $body
$response.Content

まとめ

クラウドへコードを出さないという条件が有っても、AIでのコーディングはローカルLLMでやれることが分かりました。エージェント的に作業を任せるとまでは行きませんが、単発の作業は十分に任せられそうです。他の観点でもAIを使うことに問題が無い場合に限りますが、AIを生かせるケースが増えると思います。使えるところでは使って効率を上げていきましょう!

Discussion