0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Copilot の AI Credit を節約したくて、ローカル LLM で検証してみた

0
Posted at

こんにちは、ダックスフントです。

2026年6月からGitHub Copilotの課金方式がAI Creditによる従量課金制に移行しました。以前と同じ使い方を続けていても料金がだいぶ上がった実感があり、X(旧Twitter)でも「実質値上げでは?」という声をよく目にします。

そこで「GitHub Copilotから使用するLLMの部分を、ローカルLLMに切り替えれば、AI Creditを消費せずに利用料金も抑えられるのでは?」と思いました。ローカルLLMなら推論コストはゼロなので、使い放題のはず——と思って、まず手元にあるノートPC(CPUのみ)で試してみることにしました。(実際に試してみるとローカルLLMの動作が極端に遅いことが分かり、GPU搭載ノートPCでも検証しました。)

今回の記事では、GitHub CopilotにローカルLLMを接続するためのセットアップ手順と実際に動かした結果を共有します。


TL;DR

  • Copilot Chat(Ask/Agentモード)に対して、ローカルLLMを接続して検証しました。
    • インライン補完機能(コードを書くと隣に表示されるグレーの候補)については、Continue拡張機能を使えばローカルLLMに接続できるようです。(今回は扱いません)
  • ノートPC(CPUのみ)でローカルLLMを動かした場合、実用に耐える速度は出ませんでした。「こんにちは」の挨拶だけで応答に8分31秒かかります。
  • GPUがあるだけで速度は激変します。「こんにちは」の挨拶への応答に約3秒(CPU比で約170倍)。
    • ただし今回試したどのモデルも、Agentモードの動作は不安定でした。
  • コスト節約の完全代替にはまだ遠いですが、「GitHub CopilotにローカルLLMを繋ぐ手順はどういうものか」は把握できました。

目次


1. 検証しようと思ったきっかけ

GitHub Copilotは2026年6月から、利用料金の計算方法が変わりました。従来はリクエスト回数ベースの試算でしたが、現在はLLMのトークン消費量に応じてAI Creditが計算されます。LLMがエージェントとして動いてやり取りが長くなると、その分Creditも増えます。

以前と同じように使っているだけなのに請求が増えてきた。Xでも「実質値上げ」という声が目立ちます。

このような状況を踏まえ「LLMの部分だけローカルLLMに切り替えれば、AI Creditを消費せずに済むのでは?」と思いました。ローカルLLMなら推論コストはかからないので、使い放題になるはずです。そこで手元のノートPC(CPUのみ)で試してみました。(動作があまりに遅くて実用に耐えないことがすぐ分かり、GPU搭載ノートPCでも検証しました)


2. システム構成

今回の構成の全体像

OllamaサーバでローカルLLMをホスティングしておき、Visual Studio Code上のGitHub CopilotからそのローカルLLMに接続してCopilot Chatを使う、という構成です。

ローカルPCでのシステム構成.png

主な技術要素は以下の通りです。

コンポーネント 役割
オープンウェイトモデル 重みが公開されているLLM。学習済みモデルを自分の環境にダウンロードして動かせる
ローカルLLM オープンウェイトモデルのうち、手元の端末にダウンロードして起動したもの
Docker OllamaをWSL上のコンテナで動かすことで、ホスト環境を汚さずにセットアップできる
Ollama ローカルLLMを手軽にホスティングできるツール。モデルのダウンロード、起動、API公開を担う
Ollama Library Ollamaが公式に公開しているモデルのリポジトリ。llama3.1phi4-mini など様々なオープンウェイトモデルを取得できる
GitHub Copilot BYOK VS Code 1.113以降でOllamaでホスティングしたローカルLLMをネイティブに接続できる機能。手順は 5節 に記載

検証に用いたPCのスペック

今回は2種類のPCで検証しました。

PC CPU GPU メモリ
ノートPC(CPUのみ) Intel なし(CPU専用) 32GB
ノートPC(GPU搭載) Intel NVIDIA GeForce RTX 4090 Laptop搭載 32GB DDR5

3. 検証したローカルLLM

今回試したのは phi4-minillama3.1:8b の2つです。

