2024.04.08

Cursor はどこが GitHub Copilot より優れているのか(独自機能Docsの実力)

D.M. です。
AI 搭載で話題の IDE である Cursor について、 GitHub Copilot と比べた場合の利点を掘り下げてみます。

結論ファースト

・現段階では一長一短。Cursor にしかない機能もあれば、 GitHub Copilotにしかない機能もある。
→ 特に Cursor の Docs は独自機能(GitHub Cipolotにはない)
・両方併用できる。
・Cursor のAI自動プログラミングスキルは既存の「GPT-4」と同等(ただ、モデルを変更できる)
簡単な単発バッチ処理は高速で実装できる。
複雑化すると100点は難しい。
現段階では、AIに全部書かせるのではなく、補助ツールとしてとらえるほうが効果的。

導入編:Cursorとは

AI がプログラミングしてくれる時代

2022年11月にChatGPTが発表されて以降、 LLM は簡単なプログラミングが可能ということが知られています。

LLMは プロンプトで指示をしたプログラムを即座に実装できるだけでなく、コードの解説やコードレビューも担当することができます。
【ChatGPT + PR Agent + GitHub Actions】 プルリクの AI コードレビューを10分で自動化し、レビューのルールを詳細にカスタマイズする

また AI をプログラミング業務の支援に使うツールとして、 GitHub Copilot が非常に普及しました。
GitHub Copilot にいいコードを書いてもらう方法

さらに、 OpenAI の Code Interpreter などを駆使することで、特定の要件に対して人間が手を加えず自律的な開発を担えることが分かっています。
Open Interpreter + ChatGPT に一般的な開発課題を「全自動」で対応させる(Web API、 DB操作、スクレイピング)

こうした流れの中で、 Cursor はプログラミング開発全体を AI で支援する IDE として登場し、使いやすい UI/UX と RAG を活かした機能により大きな一石を投じています。

GitHub Copilot とは(復習)

一言でいえばサジェスト機能です。
ソース上のコメントや書き始めのプログラムに対し、後に続くプログラムを予測して埋めてくれます。
VS Code などIDE の Plugin として提供されています。
プログラミングに特化して学習したモデル Codex をベースにしているため、GPTよりも高い実装力があると言われています。
(代わりにプログラミング以外の話題に答えないというフィルタを持っています。)
23年7月にはCodexはさらに進化したという記事が発表されました。
Smarter, more efficient coding: GitHub Copilot goes beyond Codex with improved AI model

Cursor とは

Cursor は AI ベースの IDE です。
Chat で指定したプロンプトに沿って自動的にプログラムを実装してくれます。
(VS Codeからフォークしており、現段階ではほとんど同じ UI を持っています。Plugin も移行でき、そのまま利用可能)
ChatGPT の Web 画面でも自動でプログラムを書いてもらえると思いますが、それと異なるのは、その場で実行してデバッグしてという通常の開発と同様の流れが非常に自然にできる点です。

ここで取り急ぎまとめてしまうと、
もし効率的なコード補完を期待している場合、GitHub Copilot のほうがあっていると思います。
もし自然言語のプロンプトから自動的にコードを生成したい場合、 Cursor がより適しています。

Cursor の独自性

Cursor は非常に優れた UI/UX があり、特にプロンプトを入力するためのインラインチャットウィンドウが非常に直感的です。
(これが本当に気持ちがいい)

また GitHub Copilot にはない独自機能が2つあります。
Docs
Auto Debug

以下で1つ1つ掘り下げていきます。

Cmd + k (Ctrl + k)(インラインチャットウィンドウ)

IDE のエディタ上でチャットウィンドウを呼び出すことができます。
これにより以下のAIへの指示をシームレスに行うことができます。
A プロンプトからコードの生成
B 選択箇所の修正

Aの例「Hello world を print してください。」

空のpythonファイル上で、 Ctrl + k を押して generate のインラインチャットウィンドウを起動します。

出ました。

プロンプトとして「Hello world を print してください。」を入れます。

生成されました!

これが何とも言えず気持ちがいい。
詳細要件を記述したプロンプトに対して、結構長大なものも出力可能です。
レスポンス速度はモデルに依存します。私は gpt-4-0125-preview を使っており1秒で返ってきます。(自分の API Key を設定)
基本的には GPT-4 を使っていますが、Claude 3 など他のものも選択可能です。(この点も GitHub Copilotとは異なります)

