From 853b5524c31ac330efedac54b2f05a0feb3423f5 Mon Sep 17 00:00:00 2001 From: Earnest Angel <57413115+earnestangel@users.noreply.github.com> Date: Tue, 19 Mar 2024 21:34:06 +0800 Subject: [PATCH] [FIX] Update to OpenAI 4, enabling GPT-4 and other models from the site. Fix prompts and tests (#344) * [FIX] Update to OpenAI 4, enabling GPT-4 and other models from the site. Fix prompts and tests * 0.14.4 --- config.example.js | 4 +- package-lock.json | 177 ++++++++++++++++++-- package.json | 4 +- src/app/Providers/AI/OpenAIProvider.js | 30 +--- src/app/Providers/AI/OpenAIProvider.test.js | 11 +- 5 files changed, 179 insertions(+), 47 deletions(-) diff --git a/config.example.js b/config.example.js index 72aa3409..012d872f 100644 --- a/config.example.js +++ b/config.example.js @@ -73,8 +73,8 @@ module.exports = { // Provider Token AIToken: "", - // Must be one of: davinci or gpt35. - GPTModel: "gpt35", + // Use any model in this page https://platform.openai.com/docs/models/overview + GPTModel: "gpt-4", // URL of the local server for Ririko AI. Leave this empty if you don't have a local server. // Example: http://localhost:5000/api/v1/ask diff --git a/package-lock.json b/package-lock.json index b21ea0d7..282545fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ririko", - "version": "0.14.3", + "version": "0.14.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ririko", - "version": "0.14.3", + "version": "0.14.4", "license": "MIT", "dependencies": { "@discordjs/builders": "^1.6.3", @@ -53,7 +53,7 @@ "node-fetch": "^3.3.1", "node-sd-webui": "^0.0.8", "npm-run-all": "^4.1.5", - "openai": "^3.2.1", + "openai": "^4.29.1", "parsec": "^2.0.2", "pino": "^8.14.1", "pino-pretty": "^10.0.0", @@ -3179,6 +3179,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.8.tgz", "integrity": "sha512-0mHckf6D2DiIAzh8fM8f3HQCvMKDpK94YQ0DSVkfWTG9BZleYIWudw9cJxX8oCk9bM+vAkDyujDV6dmKHbvQpg==" }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -3318,6 +3327,17 @@ "node": ">= 6.0.0" } }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/anime-wallpaper": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/anime-wallpaper/-/anime-wallpaper-1.1.1.tgz", @@ -4779,6 +4799,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base-64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5077,6 +5102,14 @@ "node": ">=10" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, "node_modules/cheerio": { "version": "1.0.0-rc.12", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", @@ -5477,6 +5510,14 @@ "node": ">= 8" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -5685,6 +5726,15 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/digest-fetch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz", + "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==", + "dependencies": { + "base-64": "^0.1.0", + "md5": "^2.3.0" + } + }, "node_modules/discord-api-types": { "version": "0.37.61", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.61.tgz", @@ -6432,6 +6482,31 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/formdata-node/node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "engines": { + "node": ">= 14" + } + }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", @@ -7017,6 +7092,14 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -7202,6 +7285,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -9287,6 +9375,16 @@ "node": ">= 14" } }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -10068,20 +10166,68 @@ } }, "node_modules/openai": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-3.3.0.tgz", - "integrity": "sha512-uqxI/Au+aPRnsaQRe8CojU0eCR7I0mBiKjD3sNMzY6DaC1ZVrc85u98mtJW6voDug8fgGN+DIZmTDxTthxb7dQ==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.29.1.tgz", + "integrity": "sha512-vvKRIgB4/7w48PGVbeR8OceH/PT6fRo4sTIjRC7+y7WoK7by1R0cXs2SZRx4KsEh0ZB8J0eqdVIdRgs8XzeoEg==", "dependencies": { - "axios": "^0.26.0", - "form-data": "^4.0.0" + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "digest-fetch": "^1.3.0", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + }, + "bin": { + "openai": "bin/cli" } }, - "node_modules/openai/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.26", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.26.tgz", + "integrity": "sha512-+wiMJsIwLOYCvUqSdKTrfkS8mpTp+MPINe6+Np4TAGFWWRWiBQ5kSq9nZGCSPkzx9mvT+uEukzpX4MOSCydcvw==", "dependencies": { - "follow-redirects": "^1.14.8" + "undici-types": "~5.26.4" + } + }, + "node_modules/openai/node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/openai/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/openai/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/openai/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, "node_modules/p-limit": { @@ -12214,6 +12360,11 @@ "node": ">=14.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", diff --git a/package.json b/package.json index 01739c9f..74f271df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ririko", - "version": "0.14.3", + "version": "0.14.4", "description": "Ririko - A powerful AI-powered general Discord bot that you can call your companion", "author": "Earnest Angel", "email": "me@angel.net.my", @@ -85,7 +85,7 @@ "node-fetch": "^3.3.1", "node-sd-webui": "^0.0.8", "npm-run-all": "^4.1.5", - "openai": "^3.2.1", + "openai": "^4.29.1", "parsec": "^2.0.2", "pino": "^8.14.1", "pino-pretty": "^10.0.0", diff --git a/src/app/Providers/AI/OpenAIProvider.js b/src/app/Providers/AI/OpenAIProvider.js index c715d200..8f3151ba 100644 --- a/src/app/Providers/AI/OpenAIProvider.js +++ b/src/app/Providers/AI/OpenAIProvider.js @@ -2,7 +2,7 @@ const { AIProviderBase } = require("app/Providers/AIProviderBase"); const config = require("config"); const getconfig = require("helpers/getconfig"); const openai = require("openai"); -const { OpenAIApi, Configuration } = require("openai"); +const OpenAIApi = require("openai"); class OpenAIProvider extends AIProviderBase { constructor() { @@ -14,11 +14,9 @@ class OpenAIProvider extends AIProviderBase { return; } - this.configuration = new Configuration({ + this.openAiClient = new OpenAIApi({ apiKey: this.token, }); - - this.openAiClient = new OpenAIApi(this.configuration); } getClient() { @@ -37,7 +35,7 @@ class OpenAIProvider extends AIProviderBase { const model = config.AI.GPTModel; // davinci or gpt35 const prompt = `${context}${history.join("\n")}\nHuman: ${messageText}\n`; - if (model === "gpt35") { + if (model) { const convertedChatHistory = history.map((message) => { const [role, content] = message.split(": "); return { @@ -49,10 +47,11 @@ class OpenAIProvider extends AIProviderBase { const newPrompt = [ { role: "system", content: context }, ...convertedChatHistory, + { role: "user", content: messageText } ]; - const response = await this.openAiClient.createChatCompletion({ - model: "gpt-3.5-turbo", + const response = await this.openAiClient.chat.completions.create({ + model: model, messages: newPrompt, temperature: 1, max_tokens: 2000, @@ -61,22 +60,7 @@ class OpenAIProvider extends AIProviderBase { presence_penalty: 0.9, }); - return response.data.choices[0].message.content; // Uncomment for GPT-3.5-turbo - } else if (model === "davinci") { - // Send request to OpenAI for text-davinci-002 - // NOTE: text-davinci-003 is now removed from OpenAI API - const response = await this.openAiClient.createCompletion({ - model: "text-davinci-002", - prompt, - temperature: 1, - max_tokens: 2000, - top_p: 0.2, - frequency_penalty: 0.9, - presence_penalty: 1.9, - stop: ["Human:"], - }); - - return response?.data.choices[0].text.split("Friend:")[1]?.trim(); + return response.choices[0].message.content; } else { throw new Error("Invalid GPT model. Check config.js"); } diff --git a/src/app/Providers/AI/OpenAIProvider.test.js b/src/app/Providers/AI/OpenAIProvider.test.js index 052c62a5..33984278 100644 --- a/src/app/Providers/AI/OpenAIProvider.test.js +++ b/src/app/Providers/AI/OpenAIProvider.test.js @@ -1,10 +1,8 @@ const nlpcloud = require("nlpcloud"), - { OpenAIProvider } = require("./OpenAIProvider"); -const { Configuration } = require("openai"); + { OpenAIProvider } = require("./OpenAIProvider"); jest.mock("openai", () => { - return { - OpenAIApi: class { + return class { createCompletion = () => { return { data: { @@ -12,9 +10,8 @@ jest.mock("openai", () => { }, }; }; - }, - Configuration: jest.fn(), - }; + } + }); describe("OpenAIProvider", () => {