Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 14 additions & 19 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,17 @@ OPENAI_MODELS=gpt-3.5-turbo,gpt-3.5-turbo-0301,text-davinci-003,gpt-4,gpt-4-0314

# To use Azure with this project, set the following variables. These will be used to build the API URL.
# Chat completion:
# `https://{AZURE_OPENAI_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/{AZURE_OPENAI_API_DEPLOYMENT_NAME}/chat/completions?api-version={AZURE_OPENAI_API_VERSION}`;
# `https://{AZURE_OPENAI_API_INSTANCE_NAME}.openai.azure.com/openai/deployments/{AZURE_OPENAI_API_DEPLOYMENT_NAME}/chat/completions?api-version={AZURE_OPENAI_API_VERSION}`;
# You should also consider changing the `OPENAI_MODELS` variable above to the models available in your instance/deployment.
# Note: I've noticed that the Azure API is much faster than the OpenAI API, so the streaming looks almost instantaneous.
# Note "AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME" and "AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME" are optional but might be used in the future

# AZURE_OPENAI_API_KEY=
# AZURE_OPENAI_API_INSTANCE_NAME=
# AZURE_OPENAI_API_DEPLOYMENT_NAME=
# AZURE_OPENAI_API_VERSION=
# AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME= # Optional, but may be used in future updates
# AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME= # Optional, but may be used in future updates
# AZURE_OPENAI_API_COMPLETIONS_DEPLOYMENT_NAME=
# AZURE_OPENAI_API_EMBEDDINGS_DEPLOYMENT_NAME=

##########################
# BingAI Endpoint:
Expand Down Expand Up @@ -120,27 +121,18 @@ SD_WEBUI_URL=http://0.0.0.0:7860
# PaLM (Google) Endpoint:
##########################

# PaLM 2 Client (via Google Cloud Vertex AI API)
# Steps:
# Enable the Vertex AI API on Google Cloud:
# https://console.cloud.google.com/vertex-ai
# Create a Service Account:
# https://console.cloud.google.com/projectselector/iam-admin/serviceaccounts/create?walkthrough_id=iam--create-service-account#step_index=1
# Make sure to click 'Create and Continue' to give at least the 'Vertex AI User' role.
# Create a JSON key, rename as 'auth.json' and save it in /api/data/.
# Alternatively
# Uncomment below PALM_KEY and set as "user_provided" to allow the user to provide a Service Account key JSON from the UI.
# They will follow the steps above except for renaming the file.
# Leave blank or omit to disable this endpoint
# Follow the instruction here to setup:
# https://github.com/danny-avila/LibreChat/blob/main/docs/install/apis_and_tokens.md

# PALM_KEY="user_provided"
PALM_KEY="user_provided"

# In case you need a reverse proxy for this endpoint:
# GOOGLE_REVERSE_PROXY=

##########################
# Proxy: To be Used by all endpoints
##########################

PROXY=

##########################
Expand Down Expand Up @@ -189,9 +181,12 @@ SESSION_EXPIRY=(1000 * 60 * 60 * 24) * 7

###########################
# Application Domains
# Note: server = backend, client = pubilc (url you visit)
###########################
DOMAIN_CLIENT=http://localhost:3090

# Note: server = backend, client = public (the client is the url you visit)
# For the google login to work in dev mode, you will likely need to change DOMAIN_SERVER to localhost:3090 or place it in .env.development

DOMAIN_CLIENT=http://localhost:3080
DOMAIN_SERVER=http://localhost:3080

###########################
Expand All @@ -208,4 +203,4 @@ VITE_APP_TITLE="LibreChat"
VITE_SHOW_GOOGLE_LOGIN_OPTION=false

# Allow Public Registration
ALLOW_REGISTRATION=true
ALLOW_REGISTRATION=true
24 changes: 7 additions & 17 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
# Base node image
FROM node:19-alpine AS base
WORKDIR /api
COPY /api/package*.json /api/
WORKDIR /client
COPY /client/package*.json /client/
WORKDIR /
COPY /package*.json /
FROM node:19-alpine AS node
COPY . /app
# Install dependencies
WORKDIR /app
RUN npm ci

