【Mac】NeovimでChatGPTと会話する

15 min

こんにちは。ナミレリです。今回はNeovimで使うChatGPTのプラグインである、jackMort/ChatGPT.nvimを紹介します。ChatGPT.nvimを使うとNeovimから:ChatGPTで呼び出すことができ、リアルタイムにChatGPTと会話することができます

2024年3月:最新版に沿って、大幅に内容を書き直しました。

jackMort/ChatGPT.nvimの主な機能は以下のようなものです。

jackMort/ChatGPT.nvimの主な機能

直感的なインターフェイス
Awesome ChatGPT PromptsからChatGPTの役割を選択・設定できる
プラグラミングのサポート
GitHub Copilotのようなコード補完
アクションをカスタマイズすることができる

FizzBuzzのPythonプログラムを教えて

NeovimのChatGPTのプラグインであるjackMort/ChatGPT.nvim
NeovimのChatGPTのプラグインであるjackMort/ChatGPT.nvim

ChatGPTの役割を選択・設定

ChatGPTの役割を選択・設定
ChatGPTの役割を選択・設定

この記事はこんな人にオススメ

  • NeovimでChatGPTを使いたい方
  • CLI派でなるべくnvimから離れたくない方
  • 美しいインタフェースでモチベを上げたい方
  • Neovimが大好きで仕方ない
  • Neovim独自の機能やプラグインシステムをフルに活用したい方
  • VSCodeよりNeovim派の方
この記事の環境
M3 MacBook Air
  • M3 MacBook Air 15インチ(メモリ24GB)
  • macOS Sonoma 14.4
  • Neovim v0.9.5
Parallels Desktop 20 for Macの無料トライアル もありますので、ぜひダウンロードして試してみてください。M1/M2/M3のMac上で快適にMacやUbuntu、Windowsが動作します。
NEW Parallels Desktop 20 for Mac

Parallels Desktop 20 for Macは、M1/M2/M3のMac上で快適にMacやUbuntu、Windowsが動作します。

14日間の無料トライアルもありますので、ぜひダウンロードして試してみてください。

はじめに

今回紹介するjackMort/ChatGPT.nvimついて簡単に紹介します。

jackMort/ChatGPT.nvim

jackMort/ChatGPT.nvimの主な機能は、先程も書きましたが以下の通りです。

jackMort/ChatGPT.nvimの主な機能

直感的なインターフェイス
Awesome ChatGPT PromptsからChatGPTの役割を選択・設定できる
プラグラミングのサポート
GitHub Copilotのようなコード補完
アクションをカスタマイズすることができる

ブラウザや別のアプリに切り替えることなく、Neovimの開発環境内で直接ChatGPTを利用できるのが良いです。また、コード等を編集中に直接ChatGPTに聞いたりアドバイスを求めたりもできます。凄い時代です。

あと、Neovimのプラグインなのでカスタマイズ性も高く、ほぼすべての設定を自分好みにすることもでき、とても便利なプラグインです。

Neovimのインストールと設定

Neovimをインストールしていない方は、以下の様にbrewneovimをインストールします。


brew install neovim

インストールしているneovimのバージョンを確認しておきます。


nvim --version
NVIM v0.9.5
Build type: Release
LuaJIT 2.1.1710088188

      システム vimrc: "$VIM/sysinit.vim"
       省略時の $VIM: "/opt/homebrew/Cellar/neovim/0.9.5/share/nvim"

Run :checkhealth for more info

Neovimの初期設定など最初にやっておくべき設定については下の記事をぜひご覧ください。

Neovimをかっこ良くクールに使う設定

事前準備

curlの確認

プラグインのインストールにはcurlが必要ですのでインストールされているか確認します。Macであれば標準でcurlはインストールされています。


which curl
/usr/bin/curl

$OPENAI_API_KEYの確認

openaiのサイトからAPIキーを取得します。ここから取得します。

取得したAPIキーは、他の人と共有したりPythonコード(ブラウザ、アプリ等)で公開してしまうのはNGです。漏洩のリスクを軽減するために環境変数に設定しておきますOPENAI_API_KEYという環境変数に設定します。

YOUR_API_KEYの部分に実際に取得したAPIキーを置き換えてください。


export OPENAI_API_KEY="YOUR_API_KEY"

.zshrcに設定しておく場合も漏洩には十分に注意する必要があります。

APIキーはここから取得します。https://platform.openai.com/account/api-keys

よりセキュアに、jackMort/ChatGPT.nvimがAPIキーを受け取る方法について、公式で2つの方法が紹介されています。

