こんにちは、ばやしです。
皆さんは生成AIを活用していますか?
私は趣味でも仕事でも活用しています。
画像生成AIや音声のスタイル変換、ストーリーテリングなど色々と試していますが、今回はコーディングにおける生成AIの活用について、AIの奴隷を自称している私目線でどんな使い方をしているかなどを紹介します。
※生成AI周りは日々進化しているので情報が古くなっているor間違っている可能性があります。内容を鵜呑みにしないようにしてください。
※サムネイルの背景はDreamStudioで生成したものです。
目次
コーディングに活用できるものとしては汎用型のAIチャットボットと、プログラミング補助に特化したAIツールの2種類が挙げられます。
汎用タイプはChatGPT、Google Bard、Bing AI、特化タイプはGithub Copilot、Amazon CodeWhisperer、Tabnineなどがありますね。(Bing AIとGithub CopilotはChatGPTと同じOpenAIとの共同開発、TabnineもGPT-2ベースのモデルを使用している?)
性能はChatGPT(GPT-4)が抜けているように見え、シェアもChatGPTが優位ではないでしょうか。
独占状態になるのはあまり好ましくないと思うので他のオープンソースプロジェクトなどにも期待したいですが、莫大な学習データと莫大な演算装置が必要なためか、同等の性能を実現するのは中々難しいのかもしれません。
今までは分からない事があったらGoogle検索するor人に聞くという流れが普通でしたが、その過半数がChatGPTに置き換わりました。コードの提案だけでなく、仕組みの説明なども出力してくれるのがすごくよいです。
たまにうまく動かないコードを提案してくる場合もありますが、自分で直すなり修正を依頼するなりで対処しています。
以前はGithub Copilotも使用していましたが、ChatGPTで間に合う事が多かったので現在はChatGPTのみを使用しています。(Copilot Xが正式にリリースしたら乗り換えを考えています)
主に下記のような使い方をしています。
※例はすべてGPT-4版ChatGPTを使用。出力されたコードが全て正常に動くかどうかはまでは確認していないので悪しからず。
入力例:
「get-content」というIDが設定されているbuttonタグがクリックされた時に、
クリックされたbuttonタグに設定してあるdata-url属性の値(URL)を取得し、
そのURLのページのbodyタグ内の要素をすべて取得し現在のページの「content-wrapper」
というIDの要素の中に展開するコードをVanilla JSで書いて。
出力例:
以下のJavaScriptコードはあなたが述べた動作を行います。
しかし、実際の動作はブラウザのセキュリティ設定や
CORS (Cross-Origin Resource Sharing) 設定により異なる場合があります。
------------------------
// get-contentボタンを取得
var button = document.getElementById('get-content');
button.addEventListener('click', function(e) {
// data-url属性の値を取得
var url = e.target.getAttribute('data-url');
// Fetch APIを使用してURLからデータを取得
fetch(url)
.then(response => response.text())
.then(data => {
// レスポンスデータからbodyタグ内の内容を抽出
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(data, 'text/html');
var bodyContent = htmlDoc.body.innerHTML;
// content-wrapper要素を取得し、内容を更新
var contentWrapper = document.getElementById('content-wrapper');
contentWrapper.innerHTML = bodyContent;
})
.catch(err => {
// エラーハンドリング
console.error('Fetch Error: ', err);
});
});
------------------------
上記のコードは、指定したURLからHTMLを取得し、
そのHTMLのbodyタグ内のすべての要素を現在のページの"content-wrapper"というIDの要素に挿入します。
しかし、このコードが期待通りに動作するかは、いくつかの要素に依存します。
たとえば、要求されたURLが同一オリジンポリシーやCORSの要件を満たしていなければ、
ブラウザはセキュリティ上の理由から要求をブロックします。
この問題を回避するためには、サーバ側で適切なCORSヘッダを設定するか、
またはリバースプロキシを使用するなどの方法があります。
しかし、これらの方法はどちらもサーバ側の変更を必要とするため、ブラウザのみで行うことはできません。
こちらの意図をしっかり理解してくれていて、CORSの注意までしてくれています。
やや古い情報を出力してくることがあるので必要に応じてドキュメントを読ませたりWebブラウジングさせると良いと思います。(ChatGPT Plusのみ)
「書き方が古い」と伝えるだけでちゃんと書いてくれる場合もあります。予め最新の情報に基づいて出力するようなプロンプトを与えておいても良いかもしれません。
入力例:
const variable = 10;
variable = 1;
console.log(variable);
このコードでエラーが発生しました。エラーの理由を教えてください。
出力例:
JavaScriptでは、`const`キーワードを使用して宣言した変数は再代入できません。
したがって、`variable = 1;`の行でエラーが発生します。
このエラーは「TypeError: Assignment to constant variable.」というメッセージで
表示されるでしょう。
JavaScriptで変数を宣言するための3つのキーワード
(`var`、`let`、`const`)の違いを以下にまとめます。
`var`: 関数スコープまたはグローバルスコープの変数を宣言します。再代入が可能です。
`let`: ブロックスコープの変数を宣言します。再代入が可能です。
`const`: ブロックスコープの変数を宣言しますが、一度値が割り当てられるとそれ以降その値を変更することはできません。
このケースでは、`variable`の値を再代入したい場合は`let`キーワードを使用して変数を宣言することを推奨します。
------------------------
let variable = 10;
variable = 1;
console.log(variable); // Output: 1
------------------------
このコードはエラーなく動作し、最終的な出力は1になります。
エラー文言はChromeのものとは違っていますが、内容は正しそうですね。
聞いていないのに変数宣言の方法の概要まで説明してくれていてホスピタリティが高いです。
プラグイン「Link Reader」を使用。
入力例:
https://ja.splidejs.com/guides/options/
https://ja.splidejs.com/guides/getting-started/
https://ja.splidejs.com/guides/structure/
上記のURLを参照して、splide.jsでフリードラッグの横幅500px固定のスライダーを設置する方法を
説明してください。
出力例(※長いため終盤のJS箇所のみ抜粋します):
import Splide from '@splidejs/splide';
new Splide('.splide', {
width: '500px',
drag: true,
}).mount();
フリードラッグというワードを理解していないのか「drag: true」になってしまっています(正しくは「drag: "free"」)が、概ね正しいです。
情報量が多いと、目的に合致した情報を見つけるまでに時間がかかったりするので、かなり便利な使い方です。リンク先を読ませたり、ブラウジングさせたりが可能になったことがとても大きいです。
尚、無料版でもGSAPなど有名なライブラリであれば答えてくれることが多いです。(情報は古い)
適当に書きなぐったコードをリファクタリングしてもらったりが可能です。
入力例:
var fileNamesByExtension = {};
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) { var image = images[i]; var imageUrl = image.src; // URLから拡張子を取得 var extension = ''; var dotIndex = -1; for (var j = imageUrl.length - 1; j >= 0; j--) {
if (imageUrl[j] === '.') {
dotIndex = j;
break;
}
}
if (dotIndex !== -1) {
extension = imageUrl.substring(dotIndex + 1).toLowerCase();
}
var fileName = '';
var slashIndex = -1;
for (var k = imageUrl.length - 1; k >= 0; k--) {
if (imageUrl[k] === '/') {
slashIndex = k;
break;
}
}
if (slashIndex !== -1) {
fileName = imageUrl.substring(slashIndex + 1);
}
if (!fileNamesByExtension.hasOwnProperty(extension)) {
fileNamesByExtension[extension] = [];
}
fileNamesByExtension[extension].push(fileName);
}
console.log('画像のURLと拡張子ごとのファイル名:');
console.log(fileNamesByExtension);
上記のコードをなるべく短いコードに書き直してください。
ページ内の画像URLを取得してファイル名を拡張子別で配列に格納するコードです。
出力例:
あなたの要求に応じて、上記のコードをより短く書き直しました。
以下のコードでは、`Array.prototype.forEach`を使用してループを処理し、
JavaScriptの組み込み関数を使用してURLからファイル名と拡張子を取得しています。
------------------------
// 画像の拡張子ごとにファイル名を格納するオブジェクト
var fileNamesByExtension = {};
// 画像要素を取得して拡張子ごとに分類
Array.from(document.getElementsByTagName('img')).forEach(image => {
let url = new URL(image.src);
// URLから拡張子とファイル名を取得
let [fileName, extension] = url.pathname.split('/').pop().split('.');
// 拡張子ごとにファイル名を格納する配列を初期化
fileNamesByExtension[extension] = fileNamesByExtension[extension] || [];
// ファイル名を配列に追加
fileNamesByExtension[extension].push(fileName);
});
// 結果を出力
console.log('画像のURLと拡張子ごとのファイル名:', fileNamesByExtension);
------------------------
ここで`Array.from()`は、HTMLCollectionをArrayに変換して`forEach`を使えるように
するために使用しています。
また、`URL`オブジェクトを使用して、URLからパス名を取得し、その後、
`split`関数でパス名をファイル名と拡張子に分割しています。
そして、拡張子ごとにファイル名を格納する配列を初期化し、ファイル名をその配列に追加しています。
最後に、拡張子ごとのファイル名を含むオブジェクトをログに出力しています。
このコードは動作しますが、修正前のコードではファイル名に含まれていた拡張子が修正後は含まれなくなっています。
修正するように依頼した所、正しく修正してくれたので大きな問題はありません。
弊社はエンタメ系を多く担当しているため、主にゲームやアニメのサイト製作にあたって仮の音声素材が欲しくなる時があります。
そういった場合に、ChatGPT Plusの「Speechki」というプラグインが使えます。
以下の文をspeaker_id=850で読んでください。
弊社イロコトをただの「Web制作会社」と言ってしまうと語弊があるかもしれません。
なぜなら弊社の手掛ける事業範囲は、エンタメ系のプロモーション企画を中心として、
それに伴うサイト運用・写真撮影・動画編集・生放送制作・広告代行・SNS運用など多岐に渡っているためです。
出力された音声がこちら。
もうAIで何でも出来てしまいますね。凄い時代になりました。
ChatGPTに何かを直接計算させることは無いですが、文章の論理的な構造を正しく理解してくれるかどうかは重要です。ちなみに上記の画像は間違っています。
「太郎は時速3kmで歩きます。太郎が10km離れた書店に向かった時、太郎は10分間歩き、残りは時速100kmの電車を使用しました。電車の乗車時間を求めなさい。」
というテキストを汎用対話型AIに入力してみます。
私の算数能力が小学生未満でなければ、5.7分(整数でないのは置いておきましょう)が正解なはずです。
太郎が10分間歩いた時の距離は、時速3km × (10分 / 60分) = 0.5km です。
残りの距離は、10km - 0.5km = 9.5km です。
電車の速度は時速100kmなので、電車の乗車時間を求めるには、
9.5km ÷ 100km/h = 0.095時間 = 5.7分 かかります。
したがって、太郎は電車に乗っている時間は約5.7分です。
合っていますが、間違った回答も結構出力します。
太郎が10分間歩いた場合、彼は時速3 kmで歩いているので、進む距離は以下の通りです:
太郎が歩くのに要した時間は、距離を速度で割ることで求めることができます。
歩いた時間 = 距離 / 歩行速度 = 10 km / 3 km/h ≈ 3.33 時間
10 分は、時間に換算すると 10/60 = 1/6 時間です。
残りの距離は、10 km - 歩いた距離 = 10 km - 10 km = 0 km です。
残りの距離を電車の速度で割ると、電車に乗る時間を求めることができます。
電車の乗車時間 = 残りの距離 / 電車の速度 = 0 km / 100 km/h = 0 時間
したがって、太郎は電車に乗るためには0時間かかります。
何もかも違いますね。8割くらいはこんな回答が来るのでGPT-3.5に論理的な整合性は期待しないほうが良さそうです。
まず、太郎が歩く距離を計算しましょう。太郎は時速3kmで歩き、
その速度で10分歩いたとのことです。時速を分速に変換すると、
3km/60分 = 0.05km/分となります。したがって、10分歩いた距離は0.05km/分 × 10分 = 0.5kmです。
次に、この歩いた距離を全体の距離(10km)から引くことで、
電車で移動する必要がある残りの距離を計算します。10km - 0.5km = 9.5kmです。
電車の速度は時速100kmなので、この速度で9.5km移動するのにかかる時間を計算することが
求める乗車時間となります。時間=距離/速度の公式を用いると、
9.5km ÷ 100km/時間 = 0.095時間となります。
この時間は時間単位なので、分単位に変換します。0.095時間 × 60分/時間 = 5.7分となります。
しかし、実際の時間計算では分単位は整数であるべきなので、
これを四捨五入すると、おおよそ6分となります。
したがって、電車の乗車時間は約6分と求められます。
合っています。説明が一番詳細ですね。四捨五入までしてくれています。また、何度生成しても5.7分と示してきます。
より高度な計算をしたい場合にプラグインを使用できる点も強力です。
太郎が歩いた距離は、10分間 x 3km/時 = 0.5km です。
したがって、太郎が電車で移動した距離は、10km - 0.5km = 9.5km です。
電車の乗車時間は、9.5km / 100km/時 = 0.095 時 = 5.7分 です。
したがって、答えは5.7分です。
合っていますが、誤った回答も出力します。正答率はGPT-3.5と同程度かやや優れているかも?程度です。
太郎は時速3kmで歩き、10分間歩いたので、太郎は0.5km歩きました。
そのため、太郎は電車で9.5km移動しました。
電車の速度は時速100kmなので、電車に乗る時間は
9.5km ÷ 100km/h = 0.095h、つまり約5.7分です。
合っています。
尚、「よりバランスよく」に設定すると全く見当違いな回答ばかり出力してくるので、整合性が必要な場合は「より厳密に」設定で行う必要がありそうです。
ここまで主に汎用タイプの対話型AIについて記載してきましたが、特化型のツールもいくつか使用してきたので雑感を記載します。
https://docs.github.com/ja/copilot/quickstart
「もうこれで良いんじゃないか?」と思える程度には色々な事に対応できますが、ChatGPT (GPT-4)のほうが性能だけで言えば上だと思います。拡張機能という形でプログラミング用のUIを提供している点ではChatGPTより良いかもしれませんが、ChatGPTの拡張機能も存在するので五十歩百歩でしょうか。
挙げた3つの中では、最も日本語での入力に対して適切に反応してくる感触があります。
Copilot Xはまだ検証できていませんが、チャット形式で質問できるようになったのは便利そうですね。
内部的にはほぼGPT-3〜GPT-4ですので、UIやGithubによるチューニングにどれだけ価値を見いだせるかになりますね。
https://aws.amazon.com/jp/codewhisperer/
個人利用であれば無料で使えるという太っ腹なツールです。Amazon関連のソースコードでトレーニングされているためか、AWS系に強いようです。
試用した際は無印Github Copilotと似た使用感だと思いました。ただ、対応言語が限られていて、Copilotほどの融通は効かないと思われます。とはいえ主要な物には対応しているので大きく劣るという訳では無いです。
また、日本語でのコード生成もある程度可能です。
2019年頃からあるコード補完ツールですね。この中では最先発といえます。
1行のみのオートコンプリートであれば無料で使えます。
Pro版であればCopilotのように指示を入力してコードを書かせたりできますが、私が試した段階では指示の理解度がやや低いように感じました。(書き方が悪かった可能性はあります。また、日本語入力は実用的ではありませんでした。)
オフラインで動作させたり、自分のコードで微調整を行ったり出来るようですので、部分的には上記2つより優れているかもしれません。公式ブログで他サービスとの比較を投稿しているので、参照してみてください。
上記3つを試した限りでは、特にこだわりが無ければCopilot、AWS環境をよく使う・無料で使いたい等であればCodeWhisperer、社内のコードでのチューニングやオフライン稼働などを使いたければTabnineという印象でした。どのようなプロジェクトでどのような補助を求めているかによって変わってくると思いますし、出来れば実際にいくつか試用して感触を確かめることをおすすめします。
生成AI自体の問題点については有識者にお任せするとして、コーディング補助として使うにあたっての思い当たる問題点を挙げてみます。
セキュアさが重要な実装を行う場合は全面的に頼る(出力コードをそのまま使う)のはやめたほうが良いでしょう。CodeWhispererなどセキュリティスキャンを行えるツールもあるので、そういった機能を活用することである程度リスク回避できそうです。
私がChatGPTを使う際はそのまま入力することは避けています。
基本的には問題ないと思いますが、入力が学習に使用されている場合はそのまま出力されることは無いと分かっていつつも心情的に少し怖いですね。
ChatGPT・Github Copilotの場合は学習に使用しないようにする設定がありますのでそちらを有効にすると良いでしょう。
GPT-4が出てきて、それなりに複雑なコードでもまともに動くものを提示してくるようになったので、より活用できる範囲が増えました。
これは当人の学習モチベーションに依存すると思っていますが、調べる時間をある程度短縮出来るのでむしろより効率的に学習できるのではないかと思います。
もちろん頼りすぎで何も考えずに使うのは良くないですね。
社内ではコーダー分科会を開いており、その場では生成AIの話題も話しています。まだ人によって使い方はバラバラですが、今後は全社的に活用を推進していく方向で考えており、コーディング補助に限らず生成AIによる恩恵を案件で有効活用するアイデアを常に模索していきます。既にコーダー以外でも、デザイナーの方でサイト内のキャッチコピーのアイデア出しに活用していたりもしています。
AIを活用することで作業を効率化できたり、今まで出来なかったことが出来るようになると良いですね。それではまた。
ばやし
WEBコーダー。お絵かきと音ゲーと写真撮影(旅行)が趣味。 最近はAIに脳を破壊されています。