この記事で行なっていること
凄すぎて”ズキズキワクワク"が止まりません
はじめに
ついこの間、ChatGPTは2022年1月までの情報を学習した、というい発表がありましたが、さらに今回のアップデートで 画像解析機能(GPT-4V) が追加され、アップロードした画像を使った新たなタスクの実行が可能になってます。そして、それが凄すぎます
衝撃的な投稿
まずはこちらの衝撃的な投稿をご覧ください。
動画は自転車の画像と共に「サドルを下げる手助けをしてください」で始まります。
ChatGPTからレコメンドが返ってきますが、それに対して、質問者は追加で
- ポイントになりそうな部分を拡大してアップロード
- マニュアルと自分の持っているツールの写真もアップロード
します。
その結果、その質問者は、サドルを下げることに成功!そんな内容です。
自分の環境で、画像解析機能(GPT-4V)を使えるのか?
さて、画像解析機能(GPT-4V)が自分の環境で使えるのでしょうか?
はい、ChatGPTの入力フィールドをご確認ください。
このアイコンが表示されていれば OK です。
もしアイコンが表示されない場合は、ChatGPT-4のオプションとして Default が選択されていることも確認してください。
こちらのYouTube記事が参考になると思います。
2023/10/5時点では、まだ全員にこの機能が解放されている訳ではなさそうです。まだの方は、楽しみにお待ちください。
早速電卓アプリを作ってみる
当記事は、こちらのXのポスト記事に触発されました。
あまりの衝撃に、『自分で試してみないと気が済まない』ということで、早速試してみました。
STEP1: 『あなたは、HTML, CSS, Javascriptのスペシャリストです。この電卓プログラムを再現してください』
iPhoneアプリである計算機のスクリーンショットに加え、『あなたは、HTML, CSS, Javascriptのスペシャリストです。この電卓プログラムを再現してください。』というプロンプトを入力します。
生成されたコード(HTML+JavaScript)を実行してみると、こんな感じです。
あれ?見た目が全然ちがうのですが、計算機として使えそうです。
2 + 3 を実行してみると、ちゃんと5
と出力されます。
ただし、計算結果をクリアするボタンがありません。
STEP2: 『計算結果をクリアするキーがありませので追加してください』
早速プログラムの修正依頼をします。『計算結果をクリアするキーがありませので追加してください』
生成されたコード(HTML+JavaScript)を実行してみると、こんな感じです。
ACキーが追加されました。計算結果もこれでクリアできるようになりました。
STEP3:『生成された電卓の見た目をCSSを使った再現してください』
やはり当初の目的は計算機アプリの再現ですので、見た目にもこだわりたいです。
そこで、プログラムの修正依頼をします。『生成された電卓の見た目をCSSを使った再現してください』
生成されたCSSを組み込んで実行してみると、こんな感じです。
だいぶ近づきました。
ただちょっと計算結果の枠がはみ出しているところが気になります。
STEP4:『計算結果の表示欄が電卓の幅をはみ出ています。はみ出さないように修正してください』
早速プログラムの修正依頼をします。『計算結果の表示欄が電卓の幅をはみ出ています。はみ出さないように修正してください』
提案された修正内容を組み込んで実行してみると、こんな感じです。
バッチリです。
完成したと思い、色々と計算してみると、まだ、計算機としてのロジックが正しくないことがわかりました。
例えば、このような計算をさせると計算結果が正しくありません。
(生成されたアプリでの計算結果)
2 x 3 + 4 x 5 = 20
(正しい計算結果)
2 x 3 + 4 x 5 = 26
STEP5:『四則演算ルールを守った計算結果が出力されるように、Javascriptのロジックを見直してください』
早速プログラムの修正依頼をします。『四則演算ルールを守った計算結果が出力されるように、Javascriptのロジックを見直してください』
提案された修正内容を組み込んで実行してみると、正しく動作するようになりました。
(生成されたアプリでの計算結果)
2 x 3 + 4 x 5 = 26
(正しい計算結果)
2 x 3 + 4 x 5 = 26
STEP6:『数値演算ライブラリを使用して、Javascriptのロジックを見直してください。例えば、9.19+10の答えは19.19です』
コメント欄にて、「浮動小数点数演算の誤差対策までは行われていないようですね。」というコメントをいただきました。テストが甘かったです。
早速プログラムの修正依頼をします。『数値演算ライブラリを使用して、Javascriptのロジックを見直してください。例えば、9.19+10の答えは19.19です』
提案された修正内容を組み込んで実行してみると、正しく動作するようになりました。
(生成されたアプリでの計算結果)
9.19 + 10 = 19.19
9.19 - 10 = -0.81
9.19 * 10 = 91.9
9.19 / 10 = 0.919
(正しい計算結果)
9.19 + 10 = 19.19
9.19 - 10 = -0.81
9.19 * 10 = 91.9
9.19 / 10 = 0.919
iOSアプリである計算機を忠実に再現できたわけではありませんが、今回の実験は以上で終了とさせていただきます。
自動生成されたプログラムに対しても、やはり、しっかりとしたテストが必要ですね。
おわりに
非常にシンプルな計算機アプリではありますが、スクリーンショットと自然言語を使って、1つのちゃんと動作するアプリの作成に成功しました。
何が凄いかって、視覚情報を自然言語で書き起こす手間が省けました。手間が省けたとさらりと書きましたが、もし、自然言語を使ってスクリーンショットの内容を説明するとなったら相当なワークロードがかかります。いやいや、至難の業です。
GPT-4Vには、何か大きな可能性を感じます、驚きました、そして、凄すぎてズキズキワクワク止まりません
最後に、スクリーンショットと260文字程度のプロンプトにより生成されたHTML+CSS+JavaScriptを載せておきますね。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>シンプルな電卓</title>
<style>
.calculator {
width: 250px;
height: 400px;
background-color: #222;
border-radius: 20px;
margin: 50px auto;
padding: 20px;
box-shadow: 5px 5px 10px rgba(0,0,0,0.5);
}
.display {
width: calc(100% - 30px); /* paddingを考慮して幅を調整 */
padding: 15px;
margin-bottom: 10px;
background-color: #000;
color: #FFF;
font-size: 24px;
border: none;
border-radius: 10px;
text-align: right;
overflow: hidden; /* これを追加 */
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.btn {
padding: 15px;
border-radius: 50%;
background-color: #555;
color: #FFF;
font-size: 18px;
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #444;
}
.btn-operation {
background-color: #FFA500; /* オレンジ色 */
}
.btn-operation:hover {
background-color: #FF8C00; /* 暗めのオレンジ色 */
}
.btn-equals {
background-color: #FF4500; /* 赤みのあるオレンジ色 */
}
.btn-equals:hover {
background-color: #FF6347; /* トマト色 */
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/big.js/6.1.1/big.min.js"></script>
</head>
<body>
<div class="calculator">
<input type="text" class="display" id="display" disabled>
<div class="buttons">
<button class="btn" onclick="clearAll()">AC</button>
<button class="btn" onclick="appendToDisplay('7')">7</button>
<button class="btn" onclick="appendToDisplay('8')">8</button>
<button class="btn" onclick="appendToDisplay('9')">9</button>
<button class="btn btn-operation" onclick="setOperation('/')">/</button>
<button class="btn" onclick="appendToDisplay('4')">4</button>
<button class="btn" onclick="appendToDisplay('5')">5</button>
<button class="btn" onclick="appendToDisplay('6')">6</button>
<button class="btn btn-operation" onclick="setOperation('*')">*</button>
<button class="btn" onclick="appendToDisplay('1')">1</button>
<button class="btn" onclick="appendToDisplay('2')">2</button>
<button class="btn" onclick="appendToDisplay('3')">3</button>
<button class="btn btn-operation" onclick="setOperation('-')">-</button>
<button class="btn" onclick="appendToDisplay('0')">0</button>
<button class="btn" onclick="appendToDisplay('.')">.</button>
<button class="btn btn-equals" onclick="calculate()">=</button>
<button class="btn btn-operation" onclick="setOperation('+')">+</button>
</div>
</div>
<script>
let inputs = [];
let currentInput = '';
function appendToDisplay(value) {
currentInput += value;
document.getElementById('display').value = currentInput;
}
function setOperation(operator) {
if (currentInput !== '') {
inputs.push(currentInput);
inputs.push(operator);
currentInput = '';
}
}
function calculate() {
if (currentInput !== '') {
inputs.push(currentInput);
for (let i = 0; i < inputs.length; i++) {
if (inputs[i] === '*' || inputs[i] === '/') {
if (inputs[i] === '*') {
inputs[i - 1] = (new Big(inputs[i - 1])).times(inputs[i + 1]).toString();
} else {
inputs[i - 1] = (new Big(inputs[i - 1])).div(inputs[i + 1]).toString();
}
inputs.splice(i, 2);
i--; // インデックスを調整
}
}
let result = new Big(inputs[0]);
for (let i = 1; i < inputs.length; i += 2) {
if (inputs[i] === '+') {
result = result.plus(inputs[i + 1]);
} else if (inputs[i] === '-') {
result = result.minus(inputs[i + 1]);
}
}
document.getElementById('display').value = result.toString();
currentInput = '';
inputs = [];
}
}
function clearAll() {
currentInput = '';
inputs = [];
document.getElementById('display').value = '';
}
</script>
</body>
</html>
参考
良い子は真似をしないように