見出し画像

やっつけでOpenAIを組み込んだチャットツールを作ってみる

概要

近頃流行のAIを自分たちも使いたい!という開発会社さんは多いのではないでしょうか?!
お試しでOpenAIとチャットするツールを作ってみましたので、一緒に手を動かして試してみましょう。
サーバーサイド・クライアントサイドともにJavaScriptで、サーバーサイドはWebSocketを使いますが、WebSocketについてよくわからなくても大丈夫です。

今回はこんなのを作ります!

前提

  • node.jsが動く環境

  • OpenAIに登録してあること

インストール

必要なパッケージをインストールしていきます。

mkdir hello-openai
cd hello-openai/
npm init -y
npm install ws dotenv openai

package.jsonに "type": "module" を追加して、最近の書き方ができるようにします。
↓package.jsonはこんな感じになっているはずです。

{
  "name": "hello-openai",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^16.0.3",
    "openai": "^3.2.1",
    "ws": "^8.13.0"
  }
}

設定ファイル

.envファイルを作って、先ほどメモしたOrganizationIDとAPI Keyを記載してください。

OPENAI_ORG=自分のOrganization ID 
OPENAI_API_KEY=自分のAPI Key

サーバーサイド

app.jsファイルを作って、以下の通りにしてください。

import * as dotenv from 'dotenv'
import { Configuration, OpenAIApi } from 'openai'
import { WebSocketServer } from 'ws'

dotenv.config()

const PORT = 3000

/**
 * OpenAI
 * https://platform.openai.com/docs/api-reference
 */
const openaiConfiguration = new Configuration({
    organization: process.env.OPENAI_ORG,
    apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(openaiConfiguration)

/**
 * WebSocket
 * https://github.com/websockets/ws
 */
const wss = new WebSocketServer({ port: PORT })

// ユーザーとOpenAIのやり取りを溜める配列
const messages = []

wss.on('connection', (ws) => {
    ws.on('message', async (data) => {
        // ユーザーからの質問
        const userMessage = {role: "user", content: data.toString()}
        messages.push(userMessage)

        // ユーザーからの質問をOpenAIに投げる
        const response = await openai.createChatCompletion({
            model: 'gpt-3.5-turbo',
            messages: messages,
        })

        // OpenAIからの返事
        const assistantMessage = response.data.choices[0].message
        messages.push(assistantMessage)

        // OpenAIからの返事をユーザーに返す
        ws.send(assistantMessage.content)
    })
})

ここでのミソは、ユーザーとAIとのやり取りをmessagesに溜めていることと、そのmessagesを丸ごとAPIで投げていることです。これにより、AIはこれまでのやり取りをサーバー側で保存しなくても、文脈に応じた反応ができるようになっているんですね。

クライアントサイド

publicディレクトリを作って、index.htmlとclient.jsを作って、それぞれ以下のようにしてください。

public/index.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="robots" content="noindex,nofollow">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>OpenAIテスト</title>
</head>

<body>
  <h2>質問</h2>
  <form id="send">
    <input type="text" id="sendingMessage">
    <button type="submit">送信</button>
  </form>

  <br>

  <h2>チャットリスト</h2>
  <table id="received"></table>

  <script src="client.js"></script>
</body>

</html>

public/client.js

/**
 * WebSocket
 * https://developer.mozilla.org/ja/docs/Web/API/WebSocket
 */

const sock = new WebSocket(`ws://localhost:3000/websocket`)

// 接続
sock.addEventListener('open', function (_event) {
  console.log('Socket接続成功')
})

// #sendボタン押下
const input = document.getElementById('sendingMessage')
document.getElementById('send').addEventListener('submit', function (event) {
  console.log('送信: ', input.value)
  sock.send(input.value)
  event.preventDefault()
})

// メッセージ受信
const table = document.getElementById('received')
const receivedMessages = []
sock.addEventListener('message', function (event) {
  console.log('受信:', event.data)

  receivedMessages.push(event.data)

  // 表示
  table.innerHTML = ''
  receivedMessages.forEach((receivedMessage) => {
    const td = document.createElement('td')
    td.textContent = receivedMessage
    const tr = document.createElement('tr')
    tr.append(td)
    table.append(tr)
  })
})

起動

ここまでで、以下を実行すれば、サーバーサイドが起動してWebSocketで待ち受けてくれるはずです。

node app.js

あとは、エクスプローラーでindex.htmlをダブルクリックするなどして、ブラウザで開けば、冒頭のチャット画面が開くはずです。

さらに、以下のようにすれば、app.jsを書き換えたときにnodeの再起動が不要になって、開発が便利になりますよ。(ただし、ブラウザのリロードは必要です。)

npm install -g nodemon
nodemon app.js

注意点

今回はセキュリティ面を全く考慮していません。実際に使う場合には、よくよく調査の上でご利用ください。

終わりに

現在オープンテスト中のオンライン立ち飲み屋『バチャこみ』でも、AIはいろんな活用方法があると考えています。
例えばバーテンダーさんがいないときにもNPCが相手してくれたり、場合によってはバーテンダーさんと一緒にいてサポートしてくれたり、AIによって夢が広がりますね。