OpenAIの text-davinci-edit-001
, code-davinci-edit-001
を呼び出すためのコマンドラインツールを書いたので、忘れないうちに記録に残すことにします。(この記事はポエム要素が強いのでご了承ください)
はじめに
AIの技術の進歩が早すぎて、ついていくのが大変な時代になりました。たとえば、ChatGPTのAPIが公開されたのがつい先週の話というのが、信じられないほどです。AIを使えば、これまでできなかったことができるようになりました。例えば、自然言語でAIに命令することで、コードを書いてくれるようになり、AIはコードを読んでその意味を自然言語で書くこともできるようになりました。
こうしたことを考えると、AIを使ってコードを加工する技術が、今後ますます進化していくことが予想されます。これまでは、人間の職人が、コードを少しずつ削っては、Gitで保存して、また少しずつ削ってはGitで保存してということを繰り返していましたが、今後は、AIでテンプレートを生成し、AIでコードを加工し、AIにテストケースを作らせ、AIにリファクタリングを依頼し、AIにドキュメントを書かせるというような工程が当たり前になっていくことでしょう。
この中でも、期待が持てそうなのは、コードのドキュメントを自動生成する技術です。
コマンドラインツールを作ってみる
AIを使った何かを作りたいと思いましたが、GUIのツールは作るのが大変なので、コマンドラインツールを作ることにしました。便利なRuby言語を使うか、Crystal言語を使うかで迷いましたが、今回は単にAPIを呼び出すだけであるため、ライブラリに依存する部分もないだろうと思い、Crystal言語を使ってツールを書くことにしました。
最初に、httpsやPOSTなどの概念を十分に理解していなかったので、curlでOpenAIのAPIを呼び出しているコマンドを、ChatGPTに翻訳してCrystalのコードにしてもらいました。このツール自体も、AIにテンプレートを作成してもらって作ろうという意図があります。ChatGPTは驚くべきことに、だいたい正しいCrystalのコードを出力してくれました。そのコードを使って、次のようなことをしたいと考えました。
cat foo.rb | code-editor ドキュメントを書いてください。 > foo2.rb
これはこれで素晴らしいのですが、私たちは多くのコードを既にGitで管理しています。新たに作られたfoo2.rbとの差分を diff foo.rb foo2.rb
で確認し、よかった変更だけを foo.rb
に取り込む手順は面倒です。ほとんどの現代人はGitとVSCodeなどのテキストエディタを用いて差分を検証して add
, commit
していると思います。そこで、直接ファイルを上書きするようにツールの動作を変更しました。
code-editor -i "ドキュメントを書いてください" foo.rb
この場合は、instructionはコマンドライン引数にしないと、与えられた引数がinstructionなのかファイル名なのかわからなくなってしまうので、コマンドライン引数にしました。最初の見た目の方がUnixツールらしいと思いますが、現代の標準的なコーディング環境にふさわしいのは後者だと考えました。また、標準出力できる機能も残したかったので、出力ファイルが指定できる -o
オプションを追加し、-o -
と指定した場合は編集後のコードを標準出力に出力できるようにしておきました。
その他の部分はRubyと大きく変わったところはなく、簡単にコードを書くことができました。
headers = HTTP::Headers{
"Authorization" => "Bearer #{api_key}",
"Content-Type" => "application/json",
}
このコードはかなりCrystalらしいと思います。Crystalでは、Hashっぽいクラスがあり、そうしたクラスに関しては、Rubyで見ると定数にブロックを追加するような形で記載することができます。また、ライブラリからスピナーを利用することもできました。CrystalではMakefileを提供するのが標準的なので、Makefileを書きましたが、ChatGPTを使いました。
実際に使ってみる
それでは実際に使ってみて、どの程度自動的にドキュメントを生成することができるか見てみましょう。
まず、Rubyのコードを用意します。
def meow(n)
n.times{ puts meow }
end
ドキュメントを付加するように指示を与えます。
code-editor -i "Add YARD documentation" a.rb
その結果、このようなドキュメントが追加されました。
# Prints "meow" n times
#
# @param n [Integer] number of times to print "meow"
# @return [nil]
def meow(n)
n.times{ puts meow }
end
実際に、yard
コマンドを用いて、HTMLファイルが生成できることを確認しました。
今回の例は非常に簡単で、このようなツールが実際の局面でどの程度使えるのかは別の話だと思います。
試していきたいと思います。体感としては、利用体験はかなりよいのですが、ChatGPTの方が正確な結果が出る傾向があると思いました。
しかし、ChatGPTをコマンドラインツールとしてコードの作成に利用するのはなかなか難しそうです。
ポエム
ポエムですが、将来のコードは状態を持つのではないかというようなことを考えました。今回のcode-editorのようなツールは、コードを引数に取り、コードを返す関数のようなものと考えることができます。そうやって、コードを何回も変換していくことを考えると、コードを変数としてとって、メソッドとしてcode-editを行うようなオブジェクトのようなものがぼんやり見えてくるではありませんか。その場合、コードは単にコードであるだけではなく、状態を持つことになります。これまではGitを使ってコードグラフを人間が制御してきましたが、人間以外の存在がコードの変換を行うようになると、そうした奇妙な世界が見えてくるかもしれません。
この記事は非常に適当に書かれていますので、真に受けないでください。
この記事自体も日本語をChatGPTに直してもらいました。
以上です。