モデル名 開発元 パラメータ数 ディスク使用量 ツール呼び出し対応
phi4-mini Microsoft(アメリカ) 3.8B 約2.5GB あり(ただし不具合報告あり)
llama3.1:8b Meta(アメリカ) 8B 約4.7GB あり(小規模なモデルの中でも、ツール呼び出しの精度が高い)

phi4-miniの注意点

Ollamaでホスティングしたphi4-miniを、GitHub Copilotから使用する場合、ツール実行が正常に動作しない(モデルがFunction Callingの応答をする時に形式が崩れてしまう)不具合報告が上がっています。今回の検証においても、ツール実行が動作しない挙動を確認しました。


4. ローカルLLMの起動手順(Docker + Ollama)

ここではDockerとOllamaを使ってローカルLLMを起動するまでの手順を説明します。今回はDockerfile・entrypoint.sh・docker-compose.yamlの3ファイルで構成しています。

4-1. Dockerfile

このファイルでは、Ollama用のコンテナ定義を行います。ベースイメージは公式の ollama/ollama をそのまま使いました。

FROM ollama/ollama

COPY local-llm/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

4-2. entrypoint.sh

コンテナ起動時の処理を定義するスクリプトです。まずOllamaサーバをバックグラウンドで起動し、サーバが応答できる状態になるまでポーリングしながら待機します。準備ができたら環境変数 MODEL_NAME で指定されたモデルをプルします。モデルはDockerボリュームにキャッシュされるため、2回目以降の起動では既存のキャッシュが使われてダウンロードはスキップされます。

#!/bin/bash
set -e

# Ollamaサーバをバックグラウンドで起動
ollama serve &
SERVE_PID=$!

# Ollamaサーバが起動完了するまで待機
echo "Ollamaサーバの起動を待機中..."
until ollama list > /dev/null 2>&1; do
  sleep 1
done
echo "Ollamaサーバが起動しました。"

# モデルをプル(キャッシュ済みの場合はスキップ)
echo "モデルをプル中: ${MODEL_NAME}"
ollama pull "${MODEL_NAME}"
echo "モデルをプル完了: ${MODEL_NAME}"

echo "サーバとモデルの準備が完了しました。"

# Ollamaサーバが終了するまで待機
wait $SERVE_PID

4-3. docker-compose.yaml と起動コマンド

Ollamaコンテナの起動設定をまとめたファイルです。ポートのホスト公開(11434番)、ダウンロード済みモデルのキャッシュ先となるDockerボリューム(ollama-data)、そして使用するモデル名とコンテキストウィンドウサイズの環境変数を定義しています。MODEL_NAME はデフォルトで phi4-mini が使われますが、起動コマンド時に上書きできます。

services:
  ollama:
    build:
      context: .
      dockerfile: local-llm/Dockerfile
    ports:
      - "11434:11434"
    volumes:
      - ollama-data:/root/.ollama
    environment:
      - MODEL_NAME=${MODEL_NAME:-phi4-mini}
      - OLLAMA_CONTEXT_LENGTH=16384

volumes:
  ollama-data:

GPU版のdocker-compose.yamlは以下の通りです。CPU版との主な違いは2点です。1つ目は deploy セクションで、NVIDIA GPUをすべてコンテナに割り当てる設定が追加されています。2つ目はコンテキストウィンドウサイズで、VRAMに余裕があるため llama3.1:8b が対応する最大の128K(131072トークン)に設定しています。

services:
  ollama:
    # (ポート・ボリューム設定はCPU版と同じ)
    environment:
      - MODEL_NAME=${MODEL_NAME:-llama3.1}
      - OLLAMA_CONTEXT_LENGTH=131072
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

起動コマンドはWSL上で以下を実行するだけです。初回はモデルのダウンロード(phi4-miniで約2.5GB)が走るので数分かかります。

docker compose up --build

別のモデルを試したい場合は環境変数で指定できます。

MODEL_NAME=llama3.1:8b docker compose up --build

起動したら、以下のヘルスチェックで動作を確認します。

curl http://localhost:11434

HTTP 200が返ればOllamaサーバは立ち上がっています。

4-4. つまづきポイント:コンテキストウィンドウの設定

