mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 00:40:14 +01:00
feat: update env example.
feat: support OPENAI_REVERSE_PROXY feat: support set availModels in env file fix: chatgpt Browser send logic refactor. fix: title wrong usage of responseMessage BREAKING: some env paramaters has been changed!
This commit is contained in:
parent
a5202f84cc
commit
22b9524ad3
19 changed files with 259 additions and 197 deletions
113
LOCAL_INSTALL.md
113
LOCAL_INSTALL.md
|
|
@ -1,81 +1,82 @@
|
||||||
### Local
|
### Local
|
||||||
- **Install the prerequisites**
|
|
||||||
- **Download chatgpt-clone**
|
|
||||||
- Download the latest release here: https://github.com/danny-avila/chatgpt-clone/releases/
|
|
||||||
- Or by clicking on the green code button in the top of the page and selecting "Download ZIP"
|
|
||||||
- Or (Recommended if you have Git installed) pull the latest release from the main branch
|
|
||||||
- If you downloaded a zip file, extract the content in "C:/chatgpt-clone/"
|
|
||||||
-**IMPORTANT : If you install the files somewhere else modify the instructions accordingly**
|
|
||||||
|
|
||||||
- **To enable the Conversation search feature:**
|
|
||||||
-IF YOU DON'T WANT THIS FEATURE YOU CAN SKIP THIS STEP
|
|
||||||
- Download MeileSearch latest release from : https://github.com/meilisearch/meilisearch/releases
|
|
||||||
- Copy it to "C:/chatgpt-clone/"
|
|
||||||
- Rename the file to "meilisearch.exe"
|
|
||||||
- Open it by double clicking on it
|
|
||||||
- Copy the generated Master Key and save it somewhere (You will need it later)
|
|
||||||
|
|
||||||
- **Download and Install Node.js**
|
- **Install the prerequisites**
|
||||||
- Navigate to https://nodejs.org/en/download and to download the latest Node.js version for your OS (The Node.js installer includes the NPM package manager.)
|
|
||||||
|
- **Download chatgpt-clone**
|
||||||
- **Create a MongoDB database**
|
- Download the latest release here: https://github.com/danny-avila/chatgpt-clone/releases/
|
||||||
- Navigate to https://www.mongodb.com/ and Sign In or Create an account
|
- Or by clicking on the green code button in the top of the page and selecting "Download ZIP"
|
||||||
- Create a new project
|
- Or (Recommended if you have Git installed) pull the latest release from the main branch
|
||||||
- Build a Database using the free plan and name the cluster (example: chatgpt-clone)
|
- If you downloaded a zip file, extract the content in "C:/chatgpt-clone/" -**IMPORTANT : If you install the files somewhere else modify the instructions accordingly**
|
||||||
- Use the "Username and Password" method for authentication
|
- **To enable the Conversation search feature:**
|
||||||
- Add your current IP to the access list
|
-IF YOU DON'T WANT THIS FEATURE YOU CAN SKIP THIS STEP
|
||||||
- Then in the Database Deployment tab click on Connect
|
|
||||||
- In "Choose a connection method" select "Connect your application"
|
- Download MeileSearch latest release from : https://github.com/meilisearch/meilisearch/releases
|
||||||
- Driver = Node.js / Version = 4.1 or later
|
- Copy it to "C:/chatgpt-clone/"
|
||||||
- Copy the connection string and save it somewhere(you will need it later)
|
- Rename the file to "meilisearch.exe"
|
||||||
|
- Open it by double clicking on it
|
||||||
- **Get your OpenAI API key** here: https://platform.openai.com/account/api-keys and save it somewhere safe (you will need it later)
|
- Copy the generated Master Key and save it somewhere (You will need it later)
|
||||||
|
|
||||||
- **Get your Bing Access Token**
|
- **Download and Install Node.js**
|
||||||
- Using MS Edge, navigate to bing.com
|
- Navigate to https://nodejs.org/en/download and to download the latest Node.js version for your OS (The Node.js installer includes the NPM package manager.)
|
||||||
- Make sure you are logged in
|
- **Create a MongoDB database**
|
||||||
- Open the DevTools by pressing F12 on your keyboard
|
- Navigate to https://www.mongodb.com/ and Sign In or Create an account
|
||||||
- Click on the tab "Application" (On the left of the DevTools)
|
- Create a new project
|
||||||
- Expand the "Cookies" (Under "Storage")
|
- Build a Database using the free plan and name the cluster (example: chatgpt-clone)
|
||||||
- You need to copy the value of the "_U" cookie, save it somewhere, you will need it later
|
- Use the "Username and Password" method for authentication
|
||||||
|
- Add your current IP to the access list
|
||||||
|
- Then in the Database Deployment tab click on Connect
|
||||||
|
- In "Choose a connection method" select "Connect your application"
|
||||||
|
- Driver = Node.js / Version = 4.1 or later
|
||||||
|
- Copy the connection string and save it somewhere(you will need it later)
|
||||||
|
- **Get your OpenAI API key** here: https://platform.openai.com/account/api-keys and save it somewhere safe (you will need it later)
|
||||||
|
|
||||||
|
- **Get your Bing Access Token**
|
||||||
|
- Using MS Edge, navigate to bing.com
|
||||||
|
- Make sure you are logged in
|
||||||
|
- Open the DevTools by pressing F12 on your keyboard
|
||||||
|
- Click on the tab "Application" (On the left of the DevTools)
|
||||||
|
- Expand the "Cookies" (Under "Storage")
|
||||||
|
- You need to copy the value of the "\_U" cookie, save it somewhere, you will need it later
|
||||||
|
|
||||||
- **Create the ".env" File** You will need all your credentials, (API keys, access tokens, and Mongo Connection String, MeileSearch Master Key)
|
- **Create the ".env" File** You will need all your credentials, (API keys, access tokens, and Mongo Connection String, MeileSearch Master Key)
|
||||||
- Open "C:/chatgpt-clone/api/.env.example" in a text editor
|
- Open "C:/chatgpt-clone/api/.env.example" in a text editor
|
||||||
- At this line **MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone"**
|
- At this line **MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone"**
|
||||||
Replace mongodb://127.0.0.1:27017/chatgpt-clone with the MondoDB connection string you saved earlier, **remove "&w=majority" at the end**
|
Replace mongodb://127.0.0.1:27017/chatgpt-clone with the MondoDB connection string you saved earlier, **remove "&w=majority" at the end**
|
||||||
- It should look something like this: "MONGO_URI="mongodb+srv://username:password@chatgpt-clone.lfbcwz3.mongodb.net/?retryWrites=true"
|
- It should look something like this: "MONGO_URI="mongodb+srv://username:password@chatgpt-clone.lfbcwz3.mongodb.net/?retryWrites=true"
|
||||||
- At this line **OPENAI_KEY=** you need to add your openai API key
|
- At this line **OPENAI_KEY=** you need to add your openai API key
|
||||||
- Add your Bing token to this line **BING_TOKEN=** (needed for BingChat & Sydney)
|
- Add your Bing token to this line **BINGAI_TOKEN=** (needed for BingChat & Sydney)
|
||||||
- If you want to enable Search, **SEARCH=TRUE** if you do not want to enable search **SEARCH=FALSE**
|
- If you want to enable Search, **SEARCH=TRUE** if you do not want to enable search **SEARCH=FALSE**
|
||||||
- Add your previously saved MeiliSearch Master key to this line **MEILI_MASTER_KEY=** (the key is needed if search is enabled even on local install or you may encounter errors)
|
- Add your previously saved MeiliSearch Master key to this line **MEILI_MASTER_KEY=** (the key is needed if search is enabled even on local install or you may encounter errors)
|
||||||
- Save the file as **"C:/chatgpt-clone/api/.env"**
|
- Save the file as **"C:/chatgpt-clone/api/.env"**
|
||||||
|
|
||||||
**DO THIS ONCE AFTER EVERY UPDATE**
|
**DO THIS ONCE AFTER EVERY UPDATE**
|
||||||
|
|
||||||
- **Run** `npm ci` in the "C:/chatgpt-clone/api" directory
|
- **Run** `npm ci` in the "C:/chatgpt-clone/api" directory
|
||||||
- **Run** `npm ci` in the "C:/chatgpt-clone/client" directory
|
- **Run** `npm ci` in the "C:/chatgpt-clone/client" directory
|
||||||
- **Run** `npm run build` in the "C:/chatgpt-clone/client"
|
- **Run** `npm run build` in the "C:/chatgpt-clone/client"
|
||||||
|
|
||||||
**DO THIS EVERY TIME YOU WANT TO START CHATGPT-CLONE**
|
**DO THIS EVERY TIME YOU WANT TO START CHATGPT-CLONE**
|
||||||
|
|
||||||
- **Run** `"meilisearch --master-key put_your_meilesearch_Master_Key_here"` in the "C:/chatgpt-clone" directory (Only if SEARCH=TRUE)
|
- **Run** `"meilisearch --master-key put_your_meilesearch_Master_Key_here"` in the "C:/chatgpt-clone" directory (Only if SEARCH=TRUE)
|
||||||
- **Run** `npm start` in the "C:/chatgpt-clone/api" directory
|
- **Run** `npm start` in the "C:/chatgpt-clone/api" directory
|
||||||
|
|
||||||
- **Visit** http://localhost:3080 (default port) & enjoy
|
- **Visit** http://localhost:3080 (default port) & enjoy
|
||||||
|
|
||||||
|
|
||||||
OPTIONAL BUT RECOMMENDED
|
OPTIONAL BUT RECOMMENDED
|
||||||
|
|
||||||
- **Make a batch file to automate the starting process**
|
- **Make a batch file to automate the starting process**
|
||||||
- Open a text editor
|
- Open a text editor
|
||||||
- Paste the following code in a new document
|
- Paste the following code in a new document
|
||||||
- Put your MeiliSearch master key instead of "your_master_key_goes_here"
|
- Put your MeiliSearch master key instead of "your_master_key_goes_here"
|
||||||
- Save the file as "C:/chatgpt-clone/chatgpt-clone.bat"
|
- Save the file as "C:/chatgpt-clone/chatgpt-clone.bat"
|
||||||
- you can make a shortcut of this batch file and put it anywhere
|
- you can make a shortcut of this batch file and put it anywhere
|
||||||
|
|
||||||
```
|
```
|
||||||
REM the meilisearch executable needs to be at the root of the chatgpt-clone directory
|
REM the meilisearch executable needs to be at the root of the chatgpt-clone directory
|
||||||
|
|
||||||
start "MeiliSearch" cmd /k "meilisearch --master-key your_master_key_goes_here
|
start "MeiliSearch" cmd /k "meilisearch --master-key your_master_key_goes_here
|
||||||
|
|
||||||
REM ↑↑↑ meilisearch is the name of the meilisearch executable, put your own master key there
|
REM ↑↑↑ meilisearch is the name of the meilisearch executable, put your own master key there
|
||||||
|
|
||||||
start "ChatGPT-Clone" cmd /k "cd api && npm start"
|
start "ChatGPT-Clone" cmd /k "cd api && npm start"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,34 +15,68 @@ NODE_ENV=development
|
||||||
# Change this to your MongoDB URI if different and I recommend appending chatgpt-clone
|
# Change this to your MongoDB URI if different and I recommend appending chatgpt-clone
|
||||||
MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone"
|
MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone"
|
||||||
|
|
||||||
# API key configuration.
|
|
||||||
# Leave blank if you don't want them.
|
#############################
|
||||||
|
# Endpoint OpenAI:
|
||||||
|
#############################
|
||||||
|
|
||||||
|
# Access key from OpenAI platform
|
||||||
|
# Leave it blank to disable this endpoint
|
||||||
OPENAI_KEY=
|
OPENAI_KEY=
|
||||||
|
|
||||||
# Default ChatGPT API Model, options: 'gpt-4', 'text-davinci-003', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301'
|
# Identify the available models, sperate by comma, and not space in it
|
||||||
# you will have errors if you don't have access to a model like 'gpt-4', defaults to turbo if left empty/excluded.
|
# Leave it blank to use internal settings.
|
||||||
DEFAULT_API_GPT=gpt-3.5-turbo
|
# OPENAI_MODELS=gpt-4,text-davinci-003,gpt-3.5-turbo,gpt-3.5-turbo-0301
|
||||||
|
|
||||||
# _U Cookies Value from bing.com
|
# Reverse proxy setting for OpenAI
|
||||||
BING_TOKEN=
|
# https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy
|
||||||
|
# OPENAI_REVERSE_PROXY=<YOUR REVERSE PROXY>
|
||||||
|
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# Endpoint BingAI (Also jailbreak Sydney):
|
||||||
|
#############################
|
||||||
|
|
||||||
|
# BingAI Tokens: the "_U" cookies value from bing.com
|
||||||
|
# Leave it and BINGAI_USER_TOKEN blank to disable this endpoint.
|
||||||
|
BINGAI_TOKEN=
|
||||||
|
|
||||||
|
# BingAI User defined Token
|
||||||
|
# Allow user to set their own token by client
|
||||||
|
# Uncomment this to enable this feature.
|
||||||
|
# (Not implemented yet.)
|
||||||
|
# BINGAI_USER_TOKEN=1
|
||||||
|
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# Endpoint chatGPT:
|
||||||
|
#############################
|
||||||
|
|
||||||
# ChatGPT Browser Client (free but use at your own risk)
|
# ChatGPT Browser Client (free but use at your own risk)
|
||||||
# Access token from https://chat.openai.com/api/auth/session
|
# Access token from https://chat.openai.com/api/auth/session
|
||||||
# Exposes your access token to a 3rd party
|
# Exposes your access token to CHATGPT_REVERSE_PROXY
|
||||||
|
# Leave it blank to disable this endpoint
|
||||||
CHATGPT_TOKEN=
|
CHATGPT_TOKEN=
|
||||||
# If you have access to other models on the official site, you can use them here.
|
|
||||||
# Defaults to 'text-davinci-002-render-sha' if left empty.
|
# Identify the available models, sperate by comma, and not space in it
|
||||||
# options: gpt-4, text-davinci-002-render, text-davinci-002-render-paid, or text-davinci-002-render-sha
|
# Leave it blank to use internal settings.
|
||||||
# You cannot use a model that your account does not have access to. You can check
|
# CHATGPT_MODELS=text-davinci-002-render-sha,text-davinci-002-render-paid,gpt-4
|
||||||
# which ones you have access to by opening DevTools and going to the Network tab.
|
|
||||||
# Refresh the page and look at the response body for https://chat.openai.com/backend-api/models.
|
# Reverse proxy setting for OpenAI
|
||||||
BROWSER_MODEL=
|
# https://github.com/waylaidwanderer/node-chatgpt-api#using-a-reverse-proxy
|
||||||
|
# By default it will use the node-chatgpt-api recommended proxy, (it's a third party server)
|
||||||
|
# CHATGPT_REVERSE_PROXY=<YOUR REVERSE PROXY>
|
||||||
|
|
||||||
|
|
||||||
|
#############################
|
||||||
|
# Search:
|
||||||
|
#############################
|
||||||
|
|
||||||
# ENABLING SEARCH MESSAGES/CONVOS
|
# ENABLING SEARCH MESSAGES/CONVOS
|
||||||
# Requires installation of free self-hosted Meilisearch or Paid Remote Plan (Remote not tested)
|
# Requires installation of free self-hosted Meilisearch or Paid Remote Plan (Remote not tested)
|
||||||
# The easiest setup for this is through docker-compose, which takes care of it for you.
|
# The easiest setup for this is through docker-compose, which takes care of it for you.
|
||||||
# SEARCH=TRUE
|
# SEARCH=1
|
||||||
SEARCH=TRUE
|
SEARCH=1
|
||||||
|
|
||||||
# REQUIRED FOR SEARCH: MeiliSearch Host, mainly for api server to connect to the search server.
|
# REQUIRED FOR SEARCH: MeiliSearch Host, mainly for api server to connect to the search server.
|
||||||
# must replace '0.0.0.0' with 'meilisearch' if serving meilisearch with docker-compose
|
# must replace '0.0.0.0' with 'meilisearch' if serving meilisearch with docker-compose
|
||||||
|
|
@ -63,8 +97,11 @@ MEILI_HTTP_ADDR='0.0.0.0:7700' # <-- local/remote
|
||||||
MEILI_MASTER_KEY=JKMW-hGc7v_D1FkJVdbRSDNFLZcUv3S75yrxXP0SmcU # <-- ready made secure key for docker-compose
|
MEILI_MASTER_KEY=JKMW-hGc7v_D1FkJVdbRSDNFLZcUv3S75yrxXP0SmcU # <-- ready made secure key for docker-compose
|
||||||
|
|
||||||
|
|
||||||
|
#############################
|
||||||
# User System
|
# User System
|
||||||
# global enable/disable the sample user system.
|
#############################
|
||||||
|
|
||||||
|
# Enable the user system.
|
||||||
# this is not a ready to use user system.
|
# this is not a ready to use user system.
|
||||||
# dont't use it, unless you can write your own code.
|
# dont't use it, unless you can write your own code.
|
||||||
# ENABLE_USER_SYSTEM= # <-- make sure you don't comment this back in if you're not using your own user system
|
# ENABLE_USER_SYSTEM= # <-- make sure you don't comment this back in if you're not using your own user system
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const askBing = async ({
|
||||||
|
|
||||||
const bingAIClient = new BingAIClient({
|
const bingAIClient = new BingAIClient({
|
||||||
// "_U" cookie from bing.com
|
// "_U" cookie from bing.com
|
||||||
userToken: process.env.BING_TOKEN,
|
userToken: process.env.BINGAI_TOKEN,
|
||||||
// If the above doesn't work, provide all your cookies as a string instead
|
// If the above doesn't work, provide all your cookies as a string instead
|
||||||
// cookies: '',
|
// cookies: '',
|
||||||
debug: false,
|
debug: false,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const { KeyvFile } = require('keyv-file');
|
const { KeyvFile } = require('keyv-file');
|
||||||
|
|
||||||
const modelMap = new Map([
|
|
||||||
['Default (GPT-3.5)', 'text-davinci-002-render-sha'],
|
|
||||||
['Legacy (GPT-3.5)', 'text-davinci-002-render-paid'],
|
|
||||||
['GPT-4', 'gpt-4']
|
|
||||||
]);
|
|
||||||
|
|
||||||
const browserClient = async ({
|
const browserClient = async ({
|
||||||
text,
|
text,
|
||||||
parentMessageId,
|
parentMessageId,
|
||||||
|
|
@ -21,11 +15,11 @@ const browserClient = async ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const clientOptions = {
|
const clientOptions = {
|
||||||
// Warning: This will expose your access token to a third party. Consider the risks before using this.
|
// Warning: This will expose your access token to a third party. Consider the risks before using this.
|
||||||
reverseProxyUrl: process.env.CHATGPT_REVERSE_PROXY || 'https://bypass.churchless.tech/api/conversation',
|
reverseProxyUrl: process.env.CHATGPT_REVERSE_PROXY || 'https://bypass.churchless.tech/api/conversation',
|
||||||
// Access token from https://chat.openai.com/api/auth/session
|
// Access token from https://chat.openai.com/api/auth/session
|
||||||
accessToken: process.env.CHATGPT_TOKEN,
|
accessToken: process.env.CHATGPT_TOKEN,
|
||||||
model: modelMap.get(model),
|
model: model,
|
||||||
// debug: true
|
// debug: true
|
||||||
proxy: process.env.PROXY || null
|
proxy: process.env.PROXY || null
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ const askClient = async ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const clientOptions = {
|
const clientOptions = {
|
||||||
|
// Warning: This will expose your access token to a third party. Consider the risks before using this.
|
||||||
|
reverseProxyUrl: process.env.OPENAI_REVERSE_PROXY || null,
|
||||||
|
|
||||||
modelOptions: {
|
modelOptions: {
|
||||||
model: model,
|
model: model,
|
||||||
temperature,
|
temperature,
|
||||||
|
|
@ -29,6 +32,7 @@ const askClient = async ({
|
||||||
presence_penalty,
|
presence_penalty,
|
||||||
frequency_penalty
|
frequency_penalty
|
||||||
},
|
},
|
||||||
|
|
||||||
chatGptLabel,
|
chatGptLabel,
|
||||||
promptPrefix,
|
promptPrefix,
|
||||||
proxy: process.env.PROXY || null,
|
proxy: process.env.PROXY || null,
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
require('dotenv').config();
|
|
||||||
const { KeyvFile } = require('keyv-file');
|
|
||||||
|
|
||||||
const askSydney = async ({ text, onProgress, convo }) => {
|
|
||||||
const { BingAIClient } = (await import('@waylaidwanderer/chatgpt-api'));
|
|
||||||
|
|
||||||
const sydneyClient = new BingAIClient({
|
|
||||||
// "_U" cookie from bing.com
|
|
||||||
userToken: process.env.BING_TOKEN,
|
|
||||||
// If the above doesn't work, provide all your cookies as a string instead
|
|
||||||
// cookies: '',
|
|
||||||
debug: false,
|
|
||||||
cache: { store: new KeyvFile({ filename: './data/cache.json' }) }
|
|
||||||
});
|
|
||||||
|
|
||||||
let options = {
|
|
||||||
jailbreakConversationId: true,
|
|
||||||
onProgress,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (convo.jailbreakConversationId) {
|
|
||||||
options = { ...options, jailbreakConversationId: convo.jailbreakConversationId, parentMessageId: convo.parentMessageId };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (convo.toneStyle) {
|
|
||||||
options.toneStyle = convo.toneStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('sydney options', options);
|
|
||||||
|
|
||||||
const res = await sydneyClient.sendMessage(text, options
|
|
||||||
);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
|
|
||||||
// for reference:
|
|
||||||
// https://github.com/waylaidwanderer/node-chatgpt-api/blob/main/demos/use-bing-client.js
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = { askSydney };
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
const { askClient } = require('./clients/chatgpt-client');
|
const { askClient } = require('./clients/chatgpt-client');
|
||||||
const { browserClient } = require('./clients/chatgpt-browser');
|
const { browserClient } = require('./clients/chatgpt-browser');
|
||||||
const { askBing } = require('./clients/bingai');
|
const { askBing } = require('./clients/bingai');
|
||||||
const { askSydney } = require('./clients/sydney');
|
|
||||||
const titleConvo = require('./titleConvo');
|
const titleConvo = require('./titleConvo');
|
||||||
const getCitations = require('../lib/parse/getCitations');
|
const getCitations = require('../lib/parse/getCitations');
|
||||||
const citeText = require('../lib/parse/citeText');
|
const citeText = require('../lib/parse/citeText');
|
||||||
|
|
@ -10,7 +9,6 @@ module.exports = {
|
||||||
askClient,
|
askClient,
|
||||||
browserClient,
|
browserClient,
|
||||||
askBing,
|
askBing,
|
||||||
askSydney,
|
|
||||||
titleConvo,
|
titleConvo,
|
||||||
getCitations,
|
getCitations,
|
||||||
citeText
|
citeText
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { getChatGPTBrowserModels } = require('../endpoints');
|
||||||
const { titleConvo, browserClient } = require('../../../app/');
|
const { titleConvo, browserClient } = require('../../../app/');
|
||||||
const { saveMessage, getConvoTitle, saveConvo, updateConvo, getConvo } = require('../../../models');
|
const { saveMessage, getConvoTitle, saveConvo, updateConvo, getConvo } = require('../../../models');
|
||||||
const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers');
|
const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers');
|
||||||
|
|
@ -18,6 +19,7 @@ router.post('/', async (req, res) => {
|
||||||
|
|
||||||
// build user message
|
// build user message
|
||||||
const conversationId = oldConversationId || crypto.randomUUID();
|
const conversationId = oldConversationId || crypto.randomUUID();
|
||||||
|
const isNewConversation = !oldConversationId;
|
||||||
const userMessageId = crypto.randomUUID();
|
const userMessageId = crypto.randomUUID();
|
||||||
const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000';
|
const userParentMessageId = parentMessageId || '00000000-0000-0000-0000-000000000000';
|
||||||
const userMessage = {
|
const userMessage = {
|
||||||
|
|
@ -34,6 +36,10 @@ router.post('/', async (req, res) => {
|
||||||
model: req.body?.model || 'text-davinci-002-render-sha'
|
model: req.body?.model || 'text-davinci-002-render-sha'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const availableModels = getChatGPTBrowserModels();
|
||||||
|
if (availableModels.find(model => model === endpointOption.model) === undefined)
|
||||||
|
return handleError(res, { text: 'Illegal request: model' });
|
||||||
|
|
||||||
console.log('ask log', {
|
console.log('ask log', {
|
||||||
userMessage,
|
userMessage,
|
||||||
endpointOption,
|
endpointOption,
|
||||||
|
|
@ -52,6 +58,7 @@ router.post('/', async (req, res) => {
|
||||||
|
|
||||||
// eslint-disable-next-line no-use-before-define
|
// eslint-disable-next-line no-use-before-define
|
||||||
return await ask({
|
return await ask({
|
||||||
|
isNewConversation,
|
||||||
userMessage,
|
userMessage,
|
||||||
endpointOption,
|
endpointOption,
|
||||||
conversationId,
|
conversationId,
|
||||||
|
|
@ -63,6 +70,7 @@ router.post('/', async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const ask = async ({
|
const ask = async ({
|
||||||
|
isNewConversation,
|
||||||
userMessage,
|
userMessage,
|
||||||
endpointOption,
|
endpointOption,
|
||||||
conversationId,
|
conversationId,
|
||||||
|
|
@ -71,9 +79,7 @@ const ask = async ({
|
||||||
req,
|
req,
|
||||||
res
|
res
|
||||||
}) => {
|
}) => {
|
||||||
const { text, parentMessageId: userParentMessageId, messageId: userMessageId } = userMessage;
|
let { text, parentMessageId: userParentMessageId, messageId: userMessageId } = userMessage;
|
||||||
|
|
||||||
const client = browserClient;
|
|
||||||
|
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
Connection: 'keep-alive',
|
Connection: 'keep-alive',
|
||||||
|
|
@ -89,7 +95,7 @@ const ask = async ({
|
||||||
const progressCallback = createOnProgress();
|
const progressCallback = createOnProgress();
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
res.on('close', () => abortController.abort());
|
res.on('close', () => abortController.abort());
|
||||||
let gptResponse = await client({
|
let response = await browserClient({
|
||||||
text,
|
text,
|
||||||
parentMessageId: userParentMessageId,
|
parentMessageId: userParentMessageId,
|
||||||
conversationId,
|
conversationId,
|
||||||
|
|
@ -98,50 +104,60 @@ const ask = async ({
|
||||||
abortController
|
abortController
|
||||||
});
|
});
|
||||||
|
|
||||||
gptResponse.text = gptResponse.response;
|
console.log('CLIENT RESPONSE', response);
|
||||||
console.log('CLIENT RESPONSE', gptResponse);
|
|
||||||
|
|
||||||
if (!gptResponse.parentMessageId) {
|
// STEP1 generate response message
|
||||||
gptResponse.parentMessageId = overrideParentMessageId || userMessageId;
|
response.text = response.response || '**ChatGPT refused to answer.**';
|
||||||
delete gptResponse.response;
|
|
||||||
|
let responseMessage = {
|
||||||
|
conversationId: response.conversationId,
|
||||||
|
messageId: response.messageId,
|
||||||
|
parentMessageId: overrideParentMessageId || response.parentMessageId || userMessageId,
|
||||||
|
text: await handleText(response),
|
||||||
|
sender: endpointOption?.chatGptLabel || 'ChatGPT'
|
||||||
|
};
|
||||||
|
|
||||||
|
await saveMessage(responseMessage);
|
||||||
|
|
||||||
|
// STEP2 update the conversation
|
||||||
|
conversationId = responseMessage.conversationId || conversationId;
|
||||||
|
|
||||||
|
// First update conversationId if needed
|
||||||
|
let conversationUpdate = { conversationId, endpoint: 'chatGPTBrowser' };
|
||||||
|
if (conversationId != responseMessage.conversationId && isNewConversation)
|
||||||
|
conversationUpdate = {
|
||||||
|
...conversationUpdate,
|
||||||
|
conversationId: conversationId,
|
||||||
|
newConversationId: responseMessage.conversationId || conversationId
|
||||||
|
};
|
||||||
|
conversationId = responseMessage.conversationId || conversationId;
|
||||||
|
|
||||||
|
await saveConvo(req?.session?.user?.username, conversationUpdate);
|
||||||
|
|
||||||
|
// STEP3 update the user message
|
||||||
|
userMessage.conversationId = conversationId;
|
||||||
|
userMessage.messageId = responseMessage.parentMessageId;
|
||||||
|
|
||||||
|
// If response has parentMessageId, the fake userMessage.messageId should be updated to the real one.
|
||||||
|
if (!overrideParentMessageId) {
|
||||||
|
const oldUserMessageId = userMessageId;
|
||||||
|
await saveMessage({ ...userMessage, messageId: oldUserMessageId, newMessageId: userMessage.messageId });
|
||||||
}
|
}
|
||||||
|
userMessageId = userMessage.messageId;
|
||||||
gptResponse.sender = 'ChatGPT';
|
|
||||||
// gptResponse.model = model;
|
|
||||||
gptResponse.text = await handleText(gptResponse);
|
|
||||||
// if (convo.chatGptLabel?.length > 0 && model === 'chatgptCustom') {
|
|
||||||
// gptResponse.chatGptLabel = convo.chatGptLabel;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (convo.promptPrefix?.length > 0 && model === 'chatgptCustom') {
|
|
||||||
// gptResponse.promptPrefix = convo.promptPrefix;
|
|
||||||
// }
|
|
||||||
|
|
||||||
gptResponse.parentMessageId = overrideParentMessageId || userMessageId;
|
|
||||||
|
|
||||||
if (userParentMessageId.startsWith('000')) {
|
|
||||||
await saveMessage({ ...userMessage, conversationId: gptResponse.conversationId });
|
|
||||||
}
|
|
||||||
|
|
||||||
await saveMessage(gptResponse);
|
|
||||||
await updateConvo(req?.session?.user?.username, {
|
|
||||||
...gptResponse,
|
|
||||||
oldConvoId: conversationId
|
|
||||||
});
|
|
||||||
|
|
||||||
sendMessage(res, {
|
sendMessage(res, {
|
||||||
title: await getConvoTitle(req?.session?.user?.username, conversationId),
|
title: await getConvoTitle(req?.session?.user?.username, conversationId),
|
||||||
final: true,
|
final: true,
|
||||||
conversation: await getConvo(req?.session?.user?.username, conversationId),
|
conversation: await getConvo(req?.session?.user?.username, conversationId),
|
||||||
requestMessage: userMessage,
|
requestMessage: userMessage,
|
||||||
responseMessage: gptResponse
|
responseMessage: responseMessage
|
||||||
});
|
});
|
||||||
res.end();
|
res.end();
|
||||||
|
|
||||||
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
||||||
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response: gptResponse });
|
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response: responseMessage });
|
||||||
await updateConvo(req?.session?.user?.username, {
|
await updateConvo(req?.session?.user?.username, {
|
||||||
conversationId: gptResponse.conversationId,
|
conversationId: conversationId,
|
||||||
title
|
title
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
const { getOpenAIModels } = require('../endpoints');
|
||||||
const { titleConvo, askClient } = require('../../../app/');
|
const { titleConvo, askClient } = require('../../../app/');
|
||||||
const { saveMessage, getConvoTitle, saveConvo, updateConvo, getConvo } = require('../../../models');
|
const { saveMessage, getConvoTitle, saveConvo, updateConvo, getConvo } = require('../../../models');
|
||||||
const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers');
|
const { handleError, sendMessage, createOnProgress, handleText } = require('./handlers');
|
||||||
|
|
@ -40,6 +41,10 @@ router.post('/', async (req, res) => {
|
||||||
frequency_penalty: req.body?.frequency_penalty || 0
|
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' });
|
||||||
|
|
||||||
console.log('ask log', {
|
console.log('ask log', {
|
||||||
userMessage,
|
userMessage,
|
||||||
endpointOption,
|
endpointOption,
|
||||||
|
|
@ -150,7 +155,7 @@ const ask = async ({
|
||||||
res.end();
|
res.end();
|
||||||
|
|
||||||
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
if (userParentMessageId == '00000000-0000-0000-0000-000000000000') {
|
||||||
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response });
|
const title = await titleConvo({ endpoint: endpointOption?.endpoint, text, response: responseMessage });
|
||||||
await updateConvo(req?.session?.user?.username, {
|
await updateConvo(req?.session?.user?.username, {
|
||||||
conversationId: conversationId,
|
conversationId: conversationId,
|
||||||
title
|
title
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,27 @@
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
|
const getOpenAIModels = () => {
|
||||||
|
let models = ['gpt-4', 'text-davinci-003', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301'];
|
||||||
|
if (process.env.OPENAI_MODELS) models = String(process.env.OPENAI_MODELS).split(',');
|
||||||
|
|
||||||
|
return models;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getChatGPTBrowserModels = () => {
|
||||||
|
let models = ['text-davinci-002-render-sha', 'text-davinci-002-render-paid', 'gpt-4'];
|
||||||
|
if (process.env.CHATGPT_MODELS) models = String(process.env.CHATGPT_MODELS).split(',');
|
||||||
|
|
||||||
|
return models;
|
||||||
|
};
|
||||||
|
|
||||||
router.get('/', function (req, res) {
|
router.get('/', function (req, res) {
|
||||||
const azureOpenAI = !!process.env.AZURE_OPENAI_KEY;
|
const azureOpenAI = !!process.env.AZURE_OPENAI_KEY;
|
||||||
const openAI = process.env.OPENAI_KEY
|
const openAI = process.env.OPENAI_KEY ? { availableModels: getOpenAIModels() } : false;
|
||||||
? { availableModels: ['gpt-4', 'text-davinci-003', 'gpt-3.5-turbo', 'gpt-3.5-turbo-0301'] }
|
const bingAI = !!process.env.BINGAI_TOKEN;
|
||||||
: false;
|
const chatGPTBrowser = process.env.CHATGPT_TOKEN ? { availableModels: getChatGPTBrowserModels() } : false;
|
||||||
const bingAI = !!process.env.BING_TOKEN;
|
|
||||||
const chatGPTBrowser = process.env.OPENAI_KEY
|
|
||||||
? { availableModels: ['Default (GPT-3.5)', 'Legacy (GPT-3.5)', 'GPT-4'] }
|
|
||||||
: false;
|
|
||||||
|
|
||||||
res.send(JSON.stringify({ azureOpenAI, openAI, bingAI, chatGPTBrowser }));
|
res.send(JSON.stringify({ azureOpenAI, openAI, bingAI, chatGPTBrowser }));
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = { router, getOpenAIModels, getChatGPTBrowserModels };
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ const prompts = require('./prompts');
|
||||||
const search = require('./search');
|
const search = require('./search');
|
||||||
const tokenizer = require('./tokenizer');
|
const tokenizer = require('./tokenizer');
|
||||||
const me = require('./me');
|
const me = require('./me');
|
||||||
const endpoints = require('./endpoints');
|
const { router: endpoints } = require('./endpoints');
|
||||||
const { router: auth, authenticatedOr401, authenticatedOrRedirect } = require('./auth');
|
const { router: auth, authenticatedOr401, authenticatedOrRedirect } = require('./auth');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,18 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
||||||
const setPresets = useSetRecoilState(store.presets);
|
const setPresets = useSetRecoilState(store.presets);
|
||||||
|
|
||||||
const availableEndpoints = useRecoilValue(store.availableEndpoints);
|
const availableEndpoints = useRecoilValue(store.availableEndpoints);
|
||||||
|
const endpointsFilter = useRecoilValue(store.endpointsFilter);
|
||||||
|
|
||||||
const setOption = param => newValue => {
|
const setOption = param => newValue => {
|
||||||
let update = {};
|
let update = {};
|
||||||
update[param] = newValue;
|
update[param] = newValue;
|
||||||
setPreset(prevState =>
|
setPreset(prevState =>
|
||||||
cleanupPreset({
|
cleanupPreset({
|
||||||
...prevState,
|
preset: {
|
||||||
...update
|
...prevState,
|
||||||
|
...update
|
||||||
|
},
|
||||||
|
endpointsFilter
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -38,7 +43,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
||||||
axios({
|
axios({
|
||||||
method: 'post',
|
method: 'post',
|
||||||
url: '/api/presets',
|
url: '/api/presets',
|
||||||
data: cleanupPreset(preset),
|
data: cleanupPreset({ preset, endpointsFilter }),
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
setPresets(res?.data);
|
setPresets(res?.data);
|
||||||
|
|
@ -47,7 +52,7 @@ const EditPresetDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
||||||
|
|
||||||
const exportPreset = () => {
|
const exportPreset = () => {
|
||||||
exportFromJSON({
|
exportFromJSON({
|
||||||
data: cleanupPreset(preset),
|
data: cleanupPreset({ preset, endpointsFilter }),
|
||||||
fileName: `${preset?.title}.json`,
|
fileName: `${preset?.title}.json`,
|
||||||
exportType: exportFromJSON.types.json
|
exportType: exportFromJSON.types.json
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
import exportFromJSON from 'export-from-json';
|
import exportFromJSON from 'export-from-json';
|
||||||
import DialogTemplate from '../ui/DialogTemplate.jsx';
|
import DialogTemplate from '../ui/DialogTemplate.jsx';
|
||||||
import { Dialog, DialogButton } from '../ui/Dialog.tsx';
|
import { Dialog, DialogButton } from '../ui/Dialog.tsx';
|
||||||
|
|
@ -7,12 +8,15 @@ import cleanupPreset from '~/utils/cleanupPreset';
|
||||||
|
|
||||||
import Settings from './Settings';
|
import Settings from './Settings';
|
||||||
|
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
// A preset dialog to show readonly preset values.
|
// A preset dialog to show readonly preset values.
|
||||||
const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) => {
|
||||||
// const [title, setTitle] = useState('My Preset');
|
// const [title, setTitle] = useState('My Preset');
|
||||||
const [preset, setPreset] = useState(_preset);
|
const [preset, setPreset] = useState(_preset);
|
||||||
|
|
||||||
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
|
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
|
||||||
|
const endpointsFilter = useRecoilValue(store.endpointsFilter);
|
||||||
|
|
||||||
const setOption = param => newValue => {
|
const setOption = param => newValue => {
|
||||||
let update = {};
|
let update = {};
|
||||||
|
|
@ -29,7 +33,7 @@ const EndpointOptionsDialog = ({ open, onOpenChange, preset: _preset, title }) =
|
||||||
|
|
||||||
const exportPreset = () => {
|
const exportPreset = () => {
|
||||||
exportFromJSON({
|
exportFromJSON({
|
||||||
data: cleanupPreset(preset),
|
data: cleanupPreset({ preset, endpointsFilter }),
|
||||||
fileName: `${preset?.title}.json`,
|
fileName: `${preset?.title}.json`,
|
||||||
exportType: exportFromJSON.types.json
|
exportType: exportFromJSON.types.json
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState, useRecoilValue } from 'recoil';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import DialogTemplate from '../ui/DialogTemplate';
|
import DialogTemplate from '../ui/DialogTemplate';
|
||||||
import { Dialog } from '../ui/Dialog.tsx';
|
import { Dialog } from '../ui/Dialog.tsx';
|
||||||
|
|
@ -13,14 +13,18 @@ import store from '~/store';
|
||||||
const SaveAsPresetDialog = ({ open, onOpenChange, preset }) => {
|
const SaveAsPresetDialog = ({ open, onOpenChange, preset }) => {
|
||||||
const [title, setTitle] = useState(preset?.title || 'My Preset');
|
const [title, setTitle] = useState(preset?.title || 'My Preset');
|
||||||
const setPresets = useSetRecoilState(store.presets);
|
const setPresets = useSetRecoilState(store.presets);
|
||||||
|
const endpointsFilter = useRecoilValue(store.endpointsFilter);
|
||||||
|
|
||||||
const defaultTextProps =
|
const defaultTextProps =
|
||||||
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||||
|
|
||||||
const submitPreset = () => {
|
const submitPreset = () => {
|
||||||
const _preset = cleanupPreset({
|
const _preset = cleanupPreset({
|
||||||
...preset,
|
preset: {
|
||||||
title
|
...preset,
|
||||||
|
title
|
||||||
|
},
|
||||||
|
endpointsFilter
|
||||||
});
|
});
|
||||||
|
|
||||||
axios({
|
axios({
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,12 @@ function ChatGPTOptions() {
|
||||||
|
|
||||||
const models = endpointsConfig?.['chatGPTBrowser']?.['availableModels'] || [];
|
const models = endpointsConfig?.['chatGPTBrowser']?.['availableModels'] || [];
|
||||||
|
|
||||||
|
// const modelMap = new Map([
|
||||||
|
// ['Default (GPT-3.5)', 'text-davinci-002-render-sha'],
|
||||||
|
// ['Legacy (GPT-3.5)', 'text-davinci-002-render-paid'],
|
||||||
|
// ['GPT-4', 'gpt-4']
|
||||||
|
// ]);
|
||||||
|
|
||||||
const setOption = param => newValue => {
|
const setOption = param => newValue => {
|
||||||
let update = {};
|
let update = {};
|
||||||
update[param] = newValue;
|
update[param] = newValue;
|
||||||
|
|
@ -43,7 +49,7 @@ function ChatGPTOptions() {
|
||||||
showLabel={false}
|
showLabel={false}
|
||||||
className={cn(
|
className={cn(
|
||||||
cardStyle,
|
cardStyle,
|
||||||
'min-w-48 z-50 flex h-[40px] w-48 flex-none items-center justify-center px-4 ring-0 hover:cursor-pointer hover:bg-slate-50 focus:ring-0 focus:ring-offset-0 data-[state=open]:bg-slate-50 dark:bg-gray-700 dark:hover:bg-gray-600 dark:data-[state=open]:bg-gray-600'
|
'z-50 flex h-[40px] w-[260px] min-w-[260px] flex-none items-center justify-center px-4 ring-0 hover:cursor-pointer hover:bg-slate-50 focus:ring-0 focus:ring-offset-0 data-[state=open]:bg-slate-50 dark:bg-gray-700 dark:hover:bg-gray-600 dark:data-[state=open]:bg-gray-600'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSetRecoilState } from 'recoil';
|
|
||||||
import { FileUp } from 'lucide-react';
|
import { FileUp } from 'lucide-react';
|
||||||
import store from '~/store';
|
|
||||||
import axios from 'axios';
|
|
||||||
import cleanupPreset from '~/utils/cleanupPreset.js';
|
import cleanupPreset from '~/utils/cleanupPreset.js';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
// async function fetchPresets(callback) {
|
// async function fetchPresets(callback) {
|
||||||
// try {
|
// try {
|
||||||
|
|
@ -21,6 +21,7 @@ import cleanupPreset from '~/utils/cleanupPreset.js';
|
||||||
|
|
||||||
const FileUpload = ({ onFileSelected }) => {
|
const FileUpload = ({ onFileSelected }) => {
|
||||||
// const setPresets = useSetRecoilState(store.presets);
|
// const setPresets = useSetRecoilState(store.presets);
|
||||||
|
const endpointsFilter = useRecoilValue(store.endpointsFilter);
|
||||||
|
|
||||||
const handleFileChange = event => {
|
const handleFileChange = event => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
|
|
@ -29,7 +30,7 @@ const FileUpload = ({ onFileSelected }) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = e => {
|
reader.onload = e => {
|
||||||
const jsonData = JSON.parse(e.target.result);
|
const jsonData = JSON.parse(e.target.result);
|
||||||
onFileSelected({ ...cleanupPreset(jsonData), presetId: null });
|
onFileSelected({ ...cleanupPreset({ preset: jsonData, endpointsFilter }), presetId: null });
|
||||||
};
|
};
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const cleanupPreset = _preset => {
|
const cleanupPreset = ({ preset: _preset, endpointsFilter = {} }) => {
|
||||||
const { endpoint } = _preset;
|
const { endpoint } = _preset;
|
||||||
|
|
||||||
let preset = {};
|
let preset = {};
|
||||||
|
|
@ -6,7 +6,7 @@ const cleanupPreset = _preset => {
|
||||||
preset = {
|
preset = {
|
||||||
endpoint,
|
endpoint,
|
||||||
presetId: _preset?.presetId ?? null,
|
presetId: _preset?.presetId ?? null,
|
||||||
model: _preset?.model ?? 'gpt-3.5-turbo',
|
model: _preset?.model ?? endpointsFilter[endpoint]?.availableModels?.[0] ?? 'gpt-3.5-turbo',
|
||||||
chatGptLabel: _preset?.chatGptLabel ?? null,
|
chatGptLabel: _preset?.chatGptLabel ?? null,
|
||||||
promptPrefix: _preset?.promptPrefix ?? null,
|
promptPrefix: _preset?.promptPrefix ?? null,
|
||||||
temperature: _preset?.temperature ?? 1,
|
temperature: _preset?.temperature ?? 1,
|
||||||
|
|
@ -25,11 +25,12 @@ const cleanupPreset = _preset => {
|
||||||
toneStyle: _preset?.toneStyle ?? 'fast',
|
toneStyle: _preset?.toneStyle ?? 'fast',
|
||||||
title: _preset?.title ?? 'New Preset'
|
title: _preset?.title ?? 'New Preset'
|
||||||
};
|
};
|
||||||
} else if (endpoint === 'chatGPTBrowser') {
|
} else if (endpoint === 'chatGPT') {
|
||||||
preset = {
|
preset = {
|
||||||
endpoint,
|
endpoint,
|
||||||
presetId: _preset?.presetId ?? null,
|
presetId: _preset?.presetId ?? null,
|
||||||
model: _preset?.model ?? 'Default (GPT-3.5)',
|
model:
|
||||||
|
_preset?.model ?? endpointsFilter[endpoint]?.availableModels?.[0] ?? 'text-davinci-002-render-sha',
|
||||||
title: _preset?.title ?? 'New Preset'
|
title: _preset?.title ?? 'New Preset'
|
||||||
};
|
};
|
||||||
} else if (endpoint === null) {
|
} else if (endpoint === null) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
const buildDefaultConversation = ({ conversation, endpoint, lastConversationSetup = {} }) => {
|
const buildDefaultConversation = ({
|
||||||
|
conversation,
|
||||||
|
endpoint,
|
||||||
|
endpointsFilter = {},
|
||||||
|
lastConversationSetup = {}
|
||||||
|
}) => {
|
||||||
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
||||||
conversation = {
|
conversation = {
|
||||||
...conversation,
|
...conversation,
|
||||||
endpoint,
|
endpoint,
|
||||||
model: lastConversationSetup?.model ?? 'gpt-3.5-turbo',
|
model:
|
||||||
|
lastConversationSetup?.model ?? endpointsFilter[endpoint]?.availableModels?.[0] ?? 'gpt-3.5-turbo',
|
||||||
chatGptLabel: lastConversationSetup?.chatGptLabel ?? null,
|
chatGptLabel: lastConversationSetup?.chatGptLabel ?? null,
|
||||||
promptPrefix: lastConversationSetup?.promptPrefix ?? null,
|
promptPrefix: lastConversationSetup?.promptPrefix ?? null,
|
||||||
temperature: lastConversationSetup?.temperature ?? 1,
|
temperature: lastConversationSetup?.temperature ?? 1,
|
||||||
|
|
@ -28,7 +34,10 @@ const buildDefaultConversation = ({ conversation, endpoint, lastConversationSetu
|
||||||
conversation = {
|
conversation = {
|
||||||
...conversation,
|
...conversation,
|
||||||
endpoint,
|
endpoint,
|
||||||
model: lastConversationSetup?.model ?? 'Default (GPT-3.5)'
|
model:
|
||||||
|
lastConversationSetup?.model ??
|
||||||
|
endpointsFilter[endpoint]?.availableModels?.[0] ??
|
||||||
|
'text-davinci-002-render-sha'
|
||||||
};
|
};
|
||||||
} else if (endpoint === null) {
|
} else if (endpoint === null) {
|
||||||
conversation = {
|
conversation = {
|
||||||
|
|
@ -56,7 +65,8 @@ const getDefaultConversation = ({ conversation, prevConversation, endpointsFilte
|
||||||
conversation = buildDefaultConversation({
|
conversation = buildDefaultConversation({
|
||||||
conversation,
|
conversation,
|
||||||
endpoint,
|
endpoint,
|
||||||
lastConversationSetup: preset
|
lastConversationSetup: preset,
|
||||||
|
endpointsFilter
|
||||||
});
|
});
|
||||||
return conversation;
|
return conversation;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -72,7 +82,8 @@ const getDefaultConversation = ({ conversation, prevConversation, endpointsFilte
|
||||||
// conversation = buildDefaultConversation({
|
// conversation = buildDefaultConversation({
|
||||||
// conversation,
|
// conversation,
|
||||||
// endpoint,
|
// endpoint,
|
||||||
// lastConversationSetup: prevConversation
|
// lastConversationSetup: prevConversation,
|
||||||
|
// endpointsFilter
|
||||||
// });
|
// });
|
||||||
// return conversation;
|
// return conversation;
|
||||||
// }
|
// }
|
||||||
|
|
@ -84,7 +95,7 @@ const getDefaultConversation = ({ conversation, prevConversation, endpointsFilte
|
||||||
const { endpoint = null } = lastConversationSetup;
|
const { endpoint = null } = lastConversationSetup;
|
||||||
|
|
||||||
if (endpointsFilter?.[endpoint]) {
|
if (endpointsFilter?.[endpoint]) {
|
||||||
conversation = buildDefaultConversation({ conversation, endpoint });
|
conversation = buildDefaultConversation({ conversation, endpoint, endpointsFilter });
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
@ -93,10 +104,10 @@ const getDefaultConversation = ({ conversation, prevConversation, endpointsFilte
|
||||||
|
|
||||||
const endpoint = ['openAI', 'azureOpenAI', 'bingAI', 'chatGPTBrowser'].find(e => endpointsFilter?.[e]);
|
const endpoint = ['openAI', 'azureOpenAI', 'bingAI', 'chatGPTBrowser'].find(e => endpointsFilter?.[e]);
|
||||||
if (endpoint) {
|
if (endpoint) {
|
||||||
conversation = buildDefaultConversation({ conversation, endpoint });
|
conversation = buildDefaultConversation({ conversation, endpoint, endpointsFilter });
|
||||||
return conversation;
|
return conversation;
|
||||||
} else {
|
} else {
|
||||||
conversation = buildDefaultConversation({ conversation, endpoint: null });
|
conversation = buildDefaultConversation({ conversation, endpoint: null, endpointsFilter });
|
||||||
return conversation;
|
return conversation;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ const useMessageHandler = () => {
|
||||||
const currentConversation = useRecoilValue(store.conversation) || {};
|
const currentConversation = useRecoilValue(store.conversation) || {};
|
||||||
const setSubmission = useSetRecoilState(store.submission);
|
const setSubmission = useSetRecoilState(store.submission);
|
||||||
const isSubmitting = useRecoilValue(store.isSubmitting);
|
const isSubmitting = useRecoilValue(store.isSubmitting);
|
||||||
|
const endpointsFilter = useRecoilValue(store.endpointsFilter);
|
||||||
|
|
||||||
const latestMessage = useRecoilValue(store.latestMessage);
|
const latestMessage = useRecoilValue(store.latestMessage);
|
||||||
|
|
||||||
|
|
@ -27,7 +28,8 @@ const useMessageHandler = () => {
|
||||||
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
if (endpoint === 'azureOpenAI' || endpoint === 'openAI') {
|
||||||
endpointOption = {
|
endpointOption = {
|
||||||
endpoint,
|
endpoint,
|
||||||
model: currentConversation?.model ?? 'gpt-3.5-turbo',
|
model:
|
||||||
|
currentConversation?.model ?? endpointsFilter[endpoint]?.availableModels?.[0] ?? 'gpt-3.5-turbo',
|
||||||
chatGptLabel: currentConversation?.chatGptLabel ?? null,
|
chatGptLabel: currentConversation?.chatGptLabel ?? null,
|
||||||
promptPrefix: currentConversation?.promptPrefix ?? null,
|
promptPrefix: currentConversation?.promptPrefix ?? null,
|
||||||
temperature: currentConversation?.temperature ?? 1,
|
temperature: currentConversation?.temperature ?? 1,
|
||||||
|
|
@ -52,7 +54,10 @@ const useMessageHandler = () => {
|
||||||
} else if (endpoint === 'chatGPTBrowser') {
|
} else if (endpoint === 'chatGPTBrowser') {
|
||||||
endpointOption = {
|
endpointOption = {
|
||||||
endpoint,
|
endpoint,
|
||||||
model: currentConversation?.model ?? 'Default (GPT-3.5)'
|
model:
|
||||||
|
currentConversation?.model ??
|
||||||
|
endpointsFilter[endpoint]?.availableModels?.[0] ??
|
||||||
|
'text-davinci-002-render-sha'
|
||||||
};
|
};
|
||||||
responseSender = 'ChatGPT';
|
responseSender = 'ChatGPT';
|
||||||
} else if (endpoint === null) {
|
} else if (endpoint === null) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue