mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
Rolled back to v0.0.2
This commit is contained in:
parent
57d3025717
commit
72ff47e204
20 changed files with 87 additions and 142 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -48,7 +48,7 @@ bower_components/
|
||||||
cache.json
|
cache.json
|
||||||
api/data/
|
api/data/
|
||||||
.eslintrc.js
|
.eslintrc.js
|
||||||
owner*.yml
|
owner.yml
|
||||||
archive
|
archive
|
||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
|
|
||||||
|
|
16
README.md
16
README.md
|
@ -110,7 +110,7 @@ Here are my recently completed and planned features:
|
||||||
|
|
||||||
^* ChatGPT can be 'customized' by setting a system message or prompt prefix and alternate 'role' to the API request
|
^* ChatGPT can be 'customized' by setting a system message or prompt prefix and alternate 'role' to the API request
|
||||||
|
|
||||||
[More info here](https://platform.openai.com/docs/guides/chat/instructing-chat-models). Here's an [example from this app.](#use-cases)
|
[More info here](https://platform.openai.com/docs/guides/chat/instructing-chat-models). Here's an [example from this app.]()
|
||||||
|
|
||||||
### Tech Stack
|
### Tech Stack
|
||||||
|
|
||||||
|
@ -126,8 +126,8 @@ Here are my recently completed and planned features:
|
||||||
- Node.js >= 19.0.0
|
- Node.js >= 19.0.0
|
||||||
- MongoDB installed or [MongoDB Atlas](https://account.mongodb.com/account/login) (required if not using Docker)
|
- MongoDB installed or [MongoDB Atlas](https://account.mongodb.com/account/login) (required if not using Docker)
|
||||||
- [Docker (optional)](https://www.docker.com/get-started/)
|
- [Docker (optional)](https://www.docker.com/get-started/)
|
||||||
- [OpenAI API key](https://platform.openai.com/account/api-keys) (optional: chats will not be titled and only free models will work)
|
- [OpenAI API key](https://platform.openai.com/account/api-keys)
|
||||||
- BingAI, ChatGPT access tokens (optional for free AI models)
|
- BingAI, ChatGPT access tokens (optional, free AIs)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -136,7 +136,6 @@ Here are my recently completed and planned features:
|
||||||
git clone https://github.com/danny-avila/chatgpt-clone.git
|
git clone https://github.com/danny-avila/chatgpt-clone.git
|
||||||
```
|
```
|
||||||
- If using MongoDB Atlas, remove `&w=majority` from default connection string.
|
- If using MongoDB Atlas, remove `&w=majority` from default connection string.
|
||||||
- You can configure proxy, host, and port environment variables as needed
|
|
||||||
|
|
||||||
### Local
|
### Local
|
||||||
- **Run npm** install in both the api and client directories
|
- **Run npm** install in both the api and client directories
|
||||||
|
@ -162,7 +161,12 @@ Here are my recently completed and planned features:
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>ChatGPT Free Instructions</strong></summary>
|
<summary><strong>ChatGPT Free Instructions</strong></summary>
|
||||||
To get your Access token For ChatGPT 'Free Version', login to chat.openai.com, then visit https://chat.openai.com/api/auth/session. Set it to `CHATGPT_TOKEN` in `.env` or `docker-compose.yml`
|
|
||||||
|
|
||||||
|
**This has been disabled as is no longer working as of 3-07-23**
|
||||||
|
|
||||||
|
|
||||||
|
To get your Access token For ChatGPT 'Free Version', login to chat.openai.com, then visit https://chat.openai.com/api/auth/session.
|
||||||
|
|
||||||
|
|
||||||
**Warning:** There may be a high chance of your account being banned with this method. Continue doing so at your own risk.
|
**Warning:** There may be a high chance of your account being banned with this method. Continue doing so at your own risk.
|
||||||
|
@ -171,7 +175,7 @@ To get your Access token For ChatGPT 'Free Version', login to chat.openai.com, t
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>BingAI Instructions</strong></summary>
|
<summary><strong>BingAI Instructions</strong></summary>
|
||||||
The Bing Access Token is the "_U" cookie from bing.com. Use dev tools or an extension while logged into the site to view it. Set it in `.env` or `docker-compose.yml` to `BING_TOKEN`; if setting the user token doesn't work, try setting the entire cookie string from bing request header to `BING_COOKIES`
|
The Bing Access Token is the "_U" cookie from bing.com. Use dev tools or an extension while logged into the site to view it.
|
||||||
|
|
||||||
**Note:** Specific error handling and styling for this model is still in progress.
|
**Note:** Specific error handling and styling for this model is still in progress.
|
||||||
</details>
|
</details>
|
||||||
|
|
|
@ -2,32 +2,27 @@ require('dotenv').config();
|
||||||
const { KeyvFile } = require('keyv-file');
|
const { KeyvFile } = require('keyv-file');
|
||||||
|
|
||||||
const askBing = async ({ text, progressCallback, convo }) => {
|
const askBing = async ({ text, progressCallback, convo }) => {
|
||||||
const { BingAIClient } = await import('@waylaidwanderer/chatgpt-api');
|
const { BingAIClient } = (await import('@waylaidwanderer/chatgpt-api'));
|
||||||
|
|
||||||
const clientOptions = {
|
const bingAIClient = new BingAIClient({
|
||||||
|
// "_U" cookie from bing.com
|
||||||
userToken: process.env.BING_TOKEN,
|
userToken: process.env.BING_TOKEN,
|
||||||
|
// If the above doesn't work, provide all your cookies as a string instead
|
||||||
|
// cookies: '',
|
||||||
debug: false,
|
debug: false,
|
||||||
cache: { store: new KeyvFile({ filename: './data/cache.json' }) }
|
cache: { store: new KeyvFile({ filename: './data/cache.json' }) }
|
||||||
};
|
});
|
||||||
|
|
||||||
const cookies = process.env.BING_COOKIES;
|
|
||||||
|
|
||||||
if (cookies?.length > 0) {
|
|
||||||
clientOptions.cookies = cookies;
|
|
||||||
delete clientOptions.userToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bingAIClient = new BingAIClient(clientOptions);
|
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
onProgress: async (partialRes) => await progressCallback(partialRes)
|
onProgress: async (partialRes) => await progressCallback(partialRes),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (convo) {
|
if (convo) {
|
||||||
options = { ...options, ...convo };
|
options = { ...options, ...convo };
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await bingAIClient.sendMessage(text, options);
|
const res = await bingAIClient.sendMessage(text, options
|
||||||
|
);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ const clientOptions = {
|
||||||
// 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,
|
||||||
// debug: true
|
// debug: true
|
||||||
proxy: process.env.PROXY || null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const browserClient = async ({ text, progressCallback, convo }) => {
|
const browserClient = async ({ text, progressCallback, convo }) => {
|
||||||
|
|
|
@ -5,7 +5,6 @@ const clientOptions = {
|
||||||
modelOptions: {
|
modelOptions: {
|
||||||
model: 'gpt-3.5-turbo'
|
model: 'gpt-3.5-turbo'
|
||||||
},
|
},
|
||||||
proxy: process.env.PROXY || null,
|
|
||||||
debug: false
|
debug: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ const clientOptions = {
|
||||||
modelOptions: {
|
modelOptions: {
|
||||||
model: 'gpt-3.5-turbo'
|
model: 'gpt-3.5-turbo'
|
||||||
},
|
},
|
||||||
proxy: process.env.PROXY || null,
|
|
||||||
debug: false
|
debug: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,39 +2,30 @@ require('dotenv').config();
|
||||||
const { KeyvFile } = require('keyv-file');
|
const { KeyvFile } = require('keyv-file');
|
||||||
|
|
||||||
const askSydney = async ({ text, progressCallback, convo }) => {
|
const askSydney = async ({ text, progressCallback, convo }) => {
|
||||||
const { BingAIClient } = await import('@waylaidwanderer/chatgpt-api');
|
const { BingAIClient } = (await import('@waylaidwanderer/chatgpt-api'));
|
||||||
|
|
||||||
const clientOptions = {
|
const sydneyClient = new BingAIClient({
|
||||||
|
// "_U" cookie from bing.com
|
||||||
userToken: process.env.BING_TOKEN,
|
userToken: process.env.BING_TOKEN,
|
||||||
|
// If the above doesn't work, provide all your cookies as a string instead
|
||||||
|
// cookies: '',
|
||||||
debug: false,
|
debug: false,
|
||||||
cache: { store: new KeyvFile({ filename: './data/cache.json' }) }
|
cache: { store: new KeyvFile({ filename: './data/cache.json' }) }
|
||||||
};
|
});
|
||||||
|
|
||||||
const cookies = process.env.BING_COOKIES;
|
|
||||||
|
|
||||||
if (cookies?.length > 0) {
|
|
||||||
clientOptions.cookies = cookies;
|
|
||||||
delete clientOptions.userToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sydneyClient = new BingAIClient(clientOptions);
|
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
jailbreakConversationId: true,
|
jailbreakConversationId: true,
|
||||||
onProgress: async (partialRes) => await progressCallback(partialRes)
|
onProgress: async (partialRes) => await progressCallback(partialRes),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (convo.parentMessageId) {
|
if (convo.parentMessageId) {
|
||||||
options = {
|
options = { ...options, jailbreakConversationId: convo.jailbreakConversationId, parentMessageId: convo.parentMessageId };
|
||||||
...options,
|
|
||||||
jailbreakConversationId: convo.jailbreakConversationId,
|
|
||||||
parentMessageId: convo.parentMessageId
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('sydney options', options);
|
console.log('sydney options', options);
|
||||||
|
|
||||||
const res = await sydneyClient.sendMessage(text, options);
|
const res = await sydneyClient.sendMessage(text, options
|
||||||
|
);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,24 @@
|
||||||
const { Configuration, OpenAIApi } = require('openai');
|
const { Configuration, OpenAIApi } = require('openai');
|
||||||
|
|
||||||
const titleConvo = async ({ message, response, model }) => {
|
const titleConvo = async ({ message, response, model }) => {
|
||||||
try {
|
const configuration = new Configuration({
|
||||||
const configuration = new Configuration({
|
apiKey: process.env.OPENAI_KEY
|
||||||
apiKey: process.env.OPENAI_KEY
|
});
|
||||||
});
|
const openai = new OpenAIApi(configuration);
|
||||||
const openai = new OpenAIApi(configuration);
|
const completion = await openai.createChatCompletion({
|
||||||
const completion = await openai.createChatCompletion({
|
model: 'gpt-3.5-turbo',
|
||||||
model: 'gpt-3.5-turbo',
|
messages: [
|
||||||
messages: [
|
{
|
||||||
{
|
role: 'system',
|
||||||
role: 'system',
|
content:
|
||||||
content:
|
'You are a title-generator with one job: titling the conversation provided by a user in title case.'
|
||||||
'You are a title-generator with one job: titling the conversation provided by a user in title case.'
|
},
|
||||||
},
|
{ role: 'user', content: `In 5 words or less, summarize the conversation below with a title in title case. Don't refer to the participants of the conversation by name. Do not include punctuation or quotation marks. Your response should be in title case, exclusively containing the title. Conversation:\n\nUser: "${message}"\n\n${model}: "${response}"\n\nTitle: ` },
|
||||||
{
|
]
|
||||||
role: 'user',
|
});
|
||||||
content: `In 5 words or less, summarize the conversation below with a title in title case. Don't refer to the participants of the conversation by name. Do not include punctuation or quotation marks. Your response should be in title case, exclusively containing the title. Conversation:\n\nUser: "${message}"\n\n${model}: "${response}"\n\nTitle: `
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
//eslint-disable-next-line
|
//eslint-disable-next-line
|
||||||
return completion.data.choices[0].message.content.replace(/["\.]/g, '');
|
return completion.data.choices[0].message.content.replace(/["\.]/g, '');
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return 'New Chat';
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = titleConvo;
|
module.exports = titleConvo;
|
||||||
|
|
|
@ -5,7 +5,6 @@ const cors = require('cors');
|
||||||
const routes = require('./routes');
|
const routes = require('./routes');
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = process.env.PORT || 3080;
|
const port = process.env.PORT || 3080;
|
||||||
const host = process.env.HOST || 'localhost'
|
|
||||||
const projectPath = path.join(__dirname, '..', '..', 'client');
|
const projectPath = path.join(__dirname, '..', '..', 'client');
|
||||||
dbConnect().then(() => console.log('Connected to MongoDB'));
|
dbConnect().then(() => console.log('Connected to MongoDB'));
|
||||||
|
|
||||||
|
@ -24,6 +23,6 @@ app.use('/api/convos', routes.convos);
|
||||||
app.use('/api/customGpts', routes.customGpts);
|
app.use('/api/customGpts', routes.customGpts);
|
||||||
app.use('/api/prompts', routes.prompts);
|
app.use('/api/prompts', routes.prompts);
|
||||||
|
|
||||||
app.listen(port, host, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Server listening at http://${host}:${port}`);
|
console.log(`Server listening at http://localhost:${port}`);
|
||||||
});
|
});
|
|
@ -23,8 +23,8 @@ export default function Conversation({
|
||||||
const { modelMap } = useSelector((state) => state.models);
|
const { modelMap } = useSelector((state) => state.models);
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { trigger } = manualSWR(`/api/messages/${id}`, 'get');
|
const { trigger } = manualSWR(`http://localhost:3080/api/messages/${id}`, 'get');
|
||||||
const rename = manualSWR(`/api/convos/update`, 'post');
|
const rename = manualSWR(`http://localhost:3080/api/convos/update`, 'post');
|
||||||
|
|
||||||
const clickHandler = async () => {
|
const clickHandler = async () => {
|
||||||
if (conversationId === id) {
|
if (conversationId === id) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { setMessages } from '~/store/messageSlice';
|
||||||
export default function DeleteButton({ conversationId, renaming, cancelHandler }) {
|
export default function DeleteButton({ conversationId, renaming, cancelHandler }) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { trigger } = manualSWR(
|
const { trigger } = manualSWR(
|
||||||
`/api/convos/clear`,
|
`http://localhost:3080/api/convos/clear`,
|
||||||
'post',
|
'post',
|
||||||
() => {
|
() => {
|
||||||
dispatch(setMessages([]));
|
dispatch(setMessages([]));
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default function TabLink(a) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={a.href}
|
|
||||||
title={a.title}
|
|
||||||
className={a.className}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
{a.children}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,22 +2,10 @@ import React from 'react';
|
||||||
import Markdown from 'markdown-to-jsx';
|
import Markdown from 'markdown-to-jsx';
|
||||||
import Embed from './Embed';
|
import Embed from './Embed';
|
||||||
import Highlight from './Highlight';
|
import Highlight from './Highlight';
|
||||||
import TabLink from './TabLink';
|
|
||||||
import regexSplit from '~/utils/regexSplit';
|
import regexSplit from '~/utils/regexSplit';
|
||||||
import { wrapperRegex } from '~/utils';
|
import { wrapperRegex } from '~/utils';
|
||||||
const { codeRegex, inLineRegex, markupRegex, languageMatch, newLineMatch } = wrapperRegex;
|
const { codeRegex, inLineRegex, markupRegex, languageMatch, newLineMatch } = wrapperRegex;
|
||||||
const mdOptions = {
|
const mdOptions = { wrapper: React.Fragment, forceWrapper: true };
|
||||||
wrapper: React.Fragment,
|
|
||||||
forceWrapper: true,
|
|
||||||
overrides: {
|
|
||||||
a: {
|
|
||||||
component: TabLink,
|
|
||||||
// props: {
|
|
||||||
// className: 'foo'
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const inLineWrap = (parts) => {
|
const inLineWrap = (parts) => {
|
||||||
let previousElement = null;
|
let previousElement = null;
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default function ModelDialog({ mutate, setModelSave, handleSaveState }) {
|
||||||
const [saveText, setSaveText] = useState('Save');
|
const [saveText, setSaveText] = useState('Save');
|
||||||
const [required, setRequired] = useState(false);
|
const [required, setRequired] = useState(false);
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const updateCustomGpt = manualSWR(`/api/customGpts/`, 'post');
|
const updateCustomGpt = manualSWR(`http://localhost:3080/api/customGpts/`, 'post');
|
||||||
|
|
||||||
const submitHandler = (e) => {
|
const submitHandler = (e) => {
|
||||||
if (chatGptLabel.length === 0) {
|
if (chatGptLabel.length === 0) {
|
||||||
|
|
|
@ -15,8 +15,8 @@ export default function ModelItem({ modelName, value, onSelect }) {
|
||||||
const [currentName, setCurrentName] = useState(modelName);
|
const [currentName, setCurrentName] = useState(modelName);
|
||||||
const [modelInput, setModelInput] = useState(modelName);
|
const [modelInput, setModelInput] = useState(modelName);
|
||||||
const inputRef = useRef(null);
|
const inputRef = useRef(null);
|
||||||
const rename = manualSWR(`/api/customGpts`, 'post');
|
const rename = manualSWR(`http://localhost:3080/api/customGpts`, 'post');
|
||||||
const deleteCustom = manualSWR(`/api/customGpts/delete`, 'post');
|
const deleteCustom = manualSWR(`http://localhost:3080/api/customGpts/delete`, 'post');
|
||||||
|
|
||||||
if (value === 'chatgptCustom') {
|
if (value === 'chatgptCustom') {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -27,7 +27,7 @@ export default function ModelMenu() {
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
const { model, customModel } = useSelector((state) => state.submit);
|
const { model, customModel } = useSelector((state) => state.submit);
|
||||||
const { models, modelMap, initial } = useSelector((state) => state.models);
|
const { models, modelMap, initial } = useSelector((state) => state.models);
|
||||||
const { trigger } = manualSWR(`/api/customGpts`, 'get', (res) => {
|
const { trigger } = manualSWR(`http://localhost:3080/api/customGpts`, 'get', (res) => {
|
||||||
const fetchedModels = res.map((modelItem) => ({
|
const fetchedModels = res.map((modelItem) => ({
|
||||||
...modelItem,
|
...modelItem,
|
||||||
name: modelItem.chatGptLabel
|
name: modelItem.chatGptLabel
|
||||||
|
|
|
@ -10,10 +10,10 @@ export default function ClearConvos() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { mutate } = useSWRConfig();
|
const { mutate } = useSWRConfig();
|
||||||
|
|
||||||
const { trigger } = manualSWR(`/api/convos/clear`, 'post', () => {
|
const { trigger } = manualSWR(`http://localhost:3080/api/convos/clear`, 'post', () => {
|
||||||
dispatch(setMessages([]));
|
dispatch(setMessages([]));
|
||||||
dispatch(setNewConvo());
|
dispatch(setNewConvo());
|
||||||
mutate(`/api/convos`);
|
mutate(`http://localhost:3080/api/convos`);
|
||||||
});
|
});
|
||||||
|
|
||||||
const clickHandler = () => {
|
const clickHandler = () => {
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default function Nav() {
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data, isLoading, mutate } = swr(
|
const { data, isLoading, mutate } = swr(
|
||||||
`/api/convos?pageNumber=${pageNumber}`,
|
`http://localhost:3080/api/convos?pageNumber=${pageNumber}`,
|
||||||
onSuccess
|
onSuccess
|
||||||
);
|
);
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default function handleSubmit({
|
||||||
chatGptLabel,
|
chatGptLabel,
|
||||||
promptPrefix
|
promptPrefix
|
||||||
}) {
|
}) {
|
||||||
const endpoint = `/api/ask`;
|
const endpoint = `http://localhost:3080/api/ask`;
|
||||||
let payload = { model, text, chatGptLabel, promptPrefix };
|
let payload = { model, text, chatGptLabel, promptPrefix };
|
||||||
if (convo.conversationId && convo.parentMessageId) {
|
if (convo.conversationId && convo.parentMessageId) {
|
||||||
payload = {
|
payload = {
|
||||||
|
|
|
@ -22,12 +22,6 @@ services:
|
||||||
- OPENAI_KEY=""
|
- OPENAI_KEY=""
|
||||||
- CHATGPT_TOKEN=""
|
- CHATGPT_TOKEN=""
|
||||||
- BING_TOKEN=""
|
- BING_TOKEN=""
|
||||||
# if setting the user token doesn't work, try setting the entire cookie string from bing request header
|
|
||||||
- BING_COOKIES=""
|
|
||||||
# Change this to proxy any request.
|
|
||||||
- PROXY=""
|
|
||||||
# Change this if you need to configure host name, default: 'localhost'
|
|
||||||
- HOST=""
|
|
||||||
ports:
|
ports:
|
||||||
- "9000:3080"
|
- "9000:3080"
|
||||||
volumes:
|
volumes:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue