@lobehub/chat 1.48.3 → 1.49.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 (60) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/changelog/v1.json +18 -0
  3. package/docker-compose/local/setup.sh +16 -6
  4. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +197 -194
  5. package/locales/ar/chat.json +0 -4
  6. package/locales/ar/components.json +5 -0
  7. package/locales/bg-BG/chat.json +0 -4
  8. package/locales/bg-BG/components.json +5 -0
  9. package/locales/de-DE/chat.json +0 -4
  10. package/locales/de-DE/components.json +5 -0
  11. package/locales/en-US/chat.json +0 -4
  12. package/locales/en-US/components.json +5 -0
  13. package/locales/es-ES/chat.json +0 -4
  14. package/locales/es-ES/components.json +5 -0
  15. package/locales/fa-IR/chat.json +0 -4
  16. package/locales/fa-IR/components.json +5 -0
  17. package/locales/fr-FR/chat.json +0 -4
  18. package/locales/fr-FR/components.json +5 -0
  19. package/locales/it-IT/chat.json +0 -4
  20. package/locales/it-IT/components.json +5 -0
  21. package/locales/ja-JP/chat.json +0 -4
  22. package/locales/ja-JP/components.json +5 -0
  23. package/locales/ko-KR/chat.json +0 -4
  24. package/locales/ko-KR/components.json +5 -0
  25. package/locales/nl-NL/chat.json +0 -4
  26. package/locales/nl-NL/components.json +5 -0
  27. package/locales/pl-PL/chat.json +0 -4
  28. package/locales/pl-PL/components.json +5 -0
  29. package/locales/pt-BR/chat.json +0 -4
  30. package/locales/pt-BR/components.json +5 -0
  31. package/locales/ru-RU/chat.json +0 -4
  32. package/locales/ru-RU/components.json +5 -0
  33. package/locales/tr-TR/chat.json +0 -4
  34. package/locales/tr-TR/components.json +5 -0
  35. package/locales/vi-VN/chat.json +0 -4
  36. package/locales/vi-VN/components.json +5 -0
  37. package/locales/zh-CN/chat.json +0 -4
  38. package/locales/zh-CN/components.json +5 -0
  39. package/locales/zh-TW/chat.json +0 -4
  40. package/locales/zh-TW/components.json +5 -0
  41. package/package.json +1 -1
  42. package/src/app/(main)/settings/provider/(detail)/doubao/page.tsx +40 -0
  43. package/src/app/(main)/settings/provider/features/ModelList/ModelConfigModal/index.tsx +1 -1
  44. package/src/components/Thinking/index.tsx +137 -0
  45. package/src/config/aiModels/doubao.ts +65 -0
  46. package/src/config/aiModels/index.ts +3 -0
  47. package/src/config/llm.ts +6 -0
  48. package/src/config/modelProviders/doubao.ts +23 -0
  49. package/src/config/modelProviders/index.ts +3 -0
  50. package/src/features/Conversation/Messages/Assistant/Reasoning/index.tsx +6 -110
  51. package/src/libs/agent-runtime/AgentRuntime.ts +7 -0
  52. package/src/libs/agent-runtime/doubao/index.ts +10 -0
  53. package/src/libs/agent-runtime/index.ts +1 -0
  54. package/src/libs/agent-runtime/types/type.ts +1 -0
  55. package/src/locales/default/chat.ts +0 -4
  56. package/src/locales/default/components.ts +5 -0
  57. package/src/server/globalConfig/index.ts +3 -0
  58. package/src/services/chat.ts +1 -1
  59. package/src/types/aiProvider.ts +1 -0
  60. package/src/types/user/settings/keyVaults.ts +1 -0
@@ -0,0 +1,65 @@
1
+ import { AIChatModelCard } from '@/types/aiModel';
2
+
3
+ const doubaoChatModels: AIChatModelCard[] = [
4
+ {
5
+ contextWindowTokens: 4096,
6
+ description:
7
+ '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 4k 上下文窗口的推理和精调。',
8
+ displayName: 'Doubao Lite 4k',
9
+ enabled: true,
10
+ id: 'Doubao-lite-4k',
11
+ type: 'chat',
12
+ },
13
+ {
14
+ contextWindowTokens: 32_768,
15
+ description:
16
+ '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 32k 上下文窗口的推理和精调。',
17
+ displayName: 'Doubao Lite 32k',
18
+ enabled: true,
19
+ id: 'Doubao-lite-32k',
20
+ type: 'chat',
21
+ },
22
+ {
23
+ contextWindowTokens: 128_000,
24
+ description:
25
+ '拥有极致的响应速度,更好的性价比,为客户不同场景提供更灵活的选择。支持 128k 上下文窗口的推理和精调。',
26
+ displayName: 'Doubao Lite 128k',
27
+ enabled: true,
28
+ id: 'Doubao-lite-128k',
29
+ type: 'chat',
30
+ },
31
+ {
32
+ contextWindowTokens: 4096,
33
+ description:
34
+ '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 4k 上下文窗口的推理和精调。',
35
+ displayName: 'Doubao Pro 4k',
36
+ enabled: true,
37
+ id: 'Doubao-pro-4k',
38
+ type: 'chat',
39
+ },
40
+ {
41
+ config: {
42
+ deploymentName: 'Doubao-pro-test',
43
+ },
44
+ contextWindowTokens: 32_768,
45
+ description:
46
+ '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 32k 上下文窗口的推理和精调。',
47
+ displayName: 'Doubao Pro 32k',
48
+ enabled: true,
49
+ id: 'Doubao-pro-32k',
50
+ type: 'chat',
51
+ },
52
+ {
53
+ contextWindowTokens: 128_000,
54
+ description:
55
+ '效果最好的主力模型,适合处理复杂任务,在参考问答、总结摘要、创作、文本分类、角色扮演等场景都有很好的效果。支持 128k 上下文窗口的推理和精调。',
56
+ displayName: 'Doubao Pro 128k',
57
+ enabled: true,
58
+ id: 'Doubao-pro-128k',
59
+ type: 'chat',
60
+ },
61
+ ];
62
+
63
+ export const allModels = [...doubaoChatModels];
64
+
65
+ export default allModels;
@@ -8,6 +8,7 @@ import { default as baichuan } from './baichuan';
8
8
  import { default as bedrock } from './bedrock';
9
9
  import { default as cloudflare } from './cloudflare';
10
10
  import { default as deepseek } from './deepseek';
11
+ import { default as doubao } from './doubao';
11
12
  import { default as fireworksai } from './fireworksai';
12
13
  import { default as giteeai } from './giteeai';
13
14
  import { default as github } from './github';
@@ -67,6 +68,7 @@ export const LOBE_DEFAULT_MODEL_LIST = buildDefaultModelList({
67
68
  bedrock,
68
69
  cloudflare,
69
70
  deepseek,
71
+ doubao,
70
72
  fireworksai,
71
73
  giteeai,
72
74
  github,
@@ -107,6 +109,7 @@ export { default as baichuan } from './baichuan';
107
109
  export { default as bedrock } from './bedrock';
108
110
  export { default as cloudflare } from './cloudflare';
109
111
  export { default as deepseek } from './deepseek';
112
+ export { default as doubao } from './doubao';
110
113
  export { default as fireworksai } from './fireworksai';
111
114
  export { default as giteeai } from './giteeai';
112
115
  export { default as github } from './github';
package/src/config/llm.ts CHANGED
@@ -123,6 +123,9 @@ export const getLLMConfig = () => {
123
123
 
124
124
  ENABLED_HIGRESS: z.boolean(),
125
125
  HIGRESS_API_KEY: z.string().optional(),
126
+
127
+ ENABLED_DOUBAO: z.boolean(),
128
+ DOUBAO_API_KEY: z.string().optional(),
126
129
  },
127
130
  runtimeEnv: {
128
131
  API_KEY_SELECT_MODE: process.env.API_KEY_SELECT_MODE,
@@ -244,6 +247,9 @@ export const getLLMConfig = () => {
244
247
 
245
248
  ENABLED_HIGRESS: !!process.env.HIGRESS_API_KEY,
246
249
  HIGRESS_API_KEY: process.env.HIGRESS_API_KEY,
250
+
251
+ ENABLED_DOUBAO: !!process.env.DOUBAO_API_KEY,
252
+ DOUBAO_API_KEY: process.env.DOUBAO_API_KEY,
247
253
  },
248
254
  });
249
255
  };