検証時にハマった点をご紹介します。Ollamaのデフォルトのコンテキストウィンドウサイズは num_ctx=4096 ですが、このままでは GitHub Copilot からチャットを送っても、ローカルLLMは正常に応答を返すことができません

理由はトークン数にあります。GitHub Copilotでは、ユーザーが「こんにちは」と入力しても、その裏でMCPの設定・ツール定義・スキル定義などのシステムプロンプトをLLMに送っています。このシステムプロンプトも含めた入力プロンプトの量が、デフォルトの4,096トークン上限をあっさり超えてしまうことがあります。実際に、検証した環境では入力プロンプトが8,000トークン規模になること確認しました。

入力プロンプトがコンテキストウィンドウサイズを超える場合、Ollamaが入力を途中で切り詰めてLLMに渡すので(ログに truncating input prompt limit=4096 prompt=8074 と出ます)、LLMが不完全な入力を処理することになります。結果として、Copilotが「分析中」のまま止まったり、HTTP 500エラーになったりします。

対処方法は コンテキストウィンドウサイズを大きくすることです。今回の場合は OLLAMA_CONTEXT_LENGTH 環境変数を設定します。

environment:
  - OLLAMA_CONTEXT_LENGTH=131072  # ノートPC(GPU搭載)ではVRAMに余裕があったので、検証したローカルLLMの最大長128kを設定

VRAMに余裕があるなら、Agentモードのやりとりまでカバーできるよう、できるだけ大きい値(128Kなど)を設定しておくほうが安心です。ただし、VRAMに余裕がない場合に、ここの値を大きくしすぎると、処理速度が遅くなったり、メモリ不足エラーが発生するので注意が必要です。


5. GitHub CopilotへのローカルLLM接続手順

OllamaサーバでローカルLLMを起動後、VS Codeのモデル選択メニューから数ステップで接続できます。VS Code 1.113 + Copilot Chat 0.41.0以降であればOllamaがネイティブでサポートされているので、簡単に接続できます。

手順:

1. VS CodeのCopilotチャット欄を開きます

2. モデル選択メニューから「その他のモデル」をクリックします

Copilotの設定1.png

3. モデル一覧の「モデルを追加」をクリックします

Copilotの設定2.png

4. 一覧から「Ollama」をクリックします

Copilotの設定3.png

5. 入力欄に「Ollama」と入力します

Copilotの設定4.png

6. Ollamaサーバのアドレスとして「http://localhost:11434」を入力します

Copilotの設定5.png

7. モデル一覧に「Ollama」が追加されたことを確認します

Copilotの設定6.png

8. モデル選択メニューから使いたいモデル名を選択します

Ollamaサーバで起動中のモデル(今回であれば phi4-minillama3.1:8b)が一覧に表示されます。

Copilotの設定7.png

9. チャットを送信して動作を確認します

GitHub Copilotのチャット欄にチャットを送信すると、応答が返ってきます。
応答が返ってくるまでのローカルLLMの動作状況は、Ollamaサーバ側のログから確認できます。


6. 検証結果

OllamaではローカルLLMの実行速度を以下のような指標で確認できました。以降の表にも登場するので、先に補足します。

  • 入力プロンプト評価速度:LLMが入力トークンを1秒あたり何トークン処理できたか(tok/s)を示します。例えば、入力トークン数が8,000で評価速度が20 tok/sだった場合、LLMが入力内容を解釈するだけでも400秒(約6~7分)かかる計算になります。
  • 出力プロンプト生成速度:LLMが回答を1秒あたり何トークン生成できるか(tok/s)を示します。値が低いと返答の文字が画面に出てくるスピードが遅くなります。

6-1. CopilotのAskモードで、phi4-mini(パラメータ数:3.8B)に「こんにちは」とチャットした場合

実行環境 CPU/GPU コンテキストウィンドウサイズ Copilotからの返答 応答速度 入力プロンプト評価速度 出力プロンプト生成速度 備考
ノートPC(CPUのみ) Intel Core Ultra 5 135U 16,384 Hi! How can I assist you today? 8分31秒 17.75 tok/s 2.58 tok/s Copilot経由では約8,000トークンのシステムプロンプトが付与されるため、入力プロンプトの評価だけで約8分かかってしまう
ノートPC(GPU搭載) RTX 4090 Laptop 16,384 GitHub Copilot here to assist you. How can I help you today? If you're looking for information or need assistance with a specific task, feel free to ask! 約3秒 8,591 tok/s 106 tok/s 応答速度がCPUに比べて約170倍高速

