ChatGPTの動作確認のため、node.jsで簡単なweb app作る

ChatGPTと話しながら、実際にそれっぽいものができた。備忘録。たまに間違ってるところあったりするけど、概ねちゃんと動いてすごい

```prompt: chatgpt input
node.jsのexpressで、chatgptみたいなサービスを作るコードを書いてください。
open aiのchat gpt APIの"gpt-3.5-turbo"を使って書いてください
openai.createChatCompletion
などのメソッドを利用してください
```

```shell:shell
$ npm install -g express-generator
$ express --view=ejs sampleApp
$ cd sampleAPp
$ npm openai dotenv
```

OPEN_AIのAPI keyが必要なので、これは別途発行してください。

```.env
OPENAI_API_KEY="XXXXXXX"
```


```javascript:routes/index.js
const express = require('express');
const { Configuration, OpenAIApi} = require('openai');
const router = express.Router();
require('dotenv').config();

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

router.get('/generate', async (req, res) => {
  try {
    const prompt = req.query.prompt;
    const completions = await openai.createChatCompletion({
      model: "gpt-3.5-turbo",
      messages: [{role: "user", content: `${prompt}`}],
    })
    res.send(completions.data.choices[0].message.content);
  } catch (error) {
    console.error(error);
    res.status(500).send('Server Error');
  }
});

module.exports = router;
```

```javascript:views/index.js
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>HogeGPT</h1>
    <div class="chat-container">
      <div class="chat-log"></div>
      <div class="chat-input">
        <form id="chat-form">
          <input type="text" id="chat-message" placeholder="Enter message...">
          <button type="submit">Send</button>
        </form>
      </div>
    </div>

    <script src="/javascripts/index.js"></script>
  </body>
</html>
```

```javascript:public/javascripts/index.js
const chatForm = document.querySelector('#chat-form');
const chatInput = document.querySelector('#chat-message');
const chatLog = document.querySelector('.chat-log');

chatForm.addEventListener('submit', async (event) => {
    event.preventDefault();
    const message = chatInput.value;
    if(message.trim() === '') {
        return;
    }
    addMessageToLog('You', message);
    chatInput.value = '';
    const response = await fetch(`/generate?prompt=${encodeURIComponent(message)}`);
    if(response.ok) {
        const text = await response.text();
        addMessageToLog('ChatGPT', text);
    } else {
        addMessageToLog('ChatGPT', 'Sorry, errrrror');
    }
});

function addMessageToLog(sender, message) {
    const div = document.createElement('div');
    div.innerHTML = `<strong>${sender}:</strong> ${message}`;
    chatLog.appendChild(div);
    chatLog.scrollTop = chatLog.scrollHeight;
}
```
```css:public/stylesheets/style.css
* {
  box-sizing: border-box;
  font-family: Arial, sans-serif;
  font-size: 16px;
  margin: 0;
  padding: 0;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 50px;
}

h1 {
  margin-bottom: 20px;
}

.chat-container {
  border: 1px solid black;
  border-radius: 10px;
  width: 400px;
  height: 500px;
  display: flex;
  flex-direction: column;
  overflow: auto;
  margin-bottom: 20px;
}

.chat-log {
  flex-grow: 1;
  padding: 10px;
}

.chat-input {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  padding: 10px;
}

#chat-message {
  flex-grow: 1;
  margin-right: 10px;
}

button[type="submit"] {
  padding: 5px 10px;
  background-color: black;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}
```

下みたいなものができる。

https://twitter.com/maze_rapid/status/1632046572954615808