From d5ed8690b18ed37490a682a541d8a9a9b54c0bab Mon Sep 17 00:00:00 2001 From: JinmingYang <2214962083@qq.com> Date: Sat, 8 Jul 2023 15:05:29 +0800 Subject: [PATCH] feat(gpt-runner-core): add Anthropic model support --- .../gpt-runner-core/src/langchain/helper.ts | 8 +- .../src/langchain/llm-chain/get-llm.ts | 8 +- .../llm-chain/models/anthropic.model.ts | 51 +++++++ ...ng-face.chain.ts => hugging-face.model.ts} | 0 .../{openai.chain.ts => openai.model.ts} | 0 .../src/common/helpers/constants.ts | 1 + .../common/types/config/anthropic.config.ts | 56 +++++++ .../src/common/types/config/base.config.ts | 4 +- .../src/common/types/config/index.ts | 1 + .../src/common/types/enum.ts | 7 +- .../src/common/zod/config/anthropic.zod.ts | 18 +++ .../src/common/zod/config/index.ts | 13 +- .../src/common/zod/config/openai.zod.ts | 4 +- .../src/common/zod/config/user.config.ts | 10 +- .../client/public/locales/de.json | 18 ++- .../client/public/locales/en.json | 18 ++- .../client/public/locales/ja.json | 18 ++- .../client/public/locales/zh_CN.json | 18 ++- .../client/public/locales/zh_Hant.json | 18 ++- .../chat/components/chat-panel/index.tsx | 2 +- .../anthropic-settings/model-settings.tsx | 137 ++++++++++++++++++ .../anthropic-settings/secrets-settings.tsx | 55 +++++++ .../components/model-settings/index.tsx | 15 +- .../openai-settings/model-settings.tsx | 12 +- .../src/store/zustand/global/chat.slice.ts | 2 +- 25 files changed, 427 insertions(+), 67 deletions(-) create mode 100644 packages/gpt-runner-core/src/langchain/llm-chain/models/anthropic.model.ts rename packages/gpt-runner-core/src/langchain/llm-chain/models/{hugging-face.chain.ts => hugging-face.model.ts} (100%) rename packages/gpt-runner-core/src/langchain/llm-chain/models/{openai.chain.ts => openai.model.ts} (100%) create mode 100644 packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts create mode 100644 packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts create mode 100644 packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx create mode 100644 packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/secrets-settings.tsx diff --git a/packages/gpt-runner-core/src/langchain/helper.ts b/packages/gpt-runner-core/src/langchain/helper.ts index 0af14f3..641814f 100644 --- a/packages/gpt-runner-core/src/langchain/helper.ts +++ b/packages/gpt-runner-core/src/langchain/helper.ts @@ -12,9 +12,9 @@ export function mapStoredMessagesToChatMessages( switch (message.name) { case ChatRole.User: return new HumanChatMessage(message.text) - case ChatRole.ASSISTANT: + case ChatRole.Assistant: return new AIChatMessage(message.text) - case ChatRole.SYSTEM: + case ChatRole.System: return new SystemChatMessage(message.text) default: throw new Error('Role must be defined for generic messages') @@ -29,9 +29,9 @@ export function mapStoredMessageToChatTemplateMessages( switch (message.name) { case ChatRole.User: return HumanMessagePromptTemplate.fromTemplate(message.text) - case ChatRole.ASSISTANT: + case ChatRole.Assistant: return AIMessagePromptTemplate.fromTemplate(message.text) - case ChatRole.SYSTEM: + case ChatRole.System: return SystemMessagePromptTemplate.fromTemplate(message.text) default: throw new Error('Role must be defined for generic messages') diff --git a/packages/gpt-runner-core/src/langchain/llm-chain/get-llm.ts b/packages/gpt-runner-core/src/langchain/llm-chain/get-llm.ts index e0a48b1..44154c4 100644 --- a/packages/gpt-runner-core/src/langchain/llm-chain/get-llm.ts +++ b/packages/gpt-runner-core/src/langchain/llm-chain/get-llm.ts @@ -1,13 +1,15 @@ import type { BaseLanguageModel } from 'langchain/dist/base_language' import { ChatModelType } from '@nicepkg/gpt-runner-shared/common' import type { GetLLMChainParams } from './type' -import { getOpenaiLLM } from './models/openai.chain' -import { getHuggingFaceLLM } from './models/hugging-face.chain' +import { getAnthropicLLM } from './models/anthropic.model' +import { getHuggingFaceLLM } from './models/hugging-face.model' +import { getOpenaiLLM } from './models/openai.model' export function getLLM(params: GetLLMChainParams): BaseLanguageModel { const getLLMFns: ((params: GetLLMChainParams) => BaseLanguageModel | null)[] = [ - getOpenaiLLM, + getAnthropicLLM, getHuggingFaceLLM, + getOpenaiLLM, ] if (!params.model.type) { diff --git a/packages/gpt-runner-core/src/langchain/llm-chain/models/anthropic.model.ts b/packages/gpt-runner-core/src/langchain/llm-chain/models/anthropic.model.ts new file mode 100644 index 0000000..f0f4abd --- /dev/null +++ b/packages/gpt-runner-core/src/langchain/llm-chain/models/anthropic.model.ts @@ -0,0 +1,51 @@ +import type { BaseLanguageModel } from 'langchain/dist/base_language' +import { ChatModelType } from '@nicepkg/gpt-runner-shared/common' +import { ChatAnthropic } from 'langchain/chat_models/anthropic' +import { CallbackManager } from 'langchain/callbacks' +import type { GetLLMChainParams } from '../type' + +export function getAnthropicLLM(params: GetLLMChainParams): BaseLanguageModel | null { + const { model, onTokenStream, onComplete, onError } = params + + if (model.type === ChatModelType.Anthropic) { + const { secrets, modelName, temperature, maxTokens, topP, topK } = model + + console.log('Anthropic model: ', model) + + return new ChatAnthropic({ + streaming: true, + maxRetries: 1, + anthropicApiKey: secrets?.apiKey, + anthropicApiUrl: secrets?.basePath, + modelName, + temperature, + maxTokensToSample: maxTokens, + topP, + topK, + callbackManager: CallbackManager.fromHandlers({ + handleLLMNewToken: async (token: string) => { + onTokenStream?.(token) + }, + handleLLMEnd: async () => { + onComplete?.() + }, + handleLLMError: async (e) => { + console.log('handleLLMError Error: ', e) + onError?.(e) + }, + handleChainError: async (err) => { + if (err.message.includes('Could not parse LLM output: ')) { + const output = err.message.split('Could not parse LLM output: ')[1] + onTokenStream?.(`${output} \n\n`) + } + else { + console.log('Chain Error: ', err) + onError?.(err) + } + }, + }), + }) + } + + return null +} diff --git a/packages/gpt-runner-core/src/langchain/llm-chain/models/hugging-face.chain.ts b/packages/gpt-runner-core/src/langchain/llm-chain/models/hugging-face.model.ts similarity index 100% rename from packages/gpt-runner-core/src/langchain/llm-chain/models/hugging-face.chain.ts rename to packages/gpt-runner-core/src/langchain/llm-chain/models/hugging-face.model.ts diff --git a/packages/gpt-runner-core/src/langchain/llm-chain/models/openai.chain.ts b/packages/gpt-runner-core/src/langchain/llm-chain/models/openai.model.ts similarity index 100% rename from packages/gpt-runner-core/src/langchain/llm-chain/models/openai.chain.ts rename to packages/gpt-runner-core/src/langchain/llm-chain/models/openai.model.ts diff --git a/packages/gpt-runner-shared/src/common/helpers/constants.ts b/packages/gpt-runner-shared/src/common/helpers/constants.ts index 4415836..9a38f68 100644 --- a/packages/gpt-runner-shared/src/common/helpers/constants.ts +++ b/packages/gpt-runner-shared/src/common/helpers/constants.ts @@ -2,6 +2,7 @@ export const MIN_NODE_VERSION = '16.15.0' export const SECRET_KEY_PLACEHOLDER = '********' export const STREAM_DONE_FLAG = '[DONE]' export const GPT_RUNNER_OFFICIAL_FOLDER = '.gpt-runner' +export const DEFAULT_ANTHROPIC_API_BASE_PATH = 'https://api.anthropic.com' export const DEFAULT_OPENAI_API_BASE_PATH = 'https://api.openai.com/v1' export const DEFAULT_EXCLUDE_FILES = [ diff --git a/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts b/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts new file mode 100644 index 0000000..c150006 --- /dev/null +++ b/packages/gpt-runner-shared/src/common/types/config/anthropic.config.ts @@ -0,0 +1,56 @@ +import type { ChatModelType } from '../enum' +import type { BaseModelConfig } from './base.config' + +export interface AnthropicSecrets { + /** + * The API key to use for Anthropic API requests. + */ + apiKey?: string + + /** + * override Anthropic base API url + */ + basePath?: string +} + +export interface AnthropicModelConfig extends BaseModelConfig { + /** + * mode type + */ + type: ChatModelType.Anthropic + + /** + * openai secret config + */ + secrets?: AnthropicSecrets + + /** Amount of randomness injected into the response. Ranges + * from 0 to 1. Use temp closer to 0 for analytical / + * multiple choice, and temp closer to 1 for creative + * and generative tasks. + */ + temperature?: number + + /** + * Maximum number of tokens to generate in the completion. -1 returns as many + * tokens as possible given the prompt and the model's maximum context size. + */ + maxTokens?: number + + /** Does nucleus sampling, in which we compute the + * cumulative distribution over all the options for each + * subsequent token in decreasing probability order and + * cut it off once it reaches a particular probability + * specified by top_p. Defaults to -1, which disables it. + * Note that you should either alter temperature or top_p, + * but not both. + */ + topP?: number + + /** + * Only sample from the top K options for each subsequent + * token. Used to remove "long tail" low probability + * responses. Defaults to -1, which disables it. + */ + topK?: number +} diff --git a/packages/gpt-runner-shared/src/common/types/config/base.config.ts b/packages/gpt-runner-shared/src/common/types/config/base.config.ts index fc156d9..faf5d88 100644 --- a/packages/gpt-runner-shared/src/common/types/config/base.config.ts +++ b/packages/gpt-runner-shared/src/common/types/config/base.config.ts @@ -1,4 +1,5 @@ import type { ChatModelType } from '../enum' +import type { AnthropicModelConfig } from './anthropic.config' import type { HuggingFaceModelConfig } from './hugging-face.config' import type { OpenaiModelConfig } from './openai.config' @@ -20,8 +21,9 @@ export interface BaseModelConfig { } export interface ChatModelTypeMap { - [ChatModelType.Openai]: OpenaiModelConfig + [ChatModelType.Anthropic]: AnthropicModelConfig [ChatModelType.HuggingFace]: HuggingFaceModelConfig + [ChatModelType.Openai]: OpenaiModelConfig } export type PartialChatModelTypeMap = Partial diff --git a/packages/gpt-runner-shared/src/common/types/config/index.ts b/packages/gpt-runner-shared/src/common/types/config/index.ts index 5d919a5..0045f61 100644 --- a/packages/gpt-runner-shared/src/common/types/config/index.ts +++ b/packages/gpt-runner-shared/src/common/types/config/index.ts @@ -1,3 +1,4 @@ +export * from './anthropic.config' export * from './base.config' export * from './hugging-face.config' export * from './openai.config' diff --git a/packages/gpt-runner-shared/src/common/types/enum.ts b/packages/gpt-runner-shared/src/common/types/enum.ts index d80a3bd..b5045a5 100644 --- a/packages/gpt-runner-shared/src/common/types/enum.ts +++ b/packages/gpt-runner-shared/src/common/types/enum.ts @@ -1,12 +1,13 @@ export enum ChatModelType { Openai = 'openai', HuggingFace = 'huggingFace', + Anthropic = 'anthropic', } export enum ChatRole { User = 'user', - ASSISTANT = 'assistant', - SYSTEM = 'system', + Assistant = 'assistant', + System = 'system', } export enum ChatMessageStatus { @@ -58,6 +59,8 @@ export enum LocaleLang { } export enum SecretStorageKey { + Anthropic = 'anthropic', + HuggingFace = 'huggingFace', Openai = 'openai', Proxy = 'proxy', } diff --git a/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts new file mode 100644 index 0000000..a53a85d --- /dev/null +++ b/packages/gpt-runner-shared/src/common/zod/config/anthropic.zod.ts @@ -0,0 +1,18 @@ +import { z } from 'zod' +import { type AnthropicModelConfig, type AnthropicSecrets, ChatModelType } from '../../types' +import { DEFAULT_ANTHROPIC_API_BASE_PATH } from '../../helpers' +import { BaseModelConfigSchema } from './base.zod' + +export const AnthropicSecretsSchema = z.object({ + apiKey: z.string().optional().describe('The Anthropic API key'), + basePath: z.string().optional().default(DEFAULT_ANTHROPIC_API_BASE_PATH).describe('The Anthropic base API url'), +}) satisfies z.ZodType + +export const AnthropicModelConfigSchema = BaseModelConfigSchema.extend({ + type: z.literal(ChatModelType.Anthropic).describe('Use Anthropic model'), + secrets: AnthropicSecretsSchema.optional().describe('The Anthropic API secrets config'), + temperature: z.number().optional().describe('The temperature for the Anthropic model'), + maxTokens: z.number().optional().describe('The maximum number of tokens for the Anthropic model'), + topP: z.number().optional().describe('The top P value for the Anthropic model'), + topK: z.number().optional().describe('The top K value for the Anthropic model'), +}) satisfies z.ZodType diff --git a/packages/gpt-runner-shared/src/common/zod/config/index.ts b/packages/gpt-runner-shared/src/common/zod/config/index.ts index 6b54b2f..0225517 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/index.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/index.ts @@ -1,8 +1,9 @@ import type { z } from 'zod' import type { GetModelConfigType } from '../../types' import { ChatModelType } from '../../types' -import { OpenaiModelConfigSchema, OpenaiSecretsSchema } from './openai.zod' +import { AnthropicModelConfigSchema, AnthropicSecretsSchema } from './anthropic.zod' import { HuggingFaceModelConfigSchema, HuggingFaceSecretsSchema } from './hugging-face.zod' +import { OpenaiModelConfigSchema, OpenaiSecretsSchema } from './openai.zod' export * from './base.zod' export * from './openai.zod' @@ -15,14 +16,18 @@ export function getModelConfigTypeSchema(modelType: T, secrets: z.ZodType> } } = { - [ChatModelType.Openai]: { - config: OpenaiModelConfigSchema, - secrets: OpenaiSecretsSchema, + [ChatModelType.Anthropic]: { + config: AnthropicModelConfigSchema, + secrets: AnthropicSecretsSchema, }, [ChatModelType.HuggingFace]: { config: HuggingFaceModelConfigSchema, secrets: HuggingFaceSecretsSchema, }, + [ChatModelType.Openai]: { + config: OpenaiModelConfigSchema, + secrets: OpenaiSecretsSchema, + }, } return chatModelTypeSchemaMap[modelType][schemaType] } diff --git a/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts b/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts index 4337096..d188484 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/openai.zod.ts @@ -9,11 +9,11 @@ export const OpenaiSecretsSchema = z.object({ // username: z.string().optional().describe('The OpenAI username'), // password: z.string().optional().describe('The OpenAI password'), accessToken: z.string().optional().describe('The OpenAI access token'), - basePath: z.string().optional().default(DEFAULT_OPENAI_API_BASE_PATH).describe('The Chatgpt base path'), + basePath: z.string().optional().default(DEFAULT_OPENAI_API_BASE_PATH).describe('The OpenAI base API path'), }) satisfies z.ZodType export const OpenaiModelConfigSchema = BaseModelConfigSchema.extend({ - type: z.literal(ChatModelType.Openai).describe('Use Open AI model'), + type: z.literal(ChatModelType.Openai).describe('Use OpenAI model'), secrets: OpenaiSecretsSchema.optional().describe('The OpenAI API secrets config'), temperature: z.number().optional().describe('The temperature for the OpenAI model'), maxTokens: z.number().optional().describe('The maximum number of tokens for the OpenAI model'), diff --git a/packages/gpt-runner-shared/src/common/zod/config/user.config.ts b/packages/gpt-runner-shared/src/common/zod/config/user.config.ts index adad8e2..d4e7688 100644 --- a/packages/gpt-runner-shared/src/common/zod/config/user.config.ts +++ b/packages/gpt-runner-shared/src/common/zod/config/user.config.ts @@ -2,8 +2,9 @@ import { z } from 'zod' import { type ChatModel, ChatModelType, type FilterPattern, type FormCheckboxGroupConfig, type FormFieldBaseConfig, type FormInputConfig, type FormItemConfig, type FormOption, type FormRadioGroupConfig, type FormSelectConfig, type FormTextareaConfig, type SingleChatMessage, type SingleFileConfig, type UserConfig, type UserConfigForUser } from '../../types' import { ChatRoleSchema } from '../enum.zod' import type { PartialChatModelTypeMap } from './../../types/config/base.config' -import { OpenaiModelConfigSchema } from './openai.zod' +import { AnthropicModelConfigSchema } from './anthropic.zod' import { HuggingFaceModelConfigSchema } from './hugging-face.zod' +import { OpenaiModelConfigSchema } from './openai.zod' export const FilterPatternSchema = z.union([ z.array(z.union([z.string(), z.instanceof(RegExp)])), @@ -14,15 +15,16 @@ export const FilterPatternSchema = z.union([ z.undefined(), ]) satisfies z.ZodType -// OpenaiModelConfigSchema or HuggingFaceModelConfigSchema export const ChatModelSchema = z.union([ - OpenaiModelConfigSchema, + AnthropicModelConfigSchema, HuggingFaceModelConfigSchema, + OpenaiModelConfigSchema, ]) satisfies z.ZodType export const PartialChatModelTypeMapSchema = z.object({ - [ChatModelType.Openai]: OpenaiModelConfigSchema.optional(), + [ChatModelType.Anthropic]: AnthropicModelConfigSchema.optional(), [ChatModelType.HuggingFace]: HuggingFaceModelConfigSchema.optional(), + [ChatModelType.Openai]: OpenaiModelConfigSchema.optional(), }) satisfies z.ZodType export const UserConfigSchema = z.object({ diff --git a/packages/gpt-runner-web/client/public/locales/de.json b/packages/gpt-runner-web/client/public/locales/de.json index e9fc9a7..3d12280 100644 --- a/packages/gpt-runner-web/client/public/locales/de.json +++ b/packages/gpt-runner-web/client/public/locales/de.json @@ -59,17 +59,21 @@ "context_settings_selected_files_checkbox_label": "Ausgewählte Dateien als Aufforderung. Aktuell ausgewählte{{fileNum}}Dateien{{tokenNum}}Token.", "context_settings_all_file_paths_checkbox_label": "Alle Dateipfade als Aufforderung{{tokenNum}}Token.", "model_settings_btn": "Modell-Einstellungen", - "openai_model_name": "Modellname", - "openai_temperature": "Temperatur", - "openai_max_tokens": "Maximale Antwort-Token", - "openai_top_p": "Top P", - "openai_frequency_penalty": "Frequenzstrafe", - "openai_presence_penalty": "Anwesenheitsstrafe", + "model_name": "Modellname", + "temperature": "Temperatur", + "max_tokens": "Maximale Antwort-Token", + "top_p": "Top P", + "top_k": "Top K", + "frequency_penalty": "Frequenzstrafe", + "presence_penalty": "Anwesenheitsstrafe", "version": "Version", "github": "Github", "reward": "Belohnung", "contributors": "Mitwirkende", "buy_me_a_coffee": "Kauf mir einen Kaffee", + "anthropic_api_key": "Anthropic API-Schlüssel", + "anthropic_api_key_placeholder": "Bitte geben Sie den Anthropic API-Schlüssel ein", + "anthropic_api_base_path": "Anthropic API-Basispfad", "openai_api_key": "OpenAI API-Schlüssel", "openai_api_key_placeholder": "Bitte geben Sie den OpenAI API-Schlüssel ein", "openai_api_base_path": "OpenAI API-Basispfad", @@ -90,4 +94,4 @@ "file_editor_forgot_save_tips_title": "Möchten Sie die Änderungen an {{fileName}} speichern?", "file_editor_forgot_save_tips_content": "Ihre Änderungen gehen verloren, wenn Sie sie nicht speichern." } -} \ No newline at end of file +} diff --git a/packages/gpt-runner-web/client/public/locales/en.json b/packages/gpt-runner-web/client/public/locales/en.json index 361e61e..7118cb9 100644 --- a/packages/gpt-runner-web/client/public/locales/en.json +++ b/packages/gpt-runner-web/client/public/locales/en.json @@ -59,17 +59,21 @@ "context_settings_selected_files_checkbox_label": "Selected Files As Prompt. Current Selected {{fileNum}} Files {{tokenNum}} Tokens.", "context_settings_all_file_paths_checkbox_label": "All File Path As Prompt {{tokenNum}} Tokens.", "model_settings_btn": "Model Settings", - "openai_model_name": "Model Name", - "openai_temperature": "Temperature", - "openai_max_tokens": "Max Reply Tokens", - "openai_top_p": "Top P", - "openai_frequency_penalty": "Frequency Penalty", - "openai_presence_penalty": "Presence Penalty", + "model_name": "Model Name", + "temperature": "Temperature", + "max_tokens": "Max Reply Tokens", + "top_p": "Top P", + "top_k": "Top K", + "frequency_penalty": "Frequency Penalty", + "presence_penalty": "Presence Penalty", "version": "Version", "github": "Github", "reward": "Reward", "contributors": "Contributors", "buy_me_a_coffee": "buy me a coffee", + "anthropic_api_key": "Anthropic API Key", + "anthropic_api_key_placeholder": "Please input Anthropic API Key", + "anthropic_api_base_path": "Anthropic API Base Path", "openai_api_key": "OpenAI API Key", "openai_api_key_placeholder": "Please input OpenAI API Key", "openai_api_base_path": "OpenAI API Base Path", @@ -90,4 +94,4 @@ "file_editor_forgot_save_tips_title": "Do you want to save changes to {{fileName}}?", "file_editor_forgot_save_tips_content": "Your changes will be lost if you don't save them." } -} \ No newline at end of file +} diff --git a/packages/gpt-runner-web/client/public/locales/ja.json b/packages/gpt-runner-web/client/public/locales/ja.json index c3be424..84e8f38 100644 --- a/packages/gpt-runner-web/client/public/locales/ja.json +++ b/packages/gpt-runner-web/client/public/locales/ja.json @@ -59,17 +59,21 @@ "context_settings_selected_files_checkbox_label": "選択したファイルをプロンプトとして使用。現在選択中{{fileNum}}ファイル{{tokenNum}}トークン。", "context_settings_all_file_paths_checkbox_label": "すべてのファイルパスをプロンプトとして使用{{tokenNum}}トークン。", "model_settings_btn": "モデル設定", - "openai_model_name": "モデル名", - "openai_temperature": "温度", - "openai_max_tokens": "最大回答トークン数", - "openai_top_p": "トップP", - "openai_frequency_penalty": "頻度ペナルティ", - "openai_presence_penalty": "存在ペナルティ", + "model_name": "モデル名", + "temperature": "温度", + "max_tokens": "最大回答トークン数", + "top_p": "Top P", + "top_k": "Top K", + "frequency_penalty": "頻度ペナルティ", + "presence_penalty": "存在ペナルティ", "version": "バージョン", "github": "GitHub", "reward": "寄付", "contributors": "貢献者", "buy_me_a_coffee": "コーヒーを買ってください", + "anthropic_api_key": "Anthropic APIキー", + "anthropic_api_key_placeholder": "Anthropic API キーを入力してください", + "anthropic_api_base_path": "Anthropic API ベースパス", "openai_api_key": "OpenAI APIキー", "openai_api_key_placeholder": "OpenAI API キーを入力してください", "openai_api_base_path": "OpenAI API ベースパス", @@ -90,4 +94,4 @@ "file_editor_forgot_save_tips_title": "変更を{{fileName}}に保存しますか?", "file_editor_forgot_save_tips_content": "保存しない場合、変更は失われます。" } -} \ No newline at end of file +} diff --git a/packages/gpt-runner-web/client/public/locales/zh_CN.json b/packages/gpt-runner-web/client/public/locales/zh_CN.json index f5f862d..d4b5b3a 100644 --- a/packages/gpt-runner-web/client/public/locales/zh_CN.json +++ b/packages/gpt-runner-web/client/public/locales/zh_CN.json @@ -59,17 +59,21 @@ "context_settings_selected_files_checkbox_label": "将选定的文件作为提示,当前选定 {{fileNum}} 个文件,{{tokenNum}} tokens", "context_settings_all_file_paths_checkbox_label": "将所有文件路径作为提示,{{tokenNum}} tokens", "model_settings_btn": "模型设置", - "openai_model_name": "模型名称", - "openai_temperature": "温度", - "openai_max_tokens": "最大回复令牌", - "openai_top_p": "Top P", - "openai_frequency_penalty": "频率惩罚", - "openai_presence_penalty": "存在惩罚", + "model_name": "模型名称", + "temperature": "温度", + "max_tokens": "最大回复令牌", + "top_p": "Top P", + "top_k": "Top K", + "frequency_penalty": "频率惩罚", + "presence_penalty": "存在惩罚", "version": "版本", "github": "GitHub", "reward": "赞赏", "contributors": "贡献者", "buy_me_a_coffee": "请我喝杯咖啡", + "anthropic_api_key": "Anthropic API Key", + "anthropic_api_key_placeholder": "请输入 Anthropic API Key", + "anthropic_api_base_path": "Anthropic API 基础路径", "openai_api_key": "OpenAI API Key", "openai_api_key_placeholder": "请输入 OpenAI API Key", "openai_api_base_path": "OpenAI API 基础路径", @@ -90,4 +94,4 @@ "file_editor_forgot_save_tips_title": "你想要保存对{{fileName}}的更改吗?", "file_editor_forgot_save_tips_content": "如果你不保存,你的改动将会丢失." } -} \ No newline at end of file +} diff --git a/packages/gpt-runner-web/client/public/locales/zh_Hant.json b/packages/gpt-runner-web/client/public/locales/zh_Hant.json index f30d9db..d36b283 100644 --- a/packages/gpt-runner-web/client/public/locales/zh_Hant.json +++ b/packages/gpt-runner-web/client/public/locales/zh_Hant.json @@ -59,17 +59,21 @@ "context_settings_selected_files_checkbox_label": "將選定的文件作為提示,當前選定 {{fileNum}} 個文件, {{tokenNum}} tokens", "context_settings_all_file_paths_checkbox_label": "將所有文件路徑作為提示,{{tokenNum}} tokens", "model_settings_btn": "模型設置", - "openai_model_name": "模型名稱", - "openai_temperature": "溫度", - "openai_max_tokens": "最大回覆令牌", - "openai_top_p": "前P", - "openai_frequency_penalty": "頻率處罰", - "openai_presence_penalty": "存在處罰", + "model_name": "模型名稱", + "temperature": "溫度", + "max_tokens": "最大回覆令牌", + "top_p": "Top P", + "top_k": "Top K", + "frequency_penalty": "頻率處罰", + "presence_penalty": "存在處罰", "version": "版本", "github": "GitHub", "reward": "贊賞", "contributors": "貢獻者", "buy_me_a_coffee": "請我喝杯咖啡", + "anthropic_api_key": "Anthropic API Key", + "anthropic_api_key_placeholder": "請輸入 Anthropic API Key", + "anthropic_api_base_path": "Anthropic API 基礎路徑", "openai_api_key": "OpenAI API Key", "openai_api_key_placeholder": "請輸入 OpenAI API Key", "openai_api_base_path": "OpenAI API 基礎路徑", @@ -90,4 +94,4 @@ "file_editor_forgot_save_tips_title": "你想要保存對{{fileName}}的更改嗎?", "file_editor_forgot_save_tips_content": "如果你不保存,你的改動將會丟失." } -} \ No newline at end of file +} diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/chat-panel/index.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/chat-panel/index.tsx index 03bf609..1e44f85 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/chat-panel/index.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/chat-panel/index.tsx @@ -253,7 +253,7 @@ export const ChatPanel: FC = memo((props) => { messageItems: chatInstance?.messages.map((message, i) => { const isLast = i === chatInstance.messages.length - 1 const isLastTwo = i >= chatInstance.messages.length - 2 - const isAi = message.name === ChatRole.ASSISTANT + const isAi = message.name === ChatRole.Assistant const handleRegenerateMessage = () => { if (!isLast) diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx new file mode 100644 index 0000000..84c273c --- /dev/null +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/model-settings.tsx @@ -0,0 +1,137 @@ +import type { AnthropicModelConfig, SingleFileConfig } from '@nicepkg/gpt-runner-shared/common' +import { memo, useState } from 'react' +import type { FC } from 'react' +import { useTranslation } from 'react-i18next' +import { HookFormInput } from '../../../../../../../components/hook-form/hook-form-input' +import { type ISelectOption, SelectOption } from '../../../../../../../components/select-option' +import { BaseModelSettings, type BaseModelSettingsFormItemConfig } from '../base-model-settings' + +interface FormData extends Pick { + +} + +export interface AnthropicModelSettingsProps { + singleFileConfig?: SingleFileConfig +} + +export const AnthropicModelSettings: FC = memo((props) => { + const { singleFileConfig } = props + + const { t } = useTranslation() + + const [modelTipOptions] = useState([ + { + label: 'claude-1', + value: 'claude-1', + }, + { + label: 'claude-1-100k', + value: 'claude-1-100k', + }, + { + label: 'claude-instant-1', + value: 'claude-instant-1', + }, + { + label: 'claude-instant-1-100k', + value: 'claude-instant-1-100k', + }, + ]) + + const formConfig: BaseModelSettingsFormItemConfig[] = [ + { + name: 'modelName', + buildView: ({ buildLabel, useFormReturns: { control, formState, watch, setValue } }) => { + return <> + + { + setValue('modelName', value) + }} /> + + }, + }, + { + name: 'temperature', + buildView: ({ buildLabel, useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + { + name: 'maxTokens', + buildView: ({ buildLabel, useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + { + name: 'topP', + buildView: ({ buildLabel, useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + { + name: 'topK', + buildView: ({ buildLabel, useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + ] + + return +}) + +AnthropicModelSettings.displayName = 'AnthropicModelSettings' diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/secrets-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/secrets-settings.tsx new file mode 100644 index 0000000..c4893ac --- /dev/null +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/anthropic-settings/secrets-settings.tsx @@ -0,0 +1,55 @@ +import { DEFAULT_ANTHROPIC_API_BASE_PATH } from '@nicepkg/gpt-runner-shared/common' +import type { AnthropicSecrets, SingleFileConfig } from '@nicepkg/gpt-runner-shared/common' +import { type FC, memo } from 'react' +import { useTranslation } from 'react-i18next' +import { HookFormInput } from '../../../../../../../components/hook-form/hook-form-input' +import { BaseSecretsSettings, type BaseSecretsSettingsFormItemConfig } from '../base-secrets-settings' + +interface FormData extends Pick { +} + +export interface AnthropicSecretsSettingsProps { + singleFileConfig: SingleFileConfig +} + +export const AnthropicSecretsSettings: FC = memo((props) => { + const { singleFileConfig } = props + + const { t } = useTranslation() + + const formConfig: BaseSecretsSettingsFormItemConfig[] = [ + { + name: 'apiKey', + buildView: ({ useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + { + name: 'basePath', + buildView: ({ useFormReturns: { control, formState } }) => { + return <> + + + }, + }, + ] + + return +}) + +AnthropicSecretsSettings.displayName = 'AnthropicSecretsSettings' diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx index 690a258..b49da4d 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/index.tsx @@ -3,6 +3,8 @@ import { ChatModelType, resolveSingleFileConfig } from '@nicepkg/gpt-runner-shar import type { FC, ReactNode } from 'react' import { memo, useMemo } from 'react' import { useUserConfig } from '../../../../../../hooks/use-user-config.hook' +import { AnthropicSecretsSettings } from './anthropic-settings/secrets-settings' +import { AnthropicModelSettings } from './anthropic-settings/model-settings' import { OpenaiSecretsSettings } from './openai-settings/secrets-settings' import { OpenaiModelSettings } from './openai-settings/model-settings' @@ -41,16 +43,21 @@ export const ModelSettings: FC = memo((props) => { const finalModelType = resolvedSingleFileConfig?.model?.type || ChatModelType.Openai const modelTypeViewMap: Record ReactNode>> = { - [ChatModelType.Openai]: { - secrets: () => , - model: () => , - title: () => <>OpenAI, + [ChatModelType.Anthropic]: { + secrets: () => , + model: () => , + title: () => <>Anthropic, }, [ChatModelType.HuggingFace]: { secrets: () => <>, model: () => <>, title: () => <>Hugging Face, }, + [ChatModelType.Openai]: { + secrets: () => , + model: () => , + title: () => <>OpenAI, + }, } return <>{modelTypeViewMap[finalModelType][viewType]()} diff --git a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx index ec81967..586f368 100644 --- a/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx +++ b/packages/gpt-runner-web/client/src/pages/chat/components/settings/components/model-settings/openai-settings/model-settings.tsx @@ -41,7 +41,7 @@ export const OpenaiModelSettings: FC = memo((props) => return <> = memo((props) => return <> = memo((props) => return <> = memo((props) => return <> = memo((props) => return <> = memo((props) => return <>