# React client build
FROM base AS react-client
WORKDIR /client
COPY /client/ /client/
ENV NODE_OPTIONS="--max-old-space-size=2048"
RUN npm run build
RUN npm run frontend

# Node API setup
FROM base AS node-api
WORKDIR /api
COPY /api/ /api/
COPY --from=react-client /client/dist /client/dist
EXPOSE 3080
ENV HOST=0.0.0.0
CMD ["npm", "start"]
CMD ["npm", "run", "backend"]

# Optional: for client with nginx routing
FROM nginx:stable-alpine AS nginx-client
WORKDIR /usr/share/nginx/html
COPY --from=react-client /client/dist /usr/share/nginx/html
COPY --from=node /app/client/dist /usr/share/nginx/html
COPY client/nginx.conf /etc/nginx/conf.d/default.conf
ENTRYPOINT ["nginx", "-g", "daemon off;"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

**Alternatively**

- In your ./api/.env file, set PALM_KEY as "user_provided" to allow the user to provide a Service Account key JSON from the UI.
- In your /.env file, set PALM_KEY as "user_provided" to allow the user to provide a Service Account key JSON from the UI.
- They will follow the steps above except for renaming the file, simply importing the JSON when prompted.
- The key is sent to the server but never saved except in your local storage

Expand Down
2 changes: 1 addition & 1 deletion api/server/routes/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const express = require('express');
const router = express.Router();
const config = require('../../../config/loader');
const domains = config.domains;
const isProduction = process.env.NODE_ENV;
const isProduction = config.isProduction;

/**
* Google Routes
Expand Down
6 changes: 3 additions & 3 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"version": "0.4.8",
"description": "",
"scripts": {
"build": "cross-env NODE_ENV=production dotenv -e ../.env -- vite build",
"dev": "cross-env NODE_ENV=dev dotenv -e ../.env -- vite",
"preview-prod": "cross-env NODE_ENV=dev dotenv -e ../.env -- vite preview",
"build": "cross-env NODE_ENV=production vite build",
"dev": "cross-env NODE_ENV=development vite",
"preview-prod": "cross-env NODE_ENV=dev vite preview",
"test": "cross-env NODE_ENV=test jest --watch",
"test:ci": "cross-env NODE_ENV=test jest --ci"
},
Expand Down
1 change: 1 addition & 0 deletions client/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default defineConfig({
}
},
// All other env variables are filtered out
envDir: '../',
envPrefix: ['VITE_', 'SCRIPT_', 'DOMAIN_', 'ALLOW_'],
plugins: [react(), sourcemapExclude({ excludeNodeModules: true })],
publicDir: './public',
Expand Down
4 changes: 2 additions & 2 deletions config/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class Env {
constructor() {
this.envMap = {
default: '.env',
development: '.env.dev',
development: '.env.development',
test: '.env.test',
production: '.env.prod',
production: '.env.production',
}

this.init();
Expand Down
30 changes: 16 additions & 14 deletions config/upgrade.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const initEnv = JSON.parse(JSON.stringify(process.env));

// New Paths
const rootEnvPath = loader.resolve('.env');
const devEnvPath = loader.resolve('.env.dev');
const prodEnvPath = loader.resolve('.env.prod');
const devEnvPath = loader.resolve('.env.development');
const prodEnvPath = loader.resolve('.env.production');

if (fs.existsSync(rootEnvPath)) {
console.error('Root env file already exists! Aborting');
Expand All @@ -53,12 +53,7 @@ if (!fs.existsSync(clientEnvPath)) {
* @param {*} varName
*/
function refactorPairedEnvVar(varDev, varProd, varName) {
// Manual fix for PROD DOMAIN_CLIENT as it was incorrect in the old env
if (varName === 'DOMAIN_CLIENT') {
initEnv[varProd] = initEnv[varProd] ? initEnv[varProd].replace('3080', '3090') : 'http://localhost:3090'
initEnv[varDev] = initEnv[varDev] ? initEnv[varDev].replace('3080', '3090') : 'http://localhost:3090'
}
// Lets validate if either of these are undefined, if so lets use the non-unefined one
// Lets validate if either of these are undefined, if so lets use the non-undefined one
if (initEnv[varDev] === undefined && initEnv[varProd] === undefined) {
console.error(`Both ${varDev} and ${varProd} are undefined! Manual intervention required!`);
} else if (initEnv[varDev] === undefined) {
Expand All @@ -68,17 +63,16 @@ function refactorPairedEnvVar(varDev, varProd, varName) {
} else if (initEnv[varDev] === initEnv[varProd]) {
fs.appendFileSync(rootEnvPath, `\n${varName}=${initEnv[varDev]}`);
} else {
fs.appendFileSync(rootEnvPath, `${varName}=${initEnv[varDev]}\n`);
fs.appendFileSync(rootEnvPath, `${varName}=${initEnv[varProd]}\n`);
fs.appendFileSync(devEnvPath, `${varName}=${initEnv[varDev]}\n`);
fs.appendFileSync(prodEnvPath, `${varName}=${initEnv[varProd]}\n`);
}
}

/**
* Upgrade the env files!
* 1. /api/.env will merge into /.env
* 2. /client/.env will merge into /.env
* 3. Any prod_/dev_ keys will be split up into .env.dev / .env.prod files (if they are different)
* 3. Any prod_/dev_ keys will be split up into .env.development / .env.production files (if they are different)
*/
if (fs.existsSync(apiEnvPath)) {
fs.copyFileSync(apiEnvPath, rootEnvPath);
Expand Down Expand Up @@ -129,13 +123,13 @@ loader.writeEnvFile(rootEnvPath, {'OPENAI_API_KEY': initEnv['OPENAI_KEY']})
// TODO: we need to copy over the value of: VITE_SHOW_GOOGLE_LOGIN_OPTION & VITE_APP_TITLE
fs.appendFileSync(rootEnvPath, '\n\n##########################\n# Frontend Vite Variables:\n##########################\n');
const frontend = {
'VITE_APP_TITLE': initEnv['VITE_APP_TITLE'] || '"ChatGPT Clone"',
'VITE_APP_TITLE': initEnv['VITE_APP_TITLE'] || '"LibreChat"',
'VITE_SHOW_GOOGLE_LOGIN_OPTION': initEnv['VITE_SHOW_GOOGLE_LOGIN_OPTION'] || 'false',
'ALLOW_REGISTRATION': 'true'
}
loader.writeEnvFile(rootEnvPath, frontend)

// Ensure .env.dev and .env.prod files end with a newline
// Ensure .env.development and .env.production files end with a newline
if (fs.existsSync(devEnvPath)) {
fs.appendFileSync(devEnvPath, '\n');
}
Expand All @@ -146,4 +140,12 @@ if (fs.existsSync(prodEnvPath)) {
fs.copyFileSync(clientEnvPath, rootEnvPath + '.client.bak');
fs.unlinkSync(clientEnvPath);

console.log('Upgrade complete.');
console.log('###############################################')
console.log('Upgrade completed! Please review the new .env file and make any changes as needed.');
console.log('###############################################')

// if the .env.development file exists, lets tell the user
if (fs.existsSync(devEnvPath)) {
console.log('NOTE: A .env.development file was created. This will take precedence over the .env file when running in dev mode.');
console.log('###############################################')
}
18 changes: 10 additions & 8 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,30 @@ services:
- 3080:3080 # Change it to 9000:3080 to use nginx
depends_on:
- mongodb
image: node-api # Comment this & uncomment below to build from docker hub image
image: node # Comment this & uncomment below to build from docker hub image
build:
context: .
target: node-api
target: node
# image: chatgptclone/app:latest # Uncomment this & comment above to build from docker hub image
restart: always
# extra_hosts: # if you are running APIs on docker you need access to, you will need to uncomment this line and next
# - "host.docker.internal:host-gateway"
env_file:
- ./api/.env
- .env
environment:
- HOST=0.0.0.0
- NODE_ENV=production
- MONGO_URI=mongodb://mongodb:27017/LibreChat
# - CHATGPT_REVERSE_PROXY=http://host.docker.internal:8080/api/conversation # if you are hosting your own chatgpt reverse proxy with docker
# - OPENAI_REVERSE_PROXY=http://host.docker.internal:8070/v1/chat/completions # if you are hosting your own chatgpt reverse proxy with docker
- MEILI_HOST=http://meilisearch:7700
- MEILI_HTTP_ADDR=meilisearch:7700
volumes:
- /client/node_modules
- ./api:/api
- /api/node_modules
- /app/client/node_modules
- ./api:/app/api
- ./.env:/app/.env
- ./.env.development:/app/.env.development
- ./.env.production:/app/.env.production
- /app/api/node_modules
mongodb:
container_name: chat-mongodb
ports:
Expand All @@ -56,7 +58,7 @@ services:
ports:
- 7700:7700
env_file:
- ./api/.env
- .env
environment:
- MEILI_HOST=http://meilisearch:7700
- MEILI_HTTP_ADDR=meilisearch:7700
Expand Down
2 changes: 1 addition & 1 deletion docs/features/plugins/stable_diffusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ To use Stable Diffusion with this project, you will need to download and install

4. In the app, select the plugins endpoint, open the plugins store, and install Stable Diffusion
- You will need the stable diffusion webui API URL, which should be `http://127.0.0.1:7860`
- Alternatively: you (the admin) can set the value in `api\.env` to bypass the prompt
- Alternatively: you (the admin) can set the value in `\.env` to bypass the prompt
- `SD_WEBUI_URL=http://127.0.0.1:7860`

![image](https://github.com/danny-avila/chatgpt-clone/assets/110412045/e33e0133-66c1-4781-9ca8-bbd8c174579c)
Expand Down
2 changes: 1 addition & 1 deletion docs/features/plugins/wolfram.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ An AppID must be supplied in all calls to the Wolfram|Alpha API.
2. Go to the <a href='https://developer.wolframalpha.com/portal/myapps/'>Developer Portal</a> click on "Get an AppID".
3. In the app, select the plugins endpoint, open the plugins store, and install Wolfram
- You will be prompted for your AppID
- Alternatively: you (the admin) can set the value in `api\.env` to bypass the prompt
- Alternatively: you (the admin) can set the value in `\.env` to bypass the prompt
- `WOLFRAM_APP_ID=your_app_id`

![image](https://github.com/danny-avila/chatgpt-clone/assets/110412045/e33e0133-66c1-4781-9ca8-bbd8c174579c)
Expand Down
22 changes: 11 additions & 11 deletions docs/features/user_auth_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,22 @@

**First Time Setup**

In order for the auth system to function properly, there are some environment variables that are needed. Note that this information is also included in the [/api/.env.example](https://github.com/danny-avila/chatgpt-clone/blob/main/api/.env.example) and [/client/.env.example](https://github.com/danny-avila/chatgpt-clone/blob/main/client/.env.example) files.
In order for the auth system to function properly, there are some environment variables that are needed. Note that this information is also included in the [/.env.example](https://github.com/danny-avila/chatgpt-clone/blob/main/.env.example) file.

In /api/.env, you will need to set the following variables:
In /.env, you will need to set the following variables:
```bash
# Change this to a secure string
JWT_SECRET=secret
# Set the expiration delay for the secure cookie with the JWT token
# Delay is in millisecond e.g. 7 days is 1000*60*60*24*7
SESSION_EXPIRY=1000 * 60 * 60 * 24 * 7
# Note: NODE_ENV should be set to 'development' in the Server configuration section if you want to run in dev mode
DOMAIN_SERVER=http://localhost:3080
DOMAIN_CLIENT=http://localhost:3080
```

In /client/.env, you will need to set the following variables:
```bash
DOMAIN_SERVER=http://localhost:3080
```
*Please Note: If you are wanting this to work in development mode, you will need to create a file called `.env.development` in the root directory and set `DOMAIN_CLIENT` to `http://localhost:3090` or whatever port is provided by vite when runnning `npm run frontend-dev`*

The first time you run the application, you should register a new account by clicking the "Sign up" link on the login page. The first account registered will be recieve an admin role. The admin account does not currently have extended functionality, but is valuable should you choose to create an admin dashboard for user management.
The first time you run the application, you should register a new account by clicking the "Sign up" link on the login page. The first account registered will receive an admin role. The admin account does not currently have extended functionality, but is valuable should you choose to create an admin dashboard for user management.

**Migrating Previous Conversations and Presets to new User Account**

Expand All @@ -33,7 +29,7 @@ When the first account is registered, the application will automatically migrate

The application is setup to support OAuth2/Social Login with Google. All of the code is in place for Facebook login as well, but this has not been tested because the setup process with Facebook was honestly just too painful for me to deal with. I plan to add support for other OAuth2 providers including Github and Discord at a later time.

To enable Google login, you must create an application in the [Google Cloud Console](https://cloud.google.com) and provide the client ID and client secret in the [/api/.env](https://github.com/danny-avila/chatgpt-clone/blob/main/api/.env.example) file, then set `VITE_SHOW_GOOGLE_LOGIN_OPTION=true` in the [/client/.env](https://github.com/danny-avila/chatgpt-clone/blob/main/client/.env.example) file.
To enable Google login, you must create an application in the [Google Cloud Console](https://cloud.google.com) and provide the client ID and client secret in the [/.env](https://github.com/danny-avila/chatgpt-clone/blob/main/.env.example) file, then set `VITE_SHOW_GOOGLE_LOGIN_OPTION=true`.

*Instructions for setting up Google login are provided below.*
```
Expand All @@ -46,14 +42,18 @@ To enable Google login, you must create an application in the [Google Cloud Cons
7. Add "http://localhost" "http://localhost:3080" and "http://localhost:3090" to the authorized JavaScript origins.
8. Add "http://localhost:3080/oauth/google/callback" to the authorized redirect URIs.
9. Click on "Create" and copy your client ID and client secret.
10. Paste them into your api/.env file.
11. Enable the feature in the client/.env file
10. Paste them into your /.env file.
11. Enable the feature in the /.env file
```

**Email and Password Reset**

Most of the code is in place for sending password reset emails, but is not yet feature-complete as I have not setup an email server to test it. Currently, submitting a password reset request will then display a link with the one-time reset token that can then be used to reset the password. Understanding that this is a considerable security hazard, email integration will be included in the next release.

**Disable User Registration**

To disable or re-enable registration, open up the root `.env` file and set `ALLOW_REGISTRATION=true` or `ALLOW_REGISTRATION=false` depending on if you want registration open or closed.

***Warning***

If you previously implemented your own user system using the original scaffolding that was provided, you will no longer see conversations and presets by switching to the new user system. This is because of a design flaw in the scaffolding implementation that was problematic for the inclusion of social login.
Expand Down
2 changes: 1 addition & 1 deletion docs/install/docker_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


- **Edit** the credentials you see in [docker-compose.yml](https://stackedit.io/docker-compose.yml) under api service as needed
- **Provide** all necessary credentials in the ./api/.env and client/.env files before the next step
- **Provide** all necessary credentials in the /.env file before the next step
- Docker will read those env files. See their respective `.env.example` files for reference
- **Run** `docker-compose up` to start the app
- Note: MongoDB does not support older ARM CPUs like those found in Raspberry Pis. However, you can make it work by setting MongoDB’s version to mongo:4.4.18 in docker-compose.yml, the most recent version compatible with
Expand Down
4 changes: 2 additions & 2 deletions docs/install/linux_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ sudo apt-get install -y nodejs

You will need all your credentials, (API keys, access tokens, and MongoDB Connection String, MeiliSearch Master Key)

- Open "~/chatgpt-clone/api/.env.example" in a text editor
- Open "~/chatgpt-clone/.env.example" in a text editor
- At this line MONGO_URI="mongodb://127.0.0.1:27017/chatgpt-clone", replace mongodb://127.0.0.1:27017/chatgpt-clone with the MongoDB 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"
- At this line OPENAI_API_KEY= you need to add your OpenAI API key
- 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
- 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 "~/chatgpt-clone/api/.env"
- Save the file as "~/chatgpt-clone/.env"

## Run the project

Expand Down
Loading