【KDDI Engineer&Designer 2022】AI にブラウザ用の JavaScript のプログラムをいくつか作ってもらった話 ⇒ OpenAI の ChatGPT で生成されたプログラムの解析も少々

## はじめに
こちらは、[KDDI Engineer&Designer の Advent Calendar 2022](https://qiita.com/advent-calendar/2022/engineer-designer) の 2日目の記事です。

当初は、「開発環境を作ろうとしたら、中間証明書周りのエラーが出て対策した話」を題材として考えて準備をしていたのですが、アドベントカレンダーの担当日の前夜に「OpenAI の ChatGPT」が登場して話題になったため、「この流れに乗らねば！」と思って、急遽ネタを変更しました。

仕事の合間の休憩中にちょこちょこ試していた内容を、夜に仕事が終わった後から整理し始めて、ゼロから記事を書き始めるという流れでしたが、本日中に記事を公開できました。

### 【余談】 アドベントカレンダー全体に関する話
2022年のアドベントカレンダーシーズンは、昨日、初日を 2記事同時公開という形でスタートさせたのですが、本日も 2記事公開します（明日からも、しばらく 1日2記事の日々が続く予定...）。
本記事以外の 2日目の記事として、[完走賞ゲットのため小ネタを毎日投稿しようとチャレンジする Advent Calendar 2022](https://qiita.com/advent-calendar/2022/youtoy) に、以下の記事を投稿済みです。

●【完走賞ゲット-2】ボタン搭載小型デバイスで作る簡易ワンボタンキーボード（Maker Nano RP2040 を利用） - Qiita
　https://qiita.com/youtoy/private/e8a9cf35ce16c0fee62e

ハードウェア系・CircuitPython というネタですが、よろしければお読みいただけると嬉しいです！
また、よろしければ、昨日は ｐ5．ｊｓ（JavaScript の描画ライブラリ）ネタを 2記事投稿しているため、それらもよろしければ...

1. [【Processing 2022】@yuruyurau さんの #つぶやきProcessing のプログラムを短縮されてない #p5js のプログラムにした結果と過程の話 - Qiita](https://qiita.com/youtoy/items/263f407021c4b3003365)
1. [【完走賞ゲット-1】p5.js Web Editor で Google Fonts の絵文字の Webフォントを利用する - Qiita](https://qiita.com/youtoy/items/34920d8a49f45653d77a)

さて、余談はこのへんまでにして、本題である「OpenAI の ChatGPT」の話へと戻ることにします。

## OpenAI の ChatGPT に関する話
### OpenAI の ChatGPT とは？
この記事の題材の OpenAI の ChatGPT について、最初に公式のブログへのリンクを掲載してみました。

●ChatGPT: Optimizing Language Models for Dialogue
　https://openai.com/blog/chatgpt/
![ChatGPTに関する公式ブログ記事](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/edba1fc4-b75c-e682-8077-3e6ca47090d9.png)

トップの部分に、このような説明が書かれています。
> ChatGPT: Optimizing Language Models for Dialogue
>
> We’ve trained a model called ChatGPT which interacts in a conversational way. The dialogue format makes it possible for ChatGPT to answer followup questions, admit its mistakes, challenge incorrect premises, and reject inappropriate requests. ChatGPT is a sibling model to InstructGPT, which is trained to follow an instruction in a prompt and provide a detailed response.

機械翻訳で訳すと、こんな感じになりました。

> ChatGPT 対話のための言語モデルの最適化
>
> 我々は、会話形式で対話するChatGPTと呼ばれるモデルを訓練しました。対話形式により、ChatGPTはフォローアップの質問に答えたり、自分の間違いを認めたり、間違った前提に挑戦したり、不適切な要求を拒否したりすることが可能です。ChatGPTはInstructGPTの兄弟モデルで、プロンプトの指示に従い、詳細な応答を行うように訓練されています。 

こちらが文章を入力すると、それに対する回答が文章で返ってきて、対話を行っていける仕組みのようです。

### ChatGPT はソースコードも生成してくれる！
そして、この ChatGPT の返す回答について、話題になっていたことの 1つに「ソースコードやその解説を返してくれる」というものがありました。Twitter で見かけた事例を 1つ例としてのせてみます。

https://twitter.com/yumu19/status/1598289641807175680

これを見た時、「自分も試さねば！」と思って昨晩や今朝方に ChatGPT アクセスしました。
しかし、その際はキャパオーバーで使えないという状況でした。

https://twitter.com/youtoy/status/1598429347320573952

それが今日の午前中に、仕事の休憩中にアクセスしたら試せるようになっていて、休憩時間中で試せそうな内容をまずはやってみました。

### 自分が最初に試した2つの内容
まずは、生成されたソースコードがそのまま使えるものかや、誤りがありそうかどうかが分かるもので試してみたくて、過去に自分がよく扱ったことのある内容を題材に選びました。

具体的には、過去に Qiita の記事もわりとたくさん記事を書いている [Web Bluetooth API（ブラウザで BLE を扱うデバイス系API）](https://webbluetoothcg.github.io/web-bluetooth/) とガジェットが絡む内容にしてみました（ガジェットは、[micro:bit](https://microbit.org/ja/) と [toio](https://toio.io/) で）。

↓過去に書いた記事
●「Web Bluetooth API user:youtoy」の検索結果 - Qiita
　https://qiita.com/search?q=Web+Bluetooth+API+user%3Ayoutoy

↓ChatGPT について、2つほどお試しをした結果のツイート

https://twitter.com/youtoy/status/1598496395006447616

※ この時点では、英語設定でやっていました。

#### micro:bit に関する内容の詳細
上で掲載していたツイートの引用されていたほうから見ていきます。

micro:bit というデバイスが搭載している加速度センサーの値を、Web Bluetooth API を使ってブラウザで取得する、という内容を指定しています。入力した文章は __「Web Bluetooth API を使って micro:bit の加速度センサーの値を取得する JavaScript のプログラム」__ です。

そして、その応答として以下の画像で示した 2つの文章のまとまりと、その間にはさまれる形でソースコードが生成されました。

![ソースコードの前に書かれた内容：micro:bit](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/431f6688-79e2-094c-0914-5e770e75106b.png)

![ソースコードの後に書かれた内容：micro:bit](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/20d2344d-1c7f-6bc6-0635-124797198e3a.png)

以下が、ソースコードをテキストで書き出したものです。

```javascript
// Check if the browser supports the Web Bluetooth API
if ('bluetooth' in navigator) {
  // Request access to the user's Bluetooth devices
  navigator.bluetooth.requestDevice({
    // Filter for devices that support the Accelerometer service
    filters: [{ services: ['accelerometer'] }]
  })
  .then(device => {
    // Connect to the selected device
    return device.gatt.connect();
  })
  .then(server => {
    // Get the Accelerometer service
    return server.getPrimaryService('accelerometer');
  })
  .then(service => {
    // Get the Accelerometer Data characteristic
    return service.getCharacteristic('accelerometer_data');
  })
  .then(characteristic => {
    // Start listening for changes to the Accelerometer Data characteristic
    characteristic.startNotifications()
      .then(() => {
        // Add an event listener to be notified when the accelerometer data
        // value changes
        characteristic.addEventListener('characteristicvaluechanged',
          onAccelerometerDataChanged);
      });
  });
}

// This function is called whenever the accelerometer data value changes
function onAccelerometerDataChanged(event) {
  // Get the accelerometer data value from the event
  var value = event.target.value;
  // The accelerometer data is a 3-axis vector, with X, Y, and Z values
  var x = value.getInt16(0, true); // X axis value
  var y = value.getInt16(2, true); // Y axis value
  var z = value.getInt16(4, true); // Z axis value
  // Do something with the accelerometer data values
  ...
}
```

細かなところを書いていくと、それだけでかなりの文章量になるため、ざっくりと読んでみて思ったことをいくつか箇条書きで書いてみます。

- ソースコードの前後の文章について
   - センサーの値を BLE　の通知の仕組みで取得する話がうまく書かれているように見える
- ソースコードについて
   - ぱっと見では、[アロー関数式](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions)を用いて、Web Bluetooth　API を利用する際の処理の流れが書けているように見える　← 例えば「requestDevice() ＞ getCharacteristic() ＞ getCharacteristic()」という、処理で BLE接続を進めていく部分
   - センサーの値を BLE　で取得する部分で、 `addEventListener('characteristicvaluechanged',
          onAccelerometerDataChanged)` という通知処理用の登録と、そこで指定している関数 `onAccelerometerDataChanged()` の処理が実装されている
   - `onAccelerometerDataChanged()` の中で XYZ の加速度の値を取り出す部分で、 getInt16() を用いた取り出しが行えている（※ そういえば、3軸のどの加速度の値を取得するかを指定してなかったな、とここで思ったりしました）
   - var が多用されているが、const や let を使ったほうが良い
   - micro:bit との BLE接続で必要とされる、サービスとキャラクタリスティクスの固有の UUID（※ [こちらのサイト](https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html) などで確認できるもの）を用いてないため、その部分は書きかえが必要

今日の午前中の遅めの時間から隙間時間でお試しをした内容を、今日中に記事にしあげるため、生成されたコードの細かな検証はできてないですが、実装の元として利用するのには良い感じの内容が生成されているように思いました。

ちなみに、Web Bluetooth API で micro:bit とブラウザの BLE通信を行う話は、昨年以下の記事を書いていたことがあった内容です（※ BLE接続の部分は、アロー関数式ではなく「async/await」での非同期処理を使っていたり、上記のプログラムと差分がありますが）。
●Web Bluetooth API を使い micro:bit とブラウザの間で BLE通信【 #GWアドベントカレンダー 2021/4/30 】 - Qiita
　https://qiita.com/youtoy/items/c98c0996458a21fc1e67

#### toio に関する内容の詳細
今度は、上に掲載していたツイートの本文の部分で書いていた toio に関する内容です。
先ほどの micro:bit の事例と同じ流れで、得られた結果をのせてみます。

入力した文章は __「Web Bluetooth API を使って toio を前に1秒動かす JavaScript のプログラム」__ で、toio が搭載したモーター・タイヤで 1秒だけ前方向に動かすというものです。

![ソースコードの前に書かれた内容：toio](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/514747b7-ddf6-3dbe-ea04-3fb0d14d8bd8.png)

![ソースコードの後に書かれた内容：toio](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/6d98f52d-eef7-c339-6960-1b287ad14e4a.png)


```javascript
// Check if the browser supports the Web Bluetooth API
if ('bluetooth' in navigator) {
  // Request access to the user's Bluetooth devices
  navigator.bluetooth.requestDevice({
    // Filter for devices that support the toio Core Cube service
    filters: [{ services: ['toio_core_cube'] }]
  })
  .then(device => {
    // Connect to the selected device
    return device.gatt.connect();
  })
  .then(server => {
    // Get the toio Core Cube service
    return server.getPrimaryService('toio_core_cube');
  })
  .then(service => {
    // Get the toio Core Cube Control Point characteristic
    return service.getCharacteristic('toio_core_cube_control_point');
  })
  .then(characteristic => {
    // Write the command to move the toio toy forward for 1 second
    var data = new Uint8Array([0x01, 0x01, 0x01, 0x01, 0x01]);
    characteristic.writeValue(data);
  });
}
```

ここでも、上記の micro:bit の話の時のように、ざっくりと読んでみて思ったことを箇条書きで書く形にします。

- ソースコードの前後の文章について
   - 5バイトの配列を BLE で書き込む話に関する説明が、16進数の文字列を示しつつ説明されている
- ソースコードについて
   - BLE の接続を行うステップは書かれつつも、toio の UUID を適切に設定することはできていないのは、上記の micro:bit の話と同じ
   - モーターを動かす処理は、BLE の接続処理の流れで 1回のみ実行される（※ そういえば、単発の動作なのか連続の動作なのか、ということは指定してなかった...）

この toio の事例では、5バイトの配列を具体的に用いて書き込み処理を行っているのが、特徴的だと思いました。
そしてこの処理の部分が正しいかどうかを確認してみようと思います。toio の BLE通信の仕様は、以下の公式のドキュメントで公開されているので、それと一致しているかを確認してみることにします。

細かな部分まで言うと、toio の仕様のページ以下で「通信仕様」の「モーター」の項目が、確認すべき箇所となります。
●モーター | toio™コア キューブ 技術仕様
　https://toio.github.io/toio-spec/docs/ble_motor
![toio™コア キューブ 技術仕様 ＞ モーター](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/eee57077-5019-d1b6-6387-e7936fb63711.png)

いくつか動かし方のパターンがあるのですが、一番シンプルなものを見てみます。
![モーター制御](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/fe432088-7fdc-dbca-40b2-8568ae9f1e4e.png)

上記を見ると、7バイトのデータが必要で、なおかつ省略可能な部分もなさそうです。そのため、このバイト列をそのまま書きこんでも、toio はうまく動いてくれなそうです。

このように、細かく見るとそのまま利用可能な内容にはなっていないですが、Web Bluetooth API の仕様や toio の通信仕様を理解して、これを書きかえるという使い方であれば、処理のベースを作ってもらうという観点などで活用できるかもしれません。
また、micro:bit の事例も toio の事例も、指定した処理の内容がシンプルなものだったので、もう少し入り組んだ内容にしていった場合、どのようになるかは興味があるところでした（※ 今回は、記事の公開を　12/2中に進めるため、あまり深追いはできませんでした...）。

### さらに試した内容： Babylon.js に関する内容（英語と日本語）
その後、あまり自分がまだ詳しく触れてなく、この 12月にいろいろ手をつけようと思っていた「[Babylon.js](https://www.babylonjs.com/)（※ ブラウザで動く 3D描画ライブラリの 1つ）」でのお試しもやってみました。

こちらは、入力した文章は __「Babylon.js で 青い立方体を中心に表示させるプログラム」__ です。

```javascript
// Create a new Babylon.js engine
var engine = new BABYLON.Engine(canvasElement);

// Create a new Babylon.js scene
var scene = new BABYLON.Scene(engine);

// Create a new Babylon.js camera and position it at (0, 0, 10)
var camera = new BABYLON.ArcRotateCamera(
  'arc_camera', 0, 0, 10,
  BABYLON.Vector3.Zero(), scene);

// Create a new Babylon.js light and position it at (0, 10, 0)
var light = new BABYLON.HemisphericLight(
  'hemi_light', new BABYLON.Vector3(0, 10, 0), scene);

// Create a new Babylon.js material for the cube
var material = new BABYLON.StandardMaterial('standard_mat', scene);
// Set the material's color to blue
material.diffuseColor = new BABYLON.Color3(0, 0, 1);

// Create a new Babylon.js cube
var cube = BABYLON.Mesh.CreateBox('box', 1, scene);
// Set the cube's position to (0, 0, 0)
cube.position = BABYLON.Vector3.Zero();
// Apply the material to the cube
cube.material = material;

// Register a function to run on every frame
engine.runRenderLoop(function () {
  // Update the scene
  scene.render();
});
```

この、Babylon.js については、自分がまだあまり詳しくない内容です。
そこで、このプログラムが良い感じにできているのかどうか、Babylon.js のコミュニティメンバーにメンションをとばしてみることにしました（※ それと同時に、Babylon.js のコミュニティの Discord にも投稿をしてみていました）。

![3人にメンションをとばしてみた](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e5e28304-894d-05df-5350-badefde65dcc.png)

Babylon.js のコミュニティとそれ以外でのコミュニティでもつながりのある 3人にメンションをとばしたのですが、この後、さっそくイワケンさんからリツイートでコメントをもらえました。どうやら、ChatGPT の出力した内容は良い感じのできと判断して良さそうです。

https://twitter.com/iwaken71/status/1598508101602529280

それと、このプログラムの出力の前後で書かれた文章は、以下のようになりました。
![ソースコードの前に書かれた内容：Babylon.js](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/eb58eea8-4351-3870-1c72-ee122e1ae4c5.png)

![ソースコードの後に書かれた内容：Babylon.js](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/843db01b-27ef-e881-dbbf-9136160e7033.png)

下側の処理の内容を説明したものは、ざっくり見てみると Babylon.js の以下のチュートリアルにも書かれている基本的な要素の「engine」・「scene」・「camera」を用意する話に触れられていました。さらに見ていくと、光源やテクスチャについて・レンダリングの更新についてなど、3D描画に必要な要素が、いろいろ説明されているようでした。

●基本的な 3D オブジェクトをシーンに用意する babylon.js チュートリアル - Mixed Reality | Microsoft Learn
　https://learn.microsoft.com/ja-jp/windows/mixed-reality/develop/javascript/tutorials/babylonjs-webxr-helloworld/prepare-scene-02

Babylon.js の事例は、基本的な判断部分をおまかせにしてしまいましたが、これも良い感じに活用できそうなものが生成されている感じがします。

## おわりに
アドベントカレンダーの担当日の前夜に、OpenAI の ChatGPT の話題が出て盛りあがったため、急遽、当初予定したネタを入れかえるということをやりました。

仕事を終えた夜、大急ぎで試した内容を整理して記事を書くという忙しい状態を自ら作ることをしてしまいましたが、結果として面白い知見が得られたと思いました。

今回は、シンプルな入力文で試してみただけとなりましたが、さらに複雑なものを試してみたり、出力結果を見て入力文を変えてみて良い感じの結果が再出力されるか試したり、いろいろやってみたいこともでてきています。
このあたりは、別途、手をつけていければと思います。

### 【追加】 こんなことも試してみた
プログラムを書いてもらう以外に、寝坊で会社に遅刻した言い訳も、候補を出してみてもらいました！

https://twitter.com/youtoy/status/1598697765219233792

候補は出してくれるけど、警告をされてしまう 笑

### 【追加2】 こんなこともさらに試してみた
●【完走賞ゲット-4】続・OpenAI の ChatGPT のネタ：JavaScript の特定の技術仕様を教えてもらう - Qiita
　https://qiita.com/youtoy/items/a4d9f3b0736475d0770a

### KDDI Engineer&Designer の Advent Calendar 2022　の 3日目の記事
今回の記事で扱った ChatGPT のネタ、KDDI Engineer&Designer の Advent Calendar 2022 の 3日目担当の @minorun365 さんも、急遽、取り上げることにしたようです。

![KDDI Engineer&Designer の Advent Calendar 2022　の 3日目の記事](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/dddc2afb-cf56-c39d-4b87-2fcbde75097e.png)

【追記】 公開されたようです ⇒ [この記事はすべてAIが書いています。 - Qiita](https://qiita.com/minorun365/items/a830ba65158c7df688d6)