GPUへの切り替えで、応答時間が8分31秒から約3秒に短縮されました(CPU比で約170倍)。特に入力プロンプト(8,000トークン)の評価速度において、17.75 tok/sから8,591 tok/sへと約480倍高速化しました。
ただ、日本語で質問しても英語で返答してしまうようで、これはCopilot経由のシステムプロンプトが英語であることやphi4-miniの日本語対応能力が影響していると考えられます。

この結果を踏まえ、ノートPC(CPUのみ)でのAgentモードの検証は断念しました。Askモードでこれだけ時間がかかるなら、ツール呼び出しを伴うAgentモードはさらに遅くなると考えられるためです。

6-2. ノートPC(GPU搭載:NVIDIA GeForce RTX 4090 Laptop GPU)での追加検証

phi4-mini(パラメータ数:3.8B) 実行結果

実行タスク コンテキストウィンドウサイズ 実行成否 Copilotからの返答 実行完了時間 入力プロンプト評価速度 出力プロンプト生成速度 備考
Ask モード(「こんにちは」とチャット) 128K ⚠️ 部分的成功(返答が英語) GitHub Copilot here to assist you. How can I help you today? If you're looking for information or need assistance with a specific task, feel free to ask! 約3秒 8,591 tok/s 106 tok/s
Agent モード(「PythonでHelloWorldのプログラムを作成してください」と依頼) 128K ❌ 失敗 (Pythonファイル作成ツール呼び出し用のプロンプトが返答として表示された) 約15.6秒 2,554 tok/s 13.84 tok/s Ollamaでホスティングする場合にFunction Callingが不安定になるようで、それが原因で失敗した可能性がある

Agentモードでは「PythonでHello Worldのプログラムを作成してください」と依頼しましたが、ファイル作成に失敗しました。ツール呼び出し用のJSONプロンプトがそのままチャット画面にテキストとして表示されてしまいました。これは、issue #9437 で報告されているOllama経由でのFunction Calling不安定問題が発生したと考えられます。

この検証結果を踏まえ、Function Callingの不具合報告がなく、小規模モデルの中ではツール呼び出しの精度が高いとされる llama3.1:8b でAgentモードを検証しました。

llama3.1:8b(パラメータ数:8B)実行結果

実行タスク コンテキストウィンドウサイズ 実行成否 Copilotの挙動 Copilotからの返答 実行完了時間 CopilotがLLMにリクエストした回数 入力プロンプト評価速度 出力プロンプト生成速度 備考
Ask モード(「こんにちは」とチャット) 128K ⚠️ 部分的成功 英語で返答 Sorry, I don't understand the user's request. The input appears to be a greeting in Japanese. Can you please rephrase or provide more context about what you would like me to do? 約8秒 1回 1,506 tok/s 16.11 tok/s 初回リクエスト時はモデルのロード時間も込みで約21秒掛かった
Agent モード(「PythonでHelloWorldのプログラムを作成してください」と依頼:1回目) 128K ❌ 失敗 ツールを実行せず、VSCode Jupyter Notebook セル形式のテキストを返答 (返答内容は表の下部を参照) 約43秒 3回 約1,227-1,495 tok/s 約9.39-19.46 tok/s 出力プロンプトにおいてFunction Callingのフォーマットが崩れた可能性あり
Agent モード(「PythonでHelloWorldのプログラムを作成してください」と依頼:2回目) 128K ⚠️ 部分的成功 helloworld.py は正しく作成されたが、返答に余計な内容が含まれていた Created helloworld.py Sorry, I can't assist with that. 変更を行いました。 約28秒 2回 約494-777 tok/s 約8.86-21.39 tok/s
Agent モード(「1から100までの整数のうち、素数のみを抽出してリストにして返すPythonの関数を作成してください。コードには各ステップの処理内容をコメントで記述してください。」と依頼) 128K ⚠️ 部分的成功 prime_numbers.py は正しく作成されたが、返答に余計な内容が含まれていた Created prime_numbers.py Sorry, I can't assist with that. 変更を行いました。 約46秒 2回 約634-1,202 tok/s 約7.62-18.73 tok/s
Agent モード(「prime_numbersとは別に、素数に1を加算する関数も実装してください」と依頼) 128K ⚠️ 部分的成功 既存のprime_numbers.pyファイル編集は成功したが、返答にも実装コード全文が $$...$$ 形式で表示されてしまった (返答内容は表の下部を参照) 約55秒 2回 約632-1,229 tok/s 約7.46-17.51 tok/s 「+」ボタンでprime_numbers.pyファイルへの参照を追加して依頼
  • Agent モード(「PythonでHelloWorldのプログラムを作成してください」と依頼:1回目)でのCopilotの返答内容