1つは、1Passwords CLIのOPコマンドを使用する方法。もう1つは、GPGを使用してAPIキーを含むローカルファイルを復号化する方法です。後ほどこの方法について実践しながら紹介します。

ChatGPT.nvimのインストール

では、早速、jackMort/ChatGPT.nvimを公式の通りにインストールしてみます。

パッケージマネージャはPackerを使っていますので、~/.config/nvim/lua/plugins.luaに下の内容を追加します。

~/.config/nvim/lua/plugins.luaの編集

ChatGPT.nvimの公式githubを参考に、下のように~/.config/nvim/lua/plugins.luaを編集します。

最下部のend)より前に追加します


nvim ~/.config/nvim/lua/plugins.lua


use({
  "jackMort/ChatGPT.nvim",
    config = function()
      require("chatgpt").setup()
    end,
    requires = {
      "MunifTanjim/nui.nvim",
      "nvim-lua/plenary.nvim",
      "folke/trouble.nvim",
      "nvim-telescope/telescope.nvim"
    }
})

:PackerInstallする

保存後にnvimを立ち上げ直すか、:source %で再読み込みし、:PackerInstallするとplugins.luaに書かれていてインストールされていないプラグインがインストールされます。


:PackerInstall

デフォルト設定では、modelgpt-3.5-turbotemperature0max_tokens300になっていますが、とりあえずデフォルトで機能を試してみたいと思います。

なお、デフォルト設定については、こちらに詳しく記載があります。

ChatGPT.nvimの使い方

それでは、ChatGPT.nvimを使ってみます。

ChatGPT.nvimの起動

nvimを起動して:ChatGPTで起動します。デフォルトのモデルであるgpt-3.5-turboでChatGTPと会話するインタラクティブなウィンドウが開きます。<leader>ccでも起動することができます。

<C-c>ChatGPT.nvimのウィンドウを閉じます。

ChatGPT.nvimを起動する

ChatGPT.nvimを起動する
ChatGPT.nvimを起動する
ChatGPT.nvimを起動後
ChatGPT.nvimを起動後

:ChatGPTRunの後に補完候補を表示したのが下の状態です。ChatGPTRun [action]で特定のアクションを実行することができます。例えば、ChatGPTRun translate japaneseで選択された範囲を日本語翻訳することができます。

ChatGPTRunでアクションを補完したところ

ChatGPTRunでアクションを補完したところ
ChatGPTRunでアクションを補完したところ

:ChatGPT:ChatGPTActAs:ChatGPTCompleteCodeなど、たくさんの便利なコマンドがありますので、以下に簡単にまとめます。

キーマップについてwhich-keyの設定をすると便利に使えます。

コマンドキーマップ説明
:ChatGPT<leader>ccgpt-3.5-turboモデルでChatGTPと会話するインタラクティブなウィンドウを開く。
:ChatGPTActAsgpt-3.5-turboモデルでAwesomeのChatGPTプロンプトからChatGPTの役割を選択する。
:ChatGPTCompleteCodegpt-3.5-turboモデルでコードを完成してもらう。
:ChatGPTEdiWithInstructions<leader>cecode-davinci-edit-001モデル(コーディング用に微調整されたGPT 3.5)を使用して、選択したテキストかウィンドウ全体を編集するためのインタラクティブなウィンドウを開く。
:ChatGPTRungpt-3.5-turboモデルでChatGPTRun [action]特定のアクションを実行するコマンド。以下にアクションを記載します。
:ChatGPTRun complete_code 既存のコードを完成してもらう。
:ChatGPTRun grammar_correction<leader>cg標準的なコードに修正してもらう。
:ChatGPTRun translate<leader>ct翻訳してもらう。
:ChatGPTRun translate japanesesで日本語に翻訳。
:ChatGPTRun keywords<leader>ck文章から主なキーワードを抽出してもらう。
:ChatGPTRun docstring<leader>cd指定された言語のベストプラクティスに従って、docstringを書く。
:ChatGPTRun add_tests<leader>caコードのテストを実装してもらう。
:ChatGPTRun optimize_code<leader>coコードを最適化してもらう。
:ChatGPTRun summarize<leader>cs文章を要約してもらう。
:ChatGPTRun fix_bugs<leader>cfコードのバグを修正してもらう。
:ChatGPTRun explain_code<leader>cxコードの内容を説明してもらう。
:ChatGPTRun roxygen_edit<leader>crR言語の関数を文章化するスケルトンを書いてもらう。
:ChatGPTRun code_readability_analysis<leader>clコードの可読性の問題を挙げてもらう。

