やっつけでOpenAIを組み込んだチャットツールを作ってみる
概要
近頃流行のAIを自分たちも使いたい!という開発会社さんは多いのではないでしょうか?!
お試しでOpenAIとチャットするツールを作ってみましたので、一緒に手を動かして試してみましょう。
サーバーサイド・クライアントサイドともにJavaScriptで、サーバーサイドはWebSocketを使いますが、WebSocketについてよくわからなくても大丈夫です。
前提
node.jsが動く環境
OpenAIに登録してあること
Organization ID と API Key をメモしておいてください
インストール
必要なパッケージをインストールしていきます。
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によって夢が広がりますね。