GitHub Copilot:貴方とペアを組んでプログラミングする人工知能(1/2)

アプリケーション

1.GitHub Copilot:貴方とペアを組んでプログラミングする人工知能(1/2)まとめ

・AIとペアプログラミングできると喧伝されているGitHubの新サービスCopilotの紹介
・Copilotはプログラムの文脈に基づいて関数全体やドキュメントやテストまで生成可
・機械学習と言語合成の研究の観点からは大きな前進だが実用にはやや難がある

2.GitHub Copilotの評価

以下、www.fast.aiより「Is GitHub Copilot a blessing, or a curse?」の意訳です。元記事は2021年7月19日、Jeremy Howardさんによる投稿です。

英語圏では「いよいよ、人工知能がプログラマーの職も奪いに来た!」とか「GitHubに登録していた私のコードを勝手に学習用データに使ったのか!」といったネガティブなニュアンスで結構騒がれているCopilotですが、fast.aiのJeremy HowardさんによるCopilotのレビューで視点が大局的でやはり参考になります。

個人的には凄い事は凄いのですが、私がスムーズに英語の指示が思い浮かばないせいもあり、実用に耐えないと思っています。しかし、言葉を使って人工知能と共同作業をすると言う方向性はCopilotに限らず今後も模索されていくと思うので、毛嫌いせずに可能な限り慣れ親しんで行った方が良いのかな、とも思っています。

Copilotは副操縦士の意なので、そこから連想したアイキャッチ画像のクレジットはPhoto by Mael BALLAND on Unsplash

背景

GitHub Copilotは、GitHubとOpenAIによる新しいサービスです。「貴方とペアを組んでプログラミングするAI(Your AI pair programmer)」と呼ばれています。

Copilotは、人気の高い統合開発環境であるVisual Studio Codeで利用可能なプラグインとして実装されており、現在のファイルの内容とカーソル位置に基づいてコードを自動生成してくれます。

使ってみるとは本当に魔法のようです。

例えば、以下では関数名と関数コメント(docstring)に「ファイルfnameにテキストを書き込む(Write text to file name)」と入力しました。

関数本体の灰色文字の箇所は、Copilotによって生成されました。Tabキーを押すだけで、Copilotの提案を受け入れコードに挿入する事ができます。

Copilotは確かに「AIを利用した初のプログラム合成ツール」ではありません。

2018年のGitHubの自然言語セマンティックコード検索では、わかりやすい英語の説明を使用してコード例を見つけることが実証されています。Tabnineは、ここ数年、「AIを活用した(AI powered)」コード補完技術を提供してきました。

Copilotが異なるのは、プログラムの完全な文脈に基づいて、複数行にまたがるような関数全体を記述、更にはドキュメントやテストまでをも生成できることです。

これは、誰でもAIを活用出来るようにする事(Making neural nets uncool again)を使命とするfast.aiを運営する私たちにとって特にエキサイティングです。なぜなら、プログラミングに対する敷居を下げる可能性があり、それが私たちの使命に大いに役立つからです。

したがって、私は特にCopilotを使ってみる事に熱心でした。ただし、後で説明するように、Copilotが実際に祝福であるとはまだ確信していません。それは呪いであることが判明するかもしれません。

Copilotは、GitHubで公開されているコードリポジトリでトレーニングされたCodexと呼ばれるディープニューラルネットワーク言語モデルを利用しています。

これは私にとって特に興味深いことです。2017年に、私は汎用言語モデルを微調整して、さまざまなNLP問題に関する最先端の結果を得ることができることを最初に示したからです。

私はfast.aiのレッスンの一環として、それを開発して示しました。その後、Sebastian Ruderと私はアプローチを具体化し、論文を書きました。この論文は、計算言語学会(ACL:Association for Computational Linguistics)によって2018年に発行されました。OpenAIのAlec Radfordは、この論文が、Codexの元となっているGPTを作成するきっかけになったと語っています。

以下は、言語モデルの微調整がIMDB(Internet Movie Database)内の感情分類タスクで最先端のスコアをもたらすことを、私が示した瞬間です。

言語モデルは、テキスト内の欠落している単語を推測するようにトレーニングされています。文脈を正しく推測する必要があるため、前年までに使用されていた従来の「ngram」アプローチでは、これをうまく行うことができません。たとえば、次の各例で不足している単語をどのように埋めるのかを考えてみましょう。