<VSCode.Cell id="1" language="markdown">
# Python環境の設定
Pythonのバージョンとライブラリを確認する
</VSCode.Cell>
<VSCode.Cell id="2" language="python">
import sys
print(sys.version)
import importlib
print(importlib.util.find_spec("numpy"))
</VSCode.Cell>
<VSCode.Cell id="3" language="markdown">
# Hello, World!を出力するプログラムの作成
print()関数を使って'Hello, World!'を出力する
</VSCode.Cell>
<VSCode.Cell id="4" language="python">
print("Hello, World!")
</VSCode.Cell>
  • Agent モード(「prime_numbersとは別に、素数に1を加算する関数も実装してください」と依頼)でのCopilotの返答内容(一部省略)
$$
def prime_numbers(n):
    # Initialize an empty list to store prime numbers
    primes = []
    # Iterate over the range of numbers from 2 to n (inclusive)
    for num in range(2, n + 1):
        ...
    return primes

def add_one_to_primes(primes):
    # Initialize an empty list to store prime numbers with 1 added
    primes_with_one = []
    for num in primes:
        primes_with_one.append(num + 1)
    return primes_with_one
$$

変更を行いました。

「PythonでHelloWorldのプログラムを作成してください」と依頼した時、1回目はツール呼び出しに失敗し、Jupyter Notebookのセル形式テキストが返ってきてしまいました。2回目はファイル作成自体は成功しましたが、返答に "Sorry, I can't assist with that." という拒否メッセージが混入してしまいました。
その他、ファイル作成・編集を依頼した場合は処理自体は成功しましたが、コード全体が $$...$$ 形式でチャット画面に表示されるなど、返答内容に不整合が生じました。ファイルの中身は正しく作られているのに、チャットの返答がおかしいという状態です。
結果的にllama3.1:8bでは、phi4-miniに比べるとツール呼び出しが動くケースはありましたが、応答が不安定で実用には懸念が残ります。

6-3. 確認された問題のまとめ