IDE として提供されているため、単に Plugin として提供されている GitHub Copilot よりも包括的に UI/UX 全体を効率化できている点が特徴の1つです。

※B 選択箇所の修正について、 Github Copilot 側も類似機能の Streaming inline chat を発表しています。
ほぼ同じことができるのでこの点では Cursor の独自性は薄れてしまったかも。。

https://code.visualstudio.com/updates/v1_84#_chat-agents

Docs

「外部URL参照」機能です。
サンプルコードなどがあるサイト上にある場合に、そのURLを参照し(デフォルトでOpenAIやLangChainのドキュメントが登録)、それらを参照して実装させることができます。

Docs は、 Cursor の独自機能で、 GitHub Copilot にはない機能です。(2024年4月現在)

Docs は何が嬉しいのか

AI は最新情報は持っていないため、補完するための機能が必要でした。
これは一般的に In-context Learning (Retrieval Augmented Generation。RAG。検索拡張生成) と呼ばれ、新しい情報が記載された文章をプロンプトに入れ込むことで AI の回答精度を高める手法です。
よく知られたものとして ChatGPT の Web 検索機能、 Bing 検索の Copilot がこの役割を持っていました。

これがプログラミングにおいてなぜ必要なのでしょうか。
開発において新しいライブラリなどを使うことが日常茶飯事のため、 Web 上の文章を確認して実装することは MUST の工程になります。
Cursor は UI 的に非常にシンプルに実現している点が優れています。
上述の Cmd + k のインラインチャットウィンドウ上で @ +ドキュメント名 で呼び出すことができます。
GitHub Copilot でこれと同じことを行うためには少し工夫が必要です(サンプルコードを切り出して隣のタブで開くとか)。
これは明らかに Cursor が非常に画期的であるといえると思います。

Cmd + k (ctrl + k) → @OpenAI で呼び出す

選択するとOpenAI公式サイト内の階層構造が表示されます。(Cursor内部でインデックス(キャッシュ)されているっぽい)

Docsの追加は簡単です。
Cmd + k (Ctrl + k) → @add → Add new doc

ダイアログがたちあがりURLとタイトル入力します。(今回は OpenAI の Vision のページを独立して登録しました)

Auto Debug

バグを自動で修正してくれる機能です。
これもCursorだけに備わっている独自機能になります。

例)Python でわざとエラーを起こして修正してもらう
print(“Hello world” + 2024)
文字列と数字が結合できませんよというエラーになります。
青いボタン「Debug with AI」でChatを起動できます。

print(“Hello world” + str(2024)) を修正案として出してくれました。
本体ファイルのコード書き換えまでシームレスにやってくれます。

※ただこれは結構失敗して無限ループになったりしたので、実用にはもうひとつかもしれません。

Codebase Answers(画期的なRAG機能)

Codebase Answers は、プロジェクト内のフォルダとファイルを自動的にベクターインデックス化し LLM が回答生成をするときに参照できるようにします。

ソースコードやサンプルコードがプロンプトに応じて参照できるようになるため実装の精度向上が期待できます。
これも上述の RAG の機能です。

これはChatのみで使える機能で、逆に言うとコードを選択して Cmd + k (ctrl + k) のインラインチャットで実装させる際には呼ぶことができません。

設定画面
File → Preferences → Cursor Settings

AI Code is stored locally とあるので、ローカルのベクターストアで保持しているものと思われます。
プロジェクトフォルダ以下のフォルダとファイルを自動で読みに行きます。ただ2000以上のドキュメントは自動読み込みはしないので、自分で明示的に開始する必要があります。
また Ignore files で除外も設定可能です。

※GitHub Copilot も @workspace という同じコンセプトの機能を提供しています。

Codebase は以下の実践編で使ってみます。

Cursor vs GitHub Copilot

他にも機能があるため、比較表を記載しておきます。

※こちらの記事を参考にして一部アップデートを記載いたしました。
CursorとGitHub Copilotの違い

Cursor 側にしかない機能
・Docs
・Auto Debug

GitHub Copilotにしかない機能
・プロジェクト生成
・Commitメッセージ自動生成
・パブリックコード重複検知
これらはアップデートの記事にまとまっています。
https://github.blog/changelog/2023-11-30-github-copilot-november-30th-update/

GitHub Copilot側も開発速度が非常に速いため、 Docs もすぐに追いつくのではと思ったりしています。