ある場合には「hot day(暑い日)」が正しいが、別の場合には「hot dog(ホットドッグ)」が正しいことを知るには、文章全体を読んで(ある程度)理解する必要があります。Codex言語モデルは、プログラミングコードで欠落している記号を推測することを学習するため、コンピューターコードの構造と意味について多くのことを学習する必要があります。後で説明するように、言語モデルには、基本的にこれらの作成方法に起因するいくつかの重要な制限があります。

Copilotがさまざまなライセンスの下で公開されているコードを使ってトレーニングされているという事実は、倫理的および法的意味について多くの議論につながっています。これは広く議論されているので、本稿ではこれ以上詳しく説明しませんが、知的財産権弁護士のKate Downingが指摘したCopilotのユーザーに対する明確な法的問題だけを以下にあげておきます。

「Copilotの提案するコードが複雑で長いほど、ある種の著作権で保護された表現が内包されている可能性が高くなります。」

つまり、場合によっては、Copilotの提案を使用すると、ライセンス違反になる可能性があります。(または、GPL互換ライセンスの下で自分の作品を再ライセンスする必要があります)

Copilotを使ってみる

Copilotについて詳しく説明する前に、実際にCopilotを使用した例をいくつか見ていきましょう。

自動生成されたwrite_text関数が実際に機能するかどうかを知るには、テストが必要です。Copilotにも書いてもらいましょう! この場合、テスト関数の名前を入力するだけで、Copilotが関数コメント(docstring)を入力してくれました。

その入力を受けた後、Copilotは少し混乱し、ほぼ重複したコードの多くの行を含むあまり意味のない関数を提案しました。

しかし、問題はありません。Copilotは、「Ctrl + Enter」を押すことで他の選択肢を提案する事ができます。最初にリストされているものは、実際にはかなり合理的に見えます。(最初の行の奇妙な余分なタブ文字を除く)

ここで、Copilotは、実際には存在しないread_textという関数が利用可能であると想定しています。 しかし、Copilotにread_textを書いてテストするように依頼するのは簡単です。

次に、Copilotに、「ディレクトリdirをdestにtarし、オプションでbz2、xz、またはgzip形式での圧縮を可能にする(Tar and optionally compress directory dir to dest in bz2, xz, or gzip format)」関数を作成するように依頼しました。その結果、次のようになりました。

def tar_dir(dir, dest):
    "Tar and optionally compress directory `dir` to `dest` in bz2, xz, or gzip format"
    if dest.endswith('.bz2'):
        with tarfile.open(dest,'w:bz2') as f: f.add(dir, arcname=os.path.basename(dir))
    elif dest.endswith('.xz'):
        with tarfile.open(dest,'w:xz') as f: f.add(dir, arcname=os.path.basename(dir))
    elif dest.endswith('.gz'):
        with tarfile.open(dest,'w:gz') as f: f.add(dir, arcname=os.path.basename(dir))
    else: raise ValueError('bad dest: {}'.format(dest))

また、Copilot に上記と同じ基本的なアプローチを使用してテストを作成して貰うと以下のようになりました。

with TemporaryDirectory() as tmp:
    write_text(os.path.join(tmp,'a.txt'),'hello')
    write_text(os.path.join(tmp,'b.txt'),'world')
    tar_dir(tmp,'out.tar.bz2')
    assert os.path.exists('out.tar.bz2')
    with tarfile.open('out.tar.bz2') as f:
        assert f.getnames()==['a.txt','b.txt']

最後の行のgetnamesには親ディレクトリが含まれるため、このテストは実際には合格しませんが、簡単に修正できます。Copilotは、以前に作成したwrite_text関数を使用することを賢く決定しましたが、これは私が予期していなかったことです。

Copilotを使って通常の文章を書くこともできます。私は今vscodeでこのブログ投稿を書いていて、「enable Copilot」ボタンをクリックしただけです。前の文を入力した後、Copilotが補完文として推奨した文章は次のとおりです。

「私はブログ投稿を1行書くだけでできるようになりました。Copilotが、残りの投稿を生成してくれます。(I can now write my blog post in a single line of text, and Copilot will generate the rest of the post for me.)」

