mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 06:00:56 +02:00
Added functionality to allow users to set custom api keys (#276)
* Added functionality to allow users to set custom api keys * Added error handling * Changed token to apiKey * Changed apiKey to oaiApiKey * added azure openai ui * Removed logging * Changed configure to Use * Made checked position more rounded * Made setting api key optional if it is openai * Modified error handling * Add support for insufficient_quota errors * Fixed faulty error detection * removed logging
This commit is contained in:
parent
08f3a77d58
commit
14104b276f
11 changed files with 207 additions and 32 deletions
|
@ -7,6 +7,7 @@ const askClient = async ({
|
||||||
parentMessageId,
|
parentMessageId,
|
||||||
conversationId,
|
conversationId,
|
||||||
model,
|
model,
|
||||||
|
oaiApiKey,
|
||||||
chatGptLabel,
|
chatGptLabel,
|
||||||
promptPrefix,
|
promptPrefix,
|
||||||
temperature,
|
temperature,
|
||||||
|
@ -41,10 +42,10 @@ const askClient = async ({
|
||||||
// debug: true
|
// debug: true
|
||||||
};
|
};
|
||||||
|
|
||||||
let apiKey = process.env.OPENAI_KEY;
|
let apiKey = oaiApiKey ? oaiApiKey : process.env.OPENAI_KEY || null;
|
||||||
|
|
||||||
if (azure) {
|
if (azure) {
|
||||||
apiKey = process.env.AZURE_OPENAI_API_KEY;
|
apiKey = oaiApiKey ? oaiApiKey : process.env.AZURE_OPENAI_API_KEY || null;
|
||||||
clientOptions.reverseProxyUrl = genAzureEndpoint({
|
clientOptions.reverseProxyUrl = genAzureEndpoint({
|
||||||
azureOpenAIApiInstanceName: process.env.AZURE_OPENAI_API_INSTANCE_NAME,
|
azureOpenAIApiInstanceName: process.env.AZURE_OPENAI_API_INSTANCE_NAME,
|
||||||
azureOpenAIApiDeploymentName: process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME,
|
azureOpenAIApiDeploymentName: process.env.AZURE_OPENAI_API_DEPLOYMENT_NAME,
|
||||||
|
|
|
@ -174,6 +174,7 @@ const ask = async ({
|
||||||
text,
|
text,
|
||||||
parentMessageId: userParentMessageId,
|
parentMessageId: userParentMessageId,
|
||||||
conversationId,
|
conversationId,
|
||||||
|
oaiApiKey: req.body?.token ?? null,
|
||||||
...endpointOption,
|
...endpointOption,
|
||||||
onProgress: progressCallback.call(null, {
|
onProgress: progressCallback.call(null, {
|
||||||
res,
|
res,
|
||||||
|
|
|
@ -40,7 +40,7 @@ router.get('/', async function (req, res) {
|
||||||
const azureOpenAI = !!process.env.AZURE_OPENAI_KEY;
|
const azureOpenAI = !!process.env.AZURE_OPENAI_KEY;
|
||||||
const openAI =
|
const openAI =
|
||||||
process.env.OPENAI_KEY || process.env.AZURE_OPENAI_API_KEY
|
process.env.OPENAI_KEY || process.env.AZURE_OPENAI_API_KEY
|
||||||
? { availableModels: getOpenAIModels() }
|
? { availableModels: getOpenAIModels(), userProvide: true }
|
||||||
: false;
|
: false;
|
||||||
const bingAI = process.env.BINGAI_TOKEN
|
const bingAI = process.env.BINGAI_TOKEN
|
||||||
? { userProvide: process.env.BINGAI_TOKEN == 'user_provided' }
|
? { userProvide: process.env.BINGAI_TOKEN == 'user_provided' }
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
"@radix-ui/react-dialog": "^1.0.2",
|
"@radix-ui/react-dialog": "^1.0.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||||
"@radix-ui/react-hover-card": "^1.0.5",
|
"@radix-ui/react-hover-card": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.0",
|
"@radix-ui/react-label": "^2.0.0",
|
||||||
"@radix-ui/react-slider": "^1.1.1",
|
"@radix-ui/react-slider": "^1.1.1",
|
||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default function ModelItem({ endpoint, value, onSelect }) {
|
||||||
className: 'mr-2'
|
className: 'mr-2'
|
||||||
});
|
});
|
||||||
|
|
||||||
const isuserProvide = endpointsConfig?.[endpoint]?.userProvide;
|
const isUserProvided = endpointsConfig?.[endpoint]?.userProvide;
|
||||||
|
|
||||||
// regular model
|
// regular model
|
||||||
return (
|
return (
|
||||||
|
@ -39,7 +39,7 @@ export default function ModelItem({ endpoint, value, onSelect }) {
|
||||||
{alternateName[endpoint] || endpoint}
|
{alternateName[endpoint] || endpoint}
|
||||||
{!!['azureOpenAI', 'openAI'].find(e => e === endpoint) && <sup>$</sup>}
|
{!!['azureOpenAI', 'openAI'].find(e => e === endpoint) && <sup>$</sup>}
|
||||||
<div className="flex w-4 flex-1" />
|
<div className="flex w-4 flex-1" />
|
||||||
{isuserProvide ? (
|
{isUserProvided ? (
|
||||||
<button
|
<button
|
||||||
className="invisible m-0 mr-1 flex-initial rounded-md p-0 text-xs font-medium text-gray-400 hover:text-gray-700 group-hover:visible dark:font-normal dark:text-gray-400 dark:hover:text-gray-200"
|
className="invisible m-0 mr-1 flex-initial rounded-md p-0 text-xs font-medium text-gray-400 hover:text-gray-700 group-hover:visible dark:font-normal dark:text-gray-400 dark:hover:text-gray-200"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Input } from '../../ui/Input.tsx';
|
||||||
|
import { Label } from '../../ui/Label.tsx';
|
||||||
|
import { cn } from '~/utils/';
|
||||||
|
|
||||||
|
function InputWithLabel({ value, onChange, label, id }) {
|
||||||
|
const defaultTextProps =
|
||||||
|
'rounded-md border border-gray-300 bg-transparent text-sm shadow-[0_0_10px_rgba(0,0,0,0.10)] outline-none placeholder:text-gray-400 focus:outline-none focus:ring-gray-400 focus:ring-opacity-20 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-400 dark:bg-gray-700 dark:text-gray-50 dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] dark:focus:border-gray-400 dark:focus:outline-none dark:focus:ring-0 dark:focus:ring-gray-400 dark:focus:ring-offset-0';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Label
|
||||||
|
htmlFor={id}
|
||||||
|
className="text-left text-sm font-medium"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
<br />
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
id={id}
|
||||||
|
value={value || ''}
|
||||||
|
onChange={onChange}
|
||||||
|
placeholder={`Enter ${label}`}
|
||||||
|
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'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InputWithLabel;
|
|
@ -4,11 +4,24 @@ import { Dialog } from '../../ui/Dialog.tsx';
|
||||||
import { Input } from '../../ui/Input.tsx';
|
import { Input } from '../../ui/Input.tsx';
|
||||||
import { Label } from '../../ui/Label.tsx';
|
import { Label } from '../../ui/Label.tsx';
|
||||||
import { cn } from '~/utils/';
|
import { cn } from '~/utils/';
|
||||||
|
import * as Checkbox from '@radix-ui/react-checkbox';
|
||||||
|
import { CheckIcon } from '@radix-ui/react-icons';
|
||||||
import FileUpload from '../NewConversationMenu/FileUpload';
|
import FileUpload from '../NewConversationMenu/FileUpload';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
import InputWithLabel from './InputWithLabel';
|
||||||
|
|
||||||
|
function isJson(str) {
|
||||||
|
try {
|
||||||
|
JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
||||||
const [token, setToken] = useState('');
|
const [token, setToken] = useState('');
|
||||||
|
const [showPanel, setShowPanel] = useState(false);
|
||||||
const { getToken, saveToken } = store.useToken(endpoint);
|
const { getToken, saveToken } = store.useToken(endpoint);
|
||||||
|
|
||||||
const defaultTextProps =
|
const defaultTextProps =
|
||||||
|
@ -20,9 +33,19 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setToken(getToken() ?? '');
|
let oldToken = getToken();
|
||||||
|
if (isJson(token)) {
|
||||||
|
setShowPanel(true);
|
||||||
|
}
|
||||||
|
setToken(oldToken ?? '');
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showPanel && isJson(token)) {
|
||||||
|
setToken('');
|
||||||
|
}
|
||||||
|
}, [showPanel]);
|
||||||
|
|
||||||
const helpText = {
|
const helpText = {
|
||||||
bingAI: (
|
bingAI: (
|
||||||
<small className="break-all text-gray-600">
|
<small className="break-all text-gray-600">
|
||||||
|
@ -79,6 +102,25 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getAzure(name) {
|
||||||
|
if (isJson(token)) {
|
||||||
|
let newToken = JSON.parse(token);
|
||||||
|
return newToken[name];
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAzure(name, value) {
|
||||||
|
let newToken = {};
|
||||||
|
if (isJson(token)) {
|
||||||
|
newToken = JSON.parse(token);
|
||||||
|
}
|
||||||
|
newToken[name] = value;
|
||||||
|
|
||||||
|
setToken(JSON.stringify(newToken));
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
open={open}
|
open={open}
|
||||||
|
@ -88,16 +130,9 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
||||||
title={`Set Token of ${endpoint}`}
|
title={`Set Token of ${endpoint}`}
|
||||||
main={
|
main={
|
||||||
<div className="grid w-full items-center gap-2">
|
<div className="grid w-full items-center gap-2">
|
||||||
<Label
|
|
||||||
htmlFor="chatGptLabel"
|
|
||||||
className="text-left text-sm font-medium"
|
|
||||||
>
|
|
||||||
Token Name
|
|
||||||
<br />
|
|
||||||
</Label>
|
|
||||||
{endpoint === 'google' ? (
|
{endpoint === 'google' ? (
|
||||||
<FileUpload
|
<FileUpload
|
||||||
id="googleKey"
|
id="googleKey"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
text="Import Service Account JSON Key"
|
text="Import Service Account JSON Key"
|
||||||
successText="Successfully Imported Service Account JSON Key"
|
successText="Successfully Imported Service Account JSON Key"
|
||||||
|
@ -137,17 +172,77 @@ const SetTokenDialog = ({ open, onOpenChange, endpoint }) => {
|
||||||
setToken(JSON.stringify(data));
|
setToken(JSON.stringify(data));
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : endpoint === 'openAI' ? (
|
||||||
<Input
|
<>
|
||||||
id="chatGptLabel"
|
{!showPanel ? (
|
||||||
value={token || ''}
|
<>
|
||||||
onChange={e => setToken(e.target.value || '')}
|
<InputWithLabel
|
||||||
placeholder="Set the token."
|
id={'chatGPTLabel'}
|
||||||
className={cn(
|
value={token || ''}
|
||||||
defaultTextProps,
|
onChange={e => setToken(e.target.value || '')}
|
||||||
'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'
|
label={'OpenAI API Key'}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<InputWithLabel
|
||||||
|
id={'instanceNameLabel'}
|
||||||
|
value={getAzure('instanceName') || ''}
|
||||||
|
onChange={e => setAzure('instanceName', e.target.value || '')}
|
||||||
|
label={'Azure OpenAI Instance Name'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputWithLabel
|
||||||
|
id={'deploymentNameLabel'}
|
||||||
|
value={getAzure('deploymentName') || ''}
|
||||||
|
onChange={e => setAzure('deploymentName', e.target.value || '')}
|
||||||
|
label={'Azure OpenAI Deployment Name'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputWithLabel
|
||||||
|
id={'versionLabel'}
|
||||||
|
value={getAzure('version') || ''}
|
||||||
|
onChange={e => setAzure('version', e.target.value || '')}
|
||||||
|
label={'Azure OpenAI API Version'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputWithLabel
|
||||||
|
id={'apiKeyLabel'}
|
||||||
|
value={getAzure('apiKey') || ''}
|
||||||
|
onChange={e => setAzure('apiKey', e.target.value || '')}
|
||||||
|
label={'Azure OpenAI API Key'}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
<div className="flex items-center">
|
||||||
|
<Checkbox.Root
|
||||||
|
className="flex h-[20px] w-[20px] appearance-none items-center justify-center rounded-[4px] bg-gray-100 text-white outline-none hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-900"
|
||||||
|
id="azureOpenAI"
|
||||||
|
checked={showPanel}
|
||||||
|
onCheckedChange={() => setShowPanel(!showPanel)}
|
||||||
|
>
|
||||||
|
<Checkbox.Indicator className="flex h-[20px] w-[20px] items-center justify-center rounded-[3.5px] bg-green-600">
|
||||||
|
<CheckIcon />
|
||||||
|
</Checkbox.Indicator>
|
||||||
|
</Checkbox.Root>
|
||||||
|
|
||||||
|
<label
|
||||||
|
className="pl-[8px] text-[15px] leading-none dark:text-white"
|
||||||
|
htmlFor="azureOpenAI"
|
||||||
|
>
|
||||||
|
Use Azure OpenAI.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<InputWithLabel
|
||||||
|
id={'chatGPTLabel'}
|
||||||
|
value={token || ''}
|
||||||
|
onChange={e => setToken(e.target.value || '')}
|
||||||
|
label={'Token Name'}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
<small className="text-red-600">Your token will be sent to the server, but not saved.</small>
|
<small className="text-red-600">Your token will be sent to the server, but not saved.</small>
|
||||||
{helpText?.[endpoint]}
|
{helpText?.[endpoint]}
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default function SubmitButton({
|
||||||
type="button"
|
type="button"
|
||||||
className="group absolute bottom-0 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500"
|
className="group absolute bottom-0 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500"
|
||||||
>
|
>
|
||||||
<div className="m-1 mr-0 rounded-md p-2 pt-[10px] pb-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
<div className="m-1 mr-0 rounded-md p-2 pb-[10px] pt-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
||||||
<StopGeneratingIcon />
|
<StopGeneratingIcon />
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
@ -61,7 +61,7 @@ export default function SubmitButton({
|
||||||
// </div>
|
// </div>
|
||||||
// </button>
|
// </button>
|
||||||
// );
|
// );
|
||||||
else if (!isTokenProvided) {
|
else if (!isTokenProvided && endpoint !== 'openAI') {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
|
@ -69,7 +69,7 @@ export default function SubmitButton({
|
||||||
type="button"
|
type="button"
|
||||||
className="group absolute bottom-0 right-0 flex h-[100%] w-auto items-center justify-center bg-transparent p-1 text-gray-500"
|
className="group absolute bottom-0 right-0 flex h-[100%] w-auto items-center justify-center bg-transparent p-1 text-gray-500"
|
||||||
>
|
>
|
||||||
<div className="m-1 mr-0 rounded-md p-2 pt-[10px] pb-[10px] align-middle text-xs group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
<div className="m-1 mr-0 rounded-md p-2 pb-[10px] pt-[10px] align-middle text-xs group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
||||||
<Settings className="mr-1 inline-block w-[18px]" />
|
<Settings className="mr-1 inline-block w-[18px]" />
|
||||||
Set Token First
|
Set Token First
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,7 +88,7 @@ export default function SubmitButton({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className="group absolute bottom-0 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500"
|
className="group absolute bottom-0 right-0 flex h-[100%] w-[50px] items-center justify-center bg-transparent p-1 text-gray-500"
|
||||||
>
|
>
|
||||||
<div className="m-1 mr-0 rounded-md p-2 pt-[10px] pb-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
<div className="m-1 mr-0 rounded-md p-2 pb-[10px] pt-[10px] group-hover:bg-gray-100 group-disabled:hover:bg-transparent dark:group-hover:bg-gray-900 dark:group-hover:text-gray-400 dark:group-disabled:hover:bg-transparent">
|
||||||
<svg
|
<svg
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="none"
|
fill="none"
|
||||||
|
|
|
@ -12,6 +12,15 @@ import { useGetConversationByIdQuery } from '~/data-provider';
|
||||||
import { cn } from '~/utils/';
|
import { cn } from '~/utils/';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
|
function isJson(str) {
|
||||||
|
try {
|
||||||
|
JSON.parse(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export default function Message({
|
export default function Message({
|
||||||
conversation,
|
conversation,
|
||||||
message,
|
message,
|
||||||
|
@ -62,6 +71,23 @@ export default function Message({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getError = text => {
|
||||||
|
const match = text.match(/\{[^{}]*\}/);
|
||||||
|
var json = match ? match[0] : ''
|
||||||
|
if (isJson(json)) {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
if (json.code === 'invalid_api_key') {
|
||||||
|
return 'Invalid API key. Please check your API key and try again. You can access your API key by clicking on the model logo in the top-left corner of the textbox.';
|
||||||
|
} else if (json.type === 'insufficient_quota') {
|
||||||
|
return "We're sorry, but the default API key has reached its limit. To continue using this service, please set up your own API key. You can do this by clicking on the model logo in the top-left corner of the textbox.";
|
||||||
|
} else {
|
||||||
|
return `Oops! Something went wrong. Please try again in a few moments. Here's the specific error message we encountered: ${text}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return `Oops! Something went wrong. Please try again in a few moments. Here's the specific error message we encountered: ${text}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const props = {
|
const props = {
|
||||||
className:
|
className:
|
||||||
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 bg-white dark:text-gray-100 group dark:bg-gray-800'
|
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 bg-white dark:text-gray-100 group dark:bg-gray-800'
|
||||||
|
@ -98,7 +124,7 @@ export default function Message({
|
||||||
if (!isSubmitting && !message?.isCreatedByUser) regenerate(message);
|
if (!isSubmitting && !message?.isCreatedByUser) regenerate(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyToClipboard = (setIsCopied) => {
|
const copyToClipboard = setIsCopied => {
|
||||||
setIsCopied(true);
|
setIsCopied(true);
|
||||||
copy(message?.text);
|
copy(message?.text);
|
||||||
|
|
||||||
|
@ -149,7 +175,7 @@ export default function Message({
|
||||||
{error ? (
|
{error ? (
|
||||||
<div className="flex flex min-h-[20px] flex-grow flex-col items-start gap-2 gap-4 text-red-500">
|
<div className="flex flex min-h-[20px] flex-grow flex-col items-start gap-2 gap-4 text-red-500">
|
||||||
<div className="rounded-md border border-red-500 bg-red-500/10 px-3 py-2 text-sm text-gray-600 dark:text-gray-100">
|
<div className="rounded-md border border-red-500 bg-red-500/10 px-3 py-2 text-sm text-gray-600 dark:text-gray-100">
|
||||||
{`An error occurred. Please try again in a few moments.\n\nError message: ${text}`}
|
{getError(text)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : edit ? (
|
) : edit ? (
|
||||||
|
|
|
@ -37,7 +37,8 @@ const useMessageHandler = () => {
|
||||||
temperature: currentConversation?.temperature ?? 1,
|
temperature: currentConversation?.temperature ?? 1,
|
||||||
top_p: currentConversation?.top_p ?? 1,
|
top_p: currentConversation?.top_p ?? 1,
|
||||||
presence_penalty: currentConversation?.presence_penalty ?? 0,
|
presence_penalty: currentConversation?.presence_penalty ?? 0,
|
||||||
frequency_penalty: currentConversation?.frequency_penalty ?? 0
|
frequency_penalty: currentConversation?.frequency_penalty ?? 0,
|
||||||
|
token: endpointsConfig[endpoint]?.userProvide ? getToken() : null
|
||||||
};
|
};
|
||||||
responseSender = endpointOption.chatGptLabel ?? 'ChatGPT';
|
responseSender = endpointOption.chatGptLabel ?? 'ChatGPT';
|
||||||
} else if (endpoint === 'google') {
|
} else if (endpoint === 'google') {
|
||||||
|
@ -47,7 +48,7 @@ const useMessageHandler = () => {
|
||||||
currentConversation?.model ?? endpointsConfig[endpoint]?.availableModels?.[0] ?? 'chat-bison',
|
currentConversation?.model ?? endpointsConfig[endpoint]?.availableModels?.[0] ?? 'chat-bison',
|
||||||
chatGptLabel: currentConversation?.chatGptLabel ?? null,
|
chatGptLabel: currentConversation?.chatGptLabel ?? null,
|
||||||
promptPrefix: currentConversation?.promptPrefix ?? null,
|
promptPrefix: currentConversation?.promptPrefix ?? null,
|
||||||
examples: currentConversation?.examples ?? [{ input: { content: '' }, output: { content: '' }}],
|
examples: currentConversation?.examples ?? [{ input: { content: '' }, output: { content: '' } }],
|
||||||
temperature: currentConversation?.temperature ?? 0.2,
|
temperature: currentConversation?.temperature ?? 0.2,
|
||||||
maxOutputTokens: currentConversation?.maxOutputTokens ?? 1024,
|
maxOutputTokens: currentConversation?.maxOutputTokens ?? 1024,
|
||||||
topP: currentConversation?.topP ?? 0.95,
|
topP: currentConversation?.topP ?? 0.95,
|
||||||
|
|
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -76,6 +76,7 @@
|
||||||
"@radix-ui/react-dialog": "^1.0.2",
|
"@radix-ui/react-dialog": "^1.0.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||||
"@radix-ui/react-hover-card": "^1.0.5",
|
"@radix-ui/react-hover-card": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.0",
|
"@radix-ui/react-label": "^2.0.0",
|
||||||
"@radix-ui/react-slider": "^1.1.1",
|
"@radix-ui/react-slider": "^1.1.1",
|
||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
|
@ -4216,6 +4217,14 @@
|
||||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.x || ^17.x || ^18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@radix-ui/react-id": {
|
"node_modules/@radix-ui/react-id": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -19346,6 +19355,12 @@
|
||||||
"@radix-ui/react-use-controllable-state": "1.0.0"
|
"@radix-ui/react-use-controllable-state": "1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@radix-ui/react-icons": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-jQxj/0LKgp+j9BiTXz3O3sgs26RNet2iLWmsPyRz2SIcR4q/4SbazXfnYwbAr+vLYKSfc7qxzyGQA1HLlYiuNw==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@radix-ui/react-id": {
|
"@radix-ui/react-id": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -20822,6 +20837,7 @@
|
||||||
"@radix-ui/react-dialog": "^1.0.2",
|
"@radix-ui/react-dialog": "^1.0.2",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
"@radix-ui/react-dropdown-menu": "^2.0.2",
|
||||||
"@radix-ui/react-hover-card": "^1.0.5",
|
"@radix-ui/react-hover-card": "^1.0.5",
|
||||||
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.0",
|
"@radix-ui/react-label": "^2.0.0",
|
||||||
"@radix-ui/react-slider": "^1.1.1",
|
"@radix-ui/react-slider": "^1.1.1",
|
||||||
"@radix-ui/react-tabs": "^1.0.3",
|
"@radix-ui/react-tabs": "^1.0.3",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue