From 36a524a630af15d064ca98b8229624eb98b6deb8 Mon Sep 17 00:00:00 2001 From: Danny Avila <110412045+danny-avila@users.noreply.github.com> Date: Tue, 13 Jun 2023 16:42:01 -0400 Subject: [PATCH] feat(OpenAI, PaLM): Add model support for new OpenAI models and codechat-bison (#516) * feat(OpenAI, PaLM): add new models refactor(chatgpt-client.js): use object to map max tokens for each model refactor(askChatGPTBrowser.js, askGPTPlugins.js, askOpenAI.js): comment out unused function calls and error handling feat(askGoogle.js): add support for codechat-bison model refactor(endpoints.js): add gpt-4-0613 and gpt-3.5-turbo-16k to available models for OpenAI and GPT plugins refactor(EditPresetDialog.jsx): hide examples for codechat-bison model in google endpoint style(EndpointOptionsPopover.jsx): add cn utility function import and use it to set additionalButton className refactor(Google/Settings.jsx): conditionally render custom name and prompt prefix fields based on model type The code has been refactored to conditionally render the custom name and prompt prefix fields based on the type of model selected. If the model starts with 'codechat-', the fields will not be rendered. refactor(Settings.jsx): remove duplicated code and wrap a section in a conditional statement based on a variable style(Input): add z-index to Input component to fix overlapping issue feat(GoogleOptions): disable Examples button when model starts with 'codechat-' prefix * feat(.env.example, endpoints.js): add PLUGIN_MODELS environment variable and use it to get plugin models in endpoints.js --- .env.example | 7 +- api/app/clients/chatgpt-client.js | 14 +- api/server/routes/ask/askChatGPTBrowser.js | 8 +- api/server/routes/ask/askGPTPlugins.js | 10 +- api/server/routes/ask/askGoogle.js | 2 +- api/server/routes/ask/askOpenAI.js | 8 +- api/server/routes/endpoints.js | 13 +- .../components/Endpoints/EditPresetDialog.jsx | 2 +- .../Endpoints/EndpointOptionsPopover.jsx | 5 +- .../components/Endpoints/Google/Settings.jsx | 224 +++++++++--------- .../components/Input/GoogleOptions/index.jsx | 4 +- client/src/components/Input/index.jsx | 2 +- 12 files changed, 168 insertions(+), 131 deletions(-) diff --git a/.env.example b/.env.example index c5f8cefbbd..da97e42e68 100644 --- a/.env.example +++ b/.env.example @@ -30,7 +30,7 @@ OPENAI_API_KEY="user_provided" # Identify the available models, separated by commas *without spaces*. # The first will be default. # Leave it blank to use internal settings. -OPENAI_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314 +OPENAI_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314,gpt-4-0613 # Reverse proxy settings for OpenAI: # https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy @@ -98,6 +98,11 @@ CHATGPT_MODELS=text-davinci-002-render-sha,gpt-4 # Plugins: ############################# +# Identify the available models, separated by commas *without spaces*. +# The first will be default. +# Leave it blank to use internal settings. +PLUGIN_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-16k,gpt-3.5-turbo-0301,gpt-4,gpt-4-0314,gpt-4-0613 + # For securely storing credentials, you need a fixed key and IV. You can set them here for prod and dev environments # If you don't set them, the app will crash on startup. # You need a 32-byte key (64 characters in hex) and 16-byte IV (32 characters in hex) diff --git a/api/app/clients/chatgpt-client.js b/api/app/clients/chatgpt-client.js index d975078939..984b491e68 100644 --- a/api/app/clients/chatgpt-client.js +++ b/api/app/clients/chatgpt-client.js @@ -31,7 +31,19 @@ const askClient = async ({ if (promptPrefix) { promptText = promptPrefix; } - const maxContextTokens = model === 'gpt-4-32k' ? 32767 : model.startsWith('gpt-4') ? 8191 : 4095; // 1 less than maximum + + const maxTokensMap = { + 'gpt-4': 8191, + 'gpt-4-0613': 8191, + 'gpt-4-32k': 32767, + 'gpt-4-32k-0613': 32767, + 'gpt-3.5-turbo': 4095, + 'gpt-3.5-turbo-0613': 4095, + 'gpt-3.5-turbo-0301': 4095, + 'gpt-3.5-turbo-16k': 15999, + }; + + const maxContextTokens = maxTokensMap[model] ?? 4095; // 1 less than maximum const clientOptions = { reverseProxyUrl: process.env.OPENAI_REVERSE_PROXY || null, azure, diff --git a/api/server/routes/ask/askChatGPTBrowser.js b/api/server/routes/ask/askChatGPTBrowser.js index 61e68cd629..9d4050c96f 100644 --- a/api/server/routes/ask/askChatGPTBrowser.js +++ b/api/server/routes/ask/askChatGPTBrowser.js @@ -1,7 +1,7 @@ const express = require('express'); const crypto = require('crypto'); const router = express.Router(); -const { getChatGPTBrowserModels } = require('../endpoints'); +// const { getChatGPTBrowserModels } = require('../endpoints'); const { browserClient } = require('../../../app/'); const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models'); const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers'); @@ -38,9 +38,9 @@ router.post('/', requireJwtAuth, async (req, res) => { token: req.body?.token ?? null }; - const availableModels = getChatGPTBrowserModels(); - if (availableModels.find((model) => model === endpointOption.model) === undefined) - return handleError(res, { text: 'Illegal request: model' }); + // const availableModels = getChatGPTBrowserModels(); + // if (availableModels.find((model) => model === endpointOption.model) === undefined) + // return handleError(res, { text: 'Illegal request: model' }); console.log('ask log', { userMessage, diff --git a/api/server/routes/ask/askGPTPlugins.js b/api/server/routes/ask/askGPTPlugins.js index 481c3b67b9..1c03152370 100644 --- a/api/server/routes/ask/askGPTPlugins.js +++ b/api/server/routes/ask/askGPTPlugins.js @@ -1,7 +1,7 @@ const express = require('express'); const router = express.Router(); const { titleConvo } = require('../../../app/'); -const { getOpenAIModels } = require('../endpoints'); +// const { getOpenAIModels } = require('../endpoints'); const ChatAgent = require('../../../app/langchain/ChatAgent'); const { validateTools } = require('../../../app/langchain/tools'); const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models'); @@ -63,10 +63,10 @@ router.post('/', requireJwtAuth, async (req, res) => { agentOptions }; - const availableModels = getOpenAIModels(); - if (availableModels.find((model) => model === endpointOption.modelOptions.model) === undefined) { - return handleError(res, { text: `Illegal request: model` }); - } + // const availableModels = getOpenAIModels(); + // if (availableModels.find((model) => model === endpointOption.modelOptions.model) === undefined) { + // return handleError(res, { text: `Illegal request: model` }); + // } // console.log('ask log', { // text, diff --git a/api/server/routes/ask/askGoogle.js b/api/server/routes/ask/askGoogle.js index 9a4698c813..f9d41cb8be 100644 --- a/api/server/routes/ask/askGoogle.js +++ b/api/server/routes/ask/askGoogle.js @@ -27,7 +27,7 @@ router.post('/', requireJwtAuth, async (req, res) => { } }; - const availableModels = ['chat-bison', 'text-bison']; + const availableModels = ['chat-bison', 'text-bison', 'codechat-bison']; if (availableModels.find((model) => model === endpointOption.modelOptions.model) === undefined) { return handleError(res, { text: `Illegal request: model` }); } diff --git a/api/server/routes/ask/askOpenAI.js b/api/server/routes/ask/askOpenAI.js index 13de44db95..4a37cff973 100644 --- a/api/server/routes/ask/askOpenAI.js +++ b/api/server/routes/ask/askOpenAI.js @@ -2,7 +2,7 @@ const express = require('express'); const crypto = require('crypto'); const router = express.Router(); const addToCache = require('./addToCache'); -const { getOpenAIModels } = require('../endpoints'); +// const { getOpenAIModels } = require('../endpoints'); const { titleConvo, askClient } = require('../../../app/'); const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models'); const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers'); @@ -63,9 +63,9 @@ router.post('/', requireJwtAuth, async (req, res) => { frequency_penalty: req.body?.frequency_penalty ?? 0 }; - const availableModels = getOpenAIModels(); - if (availableModels.find((model) => model === endpointOption.model) === undefined) - return handleError(res, { text: 'Illegal request: model' }); + // const availableModels = getOpenAIModels(); + // if (availableModels.find((model) => model === endpointOption.model) === undefined) + // return handleError(res, { text: 'Illegal request: model' }); console.log('ask log', { userMessage, diff --git a/api/server/routes/endpoints.js b/api/server/routes/endpoints.js index c2acdb6977..4b74025056 100644 --- a/api/server/routes/endpoints.js +++ b/api/server/routes/endpoints.js @@ -3,7 +3,7 @@ const router = express.Router(); const { availableTools } = require('../../app/langchain/tools'); const getOpenAIModels = () => { - let models = ['gpt-4', 'text-davinci-003', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301']; + let models = ['gpt-4', 'gpt-4-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-0301', 'text-davinci-003' ]; if (process.env.OPENAI_MODELS) models = String(process.env.OPENAI_MODELS).split(','); return models; @@ -16,6 +16,13 @@ const getChatGPTBrowserModels = () => { return models; }; +const getPluginModels = () => { + let models = ['gpt-4', 'gpt-4-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-0301']; + if (process.env.PLUGIN_MODELS) models = String(process.env.PLUGIN_MODELS).split(','); + + return models; +}; + let i = 0; router.get('/', async function (req, res) { let key, palmUser; @@ -38,7 +45,7 @@ router.get('/', async function (req, res) { const google = key || palmUser - ? { userProvide: palmUser, availableModels: ['chat-bison', 'text-bison'] } + ? { userProvide: palmUser, availableModels: ['chat-bison', 'text-bison', 'codechat-bison'] } : false; const azureOpenAI = !!process.env.AZURE_OPENAI_API_KEY; const apiKey = process.env.OPENAI_API_KEY || process.env.AZURE_OPENAI_API_KEY; @@ -46,7 +53,7 @@ router.get('/', async function (req, res) { ? { availableModels: getOpenAIModels(), userProvide: apiKey === 'user_provided' } : false; const gptPlugins = apiKey - ? { availableModels: ['gpt-4', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301'], availableTools } + ? { availableModels: getPluginModels(), availableTools } : false; const bingAI = process.env.BINGAI_TOKEN ? { userProvide: process.env.BINGAI_TOKEN == 'user_provided' } diff --git a/client/src/components/Endpoints/EditPresetDialog.jsx b/client/src/components/Endpoints/EditPresetDialog.jsx index 7a567a47b6..7745ca6bab 100644 --- a/client/src/components/Endpoints/EditPresetDialog.jsx +++ b/client/src/components/Endpoints/EditPresetDialog.jsx @@ -227,7 +227,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
{shouldShowSettings && } - {preset?.endpoint === 'google' && showExamples && ( + {preset?.endpoint === 'google' && showExamples && !preset?.model?.startsWith('codechat-') && (
@@ -41,7 +42,7 @@ function EndpointOptionsPopover({ {additionalButton && (