@@ -0,0 +1,23 @@
1
+ import { ModelProviderCard } from '@/types/llm';
2
+
3
+ // ref https://www.volcengine.com/docs/82379/1330310
4
+ const Doubao: ModelProviderCard = {
5
+ chatModels: [],
6
+ // checkModel: 'Doubao-lite-4k',
7
+ description: '字节跳动推出的自研大模型。通过字节跳动内部50+业务场景实践验证,每日万亿级tokens大使用量持续打磨,提供多种模态能力,以优质模型效果为企业打造丰富的业务体验。',
8
+ id: 'doubao',
9
+ modelsUrl: 'https://www.volcengine.com/product/doubao',
10
+ name: '豆包',
11
+ settings: {
12
+ disableBrowserRequest: true, // CORS error
13
+ sdkType: 'doubao',
14
+ // showModelFetcher: false,
15
+ smoothing: {
16
+ speed: 2,
17
+ text: true,
18
+ },
19
+ },
20
+ url: 'https://www.volcengine.com/product/doubao',
21
+ };
22
+
23
+ export default Doubao;
@@ -8,6 +8,7 @@ import BaichuanProvider from './baichuan';
8
8
  import BedrockProvider from './bedrock';
9
9
  import CloudflareProvider from './cloudflare';
10
10
  import DeepSeekProvider from './deepseek';
11
+ import DoubaoProvider from './doubao';
11
12
  import FireworksAIProvider from './fireworksai';
12
13
  import GiteeAIProvider from './giteeai';
13
14
  import GithubProvider from './github';
@@ -120,6 +121,7 @@ export const DEFAULT_MODEL_PROVIDER_LIST = [
120
121
  GiteeAIProvider,
121
122
  TaichuProvider,
122
123
  Ai360Provider,
124
+ DoubaoProvider,
123
125
  ];
124
126
 
