mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
feat: claude integration (#552)
* feat: bare bones implementation of claude client (WIP) * feat: client implementation of Claude (WIP) * fix: add claude to store * feat: bare bones implementation of claude client (WIP) * switch eventsource * Try new method of calling claude with anthropic sdk * (WIP) Finish initial claude client implementation and api * debugging update * fix(ClaudeClient.js): fix prompt prefixes for HUMAN_PROMPT and AI_PROMPT fix(ClaudeClient.js): refactor buildMessages logic for correct handling of messages refactor(ClaudeClient.js): refactor buildPrompt method to buildMessages for use in BaseClient sendMessage method refactor(ClaudeClient.js): refactor getCompletion method to sendCompletion for use in BaseClient sendMessage method refactor(ClaudeClient.js): omit getMessageMapMethod method for future refactoring refactor(ClaudeClient.js): remove unused sendMessage method to prefer BaseClient message fix(askClaude.js): error in getIds method was causing a frontend crash, userMessage was not defined fix(askClaude.js): import abortMessage function from utils module feat(askClaude.js): add /abort route to handle message abort requests feat(askClaude.js): create abortControllers map to store abort controllers feat(askClaude.js): implement abortAsk function to handle message abort logic feat(askClaude.js): add onStart callback to handle message start logic feat(HoverButtons.jsx): add 'claude' as a supported endpoint for branching * fix(ClaudeClient.js): update defaultPrefix and promptPrefix messages includes 'Remember your instructions' as Claude is trained to recognize labels preceding colons as participants of a conversation * Change name from claude to anthropic * add settings to handleSubmit and models to endpoints * Implement Claude settings * use svg for anthropic icon * Implement abort * Implement reverse proxy * remove png icons * replace web browser plugin * remove default prefix * fix styling of claude icon * fix console error from svg properties * remove single quote requirement from eslintrc * fix(AnthropicClient.js): fix labels for HUMAN_PROMPT and AI_PROMPT feat(AnthropicClient.js): add support for custom userLabel and modelLabel options feat(AnthropicClient.js): add user_id metadata to requestOptions in getCompletion method feat(anthropic, AnthropicClient.js): add debug logging * refactor(AnthropicClient.js): change promptSuffix variable declaration from let to const * fix(EndpointOptionsDialog.jsx): remove unnecessary code that changes endpointName from 'anthropic' to 'Claude' fix(utils/index.jsx): fix alternateName value for 'anthropic' from 'Claude' to 'Anthropic' * fix(AnthropicIcon): fix sizing/rendering/name of anthropic icon * fix(AnthropicClient.js): change maxContextTokens default value to 99999 fix(AnthropicClient.js): change maxResponseTokens default value to 1500 fix(AnthropicClient.js): remove unnecessary code for setting maxContextTokens and maxResponseTokens based on modelOptions fix(AnthropicClient.js): change max_tokens_to_sample default value to 1500 fix(anthropic.js): pass endpointOption.token to AnthropicClient constructor * Update .env.example * fix(AnthropicClient.js): remove exceeding message when it puts us over the token limit fix(AnthropicClient.js): handle case when the first message exceeds the token limit fix(AnthropicClient.js): throw error when prompt is too long fix(AnthropicClient.js): adjust max tokens calculation to use maxOutputTokens fix(anthropic.js): remove console.log statement in ask route * feat(server/index): increase incoming json payload allowed size --------- Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
This commit is contained in:
parent
981d009508
commit
9e931229e2
36 changed files with 1455 additions and 30 deletions
10
.env.example
10
.env.example
|
@ -107,6 +107,16 @@ CHATGPT_MODELS=text-davinci-002-render-sha,gpt-4
|
||||||
# By default it will use the node-chatgpt-api recommended proxy, (it's a third party server)
|
# By default it will use the node-chatgpt-api recommended proxy, (it's a third party server)
|
||||||
# CHATGPT_REVERSE_PROXY=<YOUR REVERSE PROXY>
|
# CHATGPT_REVERSE_PROXY=<YOUR REVERSE PROXY>
|
||||||
|
|
||||||
|
##########################
|
||||||
|
# Anthropic Endpoint:
|
||||||
|
##########################
|
||||||
|
# Access key from https://console.anthropic.com/
|
||||||
|
# Leave it blank to disable this feature.
|
||||||
|
# Set to "user_provided" to allow the user to provide their API key from the UI.
|
||||||
|
# Note that access to claude-1 may potentially become unavailable with the release of claude-2.
|
||||||
|
ANTHROPIC_API_KEY="user_provided"
|
||||||
|
ANTHROPIC_MODELS=claude-1,claude-instant-1,claude-2
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
# Plugins:
|
# Plugins:
|
||||||
#############################
|
#############################
|
||||||
|
|
|
@ -52,7 +52,6 @@ module.exports = {
|
||||||
'no-restricted-syntax': 'off',
|
'no-restricted-syntax': 'off',
|
||||||
'react/prop-types': ['off'],
|
'react/prop-types': ['off'],
|
||||||
'react/display-name': ['off'],
|
'react/display-name': ['off'],
|
||||||
'quotes': ['error', 'single'],
|
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,7 +36,7 @@ https://github.com/danny-avila/LibreChat/assets/110412045/c1eb0c0f-41f6-4335-b98
|
||||||
# Features
|
# Features
|
||||||
- Response streaming identical to ChatGPT through server-sent events
|
- Response streaming identical to ChatGPT through server-sent events
|
||||||
- UI from original ChatGPT, including Dark mode
|
- UI from original ChatGPT, including Dark mode
|
||||||
- AI model selection (through 5 endpoints: OpenAI API, BingAI, ChatGPT Browser, PaLM2, Plugins)
|
- AI model selection (through 6 endpoints: OpenAI API, BingAI, ChatGPT Browser, PaLM2, Claude, Plugins)
|
||||||
- Create, Save, & Share custom presets - [More info on prompt presets here](https://github.com/danny-avila/LibreChat/releases/tag/v0.3.0)
|
- Create, Save, & Share custom presets - [More info on prompt presets here](https://github.com/danny-avila/LibreChat/releases/tag/v0.3.0)
|
||||||
- Edit and Resubmit messages with conversation branching
|
- Edit and Resubmit messages with conversation branching
|
||||||
- Search all messages/conversations - [More info here](https://github.com/danny-avila/LibreChat/releases/tag/v0.1.0)
|
- Search all messages/conversations - [More info here](https://github.com/danny-avila/LibreChat/releases/tag/v0.1.0)
|
||||||
|
|
319
api/app/clients/AnthropicClient.js
Normal file
319
api/app/clients/AnthropicClient.js
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
const Keyv = require('keyv');
|
||||||
|
// const { Agent, ProxyAgent } = require('undici');
|
||||||
|
const BaseClient = require('./BaseClient');
|
||||||
|
const {
|
||||||
|
encoding_for_model: encodingForModel,
|
||||||
|
get_encoding: getEncoding
|
||||||
|
} = require('@dqbd/tiktoken');
|
||||||
|
const Anthropic = require('@anthropic-ai/sdk');
|
||||||
|
|
||||||
|
const HUMAN_PROMPT = '\n\nHuman:';
|
||||||
|
const AI_PROMPT = '\n\nAssistant:';
|
||||||
|
|
||||||
|
const tokenizersCache = {};
|
||||||
|
|
||||||
|
class AnthropicClient extends BaseClient {
|
||||||
|
|
||||||
|
constructor(apiKey, options = {}, cacheOptions = {}) {
|
||||||
|
super(apiKey, options, cacheOptions)
|
||||||
|
cacheOptions.namespace = cacheOptions.namespace || 'anthropic';
|
||||||
|
this.conversationsCache = new Keyv(cacheOptions);
|
||||||
|
this.apiKey = apiKey || process.env.ANTHROPIC_API_KEY;
|
||||||
|
this.sender = 'Anthropic';
|
||||||
|
this.userLabel = HUMAN_PROMPT;
|
||||||
|
this.assistantLabel = AI_PROMPT;
|
||||||
|
this.setOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
setOptions(options) {
|
||||||
|
if (this.options && !this.options.replaceOptions) {
|
||||||
|
// nested options aren't spread properly, so we need to do this manually
|
||||||
|
this.options.modelOptions = {
|
||||||
|
...this.options.modelOptions,
|
||||||
|
...options.modelOptions
|
||||||
|
};
|
||||||
|
delete options.modelOptions;
|
||||||
|
// now we can merge options
|
||||||
|
this.options = {
|
||||||
|
...this.options,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
const modelOptions = this.options.modelOptions || {};
|
||||||
|
this.modelOptions = {
|
||||||
|
...modelOptions,
|
||||||
|
// set some good defaults (check for undefined in some cases because they may be 0)
|
||||||
|
model: modelOptions.model || 'claude-1',
|
||||||
|
temperature: typeof modelOptions.temperature === 'undefined' ? 0.7 : modelOptions.temperature, // 0 - 1, 0.7 is recommended
|
||||||
|
topP: typeof modelOptions.topP === 'undefined' ? 0.7 : modelOptions.topP, // 0 - 1, default: 0.7
|
||||||
|
topK: typeof modelOptions.topK === 'undefined' ? 40 : modelOptions.topK, // 1-40, default: 40
|
||||||
|
stop: modelOptions.stop // no stop method for now
|
||||||
|
};
|
||||||
|
|
||||||
|
this.maxContextTokens = this.options.maxContextTokens || 99999;
|
||||||
|
this.maxResponseTokens = this.modelOptions.maxOutputTokens || 1500;
|
||||||
|
this.maxPromptTokens =
|
||||||
|
this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
|
||||||
|
|
||||||
|
if (this.maxPromptTokens + this.maxResponseTokens > this.maxContextTokens) {
|
||||||
|
throw new Error(
|
||||||
|
`maxPromptTokens + maxOutputTokens (${this.maxPromptTokens} + ${this.maxResponseTokens} = ${
|
||||||
|
this.maxPromptTokens + this.maxResponseTokens
|
||||||
|
}) must be less than or equal to maxContextTokens (${this.maxContextTokens})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startToken = '||>';
|
||||||
|
this.endToken = '';
|
||||||
|
this.gptEncoder = this.constructor.getTokenizer('cl100k_base');
|
||||||
|
|
||||||
|
if (!this.modelOptions.stop) {
|
||||||
|
const stopTokens = [this.startToken];
|
||||||
|
if (this.endToken && this.endToken !== this.startToken) {
|
||||||
|
stopTokens.push(this.endToken);
|
||||||
|
}
|
||||||
|
stopTokens.push(`${this.userLabel}`);
|
||||||
|
stopTokens.push('<|diff_marker|>');
|
||||||
|
|
||||||
|
this.modelOptions.stop = stopTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getClient() {
|
||||||
|
if(this.options.reverseProxyUrl) {
|
||||||
|
return new Anthropic({
|
||||||
|
apiKey: this.apiKey,
|
||||||
|
baseURL: this.options.reverseProxyUrl
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Anthropic({
|
||||||
|
apiKey: this.apiKey,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async buildMessages(messages, parentMessageId) {
|
||||||
|
const orderedMessages = this.constructor.getMessagesForConversation(messages, parentMessageId);
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.debug('AnthropicClient: orderedMessages', orderedMessages, parentMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const formattedMessages = orderedMessages.map((message) => ({
|
||||||
|
author: message.isCreatedByUser ? this.userLabel : this.assistantLabel,
|
||||||
|
content: message?.content ?? message.text
|
||||||
|
}));
|
||||||
|
|
||||||
|
let identityPrefix = '';
|
||||||
|
if (this.options.userLabel) {
|
||||||
|
identityPrefix = `\nHuman's name: ${this.options.userLabel}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.modelLabel) {
|
||||||
|
identityPrefix = `${identityPrefix}\nYou are ${this.options.modelLabel}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let promptPrefix = (this.options.promptPrefix || '').trim();
|
||||||
|
if (promptPrefix) {
|
||||||
|
// If the prompt prefix doesn't end with the end token, add it.
|
||||||
|
if (!promptPrefix.endsWith(`${this.endToken}`)) {
|
||||||
|
promptPrefix = `${promptPrefix.trim()}${this.endToken}\n\n`;
|
||||||
|
}
|
||||||
|
promptPrefix = `\nContext:\n${promptPrefix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identityPrefix) {
|
||||||
|
promptPrefix = `${identityPrefix}${promptPrefix}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const promptSuffix = `${promptPrefix}${this.assistantLabel}\n`; // Prompt AI to respond.
|
||||||
|
let currentTokenCount = this.getTokenCount(promptSuffix);
|
||||||
|
|
||||||
|
let promptBody = '';
|
||||||
|
const maxTokenCount = this.maxPromptTokens;
|
||||||
|
|
||||||
|
const context = [];
|
||||||
|
|
||||||
|
// Iterate backwards through the messages, adding them to the prompt until we reach the max token count.
|
||||||
|
// Do this within a recursive async function so that it doesn't block the event loop for too long.
|
||||||
|
// Also, remove the next message when the message that puts us over the token limit is created by the user.
|
||||||
|
// Otherwise, remove only the exceeding message. This is due to Anthropic's strict payload rule to start with "Human:".
|
||||||
|
const nextMessage = {
|
||||||
|
remove: false,
|
||||||
|
tokenCount: 0,
|
||||||
|
messageString: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildPromptBody = async () => {
|
||||||
|
if (currentTokenCount < maxTokenCount && formattedMessages.length > 0) {
|
||||||
|
const message = formattedMessages.pop();
|
||||||
|
const isCreatedByUser = message.author === this.userLabel;
|
||||||
|
const messageString = `${message.author}\n${message.content}${this.endToken}\n`;
|
||||||
|
let newPromptBody = `${messageString}${promptBody}`;
|
||||||
|
|
||||||
|
context.unshift(message);
|
||||||
|
|
||||||
|
const tokenCountForMessage = this.getTokenCount(messageString);
|
||||||
|
const newTokenCount = currentTokenCount + tokenCountForMessage;
|
||||||
|
|
||||||
|
if (!isCreatedByUser) {
|
||||||
|
nextMessage.messageString = messageString;
|
||||||
|
nextMessage.tokenCount = tokenCountForMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newTokenCount > maxTokenCount) {
|
||||||
|
if (!promptBody) {
|
||||||
|
// This is the first message, so we can't add it. Just throw an error.
|
||||||
|
throw new Error(`Prompt is too long. Max token count is ${maxTokenCount}, but prompt is ${newTokenCount} tokens long.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, ths message would put us over the token limit, so don't add it.
|
||||||
|
// if created by user, remove next message, otherwise remove only this message
|
||||||
|
if (isCreatedByUser) {
|
||||||
|
nextMessage.remove = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
promptBody = newPromptBody;
|
||||||
|
currentTokenCount = newTokenCount;
|
||||||
|
// wait for next tick to avoid blocking the event loop
|
||||||
|
await new Promise(resolve => setImmediate(resolve));
|
||||||
|
return buildPromptBody();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
await buildPromptBody();
|
||||||
|
|
||||||
|
if (nextMessage.remove) {
|
||||||
|
promptBody = promptBody.replace(nextMessage.messageString, '');
|
||||||
|
currentTokenCount -= nextMessage.tokenCount;
|
||||||
|
context.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = `${promptBody}${promptSuffix}`;
|
||||||
|
// Add 2 tokens for metadata after all messages have been counted.
|
||||||
|
currentTokenCount += 2;
|
||||||
|
|
||||||
|
// Use up to `this.maxContextTokens` tokens (prompt + response), but try to leave `this.maxTokens` tokens for the response.
|
||||||
|
this.modelOptions.maxOutputTokens = Math.min(this.maxContextTokens - currentTokenCount, this.maxResponseTokens);
|
||||||
|
|
||||||
|
return { prompt, context };
|
||||||
|
}
|
||||||
|
|
||||||
|
getCompletion() {
|
||||||
|
console.log('AnthropicClient doesn\'t use getCompletion (all handled in sendCompletion)');
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement abortController usage
|
||||||
|
async sendCompletion(payload, { onProgress, abortController }) {
|
||||||
|
if (!abortController) {
|
||||||
|
abortController = new AbortController();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { signal } = abortController;
|
||||||
|
|
||||||
|
const modelOptions = { ...this.modelOptions };
|
||||||
|
if (typeof onProgress === 'function') {
|
||||||
|
modelOptions.stream = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { debug } = this.options;
|
||||||
|
if (debug) {
|
||||||
|
console.debug();
|
||||||
|
console.debug(modelOptions);
|
||||||
|
console.debug();
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = this.getClient();
|
||||||
|
const metadata = {
|
||||||
|
user_id: this.user,
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = '';
|
||||||
|
const requestOptions = {
|
||||||
|
prompt: payload,
|
||||||
|
model: this.modelOptions.model,
|
||||||
|
stream: this.modelOptions.stream || true,
|
||||||
|
max_tokens_to_sample: this.modelOptions.maxOutputTokens || 1500,
|
||||||
|
metadata,
|
||||||
|
...modelOptions
|
||||||
|
};
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log('AnthropicClient: requestOptions');
|
||||||
|
console.dir(requestOptions, { depth: null });
|
||||||
|
}
|
||||||
|
const response = await client.completions.create(requestOptions);
|
||||||
|
|
||||||
|
signal.addEventListener('abort', () => {
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log('AnthropicClient: message aborted!');
|
||||||
|
}
|
||||||
|
response.controller.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
for await (const completion of response) {
|
||||||
|
if (this.options.debug) {
|
||||||
|
// Uncomment to debug message stream
|
||||||
|
// console.debug(completion);
|
||||||
|
}
|
||||||
|
text += completion.completion;
|
||||||
|
onProgress(completion.completion);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal.removeEventListener('abort', () => {
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log('AnthropicClient: message aborted!');
|
||||||
|
}
|
||||||
|
response.controller.abort();
|
||||||
|
});
|
||||||
|
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// I commented this out because I will need to refactor this for the BaseClient/all clients
|
||||||
|
// getMessageMapMethod() {
|
||||||
|
// return ((message) => ({
|
||||||
|
// author: message.isCreatedByUser ? this.userLabel : this.assistantLabel,
|
||||||
|
// content: message?.content ?? message.text
|
||||||
|
// })).bind(this);
|
||||||
|
// }
|
||||||
|
|
||||||
|
getSaveOptions() {
|
||||||
|
return {
|
||||||
|
...this.modelOptions
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getBuildMessagesOptions() {
|
||||||
|
if (this.options.debug) {
|
||||||
|
console.log('AnthropicClient doesn\'t use getBuildMessagesOptions');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getTokenizer(encoding, isModelName = false, extendSpecialTokens = {}) {
|
||||||
|
if (tokenizersCache[encoding]) {
|
||||||
|
return tokenizersCache[encoding];
|
||||||
|
}
|
||||||
|
let tokenizer;
|
||||||
|
if (isModelName) {
|
||||||
|
tokenizer = encodingForModel(encoding, extendSpecialTokens);
|
||||||
|
} else {
|
||||||
|
tokenizer = getEncoding(encoding, extendSpecialTokens);
|
||||||
|
}
|
||||||
|
tokenizersCache[encoding] = tokenizer;
|
||||||
|
return tokenizer;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTokenCount(text) {
|
||||||
|
return this.gptEncoder.encode(text, 'all').length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = AnthropicClient;
|
|
@ -370,7 +370,6 @@ class BaseClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendMessage(message, opts = {}) {
|
async sendMessage(message, opts = {}) {
|
||||||
console.log('BaseClient: sendMessage', message, opts);
|
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
conversationId,
|
conversationId,
|
||||||
|
@ -379,6 +378,7 @@ class BaseClient {
|
||||||
userMessage,
|
userMessage,
|
||||||
} = await this.handleStartMethods(message, opts);
|
} = await this.handleStartMethods(message, opts);
|
||||||
|
|
||||||
|
this.user = user;
|
||||||
// It's not necessary to push to currentMessages
|
// It's not necessary to push to currentMessages
|
||||||
// depending on subclass implementation of handling messages
|
// depending on subclass implementation of handling messages
|
||||||
this.currentMessages.push(userMessage);
|
this.currentMessages.push(userMessage);
|
||||||
|
|
|
@ -3,6 +3,7 @@ const OpenAIClient = require('./OpenAIClient');
|
||||||
const PluginsClient = require('./PluginsClient');
|
const PluginsClient = require('./PluginsClient');
|
||||||
const GoogleClient = require('./GoogleClient');
|
const GoogleClient = require('./GoogleClient');
|
||||||
const TextStream = require('./TextStream');
|
const TextStream = require('./TextStream');
|
||||||
|
const AnthropicClient = require('./AnthropicClient');
|
||||||
const toolUtils = require('./tools/util');
|
const toolUtils = require('./tools/util');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -11,5 +12,6 @@ module.exports = {
|
||||||
PluginsClient,
|
PluginsClient,
|
||||||
GoogleClient,
|
GoogleClient,
|
||||||
TextStream,
|
TextStream,
|
||||||
|
AnthropicClient,
|
||||||
...toolUtils
|
...toolUtils
|
||||||
};
|
};
|
|
@ -34,7 +34,7 @@
|
||||||
"name": "Browser",
|
"name": "Browser",
|
||||||
"pluginKey": "browser",
|
"pluginKey": "browser",
|
||||||
"description": "Scrape and summarize webpage data",
|
"description": "Scrape and summarize webpage data",
|
||||||
"icon": "/assets/web-browser.png",
|
"icon": "/assets/web-browser.svg",
|
||||||
"authConfig": [
|
"authConfig": [
|
||||||
{
|
{
|
||||||
"authField": "OPENAI_API_KEY",
|
"authField": "OPENAI_API_KEY",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const conversationPreset = {
|
const conversationPreset = {
|
||||||
// endpoint: [azureOpenAI, openAI, bingAI, chatGPTBrowser]
|
// endpoint: [azureOpenAI, openAI, bingAI, anthropic, chatGPTBrowser]
|
||||||
endpoint: {
|
endpoint: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
|
|
|
@ -20,7 +20,9 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/danny-avila/LibreChat#readme",
|
"homepage": "https://github.com/danny-avila/LibreChat#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@anthropic-ai/sdk": "^0.5.0",
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
"@keyv/mongo": "^2.1.8",
|
"@keyv/mongo": "^2.1.8",
|
||||||
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
|
|
|
@ -24,8 +24,8 @@ config.validate(); // Validate the config
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(errorController);
|
app.use(errorController);
|
||||||
app.use(express.json());
|
app.use(express.json({ limit: '3mb' }));
|
||||||
app.use(express.urlencoded({ extended: true }));
|
app.use(express.urlencoded({ extended: true, limit: '3mb' }));
|
||||||
app.use(express.static(path.join(projectPath, 'dist')));
|
app.use(express.static(path.join(projectPath, 'dist')));
|
||||||
app.use(express.static(path.join(projectPath, 'public')));
|
app.use(express.static(path.join(projectPath, 'public')));
|
||||||
|
|
||||||
|
|
186
api/server/routes/ask/anthropic.js
Normal file
186
api/server/routes/ask/anthropic.js
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const { titleConvo, AnthropicClient } = require('../../../app');
|
||||||
|
const requireJwtAuth = require('../../../middleware/requireJwtAuth');
|
||||||
|
const { abortMessage } = require('../../../utils');
|
||||||
|
const { saveMessage, getConvoTitle, saveConvo, getConvo } = require('../../../models');
|
||||||
|
const { handleError, sendMessage, createOnProgress } = require('./handlers');
|
||||||
|
|
||||||
|
const abortControllers = new Map();
|
||||||
|
|
||||||
|
router.post('/abort', requireJwtAuth, async (req, res) => {
|
||||||
|
return await abortMessage(req, res, abortControllers);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/', requireJwtAuth, async (req, res) => {
|
||||||
|
const { endpoint, text, parentMessageId, conversationId: oldConversationId } = req.body;
|
||||||
|
if (text.length === 0) return handleError(res, { text: 'Prompt empty or too short' });
|
||||||
|
if (endpoint !== 'anthropic') return handleError(res, { text: 'Illegal request' });
|
||||||
|
|
||||||
|
const endpointOption = {
|
||||||
|
promptPrefix: req.body?.promptPrefix ?? null,
|
||||||
|
modelLabel: req.body?.modelLabel ?? null,
|
||||||
|
token: req.body?.token ?? null,
|
||||||
|
modelOptions: {
|
||||||
|
model: req.body?.model ?? 'claude-1',
|
||||||
|
temperature: req.body?.temperature ?? 0.7,
|
||||||
|
maxOutputTokens: req.body?.maxOutputTokens ?? 1024,
|
||||||
|
topP: req.body?.topP ?? 0.7,
|
||||||
|
topK: req.body?.topK ?? 40
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const conversationId = oldConversationId || crypto.randomUUID();
|
||||||
|
|
||||||
|
return await ask({
|
||||||
|
text,
|
||||||
|
endpointOption,
|
||||||
|
conversationId,
|
||||||
|
parentMessageId,
|
||||||
|
req,
|
||||||
|
res
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const ask = async ({ text, endpointOption, parentMessageId = null, conversationId, req, res }) => {
|
||||||
|
res.writeHead(200, {
|
||||||
|
Connection: 'keep-alive',
|
||||||
|
'Content-Type': 'text/event-stream',
|
||||||
|
'Cache-Control': 'no-cache, no-transform',
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'X-Accel-Buffering': 'no'
|
||||||
|
});
|
||||||
|
|
||||||
|
let userMessage;
|
||||||
|
let userMessageId;
|
||||||
|
let responseMessageId;
|
||||||
|
let lastSavedTimestamp = 0;
|
||||||
|
const { overrideParentMessageId = null } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const getIds = (data) => {
|
||||||
|
userMessage = data.userMessage;
|
||||||
|
userMessageId = data.userMessage.messageId;
|
||||||
|
responseMessageId = data.responseMessageId;
|
||||||
|
if (!conversationId) {
|
||||||
|
conversationId = data.conversationId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const { onProgress: progressCallback, getPartialText } = createOnProgress({
|
||||||
|
onProgress: ({ text: partialText }) => {
|
||||||
|
const currentTimestamp = Date.now();
|
||||||
|
if (currentTimestamp - lastSavedTimestamp > 500) {
|
||||||
|
lastSavedTimestamp = currentTimestamp;
|
||||||
|
saveMessage({
|
||||||
|
messageId: responseMessageId,
|
||||||
|
sender: 'Anthropic',
|
||||||
|
conversationId,
|
||||||
|
parentMessageId: overrideParentMessageId || userMessageId,
|
||||||
|
text: partialText,
|
||||||
|
unfinished: true,
|
||||||
|
cancelled: false,
|
||||||
|
error: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
abortController.abortAsk = async function () {
|
||||||
|
this.abort();
|
||||||
|
|
||||||
|
const responseMessage = {
|
||||||
|
messageId: responseMessageId,
|
||||||
|
sender: 'Anthropic',
|
||||||
|
conversationId,
|
||||||
|
parentMessageId: overrideParentMessageId || userMessageId,
|
||||||
|
text: getPartialText(),
|
||||||
|
model: endpointOption.modelOptions.model,
|
||||||
|
unfinished: false,
|
||||||
|
cancelled: true,
|
||||||
|
error: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
saveMessage(responseMessage);
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: await getConvoTitle(req.user.id, conversationId),
|
||||||
|
final: true,
|
||||||
|
conversation: await getConvo(req.user.id, conversationId),
|
||||||
|
requestMessage: userMessage,
|
||||||
|
responseMessage: responseMessage
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStart = (userMessage) => {
|
||||||
|
sendMessage(res, { message: userMessage, created: true });
|
||||||
|
abortControllers.set(userMessage.conversationId, { abortController, ...endpointOption });
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new AnthropicClient(endpointOption.token);
|
||||||
|
|
||||||
|
let response = await client.sendMessage(text, {
|
||||||
|
getIds,
|
||||||
|
debug: false,
|
||||||
|
user: req.user.id,
|
||||||
|
conversationId,
|
||||||
|
parentMessageId,
|
||||||
|
overrideParentMessageId,
|
||||||
|
...endpointOption,
|
||||||
|
onProgress: progressCallback.call(null, {
|
||||||
|
res,
|
||||||
|
text,
|
||||||
|
parentMessageId: overrideParentMessageId || userMessageId
|
||||||
|
}),
|
||||||
|
onStart,
|
||||||
|
abortController
|
||||||
|
});
|
||||||
|
|
||||||
|
if (overrideParentMessageId) {
|
||||||
|
response.parentMessageId = overrideParentMessageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
await saveConvo(req.user.id, {
|
||||||
|
...endpointOption,
|
||||||
|
...endpointOption.modelOptions,
|
||||||
|
conversationId,
|
||||||
|
endpoint: 'anthropic'
|
||||||
|
});
|
||||||
|
|
||||||
|
await saveMessage(response);
|
||||||
|
sendMessage(res, {
|
||||||
|
title: await getConvoTitle(req.user.id, conversationId),
|
||||||
|
final: true,
|
||||||
|
conversation: await getConvo(req.user.id, conversationId),
|
||||||
|
requestMessage: userMessage,
|
||||||
|
responseMessage: response
|
||||||
|
});
|
||||||
|
res.end();
|
||||||
|
|
||||||
|
if (parentMessageId == '00000000-0000-0000-0000-000000000000') {
|
||||||
|
const title = await titleConvo({ text, response });
|
||||||
|
await saveConvo(req.user.id, {
|
||||||
|
conversationId,
|
||||||
|
title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
const errorMessage = {
|
||||||
|
messageId: responseMessageId,
|
||||||
|
sender: 'Anthropic',
|
||||||
|
conversationId,
|
||||||
|
parentMessageId,
|
||||||
|
unfinished: false,
|
||||||
|
cancelled: false,
|
||||||
|
error: true,
|
||||||
|
text: error.message
|
||||||
|
};
|
||||||
|
await saveMessage(errorMessage);
|
||||||
|
handleError(res, errorMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = router;
|
|
@ -7,6 +7,7 @@ const google = require('./google');
|
||||||
const askBingAI = require('./askBingAI');
|
const askBingAI = require('./askBingAI');
|
||||||
const gptPlugins = require('./gptPlugins');
|
const gptPlugins = require('./gptPlugins');
|
||||||
const askChatGPTBrowser = require('./askChatGPTBrowser');
|
const askChatGPTBrowser = require('./askChatGPTBrowser');
|
||||||
|
const anthropic = require('./anthropic');
|
||||||
|
|
||||||
// router.use('/azureOpenAI', askAzureOpenAI);
|
// router.use('/azureOpenAI', askAzureOpenAI);
|
||||||
router.use(['/azureOpenAI', '/openAI'], openAI);
|
router.use(['/azureOpenAI', '/openAI'], openAI);
|
||||||
|
@ -14,5 +15,6 @@ router.use('/google', google);
|
||||||
router.use('/bingAI', askBingAI);
|
router.use('/bingAI', askBingAI);
|
||||||
router.use('/chatGPTBrowser', askChatGPTBrowser);
|
router.use('/chatGPTBrowser', askChatGPTBrowser);
|
||||||
router.use('/gptPlugins', gptPlugins);
|
router.use('/gptPlugins', gptPlugins);
|
||||||
|
router.use('/anthropic', anthropic);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
|
@ -16,6 +16,12 @@ const getChatGPTBrowserModels = () => {
|
||||||
|
|
||||||
return models;
|
return models;
|
||||||
};
|
};
|
||||||
|
const getAnthropicModels = () => {
|
||||||
|
let models = ['claude-1', 'claude-1-100k', 'claude-instant-1', 'claude-instant-1-100k', 'claude-2'];
|
||||||
|
if (process.env.ANTHROPIC_MODELS) models = String(process.env.ANTHROPIC_MODELS).split(',');
|
||||||
|
|
||||||
|
return models;
|
||||||
|
};
|
||||||
|
|
||||||
const getPluginModels = () => {
|
const getPluginModels = () => {
|
||||||
let models = ['gpt-4', 'gpt-4-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-0301'];
|
let models = ['gpt-4', 'gpt-4-0613', 'gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-3.5-turbo-0613', 'gpt-3.5-turbo-0301'];
|
||||||
|
@ -55,7 +61,7 @@ router.get('/', async function (req, res) {
|
||||||
? { availableModels: getOpenAIModels(), userProvide: openAIApiKey === 'user_provided' }
|
? { availableModels: getOpenAIModels(), userProvide: openAIApiKey === 'user_provided' }
|
||||||
: false;
|
: false;
|
||||||
const azureOpenAI = azureOpenAIApiKey
|
const azureOpenAI = azureOpenAIApiKey
|
||||||
? { availableModels: getOpenAIModels({ azure: true}), userProvide: azureOpenAIApiKey === 'user_provided' }
|
? { availableModels: getOpenAIModels({ azure: true }), userProvide: azureOpenAIApiKey === 'user_provided' }
|
||||||
: false;
|
: false;
|
||||||
const gptPlugins = openAIApiKey || azureOpenAIApiKey
|
const gptPlugins = openAIApiKey || azureOpenAIApiKey
|
||||||
? { availableModels: getPluginModels(), availableTools, availableAgents: ['classic', 'functions'], userProvide: userProvidedOpenAI }
|
? { availableModels: getPluginModels(), availableTools, availableAgents: ['classic', 'functions'], userProvide: userProvidedOpenAI }
|
||||||
|
@ -69,8 +75,14 @@ router.get('/', async function (req, res) {
|
||||||
availableModels: getChatGPTBrowserModels()
|
availableModels: getChatGPTBrowserModels()
|
||||||
}
|
}
|
||||||
: false;
|
: false;
|
||||||
|
const anthropic = process.env.ANTHROPIC_API_KEY
|
||||||
|
? {
|
||||||
|
userProvide: process.env.ANTHROPIC_API_KEY == 'user_provided',
|
||||||
|
availableModels: getAnthropicModels()
|
||||||
|
}
|
||||||
|
: false;
|
||||||
|
|
||||||
res.send(JSON.stringify({ azureOpenAI, openAI, google, bingAI, chatGPTBrowser, gptPlugins }));
|
res.send(JSON.stringify({ azureOpenAI, openAI, google, bingAI, chatGPTBrowser, gptPlugins, anthropic }));
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = { router, getOpenAIModels, getChatGPTBrowserModels };
|
module.exports = { router, getOpenAIModels, getChatGPTBrowserModels };
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 99 KiB |
86
client/public/assets/web-browser.svg
Normal file
86
client/public/assets/web-browser.svg
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="135.46666mm"
|
||||||
|
height="135.46666mm"
|
||||||
|
viewBox="0 0 135.46666 135.46666"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||||
|
sodipodi:docname="web-browser.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.829812"
|
||||||
|
inkscape:cx="339.10587"
|
||||||
|
inkscape:cy="281.44968"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1369"
|
||||||
|
inkscape:window-x="1072"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1" /><defs
|
||||||
|
id="defs2"><linearGradient
|
||||||
|
id="linearGradient1021"
|
||||||
|
inkscape:collect="always"><stop
|
||||||
|
style="stop-color:#6914d1;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop1017" /><stop
|
||||||
|
style="stop-color:#c82090;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop1019" /></linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient1021"
|
||||||
|
id="linearGradient5957"
|
||||||
|
x1="75.754601"
|
||||||
|
y1="163.95738"
|
||||||
|
x2="146.97395"
|
||||||
|
y2="86.082359"
|
||||||
|
gradientUnits="userSpaceOnUse" /></defs><g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-38.978451,-51.992085)"><g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer2"
|
||||||
|
inkscape:label="Layer 2"
|
||||||
|
transform="translate(38.978451,51.992085)"
|
||||||
|
style="fill:#000000;fill-opacity:1"><rect
|
||||||
|
style="display:inline;fill:#000000;fill-opacity:1;stroke-width:34.9999"
|
||||||
|
id="rect3228"
|
||||||
|
width="135.46666"
|
||||||
|
height="135.46666"
|
||||||
|
x="0"
|
||||||
|
y="0" /></g><g
|
||||||
|
id="g5792"
|
||||||
|
transform="matrix(0.10863854,0,0,0.10863854,51.849445,65.949185)"><path
|
||||||
|
style="display:inline;fill:url(#linearGradient5957);fill-opacity:1;stroke-width:34.9999"
|
||||||
|
id="path5949"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
sodipodi:cx="106.16872"
|
||||||
|
sodipodi:cy="120.26846"
|
||||||
|
sodipodi:rx="53.232887"
|
||||||
|
sodipodi:ry="53.232887"
|
||||||
|
sodipodi:start="0.31945228"
|
||||||
|
sodipodi:end="0.31361418"
|
||||||
|
sodipodi:open="true"
|
||||||
|
sodipodi:arc-type="arc"
|
||||||
|
d="M 156.70842,136.98607 A 53.232887,53.232887 0 0 1 89.524891,170.83252 53.232887,53.232887 0 0 1 55.580426,103.69845 53.232887,53.232887 0 0 1 122.66487,69.656042 53.232887,53.232887 0 0 1 156.80516,136.69073"
|
||||||
|
transform="matrix(9.2048366,0,0,9.2048366,-477.26567,-607.05147)" /><path
|
||||||
|
d="m 500,10 c -0.1,0 -0.3,0 -0.4,0 -0.1,0 -0.1,0 -0.2,0 -0.2,0 -0.4,0 -0.6,0 C 228.7,10.6 10,229.8 10,500 c 0,270.2 218.7,489.3 488.8,490 0.2,0 0.4,0 0.6,0 0.1,0 0.1,0 0.2,0 0.2,0 0.3,0 0.4,0 C 770.6,990 990,770.6 990,500 990,229.4 770.6,10 500,10 Z m 19.6,293.2 c 51.9,-1.4 102.5,-8.3 151.2,-20.1 14.7,57.8 23.8,124.3 25.2,197.3 H 519.6 Z m 0,-39.2 V 52.3 C 572.4,66.9 626,137.4 660.1,245.4 614.8,256.3 567.9,262.7 519.6,264 Z M 480.4,51.8 V 264 c -48.7,-1.4 -96,-7.8 -141.6,-19 C 373.2,136.4 427.2,65.7 480.4,51.8 Z m 0,251.4 V 480.4 H 302.8 c 1.4,-73.1 10.6,-139.7 25.2,-197.5 49.1,12 100,18.9 152.4,20.3 z M 263.3,480.4 H 49.7 c 4.3,-100.8 41.9,-193.1 102,-266.2 43.6,24 89.9,43.7 138.4,58.4 -15.8,62.5 -25.3,133 -26.8,207.8 z m 0,39.2 c 1.4,74.8 10.9,145.2 26.8,207.8 -48.5,14.7 -94.8,34.4 -138.4,58.5 C 91.6,712.7 54,620.4 49.7,519.6 Z m 39.5,0 h 177.6 v 177 C 428,698 377.1,705 328,717 313.3,659.2 304.2,592.6 302.8,519.6 Z M 480.4,735.7 V 948.1 C 427.2,934.2 373.1,863.4 338.7,754.6 c 45.7,-11 93,-17.5 141.7,-18.9 z m 39.2,212 v -212 c 48.3,1.4 95.2,7.8 140.5,18.7 C 626,862.5 572.5,933.1 519.6,947.7 Z m 0,-251.1 v -177 H 696 C 694.6,592.5 685.5,659 670.8,716.7 622.1,704.8 571.6,698 519.6,696.6 Z m 215.8,-177 H 950.3 C 946,620.4 908.5,712.7 848.4,785.8 804.4,761.6 757.7,741.8 708.8,727 724.5,664.5 734,594.2 735.4,519.6 Z m 0,-39.2 C 734,405.7 724.5,335.3 708.7,272.8 757.6,258 804.3,238.2 848.2,214 c 60.2,73.1 97.7,165.5 102.1,266.3 z M 821.2,184.1 C 782.2,204.8 741,222 698.1,235 675.2,161.3 643,101.1 605,61.6 688.4,81.7 762.9,124.8 821.2,184.1 Z M 393.5,62 c -37.8,39.4 -69.9,99.3 -92.7,172.7 -42.6,-13 -83.4,-30 -122,-50.6 C 236.7,125.2 310.6,82.2 393.5,62 Z M 178.6,815.7 c 38.7,-20.6 79.5,-37.6 122.1,-50.6 22.8,73.4 54.9,133.4 92.7,172.9 C 310.6,917.8 236.6,874.7 178.6,815.7 Z m 426.3,122.6 c 38.1,-39.5 70.3,-99.7 93.2,-173.6 43,13.1 84.2,30.2 123.2,51 C 763,875.1 688.5,918.3 604.9,938.3 Z"
|
||||||
|
id="path5790"
|
||||||
|
style="fill:#000000;fill-opacity:1" /></g></g></svg>
|
After Width: | Height: | Size: 5 KiB |
|
@ -305,7 +305,6 @@ function Registration() {
|
||||||
)}
|
)}
|
||||||
{startupConfig?.openidLoginEnabled && startupConfig?.socialLoginEnabled && (
|
{startupConfig?.openidLoginEnabled && startupConfig?.socialLoginEnabled && (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<div className="mt-4 flex gap-x-2">
|
<div className="mt-4 flex gap-x-2">
|
||||||
<a
|
<a
|
||||||
aria-label="Login with OpenID"
|
aria-label="Login with OpenID"
|
||||||
|
|
27
client/src/components/Endpoints/Anthropic/OptionHover.jsx
Normal file
27
client/src/components/Endpoints/Anthropic/OptionHover.jsx
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { HoverCardPortal, HoverCardContent } from '~/components/ui/HoverCard.tsx';
|
||||||
|
|
||||||
|
const types = {
|
||||||
|
temp: 'Ranges from 0 to 1. Use temp closer to 0 for analytical / multiple choice, and closer to 1 for creative and generative tasks. We recommend altering this or Top P but not both.',
|
||||||
|
topp: 'Top-p changes how the model selects tokens for output. Tokens are selected from most K (see topK parameter) probable to least until the sum of their probabilities equals the top-p value.',
|
||||||
|
topk: "Top-k changes how the model selects tokens for output. A top-k of 1 means the selected token is the most probable among all tokens in the model's vocabulary (also called greedy decoding), while a top-k of 3 means that the next token is selected from among the 3 most probable tokens (using temperature).",
|
||||||
|
maxoutputtokens:
|
||||||
|
' Maximum number of tokens that can be generated in the response. Specify a lower value for shorter responses and a higher value for longer responses.'
|
||||||
|
};
|
||||||
|
|
||||||
|
function OptionHover({ type, side }) {
|
||||||
|
return (
|
||||||
|
<HoverCardPortal>
|
||||||
|
<HoverCardContent
|
||||||
|
side={side}
|
||||||
|
className="w-80 "
|
||||||
|
>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-300">{types[type]}</p>
|
||||||
|
</div>
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCardPortal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OptionHover;
|
251
client/src/components/Endpoints/Anthropic/Settings.jsx
Normal file
251
client/src/components/Endpoints/Anthropic/Settings.jsx
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import TextareaAutosize from 'react-textarea-autosize';
|
||||||
|
import SelectDropDown from '../../ui/SelectDropDown';
|
||||||
|
import { Input } from '~/components/ui/Input.tsx';
|
||||||
|
import { Label } from '~/components/ui/Label.tsx';
|
||||||
|
import { Slider } from '~/components/ui/Slider.tsx';
|
||||||
|
import { InputNumber } from '~/components/ui/InputNumber.tsx';
|
||||||
|
import OptionHover from './OptionHover';
|
||||||
|
import { HoverCard, HoverCardTrigger } from '~/components/ui/HoverCard.tsx';
|
||||||
|
import { cn } from '~/utils/';
|
||||||
|
const defaultTextProps =
|
||||||
|
'rounded-md border border-gray-200 focus:border-slate-400 focus:bg-gray-50 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.05)] 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-500 dark:bg-gray-700 focus:dark:bg-gray-600 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 optionText =
|
||||||
|
'p-0 shadow-none text-right pr-1 h-8 border-transparent focus:ring-[#10a37f] focus:ring-offset-0 focus:ring-opacity-100 hover:bg-gray-800/10 dark:hover:bg-white/10 focus:bg-gray-800/10 dark:focus:bg-white/10 transition-colors';
|
||||||
|
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
|
function Settings(props) {
|
||||||
|
const {
|
||||||
|
readonly,
|
||||||
|
model,
|
||||||
|
modelLabel,
|
||||||
|
promptPrefix,
|
||||||
|
temperature,
|
||||||
|
topP,
|
||||||
|
topK,
|
||||||
|
maxOutputTokens,
|
||||||
|
setOption
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const endpointsConfig = useRecoilValue(store.endpointsConfig);
|
||||||
|
|
||||||
|
const setModel = setOption('model');
|
||||||
|
const setModelLabel = setOption('modelLabel');
|
||||||
|
const setPromptPrefix = setOption('promptPrefix');
|
||||||
|
const setTemperature = setOption('temperature');
|
||||||
|
const setTopP = setOption('topP');
|
||||||
|
const setTopK = setOption('topK');
|
||||||
|
const setMaxOutputTokens = setOption('maxOutputTokens');
|
||||||
|
|
||||||
|
const models = endpointsConfig?.['anthropic']?.['availableModels'] || [];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={`h-[490px] overflow-y-auto md:h-[350px]`}>
|
||||||
|
<div className="grid gap-6 sm:grid-cols-2">
|
||||||
|
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
|
||||||
|
<div className="grid w-full items-center gap-2">
|
||||||
|
<SelectDropDown
|
||||||
|
value={model}
|
||||||
|
setValue={setModel}
|
||||||
|
availableValues={models}
|
||||||
|
disabled={readonly}
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
'z-50 flex w-full resize-none focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0'
|
||||||
|
)}
|
||||||
|
containerClassName="flex w-full resize-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid w-full items-center gap-2">
|
||||||
|
<Label htmlFor="modelLabel" className="text-left text-sm font-medium">
|
||||||
|
Custom Name <small className="opacity-40">(default: blank)</small>
|
||||||
|
</Label>
|
||||||
|
<Input
|
||||||
|
id="modelLabel"
|
||||||
|
disabled={readonly}
|
||||||
|
value={modelLabel || ''}
|
||||||
|
onChange={(e) => setModelLabel(e.target.value || null)}
|
||||||
|
placeholder="Set a custom name for Claude"
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="grid w-full items-center gap-2">
|
||||||
|
<Label htmlFor="promptPrefix" className="text-left text-sm font-medium">
|
||||||
|
Prompt Prefix <small className="opacity-40">(default: blank)</small>
|
||||||
|
</Label>
|
||||||
|
<TextareaAutosize
|
||||||
|
id="promptPrefix"
|
||||||
|
disabled={readonly}
|
||||||
|
value={promptPrefix || ''}
|
||||||
|
onChange={(e) => setPromptPrefix(e.target.value || null)}
|
||||||
|
placeholder="Set custom instructions or context. Ignored if empty."
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
'flex max-h-[300px] min-h-[100px] w-full resize-none px-3 py-2 '
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-1 flex flex-col items-center justify-start gap-6">
|
||||||
|
<HoverCard openDelay={300}>
|
||||||
|
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<Label htmlFor="temp-int" className="text-left text-sm font-medium">
|
||||||
|
Temperature <small className="opacity-40">(default: 0.7)</small>
|
||||||
|
</Label>
|
||||||
|
<InputNumber
|
||||||
|
id="temp-int"
|
||||||
|
disabled={readonly}
|
||||||
|
value={temperature}
|
||||||
|
onChange={(value) => setTemperature(value)}
|
||||||
|
max={1}
|
||||||
|
min={0}
|
||||||
|
step={0.01}
|
||||||
|
controls={false}
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
cn(
|
||||||
|
optionText,
|
||||||
|
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
|
value={[temperature]}
|
||||||
|
onValueChange={(value) => setTemperature(value[0])}
|
||||||
|
doubleClickHandler={() => setTemperature(1)}
|
||||||
|
max={1}
|
||||||
|
min={0}
|
||||||
|
step={0.01}
|
||||||
|
className="flex h-4 w-full"
|
||||||
|
/>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<OptionHover type="temp" side="left" />
|
||||||
|
</HoverCard>
|
||||||
|
<HoverCard openDelay={300}>
|
||||||
|
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<Label htmlFor="top-p-int" className="text-left text-sm font-medium">
|
||||||
|
Top P <small className="opacity-40">(default: 0.95)</small>
|
||||||
|
</Label>
|
||||||
|
<InputNumber
|
||||||
|
id="top-p-int"
|
||||||
|
disabled={readonly}
|
||||||
|
value={topP}
|
||||||
|
onChange={(value) => setTopP(value)}
|
||||||
|
max={1}
|
||||||
|
min={0}
|
||||||
|
step={0.01}
|
||||||
|
controls={false}
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
cn(
|
||||||
|
optionText,
|
||||||
|
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
|
value={[topP]}
|
||||||
|
onValueChange={(value) => setTopP(value[0])}
|
||||||
|
doubleClickHandler={() => setTopP(1)}
|
||||||
|
max={1}
|
||||||
|
min={0}
|
||||||
|
step={0.01}
|
||||||
|
className="flex h-4 w-full"
|
||||||
|
/>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<OptionHover type="topp" side="left" />
|
||||||
|
</HoverCard>
|
||||||
|
|
||||||
|
<HoverCard openDelay={300}>
|
||||||
|
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<Label htmlFor="top-k-int" className="text-left text-sm font-medium">
|
||||||
|
Top K <small className="opacity-40">(default: 40)</small>
|
||||||
|
</Label>
|
||||||
|
<InputNumber
|
||||||
|
id="top-k-int"
|
||||||
|
disabled={readonly}
|
||||||
|
value={topK}
|
||||||
|
onChange={(value) => setTopK(value)}
|
||||||
|
max={40}
|
||||||
|
min={1}
|
||||||
|
step={0.01}
|
||||||
|
controls={false}
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
cn(
|
||||||
|
optionText,
|
||||||
|
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
|
value={[topK]}
|
||||||
|
onValueChange={(value) => setTopK(value[0])}
|
||||||
|
doubleClickHandler={() => setTopK(0)}
|
||||||
|
max={40}
|
||||||
|
min={1}
|
||||||
|
step={0.01}
|
||||||
|
className="flex h-4 w-full"
|
||||||
|
/>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<OptionHover type="topk" side="left" />
|
||||||
|
</HoverCard>
|
||||||
|
<HoverCard openDelay={300}>
|
||||||
|
<HoverCardTrigger className="grid w-full items-center gap-2">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<Label htmlFor="max-tokens-int" className="text-left text-sm font-medium">
|
||||||
|
Max Output Tokens <small className="opacity-40">(default: 1024)</small>
|
||||||
|
</Label>
|
||||||
|
<InputNumber
|
||||||
|
id="max-tokens-int"
|
||||||
|
disabled={readonly}
|
||||||
|
value={maxOutputTokens}
|
||||||
|
onChange={(value) => setMaxOutputTokens(value)}
|
||||||
|
max={1024}
|
||||||
|
min={1}
|
||||||
|
step={1}
|
||||||
|
controls={false}
|
||||||
|
className={cn(
|
||||||
|
defaultTextProps,
|
||||||
|
cn(
|
||||||
|
optionText,
|
||||||
|
'reset-rc-number-input reset-rc-number-input-text-right h-auto w-12 border-0 group-hover/temp:border-gray-200'
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
disabled={readonly}
|
||||||
|
value={[maxOutputTokens]}
|
||||||
|
onValueChange={(value) => setMaxOutputTokens(value[0])}
|
||||||
|
doubleClickHandler={() => setMaxOutputTokens(0)}
|
||||||
|
max={1024}
|
||||||
|
min={1}
|
||||||
|
step={1}
|
||||||
|
className="flex h-4 w-full"
|
||||||
|
/>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<OptionHover type="maxoutputtokens" side="left" />
|
||||||
|
</HoverCard>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Settings;
|
|
@ -10,17 +10,12 @@ const types = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function OptionHover({ type, side }) {
|
function OptionHover({ type, side }) {
|
||||||
// const options = {};
|
|
||||||
// if (type === 'pres') {
|
|
||||||
// options.sideOffset = 45;
|
|
||||||
// }
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HoverCardPortal>
|
<HoverCardPortal>
|
||||||
<HoverCardContent
|
<HoverCardContent
|
||||||
side={side}
|
side={side}
|
||||||
className="w-80 "
|
className="w-80 "
|
||||||
// {...options}
|
|
||||||
>
|
>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<p className="text-sm text-gray-600 dark:text-gray-300">{types[type]}</p>
|
<p className="text-sm text-gray-600 dark:text-gray-300">{types[type]}</p>
|
||||||
|
|
|
@ -43,7 +43,7 @@ const SaveAsPresetDialog = ({ open, onOpenChange, preset }) => {
|
||||||
id="chatGptLabel"
|
id="chatGptLabel"
|
||||||
value={title || ''}
|
value={title || ''}
|
||||||
onChange={(e) => setTitle(e.target.value || '')}
|
onChange={(e) => setTitle(e.target.value || '')}
|
||||||
placeholder="Set a custom name, in case you can find this preset"
|
placeholder="Set a custom name for this preset"
|
||||||
className={cn(
|
className={cn(
|
||||||
defaultTextProps,
|
defaultTextProps,
|
||||||
'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0'
|
'flex h-10 max-h-10 w-full resize-none px-3 py-2 focus:outline-none focus:ring-0 focus:ring-opacity-0 focus:ring-offset-0'
|
||||||
|
|
|
@ -2,12 +2,12 @@ import OpenAISettings from './OpenAI/Settings.jsx';
|
||||||
import BingAISettings from './BingAI/Settings.jsx';
|
import BingAISettings from './BingAI/Settings.jsx';
|
||||||
import GoogleSettings from './Google/Settings.jsx';
|
import GoogleSettings from './Google/Settings.jsx';
|
||||||
import PluginsSettings from './Plugins/Settings.jsx';
|
import PluginsSettings from './Plugins/Settings.jsx';
|
||||||
|
import AnthropicSettings from './Anthropic/Settings.jsx';
|
||||||
|
|
||||||
// A preset dialog to show readonly preset values.
|
// A preset dialog to show readonly preset values.
|
||||||
const Settings = ({ preset, ...props }) => {
|
const Settings = ({ preset, ...props }) => {
|
||||||
const renderSettings = () => {
|
const renderSettings = () => {
|
||||||
const { endpoint } = preset || {};
|
const { endpoint } = preset || {};
|
||||||
console.log('endpoint', endpoint);
|
|
||||||
|
|
||||||
if (endpoint === 'openAI' || endpoint === 'azureOpenAI') {
|
if (endpoint === 'openAI' || endpoint === 'azureOpenAI') {
|
||||||
return (
|
return (
|
||||||
|
@ -47,6 +47,20 @@ const Settings = ({ preset, ...props }) => {
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
return (
|
||||||
|
<AnthropicSettings
|
||||||
|
model={preset?.model}
|
||||||
|
modelLabel={preset?.modelLabel}
|
||||||
|
promptPrefix={preset?.promptPrefix}
|
||||||
|
temperature={preset?.temperature}
|
||||||
|
topP={preset?.topP}
|
||||||
|
topK={preset?.topK}
|
||||||
|
maxOutputTokens={preset?.maxOutputTokens}
|
||||||
|
edit={true}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else if (endpoint === 'gptPlugins') {
|
} else if (endpoint === 'gptPlugins') {
|
||||||
return (
|
return (
|
||||||
<PluginsSettings
|
<PluginsSettings
|
||||||
|
|
107
client/src/components/Input/AnthropicOptions/index.jsx
Normal file
107
client/src/components/Input/AnthropicOptions/index.jsx
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Settings2 } from 'lucide-react';
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
|
import { SelectDropDown, Button } from '~/components';
|
||||||
|
import EndpointOptionsPopover from '../../Endpoints/EndpointOptionsPopover';
|
||||||
|
import SaveAsPresetDialog from '../../Endpoints/SaveAsPresetDialog';
|
||||||
|
import Settings from '../../Endpoints/Anthropic/Settings.jsx';
|
||||||
|
import { cn } from '~/utils/';
|
||||||
|
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
|
function AnthropicOptions() {
|
||||||
|
const [advancedMode, setAdvancedMode] = useState(false);
|
||||||
|
const [saveAsDialogShow, setSaveAsDialogShow] = useState(false);
|
||||||
|
|
||||||
|
const [conversation, setConversation] = useRecoilState(store.conversation) || {};
|
||||||
|
const { endpoint, conversationId } = conversation;
|
||||||
|
const { model, modelLabel, promptPrefix, temperature, topP, topK, maxOutputTokens } =
|
||||||
|
conversation;
|
||||||
|
const endpointsConfig = useRecoilValue(store.endpointsConfig);
|
||||||
|
|
||||||
|
if (endpoint !== 'anthropic') return null;
|
||||||
|
if (conversationId !== 'new') return null;
|
||||||
|
|
||||||
|
const models = endpointsConfig?.['anthropic']?.['availableModels'] || [];
|
||||||
|
|
||||||
|
const triggerAdvancedMode = () => setAdvancedMode((prev) => !prev);
|
||||||
|
|
||||||
|
const switchToSimpleMode = () => {
|
||||||
|
setAdvancedMode(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveAsPreset = () => {
|
||||||
|
setSaveAsDialogShow(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setOption = (param) => (newValue) => {
|
||||||
|
let update = {};
|
||||||
|
update[param] = newValue;
|
||||||
|
setConversation((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
...update
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardStyle =
|
||||||
|
'transition-colors shadow-md rounded-md min-w-[75px] font-normal bg-white border-black/10 hover:border-black/10 focus:border-black/10 dark:border-black/10 dark:hover:border-black/10 dark:focus:border-black/10 border dark:bg-gray-700 text-black dark:text-white';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
'openAIOptions-simple-container flex w-full flex-wrap items-center justify-center gap-2' +
|
||||||
|
(!advancedMode ? ' show' : '')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectDropDown
|
||||||
|
value={model}
|
||||||
|
setValue={setOption('model')}
|
||||||
|
availableValues={models}
|
||||||
|
showAbove={true}
|
||||||
|
showLabel={false}
|
||||||
|
className={cn(
|
||||||
|
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'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
className={cn(
|
||||||
|
cardStyle,
|
||||||
|
'min-w-4 z-50 flex h-[40px] flex-none items-center justify-center px-4 hover:bg-slate-50 focus:ring-0 focus:ring-offset-0 dark:hover:bg-gray-600'
|
||||||
|
)}
|
||||||
|
onClick={triggerAdvancedMode}
|
||||||
|
>
|
||||||
|
<Settings2 className="w-4 text-gray-600 dark:text-white" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<EndpointOptionsPopover
|
||||||
|
content={
|
||||||
|
<div className="px-4 py-4">
|
||||||
|
<Settings
|
||||||
|
model={model}
|
||||||
|
modelLabel={modelLabel}
|
||||||
|
promptPrefix={promptPrefix}
|
||||||
|
temperature={temperature}
|
||||||
|
topP={topP}
|
||||||
|
topK={topK}
|
||||||
|
maxOutputTokens={maxOutputTokens}
|
||||||
|
setOption={setOption}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
visible={advancedMode}
|
||||||
|
saveAsPreset={saveAsPreset}
|
||||||
|
switchToSimpleMode={switchToSimpleMode}
|
||||||
|
/>
|
||||||
|
<SaveAsPresetDialog
|
||||||
|
open={saveAsDialogShow}
|
||||||
|
onOpenChange={setSaveAsDialogShow}
|
||||||
|
preset={conversation}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AnthropicOptions;
|
|
@ -6,6 +6,7 @@ import PluginsOptions from './PluginsOptions';
|
||||||
import ChatGPTOptions from './ChatGPTOptions';
|
import ChatGPTOptions from './ChatGPTOptions';
|
||||||
import BingAIOptions from './BingAIOptions';
|
import BingAIOptions from './BingAIOptions';
|
||||||
import GoogleOptions from './GoogleOptions';
|
import GoogleOptions from './GoogleOptions';
|
||||||
|
import AnthropicOptions from './AnthropicOptions';
|
||||||
import NewConversationMenu from './NewConversationMenu';
|
import NewConversationMenu from './NewConversationMenu';
|
||||||
import AdjustToneButton from './AdjustToneButton';
|
import AdjustToneButton from './AdjustToneButton';
|
||||||
import Footer from './Footer';
|
import Footer from './Footer';
|
||||||
|
@ -130,6 +131,7 @@ export default function TextChat({ isSearchView = false }) {
|
||||||
<ChatGPTOptions />
|
<ChatGPTOptions />
|
||||||
<GoogleOptions />
|
<GoogleOptions />
|
||||||
<BingAIOptions show={showBingToneSetting} />
|
<BingAIOptions show={showBingToneSetting} />
|
||||||
|
<AnthropicOptions />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="input-panel md:bg-vert-light-gradient dark:md:bg-vert-dark-gradient relative w-full border-t bg-white py-2 dark:border-white/20 dark:bg-gray-800 md:border-t-0 md:border-transparent md:bg-transparent md:dark:border-transparent md:dark:bg-transparent">
|
<div className="input-panel md:bg-vert-light-gradient dark:md:bg-vert-dark-gradient relative w-full border-t bg-white py-2 dark:border-white/20 dark:bg-gray-800 md:border-t-0 md:border-transparent md:bg-transparent md:dark:border-transparent md:dark:bg-transparent">
|
||||||
|
|
|
@ -19,7 +19,7 @@ export default function HoverButtons({
|
||||||
|
|
||||||
const branchingSupported =
|
const branchingSupported =
|
||||||
// azureOpenAI, openAI, chatGPTBrowser support branching, so edit enabled // 5/21/23: Bing is allowing editing and Message regenerating
|
// azureOpenAI, openAI, chatGPTBrowser support branching, so edit enabled // 5/21/23: Bing is allowing editing and Message regenerating
|
||||||
!!['azureOpenAI', 'openAI', 'chatGPTBrowser', 'google', 'bingAI', 'gptPlugins'].find(
|
!!['azureOpenAI', 'openAI', 'chatGPTBrowser', 'google', 'bingAI', 'gptPlugins', 'anthropic'].find(
|
||||||
(e) => e === endpoint
|
(e) => e === endpoint
|
||||||
);
|
);
|
||||||
// Sydney in bingAI supports branching, so edit enabled
|
// Sydney in bingAI supports branching, so edit enabled
|
||||||
|
|
|
@ -47,6 +47,8 @@ const MessageHeader = ({ isSearchView = false }) => {
|
||||||
if (model) _title += `: ${model}`;
|
if (model) _title += `: ${model}`;
|
||||||
} else if (endpoint === 'gptPlugins') {
|
} else if (endpoint === 'gptPlugins') {
|
||||||
return plugins;
|
return plugins;
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
_title = 'Claude';
|
||||||
} else if (endpoint === null) {
|
} else if (endpoint === null) {
|
||||||
null;
|
null;
|
||||||
} else {
|
} else {
|
||||||
|
|
37
client/src/components/svg/AnthropicIcon.jsx
Normal file
37
client/src/components/svg/AnthropicIcon.jsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
export default function AnthropicIcon({ size = 25 }) {
|
||||||
|
return (
|
||||||
|
<svg viewBox="0 0 24 16" overflow="visible" width={size} height={size}>
|
||||||
|
<g
|
||||||
|
style={{
|
||||||
|
transform: 'translateX(13px) rotateZ(0deg)',
|
||||||
|
transformorigin: '4.775px 7.73501px'
|
||||||
|
}}
|
||||||
|
// eslint-disable-next-line react/no-unknown-property
|
||||||
|
transformorigin="4.7750020027160645px 7.735011100769043px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
shapeRendering="geometricPrecision"
|
||||||
|
fill="rgb(24,24,24)"
|
||||||
|
fillOpacity="1"
|
||||||
|
d=" M0,0 C0,0 6.1677093505859375,15.470022201538086 6.1677093505859375,15.470022201538086 C6.1677093505859375,15.470022201538086 9.550004005432129,15.470022201538086 9.550004005432129,15.470022201538086 C9.550004005432129,15.470022201538086 3.382294178009033,0 3.382294178009033,0 C3.382294178009033,0 0,0 0,0 C0,0 0,0 0,0z"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
style={{
|
||||||
|
transform: 'none',
|
||||||
|
transformorigin: '7.935px 7.73501px'
|
||||||
|
}}
|
||||||
|
opacity="1"
|
||||||
|
// eslint-disable-next-line react/no-unknown-property
|
||||||
|
transformorigin="7.93500280380249px 7.735011100769043px"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
shapeRendering="geometricPrecision"
|
||||||
|
fill="rgb(24,24,24)"
|
||||||
|
fillOpacity="1"
|
||||||
|
d=" M5.824605464935303,9.348296165466309 C5.824605464935303,9.348296165466309 7.93500280380249,3.911694288253784 7.93500280380249,3.911694288253784 C7.93500280380249,3.911694288253784 10.045400619506836,9.348296165466309 10.045400619506836,9.348296165466309 C10.045400619506836,9.348296165466309 5.824605464935303,9.348296165466309 5.824605464935303,9.348296165466309 C5.824605464935303,9.348296165466309 5.824605464935303,9.348296165466309 5.824605464935303,9.348296165466309z M6.166755199432373,0 C6.166755199432373,0 0,15.470022201538086 0,15.470022201538086 C0,15.470022201538086 3.4480772018432617,15.470022201538086 3.4480772018432617,15.470022201538086 C3.4480772018432617,15.470022201538086 4.709278583526611,12.22130012512207 4.709278583526611,12.22130012512207 C4.709278583526611,12.22130012512207 11.16093635559082,12.22130012512207 11.16093635559082,12.22130012512207 C11.16093635559082,12.22130012512207 12.421928405761719,15.470022201538086 12.421928405761719,15.470022201538086 C12.421928405761719,15.470022201538086 15.87000560760498,15.470022201538086 15.87000560760498,15.470022201538086 C15.87000560760498,15.470022201538086 9.703250885009766,0 9.703250885009766,0 C9.703250885009766,0 6.166755199432373,0 6.166755199432373,0 C6.166755199432373,0 6.166755199432373,0 6.166755199432373,0z"
|
||||||
|
></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
|
@ -9,3 +9,4 @@ export { default as GoogleIcon } from './GoogleIcon';
|
||||||
export { default as OpenIDIcon } from './OpenIDIcon';
|
export { default as OpenIDIcon } from './OpenIDIcon';
|
||||||
export { default as GithubIcon } from './GithubIcon';
|
export { default as GithubIcon } from './GithubIcon';
|
||||||
export { default as DiscordIcon } from './DiscordIcon';
|
export { default as DiscordIcon } from './DiscordIcon';
|
||||||
|
export { default as AnthropicIcon } from './AnthropicIcon';
|
||||||
|
|
|
@ -8,7 +8,8 @@ const endpointsConfig = atom({
|
||||||
bingAI: null,
|
bingAI: null,
|
||||||
chatGPTBrowser: null,
|
chatGPTBrowser: null,
|
||||||
gptPlugins: null,
|
gptPlugins: null,
|
||||||
google: null
|
google: null,
|
||||||
|
anthropic: null
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ const endpointsFilter = selector({
|
||||||
const availableEndpoints = selector({
|
const availableEndpoints = selector({
|
||||||
key: 'availableEndpoints',
|
key: 'availableEndpoints',
|
||||||
get: ({ get }) => {
|
get: ({ get }) => {
|
||||||
const endpoints = ['azureOpenAI', 'openAI', 'chatGPTBrowser', 'gptPlugins', 'bingAI', 'google'];
|
const endpoints = ['azureOpenAI', 'openAI', 'chatGPTBrowser', 'gptPlugins', 'bingAI', 'google', 'anthropic'];
|
||||||
const f = get(endpointsFilter);
|
const f = get(endpointsFilter);
|
||||||
return endpoints.filter((endpoint) => f[endpoint]);
|
return endpoints.filter((endpoint) => f[endpoint]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,19 @@ const cleanupPreset = ({ preset: _preset, endpointsConfig = {} }) => {
|
||||||
topK: _preset?.topK ?? 40,
|
topK: _preset?.topK ?? 40,
|
||||||
title: _preset?.title ?? 'New Preset'
|
title: _preset?.title ?? 'New Preset'
|
||||||
};
|
};
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
preset = {
|
||||||
|
endpoint,
|
||||||
|
presetId: _preset?.presetId ?? null,
|
||||||
|
model: _preset?.model ?? endpointsConfig[endpoint]?.availableModels?.[0] ?? 'claude-1',
|
||||||
|
modelLabel: _preset?.modelLabel ?? null,
|
||||||
|
promptPrefix: _preset?.promptPrefix ?? null,
|
||||||
|
temperature: _preset?.temperature ?? 0.7,
|
||||||
|
maxOutputTokens: _preset?.maxOutputTokens ?? 1024,
|
||||||
|
topP: _preset?.topP ?? 0.7,
|
||||||
|
topK: _preset?.topK ?? 40,
|
||||||
|
title: _preset?.title ?? 'New Preset'
|
||||||
|
};
|
||||||
} else if (endpoint === 'bingAI') {
|
} else if (endpoint === 'bingAI') {
|
||||||
preset = {
|
preset = {
|
||||||
endpoint,
|
endpoint,
|
||||||
|
|
|
@ -57,6 +57,22 @@ const buildDefaultConversation = ({
|
||||||
clientId: null,
|
clientId: null,
|
||||||
invocationId: 1
|
invocationId: 1
|
||||||
};
|
};
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
conversation = {
|
||||||
|
...conversation,
|
||||||
|
endpoint,
|
||||||
|
model:
|
||||||
|
lastConversationSetup?.model ??
|
||||||
|
lastSelectedModel[endpoint] ??
|
||||||
|
endpointsConfig[endpoint]?.availableModels?.[0] ??
|
||||||
|
'claude-1',
|
||||||
|
modelLabel: lastConversationSetup?.modelLabel ?? null,
|
||||||
|
promptPrefix: lastConversationSetup?.promptPrefix ?? null,
|
||||||
|
temperature: lastConversationSetup?.temperature ?? 0.7,
|
||||||
|
maxOutputTokens: lastConversationSetup?.maxOutputTokens ?? 1024,
|
||||||
|
topP: lastConversationSetup?.topP ?? 0.7,
|
||||||
|
topK: lastConversationSetup?.topK ?? 40
|
||||||
|
};
|
||||||
} else if (endpoint === 'chatGPTBrowser') {
|
} else if (endpoint === 'chatGPTBrowser') {
|
||||||
conversation = {
|
conversation = {
|
||||||
...conversation,
|
...conversation,
|
||||||
|
@ -165,7 +181,8 @@ const getDefaultConversation = ({ conversation, endpointsConfig, preset }) => {
|
||||||
'bingAI',
|
'bingAI',
|
||||||
'chatGPTBrowser',
|
'chatGPTBrowser',
|
||||||
'gptPlugins',
|
'gptPlugins',
|
||||||
'google'
|
'google',
|
||||||
|
'anthropic'
|
||||||
].find((e) => endpointsConfig?.[e]);
|
].find((e) => endpointsConfig?.[e]);
|
||||||
if (endpoint) {
|
if (endpoint) {
|
||||||
conversation = buildDefaultConversation({ conversation, endpoint, endpointsConfig });
|
conversation = buildDefaultConversation({ conversation, endpoint, endpointsConfig });
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Plugin, GPTIcon, BingIcon } from '~/components/svg';
|
import { Plugin, GPTIcon, BingIcon, AnthropicIcon } from '~/components/svg';
|
||||||
import { useAuthContext } from '~/hooks/AuthContext';
|
import { useAuthContext } from '~/hooks/AuthContext';
|
||||||
|
import { cn } from '~/utils'
|
||||||
|
|
||||||
const getIcon = (props) => {
|
const getIcon = (props) => {
|
||||||
const { size = 30, isCreatedByUser, button, model, message = true } = props;
|
const { size = 30, isCreatedByUser, button, model, message = true } = props;
|
||||||
|
@ -20,7 +21,9 @@ const getIcon = (props) => {
|
||||||
className="rounded-sm"
|
className="rounded-sm"
|
||||||
src={
|
src={
|
||||||
user?.avatar ||
|
user?.avatar ||
|
||||||
`https://api.dicebear.com/6.x/initials/svg?seed=${user?.name || 'User'}&fontFamily=Verdana&fontSize=36`
|
`https://api.dicebear.com/6.x/initials/svg?seed=${
|
||||||
|
user?.name || 'User'
|
||||||
|
}&fontFamily=Verdana&fontSize=36`
|
||||||
}
|
}
|
||||||
alt="avatar"
|
alt="avatar"
|
||||||
/>
|
/>
|
||||||
|
@ -53,6 +56,11 @@ const getIcon = (props) => {
|
||||||
const { modelLabel } = props;
|
const { modelLabel } = props;
|
||||||
icon = <img src="/assets/google-palm.svg" alt="Palm Icon"/>;
|
icon = <img src="/assets/google-palm.svg" alt="Palm Icon"/>;
|
||||||
name = modelLabel || 'PaLM2';
|
name = modelLabel || 'PaLM2';
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
const { modelLabel } = props;
|
||||||
|
icon = <AnthropicIcon size={size * 0.7} />;
|
||||||
|
bg = '#d09a74';
|
||||||
|
name = modelLabel || 'Claude';
|
||||||
} else if (endpoint === 'bingAI') {
|
} else if (endpoint === 'bingAI') {
|
||||||
const { jailbreak } = props;
|
const { jailbreak } = props;
|
||||||
icon = <BingIcon size={size * 0.7} />;
|
icon = <BingIcon size={size * 0.7} />;
|
||||||
|
@ -83,9 +91,10 @@ const getIcon = (props) => {
|
||||||
width: size,
|
width: size,
|
||||||
height: size
|
height: size
|
||||||
}}
|
}}
|
||||||
className={
|
className={cn(
|
||||||
'relative flex items-center justify-center rounded-sm text-white ' + props?.className
|
'relative flex items-center justify-center rounded-sm text-white ',
|
||||||
}
|
props?.className ?? '',
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
{error && (
|
{error && (
|
||||||
|
|
|
@ -76,6 +76,22 @@ const useMessageHandler = () => {
|
||||||
token: endpointsConfig[endpoint]?.userProvide ? getToken() : null
|
token: endpointsConfig[endpoint]?.userProvide ? getToken() : null
|
||||||
};
|
};
|
||||||
responseSender = endpointOption.jailbreak ? 'Sydney' : 'BingAI';
|
responseSender = endpointOption.jailbreak ? 'Sydney' : 'BingAI';
|
||||||
|
} else if (endpoint === 'anthropic') {
|
||||||
|
endpointOption = {
|
||||||
|
endpoint,
|
||||||
|
model:
|
||||||
|
currentConversation?.model ??
|
||||||
|
endpointsConfig[endpoint]?.availableModels?.[0] ??
|
||||||
|
'claude-1',
|
||||||
|
modelLabel: currentConversation?.modelLabel ?? null,
|
||||||
|
promptPrefix: currentConversation?.promptPrefix ?? null,
|
||||||
|
temperature: currentConversation?.temperature ?? 0.7,
|
||||||
|
maxOutputTokens: currentConversation?.maxOutputTokens ?? 1024,
|
||||||
|
topP: currentConversation?.topP ?? 0.7,
|
||||||
|
topK: currentConversation?.topK ?? 40,
|
||||||
|
token: endpointsConfig[endpoint]?.userProvide ? getToken() : null
|
||||||
|
};
|
||||||
|
responseSender = 'Anthropic';
|
||||||
} else if (endpoint === 'chatGPTBrowser') {
|
} else if (endpoint === 'chatGPTBrowser') {
|
||||||
endpointOption = {
|
endpointOption = {
|
||||||
endpoint,
|
endpoint,
|
||||||
|
|
|
@ -41,6 +41,7 @@ export const alternateName = {
|
||||||
bingAI: 'Bing',
|
bingAI: 'Bing',
|
||||||
chatGPTBrowser: 'ChatGPT',
|
chatGPTBrowser: 'ChatGPT',
|
||||||
gptPlugins: 'Plugins',
|
gptPlugins: 'Plugins',
|
||||||
google: 'PaLM'
|
google: 'PaLM',
|
||||||
|
anthropic: 'Anthropic',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
313
package-lock.json
generated
313
package-lock.json
generated
|
@ -47,7 +47,9 @@
|
||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@anthropic-ai/sdk": "^0.5.0",
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
"@keyv/mongo": "^2.1.8",
|
"@keyv/mongo": "^2.1.8",
|
||||||
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
|
@ -91,6 +93,28 @@
|
||||||
"supertest": "^6.3.3"
|
"supertest": "^6.3.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api/node_modules/@anthropic-ai/sdk": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-7T/oK6CtheVkdRZmIO9FSdHtKyUU92F6JHRz7RY99gzcm6DM5rYTNORvwVHWTe0nr9lsZuso8GpoXZsUG7Zypg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"@types/node-fetch": "^2.6.4",
|
||||||
|
"@types/qs": "^6.9.7",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"agentkeepalive": "^4.2.1",
|
||||||
|
"digest-fetch": "^1.3.0",
|
||||||
|
"form-data-encoder": "1.7.2",
|
||||||
|
"formdata-node": "^4.3.2",
|
||||||
|
"node-fetch": "^2.6.7",
|
||||||
|
"qs": "^6.10.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"api/node_modules/@types/node": {
|
||||||
|
"version": "18.16.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz",
|
||||||
|
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA=="
|
||||||
|
},
|
||||||
"api/node_modules/ansi-styles": {
|
"api/node_modules/ansi-styles": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
|
@ -371,6 +395,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"api/node_modules/langchain/node_modules/@anthropic-ai/sdk": {
|
||||||
|
"version": "0.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.4.4.tgz",
|
||||||
|
"integrity": "sha512-Z/39nQi1sSUCeLII3lsAbL1u+0JF6cR2XmUEX9sLH0VtxmIjY6cjOUYjCkYh4oapTxOkhAFnVSAFJ6cxml2qXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
|
"cross-fetch": "^3.1.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"client": {
|
"client": {
|
||||||
"name": "@librechat/frontend",
|
"name": "@librechat/frontend",
|
||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
|
@ -7560,6 +7593,28 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.0.tgz",
|
||||||
"integrity": "sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ=="
|
"integrity": "sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/node-fetch": {
|
||||||
|
"version": "2.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz",
|
||||||
|
"integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"form-data": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node-fetch/node_modules/form-data": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/parse5": {
|
"node_modules/@types/parse5": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
|
||||||
|
@ -7576,6 +7631,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/qs": {
|
||||||
|
"version": "6.9.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||||
|
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||||
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.2.11",
|
"version": "18.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.11.tgz",
|
||||||
|
@ -8320,6 +8380,19 @@
|
||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/agentkeepalive": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"depd": "^2.0.0",
|
||||||
|
"humanize-ms": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/aggregate-error": {
|
"node_modules/aggregate-error": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||||
|
@ -9213,6 +9286,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base-64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||||
|
},
|
||||||
"node_modules/base64-arraybuffer": {
|
"node_modules/base64-arraybuffer": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||||
|
@ -9754,6 +9832,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/charenc": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cheerio": {
|
"node_modules/cheerio": {
|
||||||
"version": "1.0.0-rc.12",
|
"version": "1.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
||||||
|
@ -10519,6 +10605,14 @@
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypt": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/crypto-browserify": {
|
"node_modules/crypto-browserify": {
|
||||||
"version": "3.12.0",
|
"version": "3.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
||||||
|
@ -11022,6 +11116,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/digest-fetch": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==",
|
||||||
|
"dependencies": {
|
||||||
|
"base-64": "^0.1.0",
|
||||||
|
"md5": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/dir-glob": {
|
"node_modules/dir-glob": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||||
|
@ -12898,6 +13001,11 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/form-data-encoder": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
|
||||||
|
},
|
||||||
"node_modules/format": {
|
"node_modules/format": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
|
||||||
|
@ -12906,6 +13014,18 @@
|
||||||
"node": ">=0.4.x"
|
"node": ">=0.4.x"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/formdata-node": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "1.0.0",
|
||||||
|
"web-streams-polyfill": "4.0.0-beta.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.20"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/formidable": {
|
"node_modules/formidable": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
||||||
|
@ -13894,6 +14014,14 @@
|
||||||
"node": ">=10.17.0"
|
"node": ">=10.17.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/humanize-ms": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/husky": {
|
"node_modules/husky": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
|
||||||
|
@ -18228,6 +18356,16 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/md5": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||||
|
"dependencies": {
|
||||||
|
"charenc": "0.0.2",
|
||||||
|
"crypt": "0.0.2",
|
||||||
|
"is-buffer": "~1.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/md5.js": {
|
"node_modules/md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
|
@ -18238,6 +18376,11 @@
|
||||||
"safe-buffer": "^5.1.2"
|
"safe-buffer": "^5.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/md5/node_modules/is-buffer": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||||
|
},
|
||||||
"node_modules/mdast-util-definitions": {
|
"node_modules/mdast-util-definitions": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz",
|
||||||
|
@ -19544,6 +19687,24 @@
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
|
||||||
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
|
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.11",
|
"version": "2.6.11",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
||||||
|
@ -25895,6 +26056,14 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "4.0.0-beta.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
|
||||||
|
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/webidl-conversions": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
|
@ -30217,7 +30386,9 @@
|
||||||
"@librechat/backend": {
|
"@librechat/backend": {
|
||||||
"version": "file:api",
|
"version": "file:api",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@anthropic-ai/sdk": "^0.5.0",
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
"@keyv/mongo": "^2.1.8",
|
"@keyv/mongo": "^2.1.8",
|
||||||
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
"@waylaidwanderer/chatgpt-api": "^1.37.0",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
|
@ -30259,6 +30430,28 @@
|
||||||
"supertest": "^6.3.3"
|
"supertest": "^6.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@anthropic-ai/sdk": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-7T/oK6CtheVkdRZmIO9FSdHtKyUU92F6JHRz7RY99gzcm6DM5rYTNORvwVHWTe0nr9lsZuso8GpoXZsUG7Zypg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"@types/node-fetch": "^2.6.4",
|
||||||
|
"@types/qs": "^6.9.7",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"agentkeepalive": "^4.2.1",
|
||||||
|
"digest-fetch": "^1.3.0",
|
||||||
|
"form-data-encoder": "1.7.2",
|
||||||
|
"formdata-node": "^4.3.2",
|
||||||
|
"node-fetch": "^2.6.7",
|
||||||
|
"qs": "^6.10.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"version": "18.16.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz",
|
||||||
|
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA=="
|
||||||
|
},
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
|
@ -30303,6 +30496,17 @@
|
||||||
"yaml": "^2.2.1",
|
"yaml": "^2.2.1",
|
||||||
"zod": "^3.21.4",
|
"zod": "^3.21.4",
|
||||||
"zod-to-json-schema": "^3.20.4"
|
"zod-to-json-schema": "^3.20.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@anthropic-ai/sdk": {
|
||||||
|
"version": "0.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.4.4.tgz",
|
||||||
|
"integrity": "sha512-Z/39nQi1sSUCeLII3lsAbL1u+0JF6cR2XmUEX9sLH0VtxmIjY6cjOUYjCkYh4oapTxOkhAFnVSAFJ6cxml2qXg==",
|
||||||
|
"requires": {
|
||||||
|
"@fortaine/fetch-event-source": "^3.0.6",
|
||||||
|
"cross-fetch": "^3.1.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31631,6 +31835,27 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.0.tgz",
|
||||||
"integrity": "sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ=="
|
"integrity": "sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ=="
|
||||||
},
|
},
|
||||||
|
"@types/node-fetch": {
|
||||||
|
"version": "2.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz",
|
||||||
|
"integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*",
|
||||||
|
"form-data": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"form-data": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/parse5": {
|
"@types/parse5": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz",
|
||||||
|
@ -31647,6 +31872,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz",
|
||||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||||
},
|
},
|
||||||
|
"@types/qs": {
|
||||||
|
"version": "6.9.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||||
|
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||||
|
},
|
||||||
"@types/react": {
|
"@types/react": {
|
||||||
"version": "18.2.11",
|
"version": "18.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.11.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.11.tgz",
|
||||||
|
@ -32239,6 +32469,16 @@
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"agentkeepalive": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==",
|
||||||
|
"requires": {
|
||||||
|
"debug": "^4.1.0",
|
||||||
|
"depd": "^2.0.0",
|
||||||
|
"humanize-ms": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"aggregate-error": {
|
"aggregate-error": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||||
|
@ -32943,6 +33183,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"base-64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||||
|
},
|
||||||
"base64-arraybuffer": {
|
"base64-arraybuffer": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
|
||||||
|
@ -33329,6 +33574,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||||
},
|
},
|
||||||
|
"charenc": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="
|
||||||
|
},
|
||||||
"cheerio": {
|
"cheerio": {
|
||||||
"version": "1.0.0-rc.12",
|
"version": "1.0.0-rc.12",
|
||||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
|
||||||
|
@ -33917,6 +34167,11 @@
|
||||||
"which": "^2.0.1"
|
"which": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"crypt": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="
|
||||||
|
},
|
||||||
"crypto-browserify": {
|
"crypto-browserify": {
|
||||||
"version": "3.12.0",
|
"version": "3.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
||||||
|
@ -34280,6 +34535,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"digest-fetch": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==",
|
||||||
|
"requires": {
|
||||||
|
"base-64": "^0.1.0",
|
||||||
|
"md5": "^2.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dir-glob": {
|
"dir-glob": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||||
|
@ -35709,11 +35973,25 @@
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"form-data-encoder": {
|
||||||
|
"version": "1.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
|
||||||
|
"integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
|
||||||
|
},
|
||||||
"format": {
|
"format": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz",
|
||||||
"integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="
|
"integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="
|
||||||
},
|
},
|
||||||
|
"formdata-node": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
|
||||||
|
"requires": {
|
||||||
|
"node-domexception": "1.0.0",
|
||||||
|
"web-streams-polyfill": "4.0.0-beta.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"formidable": {
|
"formidable": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz",
|
||||||
|
@ -36444,6 +36722,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||||
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
|
"integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
|
||||||
},
|
},
|
||||||
|
"humanize-ms": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
|
||||||
|
@ -39607,6 +39893,23 @@
|
||||||
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
|
||||||
"integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="
|
"integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw=="
|
||||||
},
|
},
|
||||||
|
"md5": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
|
||||||
|
"requires": {
|
||||||
|
"charenc": "0.0.2",
|
||||||
|
"crypt": "0.0.2",
|
||||||
|
"is-buffer": "~1.1.6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"is-buffer": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"md5.js": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
|
@ -40486,6 +40789,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
|
||||||
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
|
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA=="
|
||||||
},
|
},
|
||||||
|
"node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="
|
||||||
|
},
|
||||||
"node-fetch": {
|
"node-fetch": {
|
||||||
"version": "2.6.11",
|
"version": "2.6.11",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz",
|
||||||
|
@ -44889,6 +45197,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
|
||||||
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="
|
"integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="
|
||||||
},
|
},
|
||||||
|
"web-streams-polyfill": {
|
||||||
|
"version": "4.0.0-beta.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
|
||||||
|
"integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="
|
||||||
|
},
|
||||||
"webidl-conversions": {
|
"webidl-conversions": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
|
|
|
@ -12,7 +12,8 @@ export default function createPayload(submission: TSubmission) {
|
||||||
bingAI: '/api/ask/bingAI',
|
bingAI: '/api/ask/bingAI',
|
||||||
chatGPT: '/api/ask/chatGPT',
|
chatGPT: '/api/ask/chatGPT',
|
||||||
chatGPTBrowser: '/api/ask/chatGPTBrowser',
|
chatGPTBrowser: '/api/ask/chatGPTBrowser',
|
||||||
gptPlugins: '/api/ask/gptPlugins'
|
gptPlugins: '/api/ask/gptPlugins',
|
||||||
|
anthropic: '/api/ask/anthropic',
|
||||||
};
|
};
|
||||||
|
|
||||||
const server = endpointUrlMap[endpoint];
|
const server = endpointUrlMap[endpoint];
|
||||||
|
|
|
@ -24,6 +24,7 @@ export enum EModelEndpoint {
|
||||||
chatGPTBrowser = 'chatGPTBrowser',
|
chatGPTBrowser = 'chatGPTBrowser',
|
||||||
google = 'google',
|
google = 'google',
|
||||||
gptPlugins = 'gptPlugins',
|
gptPlugins = 'gptPlugins',
|
||||||
|
anthropic = 'anthropic',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TSubmission = {
|
export type TSubmission = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue