結論

ChatGPT 4 の言うとおりにプログラムを書くのは、手軽でプロトタイピングに便利だが、使いこなすにはプロンプトエンジニアリングとプログラミングの知識が必要である。

背景

OpenAI 社が公開している ChatGPT 4 は、チャット形式で手軽に高度な自然言語処理を行える人工知能として注目を集めている。先月(2023 年 11 月)、その機能として、指示(プロンプト)を事前に与えることでカスタマイズされた人工知能を手軽に作れる GPTs が公開された。

GPTs を用いれば、自分の代わりにコードを書いてくれる人工知能を手っ取り早く用意できそうだ。たまたま前から作ってみたいと思っていたものが有ったので、GPTs の力を借りてそれを実現できるか試してみることにした。

作ったもの

駅発車時刻表を編集できるシングルページアプリケーション StationTimetableEditor を作成した。

A screenshot of Station Timetable Editor authoring the timetable of Tsubojiri station

  • セルの空白部分をダブルクリックすると、新しい時刻の入力覧が表示される。0 以上 59 以下の整数を確定すると、その数値が時刻として入力される。
  • セルの時刻部分をダブルクリックすると、その時刻を編集できる。空にして確定するとその時刻を削除できる。
  • 右上の [+] ボタンをクリックすると、新しい列が追加される。
  • 最初の時間行(2 行目)と最後の時間行(最終行)の上辺と下辺にマウスカーソルを合わせると、[+] ボタンが表示される。その状態でクリックすると、その時間行の上または下に新しい時間行が追加される。
  • 最後の時間行(最終行)が空の場合、その左辺にマウスカーソルを合わせると、[×] ボタンが表示される。その状態でクリックすると、その時間行が削除される。
  • 変更内容に応じて URL が変化する。その URL に飛ぶと、時刻表を再現できる。
  • [×] ボタンが表示されていても時間行が削除されない場合が有る等、不具合が多く有る。

やったこと

  1. 求められた要求を実装するコードを出力するような GPTs を作成する。
  2. 空の index.html、style.css、script.js を持つ Git リポジトリを作成する。
  3. GPTs に実現したいことを一文で入力する。
  4. GPTs が出力したコードをコピーアンドペーストで取り込む。
  5. 入力内容をコミットログにして、変更内容を Git リポジトリにコミットする。
  6. 3-5 を繰り返す。

GPTs のプロンプト

プロンプトは具体例を含むため長い。要約は次のとおり。

  • 入力された要求を実装する変更を 1 つ以上のコードブロックとして出力する。
  • 各コードブロックの前に、変更の種類に応じて “Add”、”Update”、または “Remove” を出力する。
  • 各コードブロックは、連続する HTML コード辺、CSS ルール、または JavaScript の関数か定義を 1 つ だけ含む。
  • “Add”、”Update”、”Remove”、コード辺以外は出力しない。コードの説明はしない。
  • コードコメントは省く。
  • Web 標準に則り、アクセシビリティやパフォーマンスを考慮する。
  • 変更量を最小化する。過剰な最適化や名前の無駄な変更は避ける。

プロンプトの内容も ChatGPT に評価してもらい、変更を重ねた結果お墨付きを貰った。ただ、プロンプトの専門家ではないので、もっと良い書き方が有ると思う。提案が有ればプル要求等で教えていただきたい。

良かった点

今回試してみて何より良かったのは、JavaScript を齧った程度の自分でもそれなりに動く製品が出来上がったという点だ。それには次のような点が寄与したと考えている。

コードの品質が思った以上に高い

プロンプトに従ってコピーアンドペーストするだけで、大抵の場合そのまま動かすことができた。実行時エラーも当初予想していたよりもずっと少なかった。(JavaScript を齧った程度の自分にとって)大抵は納得できるロジックであったし、たまには自分が考え付くであろう以上に簡潔なコードが生成されることもあった。これは、JavaScript が広く使われているため、学習データに豊富に含まれていることもあるだろう。

大きい部分を小さく始めやすい

質問を正しく理解してもらい簡潔な変更を出力してもらうために、個々の要求内容は自ずと小さくなった。また、自然とその内容も大局的な部分を準備してから徐々に詳細を作り込むという正しい流れになった。