:ChatGPTコマンド

ChatGTPと会話するインタラクティブなウィンドウが立ち上がる:ChatGPTコマンドの詳細です。

ヘルプを表示する:C-h

操作するためのキーマップがわからなくなったら、C-hで下の画像のようにヘルプを表示することができます。非表示にするにはもう一度C-hを押します。

ヘルプを表示する:<C-h>

コマンドヘルプを表示する:C-h
コマンドヘルプを表示する:C-h

メッセージを送信する方法:C-Enter

まず覚えておきたいキーマップは、メッセージを送信するC-Enterです。

プロンプトの入力はiインサートモードにして普通に入力しノーマルモードにして送信はC-Enterです。

Control + Enter(C-Enterでプロンプトを送信します。

C-Enterはノーマルモードで送信します。

ウィンドウを閉じる方法:C-c

次に覚えておきたいキーマップは、閉じる方法だと思います。ウィンドウを閉じるにはC-cです。

Control + c(C-cでウィンドウを閉じます。

設定状態の表示:C-o

設定状態を確認する場合は、C-oで下のように設定状態が表示されます。非表示にするにはもう一度C-oを押します。

C-oで開いた設定ウィンドウの各項目でEnterキーを押すことで設定を変更することができます。この設定はセクション間で保存されます。

設定状態の表示:<C-o>

設定状態の表示:<C-o>
設定状態の表示:<C-o>

modelgpt-4に設定変更して、max_tokens300top_pの値は1tempratureなどが0であることがわかります。

セッションの表示:C-p

セッションを確認する場合は、C-pで下のようにセッションが表示されます。非表示にするにはもう一度C-pを押します。

セッションの表示:<C-p>

セッションの表示:<C-p>
セッションの表示:<C-p>

:ChatGPT(インタラクティブウィンドウ)でのキーマップ一覧

:ChatGPT:ChatGPTEditWithInstructionsで以下のキーマップが利用できます。

キーマップ説明
C-Enter(ノーマルモードにて)送信する
C-cウィンドウを閉じる
C-fサイクルモード
Tabサイクルウィンドウ
dメッセージの削除 / セッションの削除
C-rドラフトメッセージ
eメッセージの編集
C-n新しいセッションを開始
C-j次のメッセージ
C-k前のメッセージ
rセッション名の変更
C-d下にスクロール
C-u上にスクロール
C-c閉じる
Spaceセッションの選択
C-xメッセージ生成を停止
C-hヘルプ表示のトグル
C-rmessage role 表示のトグル
C-pセッション表示のトグル
C-o設定ウィンドウ表示のトグル
C-ssystem role 表示のトグル
C-y回答をヤンク
C-k回答のコードをヤンク
:ChatGPT(インタラクティブウィンドウ)でのキーマップ一覧

APIキーの安全な管理方法

jackMort/ChatGPT.nvim公式githubにAPIキーの管理方法について、3つの方法の記載があります。こちらです。

1つ目は、環境変数を介したやり方、2つ目は1Passwords CLIを用いる方法、3つ目はGPGを使って暗号化、復号化する方法です。ぞれぞれ見ていきましょう。

環境変数を介する方法

zshを使っている場合には、~/.zshrcの環境変数としてAPIキーを設定おく方法です。具体的には以下のようにOPENAI_API_KEYにAPIキーを設定します。

~/.zshrc


export OPENAI_API_KEY="**YOUR_API_KEY**"
メリット

環境変数に設定することでzshから直接アクセスできるためシンプルで簡単です。また、スクリプトやプログラム、アプリケーションから自動的に環境変数を読み込むことができるので、便利です。

デメリット

シェルの設定ファイルに平文で保存されるため、万が一第三者に読まれた場合にはAPIキーが漏れてしまいます。また、シェルの設定ファイルをgitで管理している場合、万が一誤って公開してしまった場合も同様に、APIキーが漏れます。

1Passwords CLIを用いる方法

1passwordについては、以下の記事で詳しく紹介していますのでぜひご覧ください。

1passwordは最も信頼できるパスワードマネージャです。opコマンドでコマンドラインから高度に使うこともできます。

1password CLIを用いてAPIキーを取得するには下のように設定します。

~/.config/nvim/init.lua


require("chatgpt").setup({
    api_key_cmd = "op read op://private/OpenAI/credential --no-newline"
})

op://private/OpenAI/credential」の部分は、1passwordで秘密参照をコピーすると簡単です。

1passwordで秘密参照をコピー
1passwordで秘密参照をコピー

その後、シェルの設定ファイルから、環境変数OPENAI_API_KEYは削除しておきます。

メリット

1Passwordは強固なセキュリティ基準を持つパスワードマネージャで、APIキーなどの機密情報を安全に管理できます。また、1Passwordはマルチプラットフォームで利用できるので、CLIツールを通じてMacやLinuxで使うことができ、スクリプトやプログラムと統合しやすいです。

デメリット

1Passwordは主にサブスクリプションサービスであるため有料。
CLIツールの使用はある程度の知識が必要で、最初は複雑に感じられるかもしれません。また、スクリプトやプログラムを起動するたびに1Passwordにアクセスするために認証をする必要があり、これが相当な手間に感じることもしばしばあります。

GPGを用いる方法

GPG(GNU Privacy Guard)は、データの暗号化とデジタル署名を行うためのツールです。公開鍵暗号化技術を使用し、メールやファイルなどの情報を安全に送受信することができます。公開鍵(暗号化に使用し、誰にでも共有できる鍵)と秘密鍵(復号化や署名の確認に使用し、所有者だけが持つ鍵)のペアを生成し、このペアの鍵で情報を保護します。またGPGはオープンソースでプライバシーとセキュリティを高めるために広く利用されています。

メリット

GPG(GNU Privacy Guard)は、公開鍵暗号方式を用いてファイルなどを高度に暗号化することができます。GPGはオープンソースであり、MacやLinuxなど多くのOSで利用できます。

デメリット

GPGの設定と鍵管理は、最初はハードルが高いです。また、公開鍵と秘密鍵のペアを適切に安全に管理する必要がでてきます。

結論:1Password CLIがベスト

セキュリティと利便性のバランスを考えると、1Password CLIに軍配が上がります。

理由は、環境変数に設定することは平文でありリスクが最も高いのでNG。GPGは設定と鍵の管理が複雑でNG。消去法でも1Password CLIという結論になりますが、1passwordは有料ですが、最も信頼でき安心して使える点が魅力です。APIキーの管理のみならず、パスワード管理の全体が便利になる点も良いと思っています。

which-keyプラグインのマッピング

which-key用の設定も用意されています。


c = {
  name = "ChatGPT",
    c = { "<cmd>ChatGPT<CR>", "ChatGPT" },
    e = { "<cmd>ChatGPTEditWithInstruction<CR>", "Edit with instruction", mode = { "n", "v" } },
    g = { "<cmd>ChatGPTRun grammar_correction<CR>", "Grammar Correction", mode = { "n", "v" } },
    t = { "<cmd>ChatGPTRun translate<CR>", "Translate", mode = { "n", "v" } },
    k = { "<cmd>ChatGPTRun keywords<CR>", "Keywords", mode = { "n", "v" } },
    d = { "<cmd>ChatGPTRun docstring<CR>", "Docstring", mode = { "n", "v" } },
    a = { "<cmd>ChatGPTRun add_tests<CR>", "Add Tests", mode = { "n", "v" } },
    o = { "<cmd>ChatGPTRun optimize_code<CR>", "Optimize Code", mode = { "n", "v" } },
    s = { "<cmd>ChatGPTRun summarize<CR>", "Summarize", mode = { "n", "v" } },
    f = { "<cmd>ChatGPTRun fix_bugs<CR>", "Fix Bugs", mode = { "n", "v" } },
    x = { "<cmd>ChatGPTRun explain_code<CR>", "Explain Code", mode = { "n", "v" } },
    r = { "<cmd>ChatGPTRun roxygen_edit<CR>", "Roxygen Edit", mode = { "n", "v" } },
    l = { "<cmd>ChatGPTRun code_readability_analysis<CR>", "Code Readability Analysis", mode = { "n", "v" } },
  },

デフォルトの設定

デフォルトの設定も公式に詳しく記載されていいます。


local M = {}
function M.defaults()
  local defaults = {
    api_key_cmd = nil,
    yank_register = "+",
    edit_with_instructions = {
      diff = false,
      keymaps = {
        close = "<C-c>",
        accept = "<C-y>",
        toggle_diff = "<C-d>",
        toggle_settings = "<C-o>",
        toggle_help = "<C-h>",
        cycle_windows = "<Tab>",
        use_output_as_input = "<C-i>",
      },
    },
    chat = {
      welcome_message = WELCOME_MESSAGE,
      loading_text = "Loading, please wait ...",
      question_sign = "", -- 🙂
      answer_sign = "ﮧ", -- 🤖
      border_left_sign = "",
      border_right_sign = "",
      max_line_length = 120,
      sessions_window = {
        active_sign = "  ",
        inactive_sign = "  ",
        current_line_sign = "",
        border = {
          style = "rounded",
          text = {
            top = " Sessions ",
          },
        },
        win_options = {
          winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
        },
      },
      keymaps = {
        close = "<C-c>",
        yank_last = "<C-y>",
        yank_last_code = "<C-k>",
        scroll_up = "<C-u>",
        scroll_down = "<C-d>",
        new_session = "<C-n>",
        cycle_windows = "<Tab>",
        cycle_modes = "<C-f>",
        next_message = "<C-j>",
        prev_message = "<C-k>",
        select_session = "<Space>",
        rename_session = "r",
        delete_session = "d",
        draft_message = "<C-r>",
        edit_message = "e",
        delete_message = "d",
        toggle_settings = "<C-o>",
        toggle_sessions = "<C-p>",
        toggle_help = "<C-h>",
        toggle_message_role = "<C-r>",
        toggle_system_role_open = "<C-s>",
        stop_generating = "<C-x>",
      },
    },
    popup_layout = {
      default = "center",
      center = {
        width = "80%",
        height = "80%",
      },
      right = {
        width = "30%",
        width_settings_open = "50%",
      },
    },
    popup_window = {
      border = {
        highlight = "FloatBorder",
        style = "rounded",
        text = {
          top = " ChatGPT ",
        },
      },
      win_options = {
        wrap = true,
        linebreak = true,
        foldcolumn = "1",
        winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
      },
      buf_options = {
        filetype = "markdown",
      },
    },
    system_window = {
      border = {
        highlight = "FloatBorder",
        style = "rounded",
        text = {
          top = " SYSTEM ",
        },
      },
      win_options = {
        wrap = true,
        linebreak = true,
        foldcolumn = "2",
        winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
      },
    },
    popup_input = {
      prompt = "  ",
      border = {
        highlight = "FloatBorder",
        style = "rounded",
        text = {
          top_align = "center",
          top = " Prompt ",
        },
      },
      win_options = {
        winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
      },
      submit = "<C-Enter>",
      submit_n = "<Enter>",
      max_visible_lines = 20,
    },
    settings_window = {
      setting_sign = "  ",
      border = {
        style = "rounded",
        text = {
          top = " Settings ",
        },
      },
      win_options = {
        winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
      },
    },
    help_window = {
      setting_sign = "  ",
      border = {
        style = "rounded",
        text = {
          top = " Help ",
        },
      },
      win_options = {
        winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
      },
    },
    openai_params = {
      model = "gpt-3.5-turbo",
      frequency_penalty = 0,
      presence_penalty = 0,
      max_tokens = 300,
      temperature = 0,
      top_p = 1,
      n = 1,
    },
    openai_edit_params = {
      model = "gpt-3.5-turbo",
      frequency_penalty = 0,
      presence_penalty = 0,
      temperature = 0,
      top_p = 1,
      n = 1,
    },
    use_openai_functions_for_edits = false,
    actions_paths = {},
    show_quickfixes_cmd = "Trouble quickfix",
    predefined_chat_gpt_prompts = "https://raw.githubusercontent.com/f/awesome-chatgpt-prompts/main/prompts.csv",
    highlights = {
      help_key = "@symbol",
      help_description = "@comment",
    },
  }
  return defaults
end

M.options = {}

M.namespace_id = vim.api.nvim_create_namespace("ChatGPTNS")

function M.setup(options)
  options = options or {}
  M.options = vim.tbl_deep_extend("force", {}, M.defaults(), options)
end

return M

最後に

最後まで読んでいただきありがとうございます。今回の【Mac】neovimでChatGPTと会話するはいかがでしたでしょうか。

普段からneovimを使っている方にとって、ChatGPT.nvimは遊んでみたくなるプラグインです。これでまたしばらくnvimから離れられない生活が続きます。

ChatGPT関連の別の記事

公式ChatGPTのMac用デスクトップアプリを使う

OpenAIライブラリ1系の変更点

neovimでChatGPT

PythonでChatGPTのAPI

MacでChatGPT

MacでChatGPT

VSCodeでChatGPT

LinuxのターミナルからChatGPT

PythonでGPT-3

カテゴリー:
関連記事