diff --git a/app/chatgpt.js b/app/chatgpt.js index 48f7e7165c..c7eb1a926f 100644 --- a/app/chatgpt.js +++ b/app/chatgpt.js @@ -1,11 +1,23 @@ require('dotenv').config(); +const Keyv = require('keyv'); +const messageStore = new Keyv(process.env.MONGODB_URI, { namespace: 'chatgpt' }); -const ask = async (question) => { +const ask = async (question, progressCallback, convo) => { const { ChatGPTAPI } = await import('chatgpt'); - const api = new ChatGPTAPI({ apiKey: process.env.OPENAI_KEY }); - const res = await api.sendMessage(question, { - onProgress: (partialRes) => console.log(partialRes.text) - }); + const api = new ChatGPTAPI({ apiKey: process.env.OPENAI_KEY, messageStore }); + let options = { + onProgress: (partialRes) => { + if (partialRes.text.length > 0) { + progressCallback(partialRes); + } + } + }; + + if (!!convo.parentMessageId && !!convo.conversationId) { + options = { ...options, ...convo }; + } + + const res = await api.sendMessage(question, options); return res; }; diff --git a/index.html b/index.html deleted file mode 100644 index 71e55d189c..0000000000 --- a/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - React App - - -
- - - diff --git a/package-lock.json b/package-lock.json index f66199677a..ea2ceeab27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@keyv/mongo": "^2.1.8", "chatgpt": "^4.1.1", "cors": "^2.8.5", "crypto-browserify": "^3.12.0", "dotenv": "^16.0.3", "eventsource": "^2.0.2", + "keyv": "^4.5.2", "mongoose": "^6.9.0", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3511,6 +3513,26 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@keyv/mongo": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@keyv/mongo/-/mongo-2.1.8.tgz", + "integrity": "sha512-IOFKS9Y10c42NCaoD/6OKmqz7FMCm/VbMbrip7ma8tBvdWcPhDkkPV3ZpLgGsGw39RePzzKO6FQ89xs0+BFCKg==", + "dependencies": { + "mongodb": "^4.5.0", + "pify": "^5.0.0" + } + }, + "node_modules/@keyv/mongo/node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -14615,6 +14637,22 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@keyv/mongo": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@keyv/mongo/-/mongo-2.1.8.tgz", + "integrity": "sha512-IOFKS9Y10c42NCaoD/6OKmqz7FMCm/VbMbrip7ma8tBvdWcPhDkkPV3ZpLgGsGw39RePzzKO6FQ89xs0+BFCKg==", + "requires": { + "mongodb": "^4.5.0", + "pify": "^5.0.0" + }, + "dependencies": { + "pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==" + } + } + }, "@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", diff --git a/package.json b/package.json index 1fca863d5d..17c79fb323 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,13 @@ }, "homepage": "https://github.com/danny-avila/rpp2210-mvp#readme", "dependencies": { + "@keyv/mongo": "^2.1.8", "chatgpt": "^4.1.1", "cors": "^2.8.5", "crypto-browserify": "^3.12.0", "dotenv": "^16.0.3", "eventsource": "^2.0.2", + "keyv": "^4.5.2", "mongoose": "^6.9.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/server/index.js b/server/index.js index 6feaec1ab3..d0296a56a2 100644 --- a/server/index.js +++ b/server/index.js @@ -15,22 +15,32 @@ app.get('/', function (req, res) { res.sendFile(path.join(projectPath, 'public', 'index.html')); }); -app.post('/ask', (req, res) => { - console.log(req.body, 'we in here'); +app.post('/ask', async (req, res) => { + console.log(req.body); + const { text, parentMessageId, conversationId } = req.body; res.writeHead(200, { Connection: 'keep-alive', 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache, no-transform', - 'Access-Control-Allow-Origin':'*', - 'X-Accel-Buffering':'no' + 'Access-Control-Allow-Origin': '*', + 'X-Accel-Buffering': 'no' }); - res.write('event: message\ndata: This is chunk 1\n\n'); - res.write('event: message\ndata: This is chunk 2\n\n'); - setTimeout(() => { - res.write('event: message\ndata: This is chunk 3\n\n'); - res.end(); - }, 3500); + + let i = 0; + const progressCallback = (partial) => { + // console.log('partial', partial); + if (i === 0) { + res.write(`event: message\ndata: ${JSON.stringify({ ...partial, initial: true })}\n\n`); + i++; + } + const data = JSON.stringify({...partial, message: true }); + res.write(`event: message\ndata: ${data}\n\n`); + }; + + const gptResponse = await ask(text, progressCallback, { parentMessageId, conversationId }); + res.write(`event: message\ndata: ${JSON.stringify(gptResponse)}\n\n`); + res.end(); }); app.listen(port, () => { diff --git a/src/App.jsx b/src/App.jsx index 5a6ce95b5e..9be5e67933 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import Messages from './components/Messages'; import TextChat from './components/TextChat'; const App = () => { @@ -8,9 +9,8 @@ const App = () => {
-
- {/*