自分がコードを書くときは、つい瑣末な実装や細かい見た目が気になってしまい、なかなか先に進まなくなって(そして遂には飽きて)しまう。言いなりプログラミングは、そういう逸る気持ちを抑える練習に役立ちそうだ。

隙間時間にコードを書ける

自分の中で、コードを書く時は集中できる時間を十分に取れる時にしたい、という気持ちが有る。これはフロー状態を作るという観点では正しいが、そのようなまとまった時間を確保するのはしばしば難しい。

言いなりプログラミングでは、やることは要求を文章にして入力するだけ。細かい実装は ChatGPT がやってくれるので、集中力を高める必要性が相対的に低い。その結果、隙間時間にコードの変更を重ねることがしやすくなった。

難しかった点

一方で、幾つか課題も浮かび上がった。まとめると、プログラミング知識が皆無でも人工知能が全て解決してくれる未来はもう少し先のようだ、ということだ。

一部プロンプトの指示をあまり聞いてくれない

“Add”、”Update”、”Remove” を出力するという指示にはよく従ってくれた。一方でコード辺以外は出力しないという指示にもかかわらず、コードの説明を出力することがある。また、コードコメントを省くという指示を守らせるのは難しく、ほぼ無視されてしまった。学習元のコードにコメントがちゃんと書かれているのが原因だろう。コードブロックについても複数の CSS ルールや JavaScript の関数をまとめて 1 つのコードブロックにしてしまうことが往々にして見受けられた。

変更内容を適切に適用するためには一定の知識が必要

応答速度の観点から、プロンプトではコードの変更内容のみを出力するようにした。その結果として、変更内容を適切に適用するために一定の知識が必要になってしまった。例えば、HTML コード辺が返ってきたときに何処に挿入するべきかは自分で判断する必要が有る。JavaScript のイベントハンドラも、同一のものが複数作られたり、同じ要素がある場合は変数で参照されたかと思えば直接クエリセレクタで参照されたりと、一貫性が無かった。コードの品質と効率を保つには、これらの問題に気付き修正できる能力が必要だ。

ただ、時間やトークンの制限が許すなら、コードの変更内容ではなく更新されたコード全体を出力することで、この問題はある程度解決できそうだ。あるいは、GNU patch 形式等でコードブロックの変更行を指定させるようなプロンプトが上手く実現できれば、変更内容を自動的に適用することができる。

一部指示を理解してもらうことが難しい

例えば、最終時間行の左下付近にマウスを近付けたときに新規行を追加する [+] ボタンと現在の時間行を削除する [×] ボタンを排他にしてほしい、という要求は、理解してもらうまでに相当数の試行錯誤が必要だった。最終的には、「([+] ボタンを追加されている時に付与される)このクラスが指定されていれば [×] ボタンを抑制する」という指示に落ち着いたが、これはかなり実装の詳細にまで踏み込んでいて、プログラムの素養が全く無ければこの指示を思い付くことは少々難しいだろう。

プロンプトの妥当性は自分で担保する必要がある

今回は上記プロンプトの項でも述べたように、コードには Web 標準のみを使うよう指示した。だが、これ以上複雑な処理を実現しようと思ったら、React 等のフレームワークを活用した方が良いだろう。当然ではあるが、ChatGPT は与えられたプロンプトの妥当性を(基本的には)疑わない。そのプロンプトの方向性が正しいかどうかは自分で判断する必要が有るし、そのためには一定の技術的知見が必要だ。

今後の展望

言いなりプログラミングはそれなりに楽しかったものの、一旦ここで打ち止めにするつもりだ。

成長し続けるコードに変更を適切に適用する労力を考えると、より精度の高い変更内容を半自動的に適用可能な形式で出力できるよう、プロンプトを改良した方が良い。また、保守性の高いコードを生成するためには、利用するフレームワーク等、プロンプトの前提となる適切な技術選定も必要だ。ソフトウェアの実装を人工知能に頼りきるためには、自分のプロンプトエンジニアリング力をもっと高めなければならない。

そして何より、実装方法が見えている問題について ChatGPT への入力をこねくり回すのは効率が悪いし、楽しくない。自分が分かる所、書きたい所は自分で書く方が早いし、楽しい。今後は、困った時に人工知能の手を借りながら、最後は自分の力でコードを書いていきたい。つまらない結論ではあるが、結局のところ人工知能と人間の良いとこ取りが現実的かつ最適な解なのだ。