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:
Dan Orlando 2023-07-13 18:35:15 -07:00 committed by GitHub
parent 981d009508
commit 9e931229e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 1455 additions and 30 deletions

View 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;

View file

@ -6,6 +6,7 @@ import PluginsOptions from './PluginsOptions';
import ChatGPTOptions from './ChatGPTOptions';
import BingAIOptions from './BingAIOptions';
import GoogleOptions from './GoogleOptions';
import AnthropicOptions from './AnthropicOptions';
import NewConversationMenu from './NewConversationMenu';
import AdjustToneButton from './AdjustToneButton';
import Footer from './Footer';
@ -130,6 +131,7 @@ export default function TextChat({ isSearchView = false }) {
<ChatGPTOptions />
<GoogleOptions />
<BingAIOptions show={showBingToneSetting} />
<AnthropicOptions />
</span>
</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">