明らかに、Copilotは自身の文章生成能力をかなり誇張して理解しています!

Copilotが書くコードの問題

Copilotが書くコードはあまり良いコードではありません。たとえば、上記のtar_dir関数について考えてみます。そこには重複する箇所がたくさんあります。つまり、将来維持するコードが増え、読む人が理解しなければならないコードが増えるということです。

さらに、docstringでは「圧縮を選択可能にする」と述べていますが、生成されたコードは常に圧縮されます。代わりに次のように記述することで、これらの問題を修正できます。

def tar_dir(dir, dest):
    "Tar and optionally compress directory `dir` to `dest` in bz2, xz, or gzip format"
    suf = ':' + Path(dest).suffix[1:]
    if suf==':tar': suf=''
    with tarfile.open(dest,f'w{suf}') as f: f.add(dir, arcname=dir)

より大きな問題は、write_textとtar_dirの両方の機能がPythonの標準ライブラリ(pathlibのwrite_textとshutilのmake_archiveとして)によってすでに提供されているため、両方の関数が新たに書かれるべきではないことです。

標準ライブラリのバージョンも優れており、pathlibのwrite_textは追加のエラーチェックを実行し、テキストエンコーディングとエラー処理をサポートします。make_archiveはzipファイルと登録したその他の圧縮形式をサポートします。

Copilotが品質の低いコードを書く理由

OpenAIの論文によると、Codexが正解を示す割合はわずか29%です。そして、これまで見てきたように、それが書き込むコードは一般にリファクタリングが不十分であり、既存のソリューション(それがPythonの標準ライブラリにある場合でも)を十分に活用できません。

Copilotは、多くの世界最高のプログラマーが書いたコードを含む、数千万のリポジトリで構成されるGitHubの公開コードアーカイブ全体を読んでいます。これを考えると、なぜCopilotはこのような劣悪なコードを書くのでしょうか?

その理由は、言語モデルの動作原理によるものです。言語モデルは、平均的な人がどのように書くかを示しています。言語モデルは何が正しいのか、何が良いのかについて何の感覚も持っていません。

GitHubのほとんどのコードは、(ソフトウェア仕様の観点からは)かなり古く、(定義上)平均的なプログラマーによって書かれています。Copilotは、あなたが望むファイルを平均的なプログラマーがどんな風に書く可能性があるかを推測し、最善の推測を出力します。OpenAIは、Codexの論文でこれについて説明しています。

次のトークンを予測する事を目標としてトレーニングされた他の大規模な言語モデルと同様に、Codexはトレーニングデータ内の分布に可能な限り類似したコードを生成します。そこから得られる結果の1つは、そのようなモデルがユーザーにとって役に立たないコードを生み出す可能性があることです。

Copilotが平均的なプログラマーよりも劣っている重要な事の1つは、コードをコンパイルしたり、機能することを確認したり、ドキュメントに記載されているとおりに機能するかどうかを検討したりしないことです。

また、Codexは、直近1~2年に作成されたコードをトレーニングに使用していないため、最近のバージョン、ライブラリ、言語機能が完全に欠落しています。たとえば、fast.aiのライブラリを使ったコードを作成するように求めると、約1年前にリリースされたv2ではなく、v1のAPIを使用した提案のみが生成されます。

しかし、Copilotによって書かれたコードの品質について不平を言うことは、人の言葉を話す犬に出くわし、その犬の言い回しについて不平を言うようなものです。犬が会話しているという事実は十分に印象的です!

はっきりさせておきましょう。Copilot(およびCodex)が妥当に見えるコードを記述しているという事実は、驚くべき成果です。機械学習と言語合成の研究の観点から、これは大きな前進です。

ただし、思った通りに機能せず、極端なケースをチェックせず、サポートされなくなった手法を使用し、冗長で技術的負債を生み出すが、合理的に見えるコードが大きな問題になる可能性があることも明確にする必要があります。

3.GitHub Copilot:貴方とペアを組んでプログラミングする人工知能(1/2)関連リンク

1)www.fast.ai
Is GitHub Copilot a blessing, or a curse?

2)copilot.github.com
GitHub Copilot · Your AI pair programmer

3)marketplace.visualstudio.com
Visual Studio IntelliCode Insiders – Visual Studio Marketplace(API Usage Examples)

タイトルとURLをコピーしました