問題 内容
応答速度(CPU環境) CPU単体では実用に耐えない。phi4-miniで「こんにちは」の応答に8分31秒。GPU環境(RTX 4090 Laptop)では同一条件で約3秒(約170倍高速)
Agentモードのツール呼び出し失敗(phi4-mini) CopilotのAgentモードでツール実行が失敗し、ツール呼び出し用のJSONがそのまま返答として表示される。Ollama経由でのFunction Callingが不安定なことが原因の可能性(issue #9437
英語での返答 日本語で質問しても英語で返ってくる場合がある。Copilot経由のシステムプロンプトが英語であることやモデルの性能が影響していると考えられる
返答メッセージの不整合(llama3.1:8b) ファイル作成・編集は成功しても、"Sorry, I can't assist with that." の混入や $$...$$ 形式でのコード全文表示など、返答内容に不整合が生じる場合がある

7. チームで使うなら: 発展形の構成案

今回の構成の限界は2点あります。CPUでは実用的な速度が出ないこと、そして個人のPCに物理的に依存しているため複数人で共用しづらいことです。

チームやプロジェクト全体でローカルLLMを使いたい場合は、ローカルLLMのホスティングの部分をクラウドに移すのが良いと考えられます。
例えば以下のような構成です。

発展形のシステム構成.png

クラウド上でローカルLLMをホスティングする場合、大きくは2つの選択肢があります。

CaaS(Container as a Service)で運用する場合:

今回作成したDockerコンテナをそのまま、GPU付きコンテナ実行環境(例:AWS ECS + GPUインスタンス)でホスティングする方法です。手順を再現しやすいメリットがある一方で、GPU環境の維持管理コストがかかります。

PaaS(Platform as a Service)で運用する場合:

Amazon Bedrockのようなマネージドサービス上でオープンウェイトモデルを使う方法です。自前でGPUインスタンスを管理しなくて済む分、運用負荷を下げられる可能性があります。ただし、どの程度コストが下がるかは利用量や選ぶモデルによって変わるため、具体的な試算は環境に合わせて別途行う必要があります。


8. これから試してみる方へ: モデル選びのポイント

今回の検証を通じて、「Ollamaで動く」「Function Calling対応」と書いてあるだけではCopilotとの組み合わせで十分に動くかどうかを判断できない、ということが分かりました。モデル単体のベンチマーク結果はあくまで参考値で、実際にCopilotのコーディングアシスタントとして動かしたときの品質を評価しておく必要があります。

モデルを選ぶ際は、以下の4点を確認しておくことをお勧めします。

1. ツール実行の安定性
Agentモードは、ファイルの作成・編集などをツール呼び出しでモデルに実行させます。モデルが正しい形式でレスポンスを返せないと何も動きません。今回のphi4-miniはまさにこれで詰まりました。Ollamaのモデルページで tools タグが付いているか確認しつつ、必ず接続した状態で実際に試してみてください。

2. 多言語対応(特に日本語)
Copilot経由のシステムプロンプトは英語のため、日本語対応が弱いモデルは日本語で質問しても英語で返ってきます(今回のllama3.1:8bがこのケースでした)。ベンチマークでは英語で評価されていることが多いと思われるので、日本語で実際に試した方が確実です。

3. コーディング補助としての対話品質
コードの正確さだけでなく、返答内容全体の品質が実用性を左右します。今回のllama3.1:8bでは、ファイル作成自体は成功しているのに "Sorry, I can't assist with that." が返答に混入するといった状態が起きました。この種の問題はベンチマークには出ないので、Agentモードで実際にコード生成を依頼して確認してください。

4. レスポンス速度
1回の応答が遅いと作業のテンポが大きく崩れます。CPUのみの環境では今回の検証通り実用になりません。ノートPC(GPU搭載)を使う場合も、モデルのサイズがVRAMに収まるかを事前に確認しておくことをお勧めします。


まとめ

  • ノートPC(CPUのみ)では無理でした。「こんにちは」の挨拶に8分31秒というのは、ちょっとした作業であっても使えるレベルではありません
  • GPUがあれば速度面はかなり高速になります。同一条件で約3秒、CPU比約170倍は体感でも十分な差です
  • GitHub Copilotネイティブのインライン補完はローカルLLMに対応していません。別手段としてContinue拡張機能 + Ollamaという方法があるようです。
  • Copilot Chat(Askモード)は使えます。GPU環境であれば高速に動作します。ただし日本語で質問しても英語で返ってくることがあります。
  • Copilot Chat(Agentモード)は不安定です。phi4-miniはツール呼び出しが失敗し、llama3.1:8bはツール呼び出しに成功する可能性は高いが、応答が不整合だったりします。別のローカルLLMを検討した方が良いかもしれません。
  • コンテキストウィンドウサイズの設定は必須です。GitHub Copilotでは、ユーザが入力した文章以外に、MCPやツール定義を含むシステムプロンプトも一緒に入力するため、OLLAMA_CONTEXT_LENGTH が大きい値でないと、Ollamaがトークン切り捨てを行ってしまい、LLMが入力を正常に解釈できなくなってしまいます。

AI Creditのコスト節約の完全代替としてはまだ厳しい状況ですが、「GitHub CopilotにローカルLLMを繋ぐ仕組みはどういうものか」「どこで動かなくなるか」は把握できました。チームで本格的に使うためには、クラウドGPUインスタンスかマネージドサービスを検討するのが次のステップだと考えます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?