実践編: gpt-4-vision-preview を実行する画面を開発

gpt-4-vision-preview は ChatGPT が画像を読み込んで説明する GPT-4V の API 版です。
この課題を選んだ理由は、私の業務で画像読み取りがあったことがありますが、
加えて、こちらのAPIの発表が2023年11月となり、 gpt-4-1106-preview (23年4月まで)を使うと知識の範囲外となることが想定できたためです。
この条件により Docs の役割をより明確に確認できると考えました。

Docs で OpenAI の公式ページを読み込ませて開発

Docsなし

まず何も読み込ませないで雑に実装させてみます。
「gpt 4 vision API を呼んでください」とだけ指定して書いてもらいました。

めっちゃハルシネーションを起こしています(笑)
よくわからないエンドポイントに対して適当にPOSTしている感じ。

DocsでOpenAI公式を指定

今度はちゃんとした知識を与えます。
上述の @OpenAI を指定して実装開始。

どうも1か所が変な実装になったので、再度特定のページの Docs を指定し直し、インラインでデバッグしてもらいます。

出来上がったコード全体です。これは動きました。

import base64
import openai
from openai import OpenAI

# OpenAI API Key
import os
from dotenv import load_dotenv
load_dotenv()
openai.api_key = os.getenv('OPENAI_API_KEY')

# Function to encode the image
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

# Path to your image
image_path = "C:\\win_data\\tmp\\IMG_101.jpg"

# Getting the base64 string
base64_image = encode_image(image_path)

# Create an OpenAI client
client = OpenAI()

# Sending the request to OpenAI API
response = client.chat.completions.create(
    model="gpt-4-vision-preview",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "この画像に何が書かれていますか?詳細に説明してください。"},
                {
                    "type": "image_url",
                    "image_url": {
                        "url": f"data:image/jpeg;base64,{base64_image}"
                    },
                },
            ],
        }
    ],
    max_tokens=300,
)

print(response.choices[0])

レスポンスが正常に得られました。
(ベトナムに行ったときのお土産のコーヒー)

OpenAI API レスポンス

Codebase で LangChain のソースコードを読み込ませる

次に、 OpenAI のライブラリでの実装でなく、 LangChain を使った実装に変更したいです。(拡張性があるので)
また Streamlit でブラウザの画面を用意して画像をアップロードできるようにしようと思います。

プロンプト
「LangChain と Streamlit と dotenv をつかって、ブラウザの画面から画像をアップロードするとその画像を説明してくれるWebアプリケーションを作成してください。」

Codebase で知識として利用するため、私は事前に LangChain の最新版を GitHub からダウンロードしておきました。
ただ全部だと結構な量があり(2000ファイル以上)だったので、関係がありそうなメインのソースコードフォルダとサンプルコードのみをプロジェクトのコードの隣のフォルダに配置しています。

Codebase はインラインではなく右の Chat 専用欄から 「with Codebase」で呼び出します。
元のプロンプトに関連する文書について、ベクトルの距離計算により関連度の高い順に取得します。
以下のように複数の関連ソースコードが検索にヒットしています。
これらをプロンプトに含めてLLMへ送信します。

Codebase Answerはどのぐらい強力なのか非常に楽しみでしたが、正直言ってこちらはどっこいどっこいの結果になりました。

成功した例

ほとんど同じコードがすでに実装されている場合、当然ですがCodebaseの参照によってそれに基づいた実装が可能です。

以下は完成したコードです。

import streamlit as st
import base64
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os

# Load the .env file to get the OPENAI_API_KEY
load_dotenv()

# Set up the OpenAI API key from the .env file
openai_api_key = os.getenv('OPENAI_API_KEY')

# Initialize the ChatOpenAI with the appropriate model and max_tokens
chat = ChatOpenAI(api_key=openai_api_key, model="gpt-4-vision-preview", max_tokens=256)

# Define the Streamlit app
def main():
    st.title('Image Description Generator')

    # File uploader allows user to add their own image
    uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])

    if uploaded_file is not None:
        # To see details
        st.image(uploaded_file, caption='Uploaded Image.', use_column_width=True)
        st.write("")

        # When 'Describe it!' button is clicked, process the image and get the description
        if st.button('Describe it!'):
            # Convert the uploaded file to a base64 string
            base64_image = base64.b64encode(uploaded_file.getvalue()).decode('utf-8')
            image_data_url = f"data:image/jpeg;base64,{base64_image}"

            # Invoke the chat model with the image
            response = chat.invoke(
                [
                    HumanMessage(
                        content=[
                            {"type": "text", "text": "What is this image showing"},
                            {
                                "type": "image_url",
                                "image_url": {
                                    "url": image_data_url
                                }
                            },
                        ]
                    )
                ]
            )
            # Display the response to the user
            if response:
                st.write("Description:")
                st.write(response.content)
            else:
                st.error("An error occurred while processing the image.")