125
127
  export const filterEnabledModels = (provider: ModelProviderCard) => {
@@ -139,6 +141,7 @@ export { default as BaichuanProviderCard } from './baichuan';
139
141
  export { default as BedrockProviderCard } from './bedrock';
140
142
  export { default as CloudflareProviderCard } from './cloudflare';
141
143
  export { default as DeepSeekProviderCard } from './deepseek';
144
+ export { default as DoubaoProviderCard } from './doubao';
142
145
  export { default as FireworksAIProviderCard } from './fireworksai';
143
146
  export { default as GiteeAIProviderCard } from './giteeai';
144
147
  export { default as GithubProviderCard } from './github';
@@ -1,123 +1,19 @@
1
- import { Icon, Markdown } from '@lobehub/ui';
2
- import { createStyles } from 'antd-style';
3
- import { AtomIcon, ChevronDown, ChevronRight } from 'lucide-react';
4
- import { rgba } from 'polished';
5
- import { memo, useEffect, useState } from 'react';
6
- import { useTranslation } from 'react-i18next';
7
- import { Flexbox } from 'react-layout-kit';
1
+ import { memo } from 'react';
8
2
 
3
+ import Thinking from '@/components/Thinking';
9
4
  import { useChatStore } from '@/store/chat';
10
5
  import { aiChatSelectors } from '@/store/chat/selectors';
11
6
 
12
- const useStyles = createStyles(({ css, token, isDarkMode }) => ({
13
- container: css`
14
- cursor: pointer;
15
-
16
- width: fit-content;
17
- padding-block: 4px;
18
- padding-inline: 8px;
19
- border-radius: 6px;
20
-
21
- color: ${token.colorTextTertiary};
22
-
23
- &:hover {
24
- background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary};
25
- }
26
- `,
27
- expand: css`
28
- background: ${isDarkMode ? token.colorFillQuaternary : token.colorFillTertiary} !important;
29
- `,
30
- shinyText: css`
31
- color: ${rgba(token.colorText, 0.45)};
32
-
33
- background: linear-gradient(
34
- 120deg,
35
- ${rgba(token.colorTextBase, 0)} 40%,
36
- ${token.colorTextSecondary} 50%,
37
- ${rgba(token.colorTextBase, 0)} 60%
38
- );
39
- background-clip: text;
40
- background-size: 200% 100%;
41
-
42
- animation: shine 1.5s linear infinite;
43
-
44
- @keyframes shine {
45
- 0% {
46
- background-position: 100%;
47
- }
48
-
49
- 100% {
50
- background-position: -100%;
51
- }
52
- }
53
- `,
54
- title: css`
55
- overflow: hidden;
56
- display: -webkit-box;
57
- -webkit-box-orient: vertical;
58
- -webkit-line-clamp: 1;
59
-
60
- font-size: 12px;
61
- text-overflow: ellipsis;
62
- `,
63
- }));
64
-
65
- interface ThinkingProps {
7
+ interface ReasoningProps {
66
8
  content?: string;
67
9
  duration?: number;
68
10
  id: string;
69
11
  }
70
12
 
71
- const Thinking = memo<ThinkingProps>(({ content = '', duration, id }) => {
72
- const { t } = useTranslation('chat');
73
- const { styles, cx } = useStyles();
74
-
75
- const [showDetail, setShowDetail] = useState(false);
76
-
13
+ const Reasoning = memo<ReasoningProps>(({ content = '', duration, id }) => {
77
14
  const isReasoning = useChatStore(aiChatSelectors.isMessageInReasoning(id));
78
15
 
79
- useEffect(() => {
80
- if (isReasoning && !content) {
81
- setShowDetail(true);
82
- }
83
-
84
- if (!isReasoning) {
85
- setShowDetail(false);
86
- }
87
- }, [isReasoning, content]);
88
-
89
- return (
90
- <Flexbox
91
- className={cx(styles.container, showDetail && styles.expand)}
92
- gap={16}
93
- onClick={() => {
94
- setShowDetail(!showDetail);
95
- }}
96
- >
97
- <Flexbox distribution={'space-between'} flex={1} horizontal>
98
- {isReasoning ? (
99
- <Flexbox gap={8} horizontal>
100
- <Icon icon={AtomIcon} />
101
- <Flexbox className={styles.shinyText} horizontal>
102
- {t('reasoning.thinking')}
103
- </Flexbox>
104
- </Flexbox>
105
- ) : (
106
- <Flexbox gap={8} horizontal>
107
- <Icon icon={AtomIcon} />
108
- {t('reasoning.thought', { duration: ((duration || 0) / 1000).toFixed(1) })}
109
- </Flexbox>
110
- )}
111
- <Icon icon={showDetail ? ChevronDown : ChevronRight} />
112
- </Flexbox>
113
-
114
- {showDetail && (
115
- <Flexbox>
116
- <Markdown variant={'chat'}>{content}</Markdown>
117
- </Flexbox>
118
- )}
119
- </Flexbox>
120
- );
16
+ return <Thinking content={content} duration={duration} thinking={isReasoning} />;
121
17
  });
122
18
 
123
- export default Thinking;
19
+ export default Reasoning;
@@ -11,6 +11,7 @@ import { LobeBaichuanAI } from './baichuan';
11
11
  import { LobeBedrockAI, LobeBedrockAIParams } from './bedrock';
12
12
  import { LobeCloudflareAI, LobeCloudflareParams } from './cloudflare';
13
13
  import { LobeDeepSeekAI } from './deepseek';
14
+ import { LobeDoubaoAI } from './doubao';
14
15
  import { LobeFireworksAI } from './fireworksai';
15
16
  import { LobeGiteeAI } from './giteeai';
16
17
  import { LobeGithubAI } from './github';
@@ -139,6 +140,7 @@ class AgentRuntime {
139
140
  bedrock: Partial<LobeBedrockAIParams>;
140
141
  cloudflare: Partial<LobeCloudflareParams>;
141
142
  deepseek: Partial<ClientOptions>;
143
+ doubao: Partial<ClientOptions>;
142
144
  fireworksai: Partial<ClientOptions>;
143
145
  giteeai: Partial<ClientOptions>;
144
146
  github: Partial<ClientOptions>;
@@ -363,6 +365,11 @@ class AgentRuntime {
363
365
  runtimeModel = new LobeHigressAI(params.higress);
364
366
  break;
365
367
  }
368
+
369
+ case ModelProvider.Doubao: {
370
+ runtimeModel = new LobeDoubaoAI(params.doubao);
371
+ break;
372
+ }
366
373
  }
367
374
  return new AgentRuntime(runtimeModel);
368
375
  }
@@ -0,0 +1,10 @@
1
+ import { ModelProvider } from '../types';
2
+ import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';
3
+
4
+ export const LobeDoubaoAI = LobeOpenAICompatibleFactory({
5
+ baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
6
+ debug: {
7
+ chatCompletion: () => process.env.DEBUG_DOUBAO_CHAT_COMPLETION === '1',
8
+ },
9
+ provider: ModelProvider.Doubao,
10
+ });
@@ -4,6 +4,7 @@ export { LobeAzureOpenAI } from './azureOpenai';
4
4
  export * from './BaseAI';
5
5
  export { LobeBedrockAI } from './bedrock';
6
6
  export { LobeDeepSeekAI } from './deepseek';
7
+ export { LobeDoubaoAI } from './doubao';
7
8
  export * from './error';
8
9
  export { LobeGoogleAI } from './google';
9
10
  export { LobeGroq } from './groq';
@@ -30,6 +30,7 @@ export enum ModelProvider {
30
30
  Bedrock = 'bedrock',
31
31
  Cloudflare = 'cloudflare',
32
32
  DeepSeek = 'deepseek',
33
+ Doubao = 'doubao',
33
34
  FireworksAI = 'fireworksai',
34
35
  GiteeAI = 'giteeai',
35
36
  Github = 'github',
@@ -84,10 +84,6 @@ export default {
84
84
  },
85
85
  },
86
86
  },
87
- reasoning: {
88
- thinking: '深度思考中',
89
- thought: '已深度思考(用时 {{duration}} 秒)',
90
- },
91
87
  regenerate: '重新生成',
92
88
  roleAndArchive: '角色与记录',
93
89
  searchAgentPlaceholder: '搜索助手...',
@@ -88,4 +88,9 @@ export default {
88
88
  emptyModel: '没有启用的模型,请前往设置开启',
89
89
  provider: '提供商',
90
90
  },
91
+ Thinking: {
92
+ thinking: '深度思考中...',
93
+ thought: '已深度思考',
94
+ thoughtWithDuration: '已深度思考(用时 {{duration}} 秒)',
95
+ },
91
96
  };
@@ -25,6 +25,9 @@ export const getServerGlobalConfig = () => {
25
25
  enabledKey: 'ENABLED_AWS_BEDROCK',
26
26
  modelListKey: 'AWS_BEDROCK_MODEL_LIST',
27
27
  },
28
+ doubao: {
29
+ withDeploymentName: true,
30
+ },
28
31
  giteeai: {
29
32
  enabledKey: 'ENABLED_GITEE_AI',
30
33
  modelListKey: 'GITEE_AI_MODEL_LIST',
@@ -221,7 +221,7 @@ class ChatService {
221
221
  let model = res.model || DEFAULT_AGENT_CONFIG.model;
222
222
 
223
223
  // if the provider is Azure, get the deployment name as the request model
224
- if (provider === ModelProvider.Azure) {
224
+ if (provider === ModelProvider.Azure || provider === ModelProvider.Doubao) {
225
225
  model = findAzureDeploymentName(model);
226
226
  }
227
227
 
@@ -18,6 +18,7 @@ export const AiProviderSDKEnum = {
18
18
  Azure: 'azure',
19
19
  Bedrock: 'bedrock',
20
20
  Cloudflare: 'cloudflare',
21
+ Doubao: 'doubao',
21
22
  Google: 'google',
22
23
  Huggingface: 'huggingface',
23
24
  Ollama: 'ollama',
@@ -39,6 +39,7 @@ export interface UserKeyVaults {
39
39
  bedrock?: AWSBedrockKeyVault;
40
40
  cloudflare?: CloudflareKeyVault;
41
41
  deepseek?: OpenAICompatibleKeyVault;
42
+ doubao?: OpenAICompatibleKeyVault;
42
43
  fireworksai?: OpenAICompatibleKeyVault;
43
44
  giteeai?: OpenAICompatibleKeyVault;
44
45
  github?: OpenAICompatibleKeyVault;