本当は教えたくない、VScode拡張の最強プログラミングアシスタントAI Phind(導入・使い方)

みなさんプログラムは書いていますでしょうか。この一年でChatGPTができ、CopilotにCopilot Chatなど色々なAIツールが出ていますが今回お勧めするのは**Phind**という**AIアシスタント**です。

# Phindとは
Phind([Phind.com](https://www.phind.com/))とは端的にいえばGPT-4を超えるコーディング能力に特化した言語AIです
参考リンク：[大規模言語モデル「Phind」がコーディングにおいてGPT-4を上回る](https://gigazine.net/news/20231102-phind-gpt-4/)

https://gigazine.net/news/20231102-phind-gpt-4/

リンク内で言われているように、WebからChatGPTやGoogleのように簡単に使うことができますが、**Phindの真髄はここでは味わえません。**

## Phindの真の実力
**Phindの本当の実力はVScode拡張を使うことによって体感することができます。**
Phindのベースモデルは[Phind-CodeLlama](https://huggingface.co/Phind/Phind-CodeLlama-34B-v2)というものを使っています。これはMeta社が作った[Codellama](https://github.com/facebookresearch/codellama)という**プログラミングに特化した言語モデル**をファインチューニング(改良)したものを使っています。

Phind.comにアクセスし実際に使ってみるとわかりますが、webをクローリングして検索結果から最適内容を表示する、というタスクでは 
### Phindの真の実力は味わえないのです。
(細かい裏側については異なっている可能性があります。あくまで推測です。)
あと、
### 無料です

# とりあえず使ってみる
### Vscode拡張機能でPhindを検索する、インストールする

![スクリーンショット 2023-12-07 14.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/3f77787f-4a02-c919-3579-3f94e379bf11.png)

### 左側の拡張機能欄にPhindが追加されるのでそれを開いて中央に表示されるログインボタンからログインする
会員登録が必要となるので、任意の方法で会員登録してください。ログインが済むと、Editorの選択ダイアログが出るので任意のEditorを選択して進んでください。今回はVScodeを選択し、Vscode拡張の前提で話を進めていきます。

![スクリーンショット 2023-12-29 20.30.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/39dd5fb0-d53c-ac05-d736-241e37cc15f2.png)

すると上記のような画面に出ます。

## 使い方
それぞれ細かい使い方の中にリンクしています
- [Ctrl/Cmd + I](#ctrlcmd--i)
    - phindを開く
- [Ctrl/Cmd + Shift + I](#ctrlcmd--shift--i)
    - 選択範囲の質問をする
- [Ctrl/Cmd + Shift + M](#ctrlcmd--shift--m)
    - 選択範囲をphindの出力に書き換える
- [Ctrl/Cmd + Shift + L](#ctrlcmd--shift--l)
    - terminalの出力について質問する
- [Alt/Option + Enter](#altoption--enter)
    - 参照ファイルをなくして出力する
- [参照ファイル/変数の追加](#参照ファイル変数の追加)
    - +Fileや+Symbolで参照するファイルや変数を追加する
- [プロンプト内での@による明示的な参照](#プロンプト内でのによる明示的な参照)
    - プロンプト内で@ファイル名などとすることにより、どのファイルを参照するかを選択する

(コメントであった操作方法についての追記)
コメントで日本語入力の変換のエンターで送信されてしまうとご指摘を受けました。
その場合は __Shift+Enterで変換のみを決定する__ ことができます。また、変換状態ではない場合はShift+Enterで改行を行うことができますのでお試しください。

<details><summary>細かい使い方</summary><div>

### Ctrl/Cmd + I
- `Ctrl/Cmd + I`で先ほどのPhindが開きます
### Ctrl/Cmd + Shift + I
- `Ctrl/Cmd + Shift + I`で選択範囲のコードについての質問ができます。例えばこの画面
![スクリーンショット 2023-12-29 20.37.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/d90c2dd0-e187-c8d6-d70c-2bce848dc40b.png)
でコードの部分を選択し、 `Ctrl/Cmd + Shift + I`を押すと
![スクリーンショット 2023-12-29 20.38.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/68839434-a609-d7f6-6ee0-a9768a8bc357.png)
このように表示されます。Phindの画面の下をよく注目すると`main.py`と`main.py:1-2`とAIが参考にするプログラムを指定された状態でこの画面が開かれます。例えばここでこのプログラムは何と聞いてみると
![スクリーンショット 2023-12-29 20.40.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/db629c09-25a7-fcd6-39a4-de377e5e73e9.png)
かなり正確に答えられています。
### Ctrl/Cmd + Shift + M
- `Ctrl/Cmd + Shift + M`はphindの出力でコードを書き換えます。
![スクリーンショット 2023-12-29 20.42.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/115caadd-c58a-2e13-6ad9-c7bc844e9ff7.png)
先ほどの選択範囲で`Ctrl/Cmd + Shift + M`を押すとこのようにどのように書き直して欲しいかを聞いてきます。ここでは試しに偶数の時だけprintするようにしてみます。
![スクリーンショット 2023-12-29 20.43.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/97e82f33-2c87-a3ba-f0f9-4f4378b05dff.png)
![スクリーンショット 2023-12-29 20.44.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/4a266997-556b-a2fa-9e60-a2a4c76f65de.png)
このようにコードを書き換えてくれるので、これでよければ再度`Ctrl/Cmd + Shift + M`を押します。
### Ctrl/Cmd + Shift + L
- `Ctrl/Cmd + Shift + L`を押すとTerminalの出力結果を参照した状態でPhindが開かれます。例えばエラーが出た時に`Ctrl/Cmd + Shift + L`するとこのような形でエラーを引用して自動で出力を出してくれます
![スクリーンショット 2023-12-29 20.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/b8ba7c6f-f977-a289-abec-cfa1b834ccec.png)
:::note info
日本人的には日本語の出力で返ってこないいのでコピペしたほうがわかりやすいかもしれないです
:::
### Alt/Option + Enter
- `Alt/Option + Enter`を押すと参照するコードをなくします。何かしらプロンプトを入れた状態で、`Alt/Option + Enter`すると参照するファイルやコードをなくした状態で結果を生成できます。

### 参照ファイル/変数の追加
入力欄上に`+File`と`+Symbol`があります。
![スクリーンショット 2023-12-29 21.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986547/968c9188-4d78-7d7e-57ac-0d5b1d97e38e.png)
ここを押してファイルを選択したり、特に参照する変数について入力することができます。

### プロンプト内での@による明示的な参照
プロンプト内で@をつけて明示的にファイルや変数などを指定することができます。これにより先項の追加に含まれていなかったファイルなども自動追加されたりします。

</div></details>

## 精度比較
ここでは精度比較を行なっていきます。今回は競プロの問題を解かせてみます。
問題文はこちらになります。引用元は[こちら](https://atcoder.jp/contests/typical90/tasks/typical90_a)です
~~~
左右の長さが L [cm] のようかんがあります。 N 個の切れ目が付けられており、左から i 番目の切れ目は左から A(i)[cm] の位置にあります。あなたは N 個の切れ目のうち K 個を選び、ようかんを K+1 個のピースに分割したいです。そこで、以下の値を スコア とします。K+1 個のピースのうち、最も短いものの長さ（cm 単位) スコアが最大となるように分割する場合に得られるスコアを求めてください。
制約
1≤K≤N≤100000
0<A(1)<A(2)​<⋯<A(N)<L≤10^9
入力はすべて整数

入力
入力は以下の形式で標準入力から与えられます。
```
N L
K
A(1) A(2) ⋯ A(N)
```​	

出力
求めるスコアを出力してください。

入力例 1
```
3 34
1
8 13 26
```
出力例 1
```
13
```
左から 2 番目の切れ目で分割すると、長さ 13 [cm] のピースと長さ 21 [cm] のピースに分かれ、スコア 13 を達成できます。

入力例 2
```
7 45
2
7 11 16 20 28 34 38
```
出力例 2
```
12
```
左から 3 番目と 5 番目の切れ目で分割すると、スコア 12 を達成できます。

入力例 3
```
3 100
1
28 54 81
```
出力例 3
```
46
```
左から 2 番目の切れ目で分割すると、スコア 46 を達成できます。

入力例 4
```
3 100
2
28 54 81
```
出力例 4
```
26
```
入力例 5
```
20 1000
4
51 69 102 127 233 295 350 388 417 466 469 523 553 587 720 739 801 855 926 954
```
出力例 5
```
170
```
~~~
以下が出力です。
~~~: phind
この問題は二分探索を用いて解くことができます。まず、スコアの最小値と最大値を設定します。最小値は1、最大値はようかんの長さLです。次に、最小値と最大値の中間値を計算し、その値をスコアとして分割可能かどうかを確認します。分割可能であれば、スコアを上げて再度確認します。分割不可能であれば、スコアを下げて再度確認します。このプロセスを最小値と最大値が逆転するまで繰り返します。

以下にPythonでの実装例を示します。

def solve():
    N, L = map(int, input().split())
    K = int(input())
    A = list(map(int, input().split()))
    A.append(L)
    B = [A[0]] + [A[i+1] - A[i] for i in range(N)]
    
    left = -1
    right = L + 1
    while right - left > 1:
        mid = (left + right) // 2
        cnt = 0
        tmp = 0
        for i in range(N+1):
            if tmp + B[i] >= mid:
                cnt += 1
                tmp = 0
            else:
                tmp += B[i]
        if cnt >= K + 1:
            left = mid
        else:
            right = mid
    print(left)

solve()
このコードは、入力を受け取り、ようかんの各部分の長さを計算し、二分探索を行って最適なスコアを見つけ出します。最後に、最適なスコアを出力します。
~~~
~~~: Copilot Chat
この問題は二分探索を使用して解くことができます。スコアが最大となるように分割するためには、最も短いピースの長さを最大化する必要があります。これは、各ピースの長さが特定の値以上であるように分割することが可能かどうかを確認することで達成できます。

以下に、この問題を解くためのPythonコードを示します。

```python
def check(mid, A, K, L):
    cnt = 0
    pre = 0
    for i in range(len(A)):
        if A[i] - pre >= mid and L - A[i] >= mid:
            cnt += 1
            pre = A[i]
    if cnt >= K:
        return True
    return False

def solve():
    N, L = map(int, input().split())
    K = int(input())
    A = list(map(int, input().split()))
    left = 0
    right = L
    while right - left > 1:
        mid = (left + right) // 2
        if check(mid, A, K, L):
            left = mid
        else:
            right = mid
    print(left)

solve()
```

このコードでは、まず`check`関数を定義しています。この関数は、与えられた長さ`mid`でようかんを分割することが可能かどうかを確認します。次に、`solve`関数では二分探索を行い、可能な最大の長さを見つけ出します。
~~~
~~~: chatGPT(GPT-4)
この問題は、特定の制約の下での最適な切断方法を見つけることを目的としています。スコアはK+1個のピースのうち最も短いものの長さで、このスコアを最大化するような切断方法を見つける必要があります。これは二分探索アルゴリズムを使用して効率的に解決できる問題です。

アルゴリズムの大まかな流れは以下の通りです：

切断可能な最小のピースの長さ（最低スコア）と最大のピースの長さ（最高スコア）を決定します。
これらの値を基にして、可能なスコアの範囲を二分探索します。
あるスコアが達成可能かどうかを判断するために、与えられた切断位置を利用します。
最終的に、最大の達成可能なスコアを見つけます。
まずは、二分探索を実装し、与えられた例でテストしてみましょう。
アルゴリズムが正しく機能していることが確認できました。与えられた例でテストした結果は以下の通りです：

入力例1: 3 34 1 [8, 13, 26] の出力は 13 です。
入力例2: 7 45 2 [7, 11, 16, 20, 28, 34, 38] の出力は 12 です。
入力例3: 3 100 1 [28, 54, 81] の出力は 46 です。
入力例4: 3 100 2 [28, 54, 81] の出力は 26 です。
入力例5: 20 1000 4 [51, 69, 102, 127, 233, 295, 350, 388, 417, 466, 469, 523, 553, 587, 720, 739, 801, 855, 926, 954] の出力は 170 です。
これらの結果は、問題で与えられた出力例と一致しています。よって、このアルゴリズムは問題を解決するために適切です。 ​​
```
def max_score(N, L, K, cuts):
    def is_possible(score):
        """ Check if a given score is possible with the current cuts """
        count, last_cut = 0, 0
        for cut in cuts:
            if cut - last_cut >= score and L - cut >= score:
                count += 1
                last_cut = cut
                if count == K:
                    return True
        return False

    low, high = 0, L
    while low < high:
        mid = (low + high + 1) // 2
        if is_possible(mid):
            low = mid
        else:
            high = mid - 1
    return low

# Test the function with the provided examples
example1 = max_score(3, 34, 1, [8, 13, 26])
example2 = max_score(7, 45, 2, [7, 11, 16, 20, 28, 34, 38])
example3 = max_score(3, 100, 1, [28, 54, 81])
example4 = max_score(3, 100, 2, [28, 54, 81])
example5 = max_score(20, 1000, 4, [51, 69, 102, 127, 233, 295, 350, 388, 417, 466, 469, 523, 553, 587, 720, 739, 801, 855, 926, 954])

example1, example2, example3, example4, example5
```
~~~

ChatGPTは自分でテストケースまで用意していてさすがといった感じですが、CopilotChatとphindも同等の出力ができています。でもここまでなら「他のでよくない？」と思う人も多いでしょう。

## Phindが優れている点
まず、Phindが他のAIアシスタントと比べて優れている点を紹介するには言語モデルの特性を知らなければいけません。それは __長い文章が苦手__ という点です。人間もそうですよね、言語モデルの構造上長い文章になればなるほど精度が落ちます。
ですから、AIに与える入力は以下の二点について気をつけなければならないです。(これはCopilotChatやChatGPTについても同じです)
- 文章は最低限の長さ
- 問題を解決するにあたっての必要十分な情報

Phindではこの二点について、以下の二つのように意識的にこの問題を解決・改善できます。
- 多すぎる文字数の時は警告が出る。
    - 6000字を超えると警告が出ます。これを超えても出力ができますが、恐らくいい答えが返ってきづらくなる閾値だと思われます。ユーザーがファイルなどを参照している場合はどれくらいの文字数になっているかわかりづらいため、参照する必要のないファイルを消すことや、過去の必要のない出力、プロンプトを明示的に調整できるようになります。
- 参照するファイルや出力、コードを簡単に選択できる。
    - 先の説明で記したとおり明示的に参照するコード、ファイルを複数同時に選べます。それにより、Phindが問題解決を行うために必要なファイルやコードをわざと参照させられるようにできます。

この二点は、ChatGPTやCopilotChatなどではうまく解決しきることができない課題であり、多少モデル性能が劣っていたところで、そのアドバンテージを大きく上回る違いを生み出します。

またこのツールは無料かつ、早いです。この点に関しても大きな違いがあります。

# 結論
類似ツールを使っている人(chatGPT、CopilotChat)はとりあえず使ってみてください。
類似ツールを使ったことがない人も、無料なので試してみてください。

このツールを試してみてから、使わないか使うかは考えてみてください。

(2024/1/1追記)
本日Phindのアップデートにより、ボタンひとつでPhindモデルとGPT-4モデルが切り替えられるようになったようです。出力を比較したり、好みのモデルを試してみてください！(課金プランでない場合はGPT-4で複数のリクエストを送ると使えなくなったりするかもしれません。その時は完全に無料なPhindモデルを使い続ければ問題ないと思われます。)