Chat-GPTでJavascript+Canvasのコードを生成するワークショップを開催しました
最近は知人の会社や、取引先の開発チームに頼まれて、デザインやコーディングでのAIやChat-GPTの活用方法のワークショップをやっています。私はChat-GPTやGithub Copilotが登場し、わりとすぐに開発に導入して活用していました。Github Copilotはコードの補完的な使い方もできてかなり重宝しますね。非常に便利ですべての開発者が導入すればいいのにと思いますが、まわりでは意外と使っていない印象です。
それでも興味をもっている人も多く、開発者本人というよりはマネージャーからチームにレクチャーしてくれないかと相談を受けます。
先日も知人の某ゲーム会社のマネージャーに頼まれて、ウェブの内製チーム向けにChat−GPTでコーディングをするワークショップをしてきました。その内容を少し紹介します。
まず最初にチーム内でやりたいけどやれていないことを聞きました。今回のウェブ内製チームでは、 WebGLやCanvasを使った表現をもっとやれるようになりたい、という声がありました。やれていない理由としては、難しそう、あまり情報がない、教えてくれる人がいない、など様々でした。
そこで今回のワークショップでは、ゼロベースで前知識なくChat-GPTを使ってどこまでCanvasのアニメーションを作れるか、というのをやりました。
Chat-GPTとの会話で心がけること
最初にChat-GPTとの会話の基本的な部分の説明をしました。AIと会話をするうえで重要なのは、論理的な指示をこころがけるということです。AIは人間と同じで、インプットのイメージが具体的であればあるほど精度の高い回答を返してくれます。ある程度こちらの意図を汲み取ってくれるとはいえ、倫理的にちぐはぐだと回答も的を得ていないものになってしまいます。
最終的なアウトプットをイメージする
そこでまず、何を作りたいかを明確にします。今回はCanvasをつかって簡単なテキストアニメーションを作ることにしました。具体的には、設定した文字列をタイプライターのように1文字目から順番にカタカタと表示をするようなアニメーションを作ります。
シンプルなプロンプト
最初に簡単なプロンプト例でコードを生成します。
Canvasに1文字ずつ文字を表示するアニメーションを実装するコードを提案してください。
生成されたコードをCodepenで実行してみます。
kおんhttps://codepen.io/masahiro8/pen/dyrOVwM?editors=1010
canvasに順番に文字を表示してくれました。これはこれでアニメーションになっているのですが、こちらが意図したものとは少し違います。プロンプトに説明が足りないからですね。ですので、もう少し詳しく説明をしてあげましょう。
論理的に説明したプロンプト
アニメーションをより具体的に説明します。さらに再生開始ボタンを追加しました。
javascriptとcanvasで文字のアニメーションを作成します。
コードを提案してください。要件は以下になります。
- 設定した文字を、1文字目から順番に画面に表示をします。
- 文字が表示され0.2秒後に次の文字を隣に表示します。
- 再生ボタンをクリックするとアニメーションを開始します。
具体的に数字で指示をだすと意図を汲み取ってくれます。
- 文字が表示され0.2秒後に次の文字を隣に表示します。
Codepenで生成されたコードを実行してみます。
タイプライター風なテキストアニメーションができました。ちなみにjavascriptのコードは生成されたものをCodepneにコピペしただけで、一切編集はしていません。
ここまでコードを一切把握していなくてもCanvasの実装がわからなくても、意図したアウトプットができました。ここでもうひとつ重要なことがあります。今回は1発で問題なくアウトプットされましたが、往々にしてうまくいかないことのほうが多いです。複雑であればあるほど1発でアウトプットをするのは難しいので、ここから対話をしながら調整をしていきます。
Chat-GPTは能力の高いコーダーだが、問題が起きたときに人間の能力が問われる
さらに意図した内容かどうかとは別に、そもそもコーディングの文法が違うことや、閉じカッコが漏れているなんていうケアレスミスも結構起こります。AIもケアレスミスはするんです。
ですので、より複雑で実用的なコードを生成してもらうためには、指示する人間もコードをある程度レビューする能力が求められます。ここが大きなポイントで、扱う人間の能力を超えて複雑なものをアウトプットしても、それを評価できる能力を人間がもっていないと問題が起きたときに対処ができません。
例えば先ほど、「ここから対話しながら調整をしていきます」と記載しましたが、複雑になってくると、ある程度コードが読めないとピンポイントで間違いを指摘できない箇所の割合が増えてきます。また、ライブラリを使ったコードが提示されると、ライブラリの把握もできていないといけないですし、提示されたコードを評価するためにはどんどん幅広い知識を必要とされてきます。
指示する人間のクリエイティビティやスキルが重要
ワークショップでは、ここまで生成したコードに機能を追加していくプロンプトを書いていきます。ワークショップ参加者に追加したい機能をあげてもらいました。そのなかで「canvasのアニメを動画にする」という案があがりました。参加者は誰もやり方がわからないのでこの案を採用し、生成することにしました。
再生したcanvasアニメーションを動画に変換をしたいです。コードを提案してください。
ここで都合よく問題が起こります。生成されたコードがCodepenで動きません。以下が生成されたコードです。
このコードは意図した通りに動作しません。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Text Animation to Video</title>
<script src="https://cdn.rawgit.com/muaz-khan/RecordRTC/master/RecordRTC.js"></script>
<script src="https://cdn.rawgit.com/antimatter15/whammy/master/whammy.js"></script>
<style>
canvas {
border: 1px solid #000 ;
}
</style>
</head>
<body>
<canvas id="textCanvas" width="400" height="100"></canvas>
<button onclick="startAnimation()">再生</button>
<button onclick="convertToVideo()">変換</button>
<script>
const canvas = document.getElementById('textCanvas');
const context = canvas.getContext('2d');
const text = "Hello, World!";
const interval = 200; // アニメーション間隔(ミリ秒)
let index = 0;
let animationInterval;
let recordedBlobs = [];
function animateText() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillText(text.charAt(index), 10, 50);
index++;
if (index < text.length) {
// 次の文字を表示する前に一定時間待機
animationInterval = setTimeout(animateText, interval);
}
}
function startAnimation() {
// アニメーションが既に実行中であればクリア
if (animationInterval) {
clearTimeout(animationInterval);
}
// インデックスをリセットしてアニメーション開始
index = 0;
animateText();
}
function convertToVideo() {
const canvasStream = canvas.captureStream();
const recordRTC = RecordRTC(canvasStream, {
type: 'canvas',
disableLogs: true
});
recordRTC.startRecording();
startAnimation();
setTimeout(() => {
recordRTC.stopRecording(() => {
const videoBlob = recordRTC.getBlob();
recordedBlobs.push(videoBlob);
const superBuffer = new Blob(recordedBlobs, { type: 'video/webm' });
const video = document.createElement('video');
video.src = window.URL.createObjectURL(superBuffer);
video.controls = true;
document.body.appendChild(video);
});
}, interval * text.length);
}
</script>
</body>
</html>
RecordRTCとWhammy.jsというライブラリを使用しています。アニメーション自体も最初の意図と違うものでしたのでそもそもそこも問題です。Chat-GPTでは修正したはずの実装がデグレすることも多々あります。ただここでは追加した動画にする機能の部分にフォーカスして修正をしていきます。
ここで対応する方法としては、
- Chat-GPT自体にデバッグさせてコードを修正する
- 実装方法そのものを見直す
になります。とりあえずChat-GPTに修正をしてもらいます。
変換ボタンを押しても変換できません。コードを修正してください。
すると、以下のようにChat-GPTは回答しました。
実装イメージができていればそれをプロントに盛り込む
今回Chat-GPTが提案するMediaRecorderAPIはJavascriptの標準のAPIです。あるていどJavacsrciptの経験がある開発者であれば、canvasを動画にする場合は真っ先にMediaRecorderAPIが思い浮かびます。経験のある開発者が実装する場合は、先程の外部のライブラリよりもMediaRecorderAPIを先に試すはずです。
このあたりの何を選択するかをChat-GPTにゆだねるとゆらぎがあります。そういう意味でもある程度の正解のイメージができているのであれば、最初からプロンプトに実装方法を盛り込んでおくことで、精度高くコードを生成してもらうこともできます。
指示する人間の実装イメージに対する引き出しの多さが、Chat-GPTの精度にも影響するので、先に少しふれたコードを評価できる人間ほど論理的に的確に実装イメージをChat−GPTに伝えることができます。
https://codepen.io/masahiro8/pen/ZEPBjoY?editors=0011
もう少し具体的にイメージを伝えます。
canvasの文字アニメーションをmediaRecorderAPIでwebmフォーマットで録画します。以下を考慮してください。
- 再生ボタンを押すと同時に録画を開始します
- 全ての文字のアニメーションの再生が終わった1秒後に録画を停止します
- 録画を停止したあとファイルをダウンロードします
おおむね実装できていますが、ダウンロードした動画を再生すると真っ黒です。Canvasをわかっていれば原因はわりとすぐに検討がつくのですが、ワークショップ参加者には経験が少なくわかりませんでした。そこでChat-GPTに修正を依頼します。
ダウンロードした動画を再生すると画面が真っ黒です。原因を特定して修正してください。
Chat-GPTの回答
それっぽい回答をしていますが、Chat−GPTは間違えています。原因は全く別のところにあります。こうなると経験の少ないエンジニアはネットを調べてもそれっぽい解決策も見つからず、この問題を解決するのが難しくなってきます。
この不具合は実は単純で、Canvasの背景色を設定していないために真っ黒になっていて、文字も黒いので何も描画されていないように見えているだけです。ですので、Canvasの描画で最初に背景を白で描画してあげれば解決します。実はとても単純なミスなんですが、わからない人には原因にたどりつくまでに時間がかかります。
ここでまた問題が発生します。プロンプトを修正し、毎回Canvasの背景に白を描画する指示を入れますが、意図したコードがあがってきません。いろいろ試すのですが、どうも意図がうまく伝わらないので、ここは手動でコードを修正します。こういうことも多々あります。どうしても言語では伝わりにくい表現もあります。こういう場合にはやはり的確なコードをかけるスキルを持っていると問題をすぐに解決できます。
最終的に以下の動画ができました。
今回のワークショップでは、Chat-GPTに意図が伝わらなかったり、回答自体が間違っていたりと、起こり得る問題をひと通り発生しました。ワークショップの中では問題が起こることが重要で、問題解決するためにプロンプトを変えたり、自分で実装してみたりを繰り返すことで経験値があがります。とてもいい経験になるワークショップだったのではないかと思います。
この記事が気に入ったらサポートをしてみませんか?