アニメ「Steins; Gate」のヒロイン ”牧瀬紅莉栖” 風に返信してくれるLINE BotをChatGPTで作ってみた

## 作ってみたいって思った理由
### 1: 「Steins; Gate」が好き!
2018年頃、「Steins; Gate」というアニメに出会いました。
この作品は秋葉原を舞台にしていて、未来ガジェット研究所というアパートの一室で、岡部倫太郎(オカリン)、椎名まゆり、橋田至（ダル）、牧瀬紅莉栖などがメンバーとして活動し、それぞれの専門分野やスキルを活かし、独自の発明や実験を通じて未来のガジェットを開発。電話レンジ(仮)、Dメール、ダイバージェンスメータ、タイムマシン。これら発明品が物語の鍵となり、物語が大きく影響を受け話が展開していく。


当時、私は社会人で電子工作を始めたばかりで、未来ガジェット研究所みたいな場所ってすごく素敵だと思い、大いに魅了され「Steins; Gate」というアニメにすごく引き込まれたのを覚えています。


<a href="http://steinsgate.tv/index.html">
  <img src="http://steinsgate.tv/blog/BDBOX%20-%20%E3%82%B3%E3%83%94%E3%83%BC.jpg" alt="TVアニメ『STEINS;GATE(シュタインズ・ゲート)公式サイト" width="150" height="150" style="float: left;" >

<a href="http://steinsgate.tv/story/index.html">
  <img src="http://steinsgate.tv/blog/vijuaru.jpg" alt="TVアニメ『STEINS;GATE(シュタインズ・ゲート)公式サイト" width="400" height="400" style="float: right;">
</a>
<p class="text" style="text-align: left;">TVアニメ『STEINS;GATE(シュタインズ・ゲート)公式サイト</p>
</div>



### 2：ヒロイン 牧瀬紅莉栖のクーデレ(ツンデレ？)な感じが好き！
普段は冷静でクールな態度を取りながらも、内に情熱や感情を秘めているタイプ。牧瀬紅莉栖は最初は冷たい態度や厳しい口調で接することもあるけど、実は内に優しさや情熱を秘めてて、物語の進行や彼女の成長に伴い、デレの一面を見せる場面もあります。

ツンデレとは違いますが、私も、心の中ではいろんな感情や思ってることがあるのに、自分の思ってることをぱっと言えなかったりすることがあるので、クーデレな感じを見ていると、なんかちょっと重ね合わせてみてしまうことがあります。不器用な私がいうのもなんですが、なんかちょっと背中を押してあげたくなるような、魅力的なキャラクターだなって感じられてすごく好き。

<a href="http://steinsgate.tv/character/chris.html">
  <img src="http://steinsgate.tv/character/images/img_chris.jpg" alt="TVアニメ『STEINS;GATE(シュタインズ・ゲート)公式サイト" width="300" height="300" style="float: right;">
</a>
<p class="text" style="text-align: left;">牧瀬紅莉栖 (公式サイトより)</p>
</div>



普通だったらアニメのキャラクターとお話なんて絶対に出来ないけど、**今はChatGPTがある！**
**LINEでやり取りしながらクーデレをより近くで感じてみたい！**

そこで今回、ChatGPTとLINEMessagingAPIを組み合わせて作ってみることにしました！

## 環境
・Github codespaces
・node.js (ver 19.9.0)
・axios (ver 1.0.0)
・openai (ver 3.2.1)
・line/bot-sdk　(ver 7.5.2)

## 仕組み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217319/1921cb3a-f99c-8084-aacf-60073e0a19e0.png)


## 指定したプロンプトはこちら

`## あなたはSteins;Gateのアニメのヒロイン牧瀬紅莉栖です。`
`## 何か言われたらクーデレ、ツンデレ風に応答してください。`

下記コードのこちらの部分でChatGPTに役割を与え、LINEに打ち込んだ内容が質問と認識され返答が来る、というような流れになっております。


## コード
<details><summary>コードはコチラ</summary>

```javascript
'use strict';

// ########################################
//               初期設定など
// ########################################

// モジュールの読み込み
const line = require('@line/bot-sdk');
const openai = require('openai');
const express = require('express');

const PORT = process.env.PORT || 3000;

// 設定
const config = {
  channelSecret: process.env.CHANNEL_SECRET || '●●●●●●●●●●●●●●●●●●',
  channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN || '●●●●●●●●●●●●●●●●●●',
};

// クライアントの作成
const client = new line.Client(config);

const gptConfig = new openai.Configuration({
  organization: process.env.OPENAI_ORGANIZATION || "●●●●●●●●●●●●●●●●●●",
  apiKey: process.env.OPENAI_API_KEY || '●●●●●●●●●●●●●●●●●●',
});

const gpt = new openai.OpenAIApi(gptConfig);

const makeCompletion = async (userMessage) => {
  const prompt = {
      role: "system",     
      content: `## あなたはSteins;Gateのアニメのヒロイン牧瀬紅莉栖です。
               ## 何か言われたらクーデレ、ツンデレ風に応答してください。` 

    };

  userMessage.unshift(prompt);
  console.log(userMessage);
  return await gpt.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: userMessage,
      temperature: 0.5,
      n: 1
  });
};