# Run the Streamlit app
if __name__ == '__main__':
    main()

実際はデバッグに90分ぐらいかかっています。
(95%は5分でできましたが..)
自分で実装したほうが早かったのではないでしょうか。。

難しかった箇所

大量の文書があるといろんなサンプルに引っ張られる問題が発生します。
gpt-4-vision-preview は 従来の gpt-4 などのモデルに比べ LangChain のコードがぜんぜん違います。
そのため大半のコードがあまり参考にならず、むしろノイズとして間違った実装をさせる誘因となってしまいました。
特に HumanMessage オブジェクトの使い方があまりなく、これを使わない実装に固執してしまいました。
そのため、最終的には答えとなるサンプルコードをほぼそのままプロンプトに貼り付けて実装させています。

RAGについてはチューニング方法が多々あるため、今後このツールが進歩することで精度向上が期待できると思います。

Appendex 補足的な情報

Copilot++

Cursor には GitHub Copilot同様のサジェスト機能があります。(同様にタブを押すと反映される)

まだBeta提供段階のようです。
これは独自のカスタムモデルにアクセスするので、Cursor有料プランで使ってくださいとありましたが、私はいまのところ無料プランでも使えています。
https://forum.cursor.sh/t/copilot-how-to-use-more-details/1595/11
以下にもうちょっとデモがあります。
https://forum.cursor.sh/t/copilot-can-someone-give-me-an-overview/2648/2

New AI Project

Cursor で TODO リストなどのプロジェクトのベースを自動生成してくれる機能がありましたが、2024年4月になくなったようです。

https://docs.cursor.sh/features/new-ai-project

(質が低く苦情も多かったとのこと。ただ復活の可能性もあります)
https://forum.cursor.sh/t/new-ai-project-gone/3937/3

積み残したTODO

どちらが使いやすいのか、比較をしたい項目がいくつかあります。
・Cursor の Cmd + k vs Github Copilot の Streaming inline chat
・Cursor の Codebase Answer vs Github Copilot の @Workspace
・Cursor の Copilot++ vs Github Copilot のサジェスト機能
これらは近い機能ですが、中身が若干異なると思われます。
具体的な課題を設定して検証したい部分です。

将来的な可能性

簡単な実装であれば自律的に開発可能というのがすでに現実のものとなっています。
より発展的な全自動開発に向けて、ざっと検索すると以下のような仕組みの提案が見つかりました。

AutoDev (Microsoft)
Devin (Cognition)
Copilot Workspace (GitHub)
https://www.publickey1.jp/blog/23/githubcopilotcopilot_workspacecopilotcopilotgithub_universe_2023.html

次の大きな波をとらえるべく、継続してウォッチしていきたいと思います。

まとめ

Cursor は何より UI/UX は本当に気持ちがいいです。
(それのせいか、変にAIに実装させたくなり、自分で実装するぞという意識が減ってしまいましたw)
GitHub Copilot もそうなのですが、とにかく開発が楽しくなったという点でとてもいい体験を提供しているのではないでしょうか。

機能面は Cursor と GitHub Copilot でまだまだ比較が必要と思います。
まだまだ優れていない点がありつつも、両社の開発速度は非常に速いため、おそらくすぐにお互いに進化していくものと思われ、目が離せない状況です。

対立的な視点で見てしまいがちですが、Cursor上でGithub Copilotを使うもことも可能です。
より良い開発ライフに向けて我々開発者もどんどんツールを使いこなして AI 使いとしてのレベルを上げていきたいですね。

宣伝

次世代システム研究室では、最新のテクノロジーを調査・検証しながら、インターネットにおける挑戦的なアプリケーション開発を行うアーキテクトを募集しています!
募集職種一覧 からご応募をお待ちしています!

  • Twitter
  • Facebook
  • はてなブックマークに追加

グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。

 
  • AI研究開発室
  • 大阪研究開発グループ

関連記事