@lobehub/chat 0.122.8 → 0.123.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/.env.example +22 -2
  2. package/.eslintrc.js +1 -0
  3. package/CHANGELOG.md +50 -0
  4. package/README.md +11 -9
  5. package/README.zh-CN.md +11 -9
  6. package/docs/Deployment/Environment-Variable.md +65 -23
  7. package/docs/Deployment/Environment-Variable.zh-CN.md +64 -22
  8. package/locales/ar/chat.json +12 -1
  9. package/locales/ar/common.json +16 -0
  10. package/locales/ar/error.json +35 -6
  11. package/locales/ar/setting.json +53 -6
  12. package/locales/de-DE/chat.json +12 -1
  13. package/locales/de-DE/common.json +16 -0
  14. package/locales/de-DE/error.json +35 -6
  15. package/locales/de-DE/setting.json +53 -6
  16. package/locales/en-US/chat.json +13 -2
  17. package/locales/en-US/common.json +16 -0
  18. package/locales/en-US/error.json +35 -6
  19. package/locales/en-US/setting.json +53 -6
  20. package/locales/es-ES/chat.json +12 -1
  21. package/locales/es-ES/common.json +16 -0
  22. package/locales/es-ES/error.json +35 -6
  23. package/locales/es-ES/setting.json +53 -6
  24. package/locales/fr-FR/chat.json +13 -2
  25. package/locales/fr-FR/common.json +16 -0
  26. package/locales/fr-FR/error.json +35 -6
  27. package/locales/fr-FR/setting.json +53 -6
  28. package/locales/it-IT/chat.json +12 -1
  29. package/locales/it-IT/common.json +16 -0
  30. package/locales/it-IT/error.json +35 -6
  31. package/locales/it-IT/setting.json +53 -6
  32. package/locales/ja-JP/chat.json +12 -1
  33. package/locales/ja-JP/common.json +16 -0
  34. package/locales/ja-JP/error.json +35 -6
  35. package/locales/ja-JP/setting.json +53 -6
  36. package/locales/ko-KR/chat.json +12 -1
  37. package/locales/ko-KR/common.json +16 -0
  38. package/locales/ko-KR/error.json +35 -6
  39. package/locales/ko-KR/setting.json +53 -6
  40. package/locales/nl-NL/chat.json +12 -1
  41. package/locales/nl-NL/common.json +16 -0
  42. package/locales/nl-NL/error.json +35 -6
  43. package/locales/nl-NL/setting.json +53 -6
  44. package/locales/pl-PL/chat.json +12 -1
  45. package/locales/pl-PL/common.json +16 -0
  46. package/locales/pl-PL/error.json +35 -6
  47. package/locales/pl-PL/setting.json +53 -6
  48. package/locales/pt-BR/chat.json +12 -1
  49. package/locales/pt-BR/common.json +16 -0
  50. package/locales/pt-BR/error.json +35 -6
  51. package/locales/pt-BR/setting.json +53 -6
  52. package/locales/ru-RU/chat.json +12 -1
  53. package/locales/ru-RU/common.json +16 -0
  54. package/locales/ru-RU/error.json +35 -6
  55. package/locales/ru-RU/setting.json +53 -6
  56. package/locales/tr-TR/chat.json +12 -1
  57. package/locales/tr-TR/common.json +16 -0
  58. package/locales/tr-TR/error.json +35 -6
  59. package/locales/tr-TR/setting.json +53 -6
  60. package/locales/vi-VN/chat.json +12 -1
  61. package/locales/vi-VN/common.json +16 -0
  62. package/locales/vi-VN/error.json +35 -6
  63. package/locales/vi-VN/setting.json +53 -6
  64. package/locales/zh-CN/chat.json +12 -1
  65. package/locales/zh-CN/common.json +16 -0
  66. package/locales/zh-CN/error.json +34 -5
  67. package/locales/zh-CN/setting.json +59 -12
  68. package/locales/zh-TW/chat.json +12 -1
  69. package/locales/zh-TW/common.json +16 -0
  70. package/locales/zh-TW/error.json +35 -6
  71. package/locales/zh-TW/setting.json +53 -6
  72. package/next.config.mjs +8 -2
  73. package/package.json +8 -1
  74. package/src/app/api/chat/[provider]/agentRuntime.ts +129 -0
  75. package/src/app/api/chat/[provider]/route.ts +64 -0
  76. package/src/app/api/chat/auth.ts +42 -0
  77. package/src/app/api/chat/google/route.ts +86 -0
  78. package/src/app/api/config/route.ts +6 -1
  79. package/src/app/api/config.ts +3 -3
  80. package/src/app/api/errorResponse.test.ts +8 -8
  81. package/src/app/api/errorResponse.ts +43 -6
  82. package/src/app/api/openai/createBizOpenAI/createAzureOpenai.ts +1 -1
  83. package/src/app/api/openai/createBizOpenAI/createOpenai.ts +1 -1
  84. package/src/app/api/openai/createBizOpenAI/index.ts +2 -2
  85. package/src/app/chat/(desktop)/features/ChatHeader.tsx +6 -4
  86. package/src/app/chat/(desktop)/features/ChatInput/Footer/index.tsx +13 -3
  87. package/src/app/chat/(desktop)/features/ChatInput/Header/index.tsx +16 -24
  88. package/src/app/chat/(desktop)/features/SideBar/index.tsx +1 -0
  89. package/src/app/chat/features/ChatHeader/ShareButton/Preview.tsx +3 -3
  90. package/src/app/chat/features/SessionListContent/List/Item/index.tsx +2 -3
  91. package/src/app/settings/llm/Azure/index.tsx +145 -0
  92. package/src/app/settings/llm/Bedrock/index.tsx +109 -0
  93. package/src/app/settings/llm/{LLM/Checker.tsx → Checker.tsx} +20 -22
  94. package/src/app/settings/llm/Google/index.tsx +74 -0
  95. package/src/app/settings/llm/{LLM → OpenAI}/index.tsx +27 -45
  96. package/src/app/settings/llm/Zhipu/index.tsx +78 -0
  97. package/src/app/settings/llm/const.ts +13 -0
  98. package/src/app/settings/llm/page.tsx +42 -2
  99. package/src/app/settings/llm/useSyncSettings.ts +23 -0
  100. package/src/chains/__tests__/langDetect.test.ts +2 -2
  101. package/src/chains/__tests__/pickEmoji.test.ts +2 -2
  102. package/src/chains/langDetect.ts +2 -2
  103. package/src/chains/pickEmoji.ts +2 -2
  104. package/src/chains/summaryAgentName.ts +2 -2
  105. package/src/chains/summaryDescription.ts +2 -2
  106. package/src/chains/summaryTags.ts +2 -2
  107. package/src/chains/summaryTitle.ts +2 -2
  108. package/src/chains/translate.ts +2 -2
  109. package/src/components/ModelIcon/index.tsx +37 -0
  110. package/src/components/ModelProviderIcon/index.tsx +44 -0
  111. package/src/components/ModelSelect/index.tsx +133 -0
  112. package/src/components/ModelTag/ModelIcon.tsx +35 -0
  113. package/src/components/ModelTag/index.tsx +13 -0
  114. package/src/config/modelProviders/bedrock.ts +43 -0
  115. package/src/config/modelProviders/google.ts +20 -0
  116. package/src/config/modelProviders/index.ts +18 -0
  117. package/src/config/modelProviders/openai.ts +102 -0
  118. package/src/config/modelProviders/zhipu.ts +34 -0
  119. package/src/config/{server.ts → server/app.ts} +1 -24
  120. package/src/config/server/index.ts +13 -0
  121. package/src/config/server/provider.ts +78 -0
  122. package/src/const/auth.ts +30 -0
  123. package/src/const/fetch.ts +3 -0
  124. package/src/const/settings.ts +24 -4
  125. package/src/database/core/migrations/migrateSettingsToUser/index.test.ts +2 -1
  126. package/src/database/core/migrations/migrateSettingsToUser/index.ts +1 -18
  127. package/src/database/core/migrations/migrateSettingsToUser/type.ts +100 -0
  128. package/src/database/models/message.ts +3 -1
  129. package/src/database/schemas/message.ts +1 -0
  130. package/src/database/schemas/session.ts +1 -0
  131. package/src/features/AgentSetting/AgentConfig/ModelSelect.tsx +71 -0
  132. package/src/features/AgentSetting/AgentConfig/index.tsx +171 -161
  133. package/src/features/AgentSetting/AgentConfig/useSyncConfig.ts +23 -0
  134. package/src/features/AgentSetting/AgentPrompt/TokenTag.tsx +39 -0
  135. package/src/features/AgentSetting/AgentPrompt/index.tsx +4 -26
  136. package/src/features/AgentSetting/store/index.ts +10 -2
  137. package/src/features/ChatInput/ActionBar/FileUpload.tsx +11 -4
  138. package/src/features/ChatInput/ActionBar/ModelSwitch.tsx +56 -14
  139. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +42 -7
  140. package/src/features/ChatInput/ActionBar/Token/index.tsx +5 -2
  141. package/src/features/ChatInput/ActionBar/Tools/index.tsx +11 -1
  142. package/src/features/ChatInput/useChatInput.ts +5 -1
  143. package/src/features/Conversation/Error/APIKeyForm/Bedrock.tsx +80 -0
  144. package/src/features/Conversation/Error/APIKeyForm/Google.tsx +61 -0
  145. package/src/features/Conversation/Error/APIKeyForm/OpenAI.tsx +63 -0
  146. package/src/features/Conversation/Error/APIKeyForm/Zhipu.tsx +62 -0
  147. package/src/features/Conversation/Error/APIKeyForm/index.tsx +72 -0
  148. package/src/features/Conversation/Error/AccessCodeForm.tsx +63 -0
  149. package/src/features/Conversation/Error/ErrorJsonViewer.tsx +26 -0
  150. package/src/features/Conversation/Error/InvalidAPIKey.tsx +16 -0
  151. package/src/features/Conversation/Error/InvalidAccessCode.tsx +50 -0
  152. package/src/features/Conversation/Error/OpenAiBizError.tsx +9 -17
  153. package/src/features/Conversation/Error/{Plugin/PluginSettings.tsx → PluginSettings.tsx} +8 -3
  154. package/src/features/Conversation/Error/index.tsx +75 -70
  155. package/src/features/Conversation/Error/style.tsx +9 -3
  156. package/src/features/Conversation/Extras/Assistant.tsx +2 -3
  157. package/src/features/Conversation/Plugins/Inspector/index.tsx +8 -2
  158. package/src/features/Conversation/components/ChatItem/index.tsx +9 -24
  159. package/src/features/Conversation/types/index.tsx +2 -5
  160. package/src/hooks/_header.ts +35 -0
  161. package/src/libs/agent-runtime/BaseAI.ts +9 -0
  162. package/src/libs/agent-runtime/azureOpenai/index.ts +72 -0
  163. package/src/libs/agent-runtime/bedrock/index.ts +134 -0
  164. package/src/libs/agent-runtime/error.ts +26 -0
  165. package/src/libs/agent-runtime/google/index.ts +160 -0
  166. package/src/libs/agent-runtime/index.ts +9 -0
  167. package/src/libs/agent-runtime/openai/index.test.ts +176 -0
  168. package/src/libs/agent-runtime/openai/index.ts +107 -0
  169. package/src/libs/agent-runtime/types/chat.ts +119 -0
  170. package/src/libs/agent-runtime/types/index.ts +2 -0
  171. package/src/libs/agent-runtime/types/type.ts +34 -0
  172. package/src/libs/agent-runtime/utils/createError.ts +10 -0
  173. package/src/libs/agent-runtime/utils/debugStream.ts +18 -0
  174. package/src/libs/agent-runtime/utils/env.ts +1 -0
  175. package/src/libs/agent-runtime/utils/handleOpenAIError.ts +39 -0
  176. package/src/libs/agent-runtime/utils/uriParser.ts +16 -0
  177. package/src/libs/agent-runtime/zhipu/authToken.ts +22 -0
  178. package/src/libs/agent-runtime/zhipu/index.ts +125 -0
  179. package/src/locales/default/chat.ts +12 -2
  180. package/src/locales/default/common.ts +16 -0
  181. package/src/locales/default/error.ts +42 -5
  182. package/src/locales/default/setting.ts +61 -12
  183. package/src/services/__tests__/chat.test.ts +8 -2
  184. package/src/services/__tests__/message.test.ts +1 -1
  185. package/src/services/_auth.ts +106 -0
  186. package/src/services/_header.ts +1 -0
  187. package/src/services/_url.ts +0 -2
  188. package/src/services/chat.ts +32 -14
  189. package/src/store/chat/slices/message/action.ts +9 -6
  190. package/src/store/global/slices/common/action.ts +8 -2
  191. package/src/store/global/slices/settings/action.test.ts +2 -2
  192. package/src/store/global/slices/settings/action.ts +11 -4
  193. package/src/store/global/slices/settings/selectors/__snapshots__/modelProvider.test.ts.snap +242 -78
  194. package/src/store/global/slices/settings/selectors/__snapshots__/selectors.test.ts.snap +2 -0
  195. package/src/store/global/slices/settings/selectors/modelProvider.test.ts +171 -47
  196. package/src/store/global/slices/settings/selectors/modelProvider.ts +136 -43
  197. package/src/store/session/slices/agent/selectors.test.ts +0 -48
  198. package/src/store/session/slices/agent/selectors.ts +7 -12
  199. package/src/types/agent/index.ts +6 -2
  200. package/src/types/fetch.ts +4 -2
  201. package/src/types/files.ts +3 -3
  202. package/src/types/llm.ts +27 -0
  203. package/src/types/message/index.ts +7 -3
  204. package/src/types/openai/chat.ts +6 -11
  205. package/src/types/settings/index.ts +1 -0
  206. package/src/types/settings/modelProvider.ts +37 -1
  207. package/src/utils/__snapshots__/parseModels.test.ts.snap +63 -0
  208. package/src/utils/parseModels.test.ts +24 -0
  209. package/src/utils/parseModels.ts +37 -0
  210. package/src/app/api/openai/chat/createChatCompletion.test.ts +0 -166
  211. package/src/app/api/openai/chat/createChatCompletion.ts +0 -76
  212. package/src/app/api/openai/chat/route.ts +0 -19
  213. package/src/app/api/openai/models/route.ts +0 -17
  214. package/src/app/settings/llm/LLM/ModelList.tsx +0 -51
  215. package/src/app/settings/llm/LLM/getModelList.ts +0 -9
  216. package/src/app/settings/llm/index.tsx +0 -36
  217. package/src/const/llm.ts +0 -32
  218. package/src/features/Conversation/Error/ApiKeyForm.tsx +0 -87
  219. package/src/features/Conversation/Error/ErrorActionContainer.tsx +0 -23
  220. package/src/features/Conversation/Error/InvalidAccess.tsx +0 -90
  221. package/src/features/Conversation/Error/OpenAPIKey.tsx +0 -13
  222. package/src/features/Conversation/Error/Plugin/PluginError.tsx +0 -30
  223. package/src/services/modelList.ts +0 -15
  224. /package/src/app/chat/(desktop)/features/ChatInput/{Header → Footer}/DragUpload.tsx +0 -0
  225. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.test.ts +0 -0
  226. /package/src/{app/api/openai/chat → libs/agent-runtime/utils}/desensitizeUrl.ts +0 -0
  227. /package/src/types/{translate.ts → message/translate.ts} +0 -0
@@ -2,24 +2,27 @@ import { PluginRequestPayload, createHeadersWithPluginSettings } from '@lobehub/
2
2
  import { produce } from 'immer';
3
3
  import { merge } from 'lodash-es';
4
4
 
5
- import { isVisionModel } from '@/const/llm';
6
5
  import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
6
+ import { ModelProvider } from '@/libs/agent-runtime';
7
7
  import { filesSelectors, useFileStore } from '@/store/file';
8
+ import { useGlobalStore } from '@/store/global';
9
+ import { modelProviderSelectors } from '@/store/global/selectors';
8
10
  import { useToolStore } from '@/store/tool';
9
11
  import { pluginSelectors, toolSelectors } from '@/store/tool/selectors';
10
12
  import { ChatMessage } from '@/types/message';
11
- import type { OpenAIChatMessage, OpenAIChatStreamPayload } from '@/types/openai/chat';
13
+ import type { ChatStreamPayload, OpenAIChatMessage } from '@/types/openai/chat';
12
14
  import { UserMessageContentPart } from '@/types/openai/chat';
13
15
  import { fetchAIFactory, getMessageError } from '@/utils/fetch';
14
16
 
17
+ import { createHeaderWithAuth } from './_auth';
15
18
  import { createHeaderWithOpenAI } from './_header';
16
- import { OPENAI_URLS, PLUGINS_URLS } from './_url';
19
+ import { PLUGINS_URLS } from './_url';
17
20
 
18
21
  interface FetchOptions {
19
22
  signal?: AbortSignal | undefined;
20
23
  }
21
24
 
22
- interface GetChatCompletionPayload extends Partial<Omit<OpenAIChatStreamPayload, 'messages'>> {
25
+ interface GetChatCompletionPayload extends Partial<Omit<ChatStreamPayload, 'messages'>> {
23
26
  messages: ChatMessage[];
24
27
  }
25
28
 
@@ -48,29 +51,39 @@ class ChatService {
48
51
 
49
52
  const filterTools = toolSelectors.enabledSchema(enabledPlugins)(useToolStore.getState());
50
53
 
54
+ // check this model can use function call
55
+ const canUseFC = modelProviderSelectors.modelEnabledFunctionCall(payload.model)(
56
+ useGlobalStore.getState(),
57
+ );
51
58
  // the rule that model can use tools:
52
59
  // 1. tools is not empty
53
- // 2. model is not in vision white list, because vision model can't use tools
54
- // TODO: we need to find some method to let vision model use tools
55
- const shouldUseTools = filterTools.length > 0 && !isVisionModel(payload.model);
60
+ // 2. model can use function call
61
+ const shouldUseTools = filterTools.length > 0 && canUseFC;
62
+
56
63
  const tools = shouldUseTools ? filterTools : undefined;
57
64
 
58
65
  return this.getChatCompletion({ ...params, messages: oaiMessages, tools }, options);
59
66
  };
60
67
 
61
- getChatCompletion = (params: Partial<OpenAIChatStreamPayload>, options?: FetchOptions) => {
68
+ getChatCompletion = async (params: Partial<ChatStreamPayload>, options?: FetchOptions) => {
69
+ const { provider = ModelProvider.OpenAI, ...res } = params;
62
70
  const payload = merge(
63
71
  {
64
72
  model: DEFAULT_AGENT_CONFIG.model,
65
73
  stream: true,
66
74
  ...DEFAULT_AGENT_CONFIG.params,
67
75
  },
68
- params,
76
+ res,
69
77
  );
70
78
 
71
- return fetch(OPENAI_URLS.chat, {
79
+ const headers = await createHeaderWithAuth({
80
+ headers: { 'Content-Type': 'application/json' },
81
+ provider,
82
+ });
83
+
84
+ return fetch(`/api/chat/${provider}`, {
72
85
  body: JSON.stringify(payload),
73
- headers: createHeaderWithOpenAI({ 'Content-Type': 'application/json' }),
86
+ headers,
74
87
  method: 'POST',
75
88
  signal: options?.signal,
76
89
  });
@@ -112,7 +125,7 @@ class ChatService {
112
125
  model,
113
126
  }: {
114
127
  messages: ChatMessage[];
115
- model?: string;
128
+ model: string;
116
129
  tools?: string[];
117
130
  }): OpenAIChatMessage[] => {
118
131
  // handle content type for vision model
@@ -125,7 +138,9 @@ class ChatService {
125
138
 
126
139
  if (imageList.length === 0) return m.content;
127
140
 
128
- if (!isVisionModel(model)) {
141
+ const hasVision = modelProviderSelectors.modelEnabledVision(model)(useGlobalStore.getState());
142
+
143
+ if (!hasVision) {
129
144
  return m.content;
130
145
  }
131
146
 
@@ -156,11 +171,14 @@ class ChatService {
156
171
 
157
172
  return produce(postMessages, (draft) => {
158
173
  if (!tools || tools.length === 0) return;
174
+ const hasFC = modelProviderSelectors.modelEnabledFunctionCall(model)(
175
+ useGlobalStore.getState(),
176
+ );
177
+ if (!hasFC) return;
159
178
 
160
179
  const systemMessage = draft.find((i) => i.role === 'system');
161
180
 
162
181
  const toolsSystemRoles = toolSelectors.enabledSystemRoles(tools)(useToolStore.getState());
163
-
164
182
  if (!toolsSystemRoles) return;
165
183
 
166
184
  if (systemMessage) {
@@ -5,7 +5,6 @@ import { template } from 'lodash-es';
5
5
  import useSWR, { SWRResponse, mutate } from 'swr';
6
6
  import { StateCreator } from 'zustand/vanilla';
7
7
 
8
- import { GPT4_VISION_MODEL_DEFAULT_MAX_TOKENS } from '@/const/llm';
9
8
  import { LOADING_FLAT, isFunctionMessageAtStart, testFunctionMessageAtEnd } from '@/const/message';
10
9
  import { CreateMessageParams } from '@/database/models/message';
11
10
  import { chatService } from '@/services/chat';
@@ -255,13 +254,14 @@ export const chatMessage: StateCreator<
255
254
  coreProcessMessage: async (messages, userMessageId) => {
256
255
  const { fetchAIChatMessage, triggerFunctionCall, refreshMessages, activeTopicId } = get();
257
256
 
258
- const { model } = getAgentConfig();
257
+ const { model, provider } = getAgentConfig();
259
258
 
260
259
  // 1. Add an empty message to place the AI response
261
260
  const assistantMessage: CreateMessageParams = {
262
261
  role: 'assistant',
263
262
  content: LOADING_FLAT,
264
263
  fromModel: model,
264
+ fromProvider: provider,
265
265
 
266
266
  parentId: userMessageId,
267
267
  sessionId: get().activeId,
@@ -288,13 +288,14 @@ export const chatMessage: StateCreator<
288
288
  const functionMessage: CreateMessageParams = {
289
289
  role: 'function',
290
290
  content: functionCallContent,
291
- extra: {
292
- fromModel: model,
293
- },
291
+ fromModel: model,
292
+ fromProvider: provider,
293
+
294
294
  parentId: userMessageId,
295
295
  sessionId: get().activeId,
296
296
  topicId: activeTopicId,
297
297
  };
298
+
298
299
  functionId = await messageService.create(functionMessage);
299
300
  }
300
301
 
@@ -368,7 +369,8 @@ export const chatMessage: StateCreator<
368
369
  if (config.model === 'gpt-4-vision-preview') {
369
370
  /* eslint-disable unicorn/no-lonely-if */
370
371
  if (!config.params.max_tokens)
371
- config.params.max_tokens = GPT4_VISION_MODEL_DEFAULT_MAX_TOKENS;
372
+ // refs: https://github.com/lobehub/lobe-chat/issues/837
373
+ config.params.max_tokens = 2048;
372
374
  }
373
375
 
374
376
  const fetcher = () =>
@@ -376,6 +378,7 @@ export const chatMessage: StateCreator<
376
378
  {
377
379
  messages: preprocessMsgs,
378
380
  model: config.model,
381
+ provider: config.provider,
379
382
  ...config.params,
380
383
  plugins: config.plugins,
381
384
  },
@@ -1,5 +1,6 @@
1
1
  import { gt } from 'semver';
2
2
  import useSWR, { SWRResponse, mutate } from 'swr';
3
+ import { DeepPartial } from 'utility-types';
3
4
  import type { StateCreator } from 'zustand/vanilla';
4
5
 
5
6
  import { INBOX_SESSION_ID } from '@/const/session';
@@ -8,7 +9,7 @@ import { CURRENT_VERSION } from '@/const/version';
8
9
  import { globalService } from '@/services/global';
9
10
  import { UserConfig, userService } from '@/services/user';
10
11
  import type { GlobalStore } from '@/store/global';
11
- import type { GlobalServerConfig } from '@/types/settings';
12
+ import type { GlobalServerConfig, GlobalSettings } from '@/types/settings';
12
13
  import { merge } from '@/utils/merge';
13
14
  import { setNamespace } from '@/utils/storeDebug';
14
15
 
@@ -63,7 +64,12 @@ export const createCommonSlice: StateCreator<
63
64
  useSWR<GlobalServerConfig>('fetchGlobalConfig', globalService.getGlobalConfig, {
64
65
  onSuccess: (data) => {
65
66
  if (data) {
66
- const defaultSettings = merge(get().defaultSettings, { defaultAgent: data.defaultAgent });
67
+ const serverSettings: DeepPartial<GlobalSettings> = {
68
+ defaultAgent: data.defaultAgent,
69
+ languageModel: data.languageModel,
70
+ };
71
+
72
+ const defaultSettings = merge(get().defaultSettings, serverSettings);
67
73
  set({ defaultSettings, serverConfig: data }, false, n('initGlobalConfig'));
68
74
  }
69
75
  },
@@ -67,14 +67,14 @@ describe('SettingsAction', () => {
67
67
  });
68
68
  });
69
69
 
70
- describe('setOpenAIConfig', () => {
70
+ describe('setModelProviderConfig', () => {
71
71
  it('should set OpenAI configuration', async () => {
72
72
  const { result } = renderHook(() => useGlobalStore());
73
73
  const openAIConfig: Partial<OpenAIConfig> = { OPENAI_API_KEY: 'test-key' };
74
74
 
75
75
  // Perform the action
76
76
  await act(async () => {
77
- await result.current.setOpenAIConfig(openAIConfig);
77
+ await result.current.setModelProviderConfig('openAI', openAIConfig);
78
78
  });
79
79
 
80
80
  // Assert that updateUserSettings was called with the correct OpenAI configuration
@@ -7,7 +7,7 @@ import { userService } from '@/services/user';
7
7
  import type { GlobalStore } from '@/store/global';
8
8
  import { SettingsTabs } from '@/store/global/initialState';
9
9
  import { LobeAgentSettings } from '@/types/session';
10
- import type { GlobalSettings, OpenAIConfig } from '@/types/settings';
10
+ import { GlobalLLMConfig, GlobalLLMProviderKey, GlobalSettings } from '@/types/settings';
11
11
  import { difference } from '@/utils/difference';
12
12
  import { merge } from '@/utils/merge';
13
13
 
@@ -17,10 +17,14 @@ import { merge } from '@/utils/merge';
17
17
  export interface SettingsAction {
18
18
  importAppSettings: (settings: GlobalSettings) => Promise<void>;
19
19
  resetSettings: () => Promise<void>;
20
- setOpenAIConfig: (config: Partial<OpenAIConfig>) => Promise<void>;
20
+ setModelProviderConfig: <T extends GlobalLLMProviderKey>(
21
+ provider: T,
22
+ config: Partial<GlobalLLMConfig[T]>,
23
+ ) => Promise<void>;
21
24
  setSettings: (settings: DeepPartial<GlobalSettings>) => Promise<void>;
22
25
  switchSettingTabs: (tab: SettingsTabs) => void;
23
26
  switchThemeMode: (themeMode: ThemeMode) => Promise<void>;
27
+ toggleProviderEnabled: (provider: GlobalLLMProviderKey, enabled: boolean) => Promise<void>;
24
28
  updateDefaultAgent: (agent: DeepPartial<LobeAgentSettings>) => Promise<void>;
25
29
  }
26
30
 
@@ -41,8 +45,8 @@ export const createSettingsSlice: StateCreator<
41
45
  await userService.resetUserSettings();
42
46
  await get().refreshUserConfig();
43
47
  },
44
- setOpenAIConfig: async (config) => {
45
- await get().setSettings({ languageModel: { openAI: config } });
48
+ setModelProviderConfig: async (provider, config) => {
49
+ await get().setSettings({ languageModel: { [provider]: config } });
46
50
  },
47
51
  setSettings: async (settings) => {
48
52
  const { settings: prevSetting, defaultSettings } = get();
@@ -63,6 +67,9 @@ export const createSettingsSlice: StateCreator<
63
67
  switchThemeMode: async (themeMode) => {
64
68
  await get().setSettings({ themeMode });
65
69
  },
70
+ toggleProviderEnabled: async (provider, enabled) => {
71
+ await get().setSettings({ languageModel: { [provider]: { enabled } } });
72
+ },
66
73
  updateDefaultAgent: async (defaultAgent) => {
67
74
  await get().setSettings({ defaultAgent });
68
75
  },
@@ -3,16 +3,30 @@
3
3
  exports[`modelProviderSelectors > CUSTOM_MODELS > custom deletion, addition, and renaming of models 1`] = `
4
4
  [
5
5
  {
6
- "displayName": "llama",
7
- "name": "llama",
8
- },
9
- {
10
- "displayName": "claude-2",
11
- "name": "claude-2",
12
- },
13
- {
14
- "displayName": "gpt-4-32k",
15
- "name": "gpt-4-0125-preview",
6
+ "chatModels": [
7
+ {
8
+ "displayName": "llama",
9
+ "functionCall": true,
10
+ "id": "llama",
11
+ "isCustom": true,
12
+ "vision": true,
13
+ },
14
+ {
15
+ "displayName": "claude-2",
16
+ "functionCall": true,
17
+ "id": "claude-2",
18
+ "isCustom": true,
19
+ "vision": true,
20
+ },
21
+ {
22
+ "displayName": "gpt-4-32k",
23
+ "functionCall": true,
24
+ "id": "gpt-4-0125-preview",
25
+ "tokens": 128000,
26
+ },
27
+ ],
28
+ "enabled": true,
29
+ "id": "openai",
16
30
  },
17
31
  ]
18
32
  `;
@@ -20,32 +34,101 @@ exports[`modelProviderSelectors > CUSTOM_MODELS > custom deletion, addition, and
20
34
  exports[`modelProviderSelectors > CUSTOM_MODELS > duplicate naming model 1`] = `
21
35
  [
22
36
  {
23
- "displayName": "gpt-3.5-turbo",
24
- "name": "gpt-3.5-turbo",
25
- },
26
- {
27
- "displayName": "gpt-3.5-turbo-1106",
28
- "name": "gpt-3.5-turbo-1106",
29
- },
30
- {
31
- "displayName": "gpt-3.5-turbo-16k",
32
- "name": "gpt-3.5-turbo-16k",
33
- },
34
- {
35
- "displayName": "gpt-4",
36
- "name": "gpt-4",
37
- },
38
- {
39
- "displayName": "gpt-4-32k",
40
- "name": "gpt-4-32k",
41
- },
42
- {
43
- "displayName": "gpt-4-vision-preview",
44
- "name": "gpt-4-vision-preview",
45
- },
46
- {
47
- "displayName": "gpt-4-32k",
48
- "name": "gpt-4-0125-preview",
37
+ "chatModels": [
38
+ {
39
+ "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务",
40
+ "displayName": "GPT-3.5 Turbo",
41
+ "functionCall": true,
42
+ "id": "gpt-3.5-turbo",
43
+ "tokens": 4096,
44
+ },
45
+ {
46
+ "displayName": "GPT-3.5 Turbo (0125)",
47
+ "functionCall": true,
48
+ "id": "gpt-3.5-turbo-0125",
49
+ "tokens": 16385,
50
+ },
51
+ {
52
+ "displayName": "GPT-3.5 Turbo (1106)",
53
+ "functionCall": true,
54
+ "hidden": true,
55
+ "id": "gpt-3.5-turbo-1106",
56
+ "tokens": 16385,
57
+ },
58
+ {
59
+ "hidden": true,
60
+ "id": "gpt-3.5-turbo-instruct",
61
+ "tokens": 4096,
62
+ },
63
+ {
64
+ "hidden": true,
65
+ "id": "gpt-3.5-turbo-16k",
66
+ "tokens": 16385,
67
+ },
68
+ {
69
+ "hidden": true,
70
+ "id": "gpt-3.5-turbo-0613",
71
+ "legacy": true,
72
+ "tokens": 4096,
73
+ },
74
+ {
75
+ "hidden": true,
76
+ "id": "gpt-3.5-turbo-16k-0613",
77
+ "legacy": true,
78
+ "tokens": 4096,
79
+ },
80
+ {
81
+ "displayName": "GPT-4 Turbo Preview",
82
+ "functionCall": true,
83
+ "id": "gpt-4-turbo-preview",
84
+ "tokens": 128000,
85
+ },
86
+ {
87
+ "displayName": "gpt-4-32k",
88
+ "functionCall": true,
89
+ "id": "gpt-4-0125-preview",
90
+ "tokens": 128000,
91
+ },
92
+ {
93
+ "description": "GPT-4 视觉预览版,支持视觉任务",
94
+ "displayName": "GPT-4 Turbo Vision (Preview)",
95
+ "id": "gpt-4-vision-preview",
96
+ "tokens": 128000,
97
+ "vision": true,
98
+ },
99
+ {
100
+ "functionCall": true,
101
+ "hidden": true,
102
+ "id": "gpt-4-1106-preview",
103
+ "tokens": 128000,
104
+ },
105
+ {
106
+ "functionCall": true,
107
+ "hidden": true,
108
+ "id": "gpt-4",
109
+ "tokens": 8192,
110
+ },
111
+ {
112
+ "functionCall": true,
113
+ "hidden": true,
114
+ "id": "gpt-4-0613",
115
+ "tokens": 8192,
116
+ },
117
+ {
118
+ "functionCall": true,
119
+ "hidden": true,
120
+ "id": "gpt-4-32k",
121
+ "tokens": 32768,
122
+ },
123
+ {
124
+ "functionCall": true,
125
+ "hidden": true,
126
+ "id": "gpt-4-32k-0613",
127
+ "tokens": 32768,
128
+ },
129
+ ],
130
+ "enabled": true,
131
+ "id": "openai",
49
132
  },
50
133
  ]
51
134
  `;
@@ -53,48 +136,129 @@ exports[`modelProviderSelectors > CUSTOM_MODELS > duplicate naming model 1`] = `
53
136
  exports[`modelProviderSelectors > CUSTOM_MODELS > only add the model 1`] = `
54
137
  [
55
138
  {
56
- "displayName": "gpt-3.5-turbo",
57
- "name": "gpt-3.5-turbo",
58
- },
59
- {
60
- "displayName": "gpt-3.5-turbo-1106",
61
- "name": "gpt-3.5-turbo-1106",
62
- },
63
- {
64
- "displayName": "gpt-3.5-turbo-16k",
65
- "name": "gpt-3.5-turbo-16k",
66
- },
67
- {
68
- "displayName": "gpt-4",
69
- "name": "gpt-4",
70
- },
71
- {
72
- "displayName": "gpt-4-32k",
73
- "name": "gpt-4-32k",
74
- },
75
- {
76
- "displayName": "gpt-4-0125-preview",
77
- "name": "gpt-4-0125-preview",
78
- },
79
- {
80
- "displayName": "gpt-4-vision-preview",
81
- "name": "gpt-4-vision-preview",
82
- },
83
- {
84
- "displayName": "model1",
85
- "name": "model1",
86
- },
87
- {
88
- "displayName": "model2",
89
- "name": "model2",
90
- },
91
- {
92
- "displayName": "model3",
93
- "name": "model3",
94
- },
95
- {
96
- "displayName": "model4",
97
- "name": "model4",
139
+ "chatModels": [
140
+ {
141
+ "description": "GPT 3.5 Turbo,适用于各种文本生成和理解任务",
142
+ "displayName": "GPT-3.5 Turbo",
143
+ "functionCall": true,
144
+ "id": "gpt-3.5-turbo",
145
+ "tokens": 4096,
146
+ },
147
+ {
148
+ "displayName": "GPT-3.5 Turbo (0125)",
149
+ "functionCall": true,
150
+ "id": "gpt-3.5-turbo-0125",
151
+ "tokens": 16385,
152
+ },
153
+ {
154
+ "displayName": "GPT-3.5 Turbo (1106)",
155
+ "functionCall": true,
156
+ "hidden": true,
157
+ "id": "gpt-3.5-turbo-1106",
158
+ "tokens": 16385,
159
+ },
160
+ {
161
+ "hidden": true,
162
+ "id": "gpt-3.5-turbo-instruct",
163
+ "tokens": 4096,
164
+ },
165
+ {
166
+ "hidden": true,
167
+ "id": "gpt-3.5-turbo-16k",
168
+ "tokens": 16385,
169
+ },
170
+ {
171
+ "hidden": true,
172
+ "id": "gpt-3.5-turbo-0613",
173
+ "legacy": true,
174
+ "tokens": 4096,
175
+ },
176
+ {
177
+ "hidden": true,
178
+ "id": "gpt-3.5-turbo-16k-0613",
179
+ "legacy": true,
180
+ "tokens": 4096,
181
+ },
182
+ {
183
+ "displayName": "GPT-4 Turbo Preview",
184
+ "functionCall": true,
185
+ "id": "gpt-4-turbo-preview",
186
+ "tokens": 128000,
187
+ },
188
+ {
189
+ "displayName": "GPT-4 Turbo Preview (0125)",
190
+ "functionCall": true,
191
+ "id": "gpt-4-0125-preview",
192
+ "tokens": 128000,
193
+ },
194
+ {
195
+ "description": "GPT-4 视觉预览版,支持视觉任务",
196
+ "displayName": "GPT-4 Turbo Vision (Preview)",
197
+ "id": "gpt-4-vision-preview",
198
+ "tokens": 128000,
199
+ "vision": true,
200
+ },
201
+ {
202
+ "functionCall": true,
203
+ "hidden": true,
204
+ "id": "gpt-4-1106-preview",
205
+ "tokens": 128000,
206
+ },
207
+ {
208
+ "functionCall": true,
209
+ "hidden": true,
210
+ "id": "gpt-4",
211
+ "tokens": 8192,
212
+ },
213
+ {
214
+ "functionCall": true,
215
+ "hidden": true,
216
+ "id": "gpt-4-0613",
217
+ "tokens": 8192,
218
+ },
219
+ {
220
+ "functionCall": true,
221
+ "hidden": true,
222
+ "id": "gpt-4-32k",
223
+ "tokens": 32768,
224
+ },
225
+ {
226
+ "functionCall": true,
227
+ "hidden": true,
228
+ "id": "gpt-4-32k-0613",
229
+ "tokens": 32768,
230
+ },
231
+ {
232
+ "displayName": "model1",
233
+ "functionCall": true,
234
+ "id": "model1",
235
+ "isCustom": true,
236
+ "vision": true,
237
+ },
238
+ {
239
+ "displayName": "model2",
240
+ "functionCall": true,
241
+ "id": "model2",
242
+ "isCustom": true,
243
+ "vision": true,
244
+ },
245
+ {
246
+ "displayName": "model3",
247
+ "functionCall": true,
248
+ "id": "model3",
249
+ "isCustom": true,
250
+ "vision": true,
251
+ },
252
+ {
253
+ "displayName": "model4",
254
+ "functionCall": true,
255
+ "id": "model4",
256
+ "isCustom": true,
257
+ "vision": true,
258
+ },
259
+ ],
260
+ "enabled": true,
261
+ "id": "openai",
98
262
  },
99
263
  ]
100
264
  `;
@@ -81,6 +81,7 @@ exports[`settingsSelectors > defaultAgent > should merge DEFAULT_AGENT and s.set
81
81
  "top_p": 1,
82
82
  },
83
83
  "plugins": [],
84
+ "provider": "openai",
84
85
  "systemRole": "user",
85
86
  "tts": {
86
87
  "showAllLocaleVoice": false,
@@ -112,6 +113,7 @@ exports[`settingsSelectors > defaultAgentConfig > should merge DEFAULT_AGENT_CON
112
113
  "top_p": 1,
113
114
  },
114
115
  "plugins": [],
116
+ "provider": "openai",
115
117
  "systemRole": "user",
116
118
  "tts": {
117
119
  "showAllLocaleVoice": false,