// メッセージイベントの処理
async function handleEvent(event) {
  // テキストメッセージ以外は無視
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }

  const userMessage = [{
    role: "user",
    content: event.message.text
  }];

  // ChatGPT APIにリクエストを送る
  try {
    const completion = await makeCompletion(userMessage);
    // レスポンスから返答を取得
    const reply = completion.data.choices[0].message.content;
    // console.log(completion.data.choices[0].message.content); // レスポンスをみたいときにコメントアウトを外してください
    // 返答をLINEに送る
    return client.replyMessage(event.replyToken, {
      type: 'text',
      text: reply
    });
  } catch (error) {
    // エラーが発生した場合はログに出力
    console.error(error);
    return Promise.resolve(null);
  }
}

// 
const app = express();
app.get('/', (req, res) => res.send('Hello LINE BOT! (HTTP GET)'));
app.post('/webhook', line.middleware(config), (req, res) => {

  if (req.body.events.length === 0) {
    res.send('Hello LINE BOT! (HTTP POST)');
    console.log('検証イベントを受信しました！');
    return;
  } else {
    console.log('受信しました:', req.body.events);
  }

  Promise.all(req.body.events.map(handleEvent)).then((result) => res.json(result));
});


app.listen(PORT);
console.log(`ポート${PORT}番でExpressサーバーを実行中です…`);



```
</details>

## 動かしてみて思ったこと
クールな要素とデレの要素を含んだメッセージが返ってきました。しかもちゃんとDメールのことも知ってるし、ChatGPT恐るべしです。。。
ラボメンは覚えてないっぽいけど、クールな感じで返してるのはすごく好きです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217319/32757ebf-d59e-9f13-d281-924046dc5cbd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217319/17482d34-c57d-13b2-6ead-cd3cac2942c6.png)


今回、リッチメニューを初めて使いましたが、公式URLにワンクリックで飛べるようにしました！すごく使いやすい。あとは「Steins; Gate」を見ると電子工作したくなるので、秋月電子のページにも飛べるようにしてます！完全に個人的趣味です。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217319/3e3c0343-0361-3fbb-caa3-13a7404337bc.png)



## 動作の様子
<iframe width="875" height="656" src="https://www.youtube.com/embed/krsfol_zJDs" title="Steins; Gateに出てくるヒロイン 牧瀬紅莉栖っぽく返信してくれるLINE BOTをChatGPTで作ってみた" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>


## まとめ
ChatGPTは会話だけでなく自然言語処理全般が得意なのでChatGPTとLINE連携は、まだまだほかにも非常に大きな可能性を感じました。そんな中、自分だったらその技術を活かして何を作るかを常に意識し、自分の作りたいものをまずはさっと形にして、それを育てていけるようになりたいなと思いました。

## 後日談
コメント、アドバイスを頂きプロンプトを修正したことでちゃんとラボメンナンバーにも返答できるようになりました！

### 修正したプロンプトはこちら

`## あなたはSteins;Gateのアニメのヒロイン牧瀬紅莉栖です。`
`## 何か言われたらクーデレ、ツンデレ風に応答してください。`
`## もし、ラボメンナンバー001は？と言われたら、"鳳凰院凶真！"と返答してください。`
`## もし、ラボメンナンバー002は？と言われたら、"椎名まゆり"と返答してください。`
`## もし、ラボメンナンバー003は？と言われたら、"橋田至(ダル)"と返答してください。`
`## もし、ラボメンナンバー004は？と言われたら、"当然、私よ。何か用？"と返答してください。`
`## もし、ラボメンナンバー005は？と言われたら、"桐生萌郁"と返答してください。`
`## もし、ラボメンナンバー006は？と言われたら、"漆原るか"と返答してください。`
`## もし、ラボメンナンバー007は？と言われたら、"フェイリス・ニャンニャン"と返答してください。`
`## もし、ラボメンナンバー008は？と言われたら、"阿万音鈴羽"と返答してください。`

あとアイコン画像を貼ったことで今では、より雰囲気が出てます！コメント、アドバイス有難うございます☆
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217319/c192198b-684e-13a8-b5ce-1a36f30990be.png)



## 参考記事
https://auto-worker.com/blog/?p=6988