🔧 Fix: Resolve Anthropic Client Issues 🧠 (#1226)

* fix: correct preset title for Anthropic endpoint

* fix(Settings/Anthropic): show correct default value for LLM temperature

* fix(AnthropicClient): use `getModelMaxTokens` to get the correct LLM max context tokens, correctly set default temperature to 1, use only 2 params for class constructor, use `getResponseSender` to add correct sender to response message

* refactor(/api/ask|edit/anthropic): save messages to database after the final response is sent to the client, and do not save conversation from route controller

* fix(initializeClient/anthropic): correctly pass client options (endpointOption) to class initialization

* feat(ModelService/Anthropic): add claude-1.2
This commit is contained in:
Danny Avila 2023-11-26 14:44:57 -05:00 committed by GitHub
parent 4b289640f2
commit d7ef4590ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 73 additions and 45 deletions

View file

@ -1,7 +1,8 @@
// const { Agent, ProxyAgent } = require('undici');
const BaseClient = require('./BaseClient');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const Anthropic = require('@anthropic-ai/sdk');
const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken');
const { getResponseSender, EModelEndpoint } = require('~/server/routes/endpoints/schemas');
const { getModelMaxTokens } = require('~/utils');
const BaseClient = require('./BaseClient');
const HUMAN_PROMPT = '\n\nHuman:';
const AI_PROMPT = '\n\nAssistant:';
@ -9,13 +10,9 @@ const AI_PROMPT = '\n\nAssistant:';
const tokenizersCache = {};
class AnthropicClient extends BaseClient {
constructor(apiKey, options = {}, cacheOptions = {}, baseURL) {
super(apiKey, options, cacheOptions);
constructor(apiKey, options = {}) {
super(apiKey, options);
this.apiKey = apiKey || process.env.ANTHROPIC_API_KEY;
this.sender = 'Anthropic';
if (baseURL) {
this.baseURL = baseURL;
}
this.userLabel = HUMAN_PROMPT;
this.assistantLabel = AI_PROMPT;
this.setOptions(options);
@ -43,13 +40,13 @@ class AnthropicClient extends BaseClient {
...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
temperature: typeof modelOptions.temperature === 'undefined' ? 1 : modelOptions.temperature, // 0 - 1, 1 is default
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.maxContextTokens = getModelMaxTokens(this.modelOptions.model) ?? 100000;
this.maxResponseTokens = this.modelOptions.maxOutputTokens || 1500;
this.maxPromptTokens =
this.options.maxPromptTokens || this.maxContextTokens - this.maxResponseTokens;
@ -62,6 +59,14 @@ class AnthropicClient extends BaseClient {
);
}
this.sender =
this.options.sender ??
getResponseSender({
model: this.modelOptions.model,
endpoint: EModelEndpoint.anthropic,
modelLabel: this.options.modelLabel,
});
this.startToken = '||>';
this.endToken = '';
this.gptEncoder = this.constructor.getTokenizer('cl100k_base');
@ -81,16 +86,15 @@ class AnthropicClient extends BaseClient {
}
getClient() {
if (this.baseURL) {
return new Anthropic({
apiKey: this.apiKey,
baseURL: this.baseURL,
});
} else {
return new Anthropic({
apiKey: this.apiKey,
});
const options = {
apiKey: this.apiKey,
};
if (this.options.reverseProxyUrl) {
options.baseURL = this.options.reverseProxyUrl;
}
return new Anthropic(options);
}
async buildMessages(messages, parentMessageId) {