## 経緯
[[GitHub Copilot]]や[[Cursor]]を筆頭に近年エディタのAI化が進んでいる。個人的には[[Neovim]]で開発しているだけで満足だし、速度も速くて困ってもないが、このAIのビッグウェーブに乗り遅れるのもどうなのか... ということがあるので、[[Neovim]]で最近話題になっている[[avante.nvim]]を試してみることにする。
なお、[[avante.nvim]]は[[Azure OpenAI Service]]にも対応しており、これなら仕事でも使える可能性が出てきた。仕事では[[GitHub Copilot]]や[[OpenAI]]、[[Cursor]]が利用できないため見送っていたが、それならアリかもということで。
## 目的
[[OpenAI API]]の[[GPT-4o]]モデル(または[[GPT-4o mini]]モデル)を利用して、どこまで実用的であるかを確かめる。
## OpenAIのAPIキーを作成
> [!warning]
> ここで作成したキーはorganizationのキーだったので間違ってる。
[[OpenAI Platform]]からログインする。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://platform.openai.com/favicon-dashboard.svg" />
<span class="link-card-v2-site-name">platform.openai.com</span>
</div>
<div class="link-card-v2-title">
OpenAI Platform
</div>
<div class="link-card-v2-content">
Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.
</div>
<img class="link-card-v2-image" src="https://cdn.openai.com/API/images/opengraph.png" />
<a href="https://platform.openai.com/docs/overview"></a>
</div>
Introductionでいきなり `Project keys` と `User keys` の紹介があり、`User keys` はlegacyで非推奨っぽかったので困ったが、[[o1]]に聞いてみたところエディタ利用用途なら問題なさそうらしい。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://cdn.oaistatic.com/assets/favicon-o20kmmos.svg" />
<span class="link-card-v2-site-name">ChatGPT</span>
</div>
<div class="link-card-v2-title">
ChatGPT - User vs Project keys
</div>
<div class="link-card-v2-content">
OPENAI_API_KEYを作成しようとしたが、project keysとuser keysがあって迷っている。 Cursorやavante.nvimのようにOpenAI APIを使ってAI開発をサポートするエディタ/プラグインで利用する場合はどちらを使えばいい?
</div>
<img class="link-card-v2-image" src="https://cdn.oaistatic.com/assets/chatgpt-share-og-u7j5uyao.webp" />
<a href="https://chatgpt.com/share/67850531-0a20-800a-aa31-883769a8b218"></a>
</div>
というわけで[API keys作成画面](https://platform.openai.com/settings/organization/api-keys)に移動する。名前を適当につけて、`Default project` を選択して作成。
![[Pasted image 20250113212620.png]]
作成されたキーを補完して終わり。
## avante.nvimのインストール
[[avante.nvim]]をインストールする。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" />
<span class="link-card-v2-site-name">GitHub</span>
</div>
<div class="link-card-v2-title">
GitHub - yetone/avante.nvim: Use your Neovim like using Cursor AI IDE!
</div>
<div class="link-card-v2-content">
Use your Neovim like using Cursor AI IDE! Contribute to yetone/avante.nvim development by creating an account on ...
</div>
<img class="link-card-v2-image" src="https://opengraph.githubassets.com/281ab96825f4251fa50ddb27d4f930882f8d6652828826f998d160631a648eab/yetone/avante.nvim" />
<a href="https://github.com/yetone/avante.nvim"></a>
</div>
設定を追加。まずは `opts` 以外。
```lua
{
"yetone/avante.nvim",
event = "VeryLazy",
lazy = false,
opts = {},
build = "make",
dependencies = {
"stevearc/dressing.nvim",
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
},
}
```
[[Neovim]]の起動速度が10msほど遅くなってしまった...。
```console
★ start avante.nvim 8.3ms
‒ dressing.nvim 0.48ms
● dressing.nvim/plugin/dressing.lua 0.39ms
‒ plenary.nvim 0.06ms
● plenary.nvim/plugin/plenary.vim 0.03ms
‒ nui.nvim 0.07ms
‒ nvim-web-devicons 0.09ms
● nvim-web-devicons/plugin/nvim-web-devicons.vim 0.03ms
‒ avante.nvim/plugin/avante.lua 2.28ms
```
続いて `opts` を設定する。[config.lua](https://github.com/yetone/avante.nvim/blob/main/lua/avante/config.lua#L21) を確認。
```lua
---@type AvanteSupportedProvider
openai = {
endpoint = "https://api.openai.com/v1",
model = "gpt-4o",
timeout = 30000, -- Timeout in milliseconds
temperature = 0,
max_tokens = 4096,
},
```
この設定で問題なさそうなので、特に指定はしない。よって。
```lua
{
"yetone/avante.nvim",
event = "VeryLazy",
lazy = false,
build = "make",
dependencies = {
"stevearc/dressing.nvim",
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
},
opts = {
provider = "openai",
auto_suggestions_provider = "openai",
},
}
```
でOK。
最後に作成した[[OpenAI API]]のキーを環境変数に設定する。[READMEのUsageに記載されている](https://github.com/yetone/avante.nvim?tab=readme-ov-file#usage)内容に従う。
```console
export OPENAI_API_KEY=<your-api-key>
```
## 動かしてみる
適当にプロジェクトを作成して動かしてみる。無難に[[Deno]]プロジェクトを[[toki]]で作成してみる。
```console
toki deno deno-sandbox
cd deno-sandbox
```
`main.ts`
```ts
export function add(a: number, b: number): number {
return a + b;
}
function main() {}
main();
```
[[Neovim]]で `main.ts` を開く。そして `:AvanteAsk` コマンドを実行してみる。
![[Pasted image 20250113215217.png]]
*Chatが展開された!*
既に `Tokens: 748` と書いてあるのは、このまま送信するとINPUTトークンが748であることを示していそう。コードのトークン数は少ないけど、コンテキストやデフォルトプロンプトの文字数が多そうな気がしている。基本料金みたいな。
[[📰OpenAI APIの料金]]を事前に調べた限りだと、入力トークンは1000トークンあたり 0.375円 ($1 = 150円として) なので、1発で0.4円ほどになりそう。出力トークンは場合によっては多くなるけど、コードの場合は全部英語だし、1単語1トークンならそこまででもないかも。
## エラーになる
メッセージを書いて送信したらエラーになってしまった。。
```error
Error: "API request failed with status 404. Body: '{\\n \"error\": {\\n \"message\": \"The model `gpt-4o` does not exist or you do not have access to it.\",\\n \"type\": \"invalid_request_error\",\\n \"param\": null,\\n \"code\": \"model_not_found\"\\n }\\n}'"
```
### キーをつくりなおす
よく見たらorganizationのキーを作成していたぽい。
![[Pasted image 20250113220439.png]]
userのキーなので `Your profile` の方みたい。
作り直したけど結果は変わらなそう。
```error
Error: "API request failed with status 404. Body: '{\\n \"error\": {\\n \"message\": \"The model `gpt-4o` does not exist or you do not have access to it.\",\\n \"type\": \"invalid_request_error\",\\n \"param\": null,\\n \"code\": \"model_not_found\"\\n }\\n}'"
```
### 支払い登録をする
そもそもfreeのお試し枠しか利用してなく、Creditも切れているので、それが原因な気がする。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
📜2025-01-13 OpenAI APIに課金してみた
</div>
<div class="link-card-v2-content">OpenAI APIのFree trialで上限に達した後、Neovimのavante.nvimを試すため課金登録を実施した。Billing画面から支払い方法を登録し、自動課金を無効化した上で初期クレジット$10を選択した。登録後、画面表示が更新された。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/activity.webp" />
<a data-href="📜2025-01-13 OpenAI APIに課金してみた" class="internal-link"></a>
</div>
%%[[📜2025-01-13 OpenAI APIに課金してみた]]%%
まだダメそう...。
```error
Error: "API request failed with status 404. Body: '{\\n \"error\": {\\n \"message\": \"The model `gpt-4o` does not exist or you do not have access to it.\",\\n \"type\": \"invalid_request_error\",\\n \"param\": null,\\n \"code\": \"model_not_found\"\\n }\\n}'"
```
と思ったらしばらくしたら動いた。時間差があったのかもしれない...。
## 料金
先ほどの小さなコードの概要を聞いただけで1500トークンも消費してしまった。
![[Pasted image 20250113223316.png]]
`0.375*1.233 + 1.5*0.212 = 0.78円` なので、一発1円。ただ、実際のコードは100倍以上の量があるため、一発100円とかのレベルになるのだろうか...。
## コードを書かせてみる
簡単なお願いだが、ちゃんと `add` 関数を使って期待通りのコードをサジェストしてくれた。
![[Pasted image 20250113224030.png]]
カーソルをコードブロックにあわせると何か出てきた...。
![[Pasted image 20250113224118.png]]
`a` を押したところ以下のように `main` 関数に異変が。
![[Pasted image 20250113224152.png]]
キーマップの定義が以下のようになっているので `ca` を押してみる。
```lua
mappings = {
--- @class AvanteConflictMappings
diff = {
ours = "co",
theirs = "ct",
all_theirs = "ca",
both = "cb",
cursor = "cc",
next = "]x",
prev = "[x",
},
```
すると変更が反映された! たしかにこれはCOOLだ。
![[Pasted image 20250113224336.png]]
### 料金
現時点では以下の通り。
![[Pasted image 20250113224441.png]]
`Cached input` はたしか半額だったので、1.5円弱/2req という結果だ。
```
0.375*1.47 + 0.375*1.024/2 + 1.5*0.386 = 1.322円
```
常にこれくらいなら100回使ってもコーヒー1杯にも満たないくらいなので気にしなくて良さそうである。
## コードを変更させてみる
以下の関数について、引数を2つ以上4つ以下で指定できるようにしたい。
```ts
export function add(a: number, b: number): number {
return a + b;
}
```
[[ビジュアルモード]]になると、[[avante.nvim]]のキーバインドが[[virtual text (Neovim)|virtual text]]に表示される。
![[Pasted image 20250113230241.png]]
今回は編集をしたいので `edit` を実行する。 `<leader>` が `\` だったので `\ae` とキーを押す。
![[Pasted image 20250113230441.png]]
入力欄が出てくるので、編集の内容を支持する。
![[Pasted image 20250113230520.png|frame]]
*折り返しで表示されないのは微妙...*
`<C-s>` を押したらいきなり内容が変更された。確認されないのね...。
![[Pasted image 20250113230645.png]]
> [!info]- この時点の消費トークン数
> ![[Pasted image 20250113231013.png]]
悪くはないが、引数が可変長だと使う側にとって優しくない。今後は `ask` を使ってみる。
![[Pasted image 20250113230909.png|frame]]
*askの場合は赤枠のバッファができてコードが差し込まれるらしい*
このままオーダーを出してみる。
![[Pasted image 20250113231106.png|frame]]
*面倒くさいレビュアーのコメント感 半端ない*
![[Pasted image 20250113231238.png]]
違う、そうじゃない。
![[Pasted image 20250113231349.png|frame]]
*無駄な説明はお金の無駄なのでそこもカットしたい*
ちゃんと意図は通じたみたい。
![[Pasted image 20250113231525.png]]
あとは先ほどと同様に反映させる。反映行が2行ずれてたけど、まあそれはご愛敬。
### 料金
いくつか応酬があったので、トークン数が増えた。
![[Pasted image 20250113231742.png]]
```
0.375*3.943 + 0.375*2.048/2 + 1.5*0.786 = 3.04円
```
昔の円周率と一緒の金額。仕事としては言わずもがな、個人としても気にせず使える料金だと思う。この程度のお遊びプログラムならだけど。
## ガチなソースコードに対して使ってみる
[[🦉Carnelian]]のソースコードに対して、実装のテストを書かせてみる。
- `collections.ts` 80行
- `collections.spec.ts` 127行
`collections.ts` の以下
```ts
export function duplicateObject<T>(obj: T, count: number): T[] {
return Array.from({ length: count }, () => ({ ...obj }));
}
```
テストを書いていないので書かせてみたときにどれだけのものができるか...?
![[Pasted image 20250113232332.png]]
![[Pasted image 20250113232741.png]]
こちらの命令は無視だけど、コードの筋は良さそう。ここから色々込み入ったのでこの辺にしておく。
## 終わりに
個人的に一番使いそうな用途はこれだった。[[ChatGPT]]に尋ねるよりも速い。
![[2025-01-13-23-42-29.webm]]
文脈を考慮するから100行の[[Markdown]]ファイルだと1500入力トークンくらい使うけど、もし文脈を考慮したやりとりをするならむしろそれはプラスに働くかなと。
AIエディタも戦略が大事だなと思った。
> [[OpenAI API]]の[[GPT-4o]]モデル(または[[GPT-4o mini]]モデル)を利用して、どこまで実用的であるかを確かめる。
[[avante.nvim]]は誕生したばかりだから不安定なところもありつつ、実用レベルに到達するポテンシャルを感じた。何よりも[[Neovim]]で動くというのがデカイ。現状だとAIコーディングしたければ大人しく[[Cursor]]使ってた方がいいかもだけど。
[[GPT-4o]]でもコストがシビアでなければ、使いどころで使う分には金銭面は気にしすぎなくてもいい気がした。どうしても気になるなら[[GPT-4o mini]]にすればいい。両者の値段は15倍くらい違うので。([[GPT-4o]]で1500円請求されるところを[[GPT-4o mini]]なら100円)
## 2025/01/14 追記
実際のUIはもっとスマートだったという話。
<div class="link-card-v2">
<div class="link-card-v2-site">
<img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" />
<span class="link-card-v2-site-name">Minerva</span>
</div>
<div class="link-card-v2-title">
📝avante.nvimのチャットバッファのUIがファイルを開いた後と前で変わってしまう
</div>
<div class="link-card-v2-content">lualine.nvimがwinbar表示を切り替えてしまっていたため。</div>
<img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/troubleshooting.webp" />
<a data-href="📝avante.nvimのチャットバッファのUIがファイルを開いた後と前で変わってしまう" class="internal-link"></a>
</div>
%%[[📝avante.nvimのチャットバッファのUIがファイルを開いた後と前で変わってしまう]]%%
![[2025-01-14-21-54-29.webp]]