シンギュラリティ？AIチャットプログラムChatGPTにチャットプログラムを作ってもらう

# TL;DR
AIチャットプログラムのChatGPTが人工無能チャットのプログラムを書いてくれました。(シンギュラリティまではもう少し先…だと思う)

# はじめに
大規模会話モデルGPTを使用したチャットプログラムの[ChatGPT](https://chat.openai.com/chat)が話題になっています。ユーザーの質問に対して応答するだけでなく，なんと簡単なプログラミングまでできてしまうとか。(参考：[ChatGPT使い方総まとめ](https://qiita.com/sakasegawa/items/82069c97a1ee011c2d1e))

ChatGPTはChatGPT自身をプログラムで再現できるのでしょうか？もし可能であるならば自己言及のQuineが不完全性定理して不動点なシンギュラリティする[^1]ような気がしますが，さすがに数千億パラメータのGPTを作れというのはまだ酷な気がします。
でも[人工無能](https://ja.wikipedia.org/wiki/%E4%BA%BA%E5%B7%A5%E7%84%A1%E8%84%B3)と呼ばれた擬似的な会話プログラムぐらいなら作れるかも？？？

[^1]:知ったかぶりして適当に書いています。まじめな参考文献としては[不完全性定理とはなにか](https://bookclub.kodansha.co.jp/product?item=0000194771)(竹内 薫，2013，講談社)など

# 実際のやり取り
まずChatGPTが[ご先祖様](https://ja.wikipedia.org/wiki/ELIZA)を知っているか聞いてみました。

![ChatGPT-Eliza_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319482/5418ae58-582e-66c2-ae27-0438f491e97a.png)

なぜか応答が英語になってしまっています。

![ChatGPT-Eliza_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319482/b95cf36c-acf2-7599-c2be-9dc071055066.png)

ちゃんと知っているようですね。  
ではご先祖様を再現してもらいましょうか。

![ChatGPT-Eliza_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319482/02709969-f4be-deef-ffc7-f098028f3b80.png)

コピペできるよう，下記に転記しておきます。

```JavaScript:eliza.js
const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// List of responses for the program to use
const responses = [
  "I'm sorry, could you please elaborate on that?",
  "I see. Can you tell me more?",
  "Interesting. Could you say more?",
  "I'm sorry, I don't quite understand. Could you please rephrase that?"
];

console.log("Hello, I am Eliza. How can I help you today?");

// Prompt the user for input and repeat the conversation until they enter "goodbye"
rl.prompt();
rl.on('line', (input) => {
  if (input.trim().toLowerCase() === 'goodbye') {
    console.log("Thank you for chatting with me. Have a great day!");
    rl.close();
  } else {
    // Use a random response from the list of responses
    let response = responses[Math.floor(Math.random() * responses.length)];
    console.log(response);
    rl.prompt();
  }
});
```

おお，ちゃんとプログラムとして成立しています。  
では実行してみましょう。

```
pi4:~/projects/ChatGPT $ node eliza.js 
Hello, I am Eliza. How can I help you today?
> I am afraid of artificial intelligence.
I see. Can you tell me more?
> Will artificial intelligence take our jobs?
I'm sorry, could you please elaborate on that?
> Will the development of artificial intelligence make programmers unnecessary?
I'm sorry, could you please elaborate on that?
> It looks like it's still in good shape. I feel more energetic.
I'm sorry, could you please elaborate on that?
> goodbye
Thank you for chatting with me. Have a great day!
```

…まだ人間の方が勝てそうなレベルでした。今年一杯ぐらいなら失業せずにすみそうです。

# おまけ
![ChatGPT-Eliza_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319482/d8efa25a-edc5-e3bd-4c52-b075418efdac.png)

なんと実行例まで出てきます。来年にはAIに仕事取られて失業かも😢

# 裏話
質問～回答～実行例までやらせ無しですが，何度かやり直しています。

## 1回目
Elizaについて「ユーザーの入力を反転して応答を返すプログラム」と紹介してくれました。
非常に惜しいプログラムを生成しましたが，ライブラリの[natural](https://www.npmjs.com/package/natural)が日本語対応しておらず没に。

```JavaScript:
// 言語処理ライブラリをインポートする
const natural = require('natural');

// 形態素解析器を作成する
const tokenizer = new natural.WordTokenizer();

// ELIZAのロジックを定義する
function eliza(input) {
  // 入力された文章を形態素解析する
  const tokens = tokenizer.tokenize(input);

  // 入力された文章をフレーズを反転させた形式で返す
  return tokens.reverse().join(' ');
}

// ユーザーの入力を受け取る
const input = 'こんにちは。';

// ELIZAに入力された文章を渡して応答を取得する
const response = eliza(input);

// 応答を出力する
console.log(response);
```

ChatGPT自身による実行例の例示。

```
は。こんにち
```

…反転した応答というのはそういう意味じゃない。

## 2回目
コンソールではprompt()が使えないので没に。一番凝ったプログラムでした。

```JavaScript:
// ユーザーの入力を受け取る
const input = prompt("お話してください");

// 入力からフレーズやフレーズパターンを検出する
const phrases = [
  "私",
  "私たち",
  "僕",
  "僕たち",
  "私たちは",
  "僕たちは"
];
const detectedPhrase = phrases.find(phrase => input.includes(phrase));

// 検出したフレーズに応じて応答を生成する
let response;
if (detectedPhrase === "私") {
  response = "あなたのことですね。どうかしましたか？";
} else if (detectedPhrase === "私たち") {
  response = "みんなのことですね。どうしてますか？";
} else if (detectedPhrase === "僕") {
  response = "あなたのことですね。どうかしましたか？";
} else if (detectedPhrase === "僕たち") {
  response = "みんなのことですね。どうしてますか？";
} else if (detectedPhrase === "私たちは" || detectedPhrase === "僕たちは") {
  response = "どういたしまして。みんなで何か悩んでいますか？";
} else {
  response = "ごめんなさい、よくわかりません。もう一度お話してください。";
}

// 応答を表示する
console.log(response);
```

## 3回目
コンソールでの実行を指定しました。2回目と同様の処理ですがプログラムの最後が切れています。
続きを書くように指示しましたがどうしても切れてしまい，断念。
そして4回目が本文のプログラムです。

```JavaScript:
// 入力を受け取るためのモジュールをロードする
const readline = require("readline");

// 入力を受け取るためのインタフェースを作成する
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// ユーザーからの入力を受け取り、応答を生成する関数
const generateResponse = input => {
  // 入力からフレーズやフレーズパターンを検出する
  const phrases = [
    "私",
    "私たち",
    "僕",
    "僕たち",
    "私たちは",
    "僕たちは"
  ];
  const detectedPhrase = phrases.find(phrase => input.includes(phrase));

  // 検出したフレーズに応じて応答を生成する
  let response;
  if (detectedPhrase === "私") {
    response = "あなたのことですね。どうかしましたか？";
  } else if (detectedPhrase === "私たち") {
    response = "みんなのことですね。どうしてますか？";
  } else if (detectedPhrase === "僕") {
    response = "あなたのことですね。どうかしましたか？";
  } else if (detectedPhrase === "僕たち") {
    response = "みんなのことですね。どうしてますか？";
  } else if (detectedPhrase === "私たちは" || detectedPhrase === "僕たちは") {
    response = "どういたしまして。みんなで何か悩んでいますか？";
  } else {
    response = "ごめんなさい、よくわかりません。もう一度お話してください。";
  }

  // 応答を返す
  return response;
};

// ユーザーからの入力を受け付ける
rl.question("お話してください: ", input => {
  // 入力をもとに応答を生成する
  const response = generateResponse(
```