@lobehub/chat 1.23.1 → 1.24.1
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.
- package/CHANGELOG.md +50 -0
- package/Dockerfile +2 -0
- package/Dockerfile.database +2 -0
- package/locales/ar/modelProvider.json +16 -0
- package/locales/ar/models.json +27 -0
- package/locales/ar/providers.json +1 -0
- package/locales/bg-BG/modelProvider.json +16 -0
- package/locales/bg-BG/models.json +27 -0
- package/locales/bg-BG/providers.json +1 -0
- package/locales/de-DE/modelProvider.json +16 -0
- package/locales/de-DE/models.json +27 -0
- package/locales/de-DE/providers.json +1 -0
- package/locales/en-US/modelProvider.json +16 -0
- package/locales/en-US/models.json +27 -0
- package/locales/en-US/providers.json +1 -0
- package/locales/es-ES/modelProvider.json +16 -0
- package/locales/es-ES/models.json +27 -0
- package/locales/es-ES/providers.json +1 -0
- package/locales/fr-FR/modelProvider.json +16 -0
- package/locales/fr-FR/models.json +27 -0
- package/locales/fr-FR/providers.json +1 -0
- package/locales/it-IT/modelProvider.json +16 -0
- package/locales/it-IT/models.json +27 -0
- package/locales/it-IT/providers.json +1 -0
- package/locales/ja-JP/modelProvider.json +16 -0
- package/locales/ja-JP/models.json +27 -0
- package/locales/ja-JP/providers.json +1 -0
- package/locales/ko-KR/modelProvider.json +16 -0
- package/locales/ko-KR/models.json +27 -0
- package/locales/ko-KR/providers.json +1 -0
- package/locales/nl-NL/modelProvider.json +16 -0
- package/locales/nl-NL/models.json +27 -0
- package/locales/nl-NL/providers.json +1 -0
- package/locales/pl-PL/modelProvider.json +16 -0
- package/locales/pl-PL/models.json +27 -0
- package/locales/pl-PL/providers.json +1 -0
- package/locales/pt-BR/modelProvider.json +16 -0
- package/locales/pt-BR/models.json +27 -0
- package/locales/pt-BR/providers.json +1 -0
- package/locales/ru-RU/modelProvider.json +16 -0
- package/locales/ru-RU/models.json +27 -0
- package/locales/ru-RU/providers.json +1 -0
- package/locales/tr-TR/modelProvider.json +16 -0
- package/locales/tr-TR/models.json +27 -0
- package/locales/tr-TR/providers.json +1 -0
- package/locales/vi-VN/modelProvider.json +16 -0
- package/locales/vi-VN/models.json +27 -0
- package/locales/vi-VN/providers.json +1 -0
- package/locales/zh-CN/modelProvider.json +16 -0
- package/locales/zh-CN/models.json +27 -0
- package/locales/zh-CN/providers.json +1 -0
- package/locales/zh-TW/modelProvider.json +16 -0
- package/locales/zh-TW/models.json +27 -0
- package/locales/zh-TW/providers.json +1 -0
- package/package.json +4 -4
- package/src/app/(main)/chat/(workspace)/_layout/Desktop/Portal.tsx +8 -8
- package/src/app/(main)/settings/llm/ProviderList/SenseNova/index.tsx +44 -0
- package/src/app/(main)/settings/llm/ProviderList/providers.tsx +4 -0
- package/src/config/llm.ts +10 -0
- package/src/config/modelProviders/index.ts +4 -0
- package/src/config/modelProviders/sensenova.ts +124 -0
- package/src/const/auth.ts +3 -0
- package/src/const/layoutTokens.ts +3 -2
- package/src/const/settings/llm.ts +5 -0
- package/src/features/Conversation/Error/APIKeyForm/SenseNova.tsx +49 -0
- package/src/features/Conversation/Error/APIKeyForm/index.tsx +3 -0
- package/src/libs/agent-runtime/AgentRuntime.ts +7 -0
- package/src/libs/agent-runtime/google/index.test.ts +4 -91
- package/src/libs/agent-runtime/google/index.ts +5 -49
- package/src/libs/agent-runtime/index.ts +1 -0
- package/src/libs/agent-runtime/sensenova/authToken.test.ts +18 -0
- package/src/libs/agent-runtime/sensenova/authToken.ts +27 -0
- package/src/libs/agent-runtime/sensenova/index.test.ts +321 -0
- package/src/libs/agent-runtime/sensenova/index.ts +98 -0
- package/src/libs/agent-runtime/types/type.ts +1 -0
- package/src/locales/default/modelProvider.ts +17 -0
- package/src/server/globalConfig/index.ts +12 -0
- package/src/server/modules/AgentRuntime/index.ts +10 -0
- package/src/services/_auth.ts +14 -0
- package/src/store/user/slices/modelList/selectors/keyVaults.ts +2 -0
- package/src/store/user/slices/modelList/selectors/modelConfig.ts +2 -0
- package/src/types/user/settings/keyVaults.ts +6 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.24.1",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -43,7 +43,7 @@
|
|
43
43
|
"docs:seo": "lobe-seo && npm run lint:mdx",
|
44
44
|
"i18n": "npm run workflow:i18n && lobe-i18n",
|
45
45
|
"lint": "npm run lint:ts && npm run lint:style && npm run type-check && npm run lint:circular",
|
46
|
-
"lint:circular": "dpdm src/**/*.ts --warning
|
46
|
+
"lint:circular": "dpdm src/**/*.ts --no-warning --no-tree --exit-code circular:1 --no-progress -T true --skip-dynamic-imports circular",
|
47
47
|
"lint:md": "remark . --quiet --frail --output",
|
48
48
|
"lint:mdx": "npm run workflow:mdx-with-lint && prettier -c --write \"{src,docs}/**/*.mdx\" && npm run workflow:mdx-with-lint",
|
49
49
|
"lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
|
@@ -116,7 +116,7 @@
|
|
116
116
|
"@clerk/themes": "^2.1.37",
|
117
117
|
"@codesandbox/sandpack-react": "^2.19.9",
|
118
118
|
"@cyntler/react-doc-viewer": "^1.17.0",
|
119
|
-
"@google/generative-ai": "^0.
|
119
|
+
"@google/generative-ai": "^0.21.0",
|
120
120
|
"@huggingface/inference": "^2.8.1",
|
121
121
|
"@icons-pack/react-simple-icons": "9.6.0",
|
122
122
|
"@khmyznikov/pwa-install": "^0.3.9",
|
@@ -270,7 +270,7 @@
|
|
270
270
|
"commitlint": "^19.5.0",
|
271
271
|
"consola": "^3.2.3",
|
272
272
|
"dotenv": "^16.4.5",
|
273
|
-
"dpdm": "^
|
273
|
+
"dpdm-fast": "^1.0.4",
|
274
274
|
"drizzle-kit": "^0.26.0",
|
275
275
|
"eslint": "^8.57.1",
|
276
276
|
"eslint-plugin-mdx": "^2.3.4",
|
@@ -6,7 +6,11 @@ import { rgba } from 'polished';
|
|
6
6
|
import { PropsWithChildren, memo } from 'react';
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
8
8
|
|
9
|
-
import {
|
9
|
+
import {
|
10
|
+
CHAT_PORTAL_MAX_WIDTH,
|
11
|
+
CHAT_PORTAL_TOOL_UI_WIDTH,
|
12
|
+
CHAT_PORTAL_WIDTH,
|
13
|
+
} from '@/const/layoutTokens';
|
10
14
|
import { useChatStore } from '@/store/chat';
|
11
15
|
import { chatPortalSelectors } from '@/store/chat/slices/portal/selectors';
|
12
16
|
|
@@ -25,12 +29,8 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
25
29
|
`,
|
26
30
|
panel: css`
|
27
31
|
overflow: hidden;
|
28
|
-
|
29
32
|
height: 100%;
|
30
|
-
margin: 4px;
|
31
|
-
|
32
33
|
background: ${isDarkMode ? rgba(token.colorBgElevated, 0.8) : token.colorBgElevated};
|
33
|
-
border-radius: 8px;
|
34
34
|
`,
|
35
35
|
}));
|
36
36
|
|
@@ -53,8 +53,8 @@ const PortalPanel = memo(({ children }: PropsWithChildren) => {
|
|
53
53
|
}}
|
54
54
|
expand
|
55
55
|
hanlderStyle={{ display: 'none' }}
|
56
|
-
maxWidth={
|
57
|
-
minWidth={showArtifactUI || showToolUI ?
|
56
|
+
maxWidth={CHAT_PORTAL_MAX_WIDTH}
|
57
|
+
minWidth={showArtifactUI || showToolUI ? CHAT_PORTAL_TOOL_UI_WIDTH : CHAT_PORTAL_WIDTH}
|
58
58
|
mode={md ? 'fixed' : 'float'}
|
59
59
|
placement={'right'}
|
60
60
|
showHandlerWhenUnexpand={false}
|
@@ -65,7 +65,7 @@ const PortalPanel = memo(({ children }: PropsWithChildren) => {
|
|
65
65
|
flex: 'none',
|
66
66
|
height: '100%',
|
67
67
|
maxHeight: '100vh',
|
68
|
-
minWidth:
|
68
|
+
minWidth: CHAT_PORTAL_WIDTH,
|
69
69
|
}}
|
70
70
|
>
|
71
71
|
<Flexbox className={styles.panel}>{children}</Flexbox>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Input } from 'antd';
|
4
|
+
import { useTranslation } from 'react-i18next';
|
5
|
+
|
6
|
+
import { SenseNovaProviderCard } from '@/config/modelProviders';
|
7
|
+
import { GlobalLLMProviderKey } from '@/types/user/settings';
|
8
|
+
|
9
|
+
import { KeyVaultsConfigKey } from '../../const';
|
10
|
+
import { ProviderItem } from '../../type';
|
11
|
+
|
12
|
+
const providerKey: GlobalLLMProviderKey = 'sensenova';
|
13
|
+
|
14
|
+
export const useSenseNovaProvider = (): ProviderItem => {
|
15
|
+
const { t } = useTranslation('modelProvider');
|
16
|
+
|
17
|
+
return {
|
18
|
+
...SenseNovaProviderCard,
|
19
|
+
apiKeyItems: [
|
20
|
+
{
|
21
|
+
children: (
|
22
|
+
<Input.Password
|
23
|
+
autoComplete={'new-password'}
|
24
|
+
placeholder={t(`${providerKey}.sensenovaAccessKeyID.placeholder`)}
|
25
|
+
/>
|
26
|
+
),
|
27
|
+
desc: t(`${providerKey}.sensenovaAccessKeyID.desc`),
|
28
|
+
label: t(`${providerKey}.sensenovaAccessKeyID.title`),
|
29
|
+
name: [KeyVaultsConfigKey, providerKey, 'sensenovaAccessKeyID'],
|
30
|
+
},
|
31
|
+
{
|
32
|
+
children: (
|
33
|
+
<Input.Password
|
34
|
+
autoComplete={'new-password'}
|
35
|
+
placeholder={t(`${providerKey}.sensenovaAccessKeySecret.placeholder`)}
|
36
|
+
/>
|
37
|
+
),
|
38
|
+
desc: t(`${providerKey}.sensenovaAccessKeySecret.desc`),
|
39
|
+
label: t(`${providerKey}.sensenovaAccessKeySecret.title`),
|
40
|
+
name: [KeyVaultsConfigKey, providerKey, 'sensenovaAccessKeySecret'],
|
41
|
+
},
|
42
|
+
],
|
43
|
+
};
|
44
|
+
};
|
@@ -35,6 +35,7 @@ import { useHuggingFaceProvider } from './HuggingFace';
|
|
35
35
|
import { useOllamaProvider } from './Ollama';
|
36
36
|
import { useOpenAIProvider } from './OpenAI';
|
37
37
|
import { useWenxinProvider } from './Wenxin';
|
38
|
+
import { useSenseNovaProvider } from './SenseNova';
|
38
39
|
|
39
40
|
export const useProviderList = (): ProviderItem[] => {
|
40
41
|
const AzureProvider = useAzureProvider();
|
@@ -44,6 +45,7 @@ export const useProviderList = (): ProviderItem[] => {
|
|
44
45
|
const GithubProvider = useGithubProvider();
|
45
46
|
const HuggingFaceProvider = useHuggingFaceProvider();
|
46
47
|
const WenxinProvider = useWenxinProvider();
|
48
|
+
const SenseNovaProvider = useSenseNovaProvider();
|
47
49
|
|
48
50
|
return useMemo(
|
49
51
|
() => [
|
@@ -71,6 +73,7 @@ export const useProviderList = (): ProviderItem[] => {
|
|
71
73
|
SparkProviderCard,
|
72
74
|
ZhiPuProviderCard,
|
73
75
|
ZeroOneProviderCard,
|
76
|
+
SenseNovaProvider,
|
74
77
|
StepfunProviderCard,
|
75
78
|
MoonshotProviderCard,
|
76
79
|
BaichuanProviderCard,
|
@@ -87,6 +90,7 @@ export const useProviderList = (): ProviderItem[] => {
|
|
87
90
|
GithubProvider,
|
88
91
|
WenxinProvider,
|
89
92
|
HuggingFaceProvider,
|
93
|
+
SenseNovaProvider,
|
90
94
|
],
|
91
95
|
);
|
92
96
|
};
|
package/src/config/llm.ts
CHANGED
@@ -144,6 +144,11 @@ export const getLLMConfig = () => {
|
|
144
144
|
HUGGINGFACE_API_KEY: z.string().optional(),
|
145
145
|
HUGGINGFACE_PROXY_URL: z.string().optional(),
|
146
146
|
HUGGINGFACE_MODEL_LIST: z.string().optional(),
|
147
|
+
|
148
|
+
ENABLED_SENSENOVA: z.boolean(),
|
149
|
+
SENSENOVA_ACCESS_KEY_ID: z.string().optional(),
|
150
|
+
SENSENOVA_ACCESS_KEY_SECRET: z.string().optional(),
|
151
|
+
SENSENOVA_MODEL_LIST: z.string().optional(),
|
147
152
|
},
|
148
153
|
runtimeEnv: {
|
149
154
|
API_KEY_SELECT_MODE: process.env.API_KEY_SELECT_MODE,
|
@@ -285,6 +290,11 @@ export const getLLMConfig = () => {
|
|
285
290
|
HUGGINGFACE_API_KEY: process.env.HUGGINGFACE_API_KEY,
|
286
291
|
HUGGINGFACE_PROXY_URL: process.env.HUGGINGFACE_PROXY_URL,
|
287
292
|
HUGGINGFACE_MODEL_LIST: process.env.HUGGINGFACE_MODEL_LIST,
|
293
|
+
|
294
|
+
ENABLED_SENSENOVA: !!process.env.SENSENOVA_ACCESS_KEY_ID && !!process.env.SENSENOVA_ACCESS_KEY_SECRET,
|
295
|
+
SENSENOVA_ACCESS_KEY_ID: process.env.SENSENOVA_ACCESS_KEY_ID,
|
296
|
+
SENSENOVA_ACCESS_KEY_SECRET: process.env.SENSENOVA_ACCESS_KEY_SECRET,
|
297
|
+
SENSENOVA_MODEL_LIST: process.env.SENSENOVA_MODEL_LIST,
|
288
298
|
},
|
289
299
|
});
|
290
300
|
};
|
@@ -22,6 +22,7 @@ import OpenAIProvider from './openai';
|
|
22
22
|
import OpenRouterProvider from './openrouter';
|
23
23
|
import PerplexityProvider from './perplexity';
|
24
24
|
import QwenProvider from './qwen';
|
25
|
+
import SenseNovaProvider from './sensenova';
|
25
26
|
import SiliconCloudProvider from './siliconcloud';
|
26
27
|
import SparkProvider from './spark';
|
27
28
|
import StepfunProvider from './stepfun';
|
@@ -63,6 +64,7 @@ export const LOBE_DEFAULT_MODEL_LIST: ChatModelCard[] = [
|
|
63
64
|
Ai21Provider.chatModels,
|
64
65
|
HunyuanProvider.chatModels,
|
65
66
|
WenxinProvider.chatModels,
|
67
|
+
SenseNovaProvider.chatModels,
|
66
68
|
].flat();
|
67
69
|
|
68
70
|
export const DEFAULT_MODEL_PROVIDER_LIST = [
|
@@ -90,6 +92,7 @@ export const DEFAULT_MODEL_PROVIDER_LIST = [
|
|
90
92
|
SparkProvider,
|
91
93
|
ZhiPuProvider,
|
92
94
|
ZeroOneProvider,
|
95
|
+
SenseNovaProvider,
|
93
96
|
StepfunProvider,
|
94
97
|
MoonshotProvider,
|
95
98
|
BaichuanProvider,
|
@@ -130,6 +133,7 @@ export { default as OpenAIProviderCard } from './openai';
|
|
130
133
|
export { default as OpenRouterProviderCard } from './openrouter';
|
131
134
|
export { default as PerplexityProviderCard } from './perplexity';
|
132
135
|
export { default as QwenProviderCard } from './qwen';
|
136
|
+
export { default as SenseNovaProviderCard } from './sensenova';
|
133
137
|
export { default as SiliconCloudProviderCard } from './siliconcloud';
|
134
138
|
export { default as SparkProviderCard } from './spark';
|
135
139
|
export { default as StepfunProviderCard } from './stepfun';
|
@@ -0,0 +1,124 @@
|
|
1
|
+
import { ModelProviderCard } from '@/types/llm';
|
2
|
+
|
3
|
+
// ref https://platform.sensenova.cn/pricing
|
4
|
+
// ref https://platform.sensenova.cn/release?path=/release-202409.md
|
5
|
+
const SenseNova: ModelProviderCard = {
|
6
|
+
chatModels: [
|
7
|
+
{
|
8
|
+
description: '最新版本模型 (V5.5),128K上下文长度,在数学推理、英文对话、指令跟随以及长文本理解等领域能力显著提升,比肩GPT-4o',
|
9
|
+
displayName: 'SenseChat 5.5',
|
10
|
+
enabled: true,
|
11
|
+
functionCall: true,
|
12
|
+
id: 'SenseChat-5',
|
13
|
+
pricing: {
|
14
|
+
currency: 'CNY',
|
15
|
+
input: 40,
|
16
|
+
output: 100,
|
17
|
+
},
|
18
|
+
tokens: 131_072,
|
19
|
+
},
|
20
|
+
{
|
21
|
+
description: '最新版本模型 (V5.5),16K上下文长度,支持多图的输入,全面实现模型基础能力优化,在对象属性识别、空间关系、动作事件识别、场景理解、情感识别、逻辑常识推理和文本理解生成上都实现了较大提升。',
|
22
|
+
displayName: 'SenseChat 5.5 Vision',
|
23
|
+
enabled: true,
|
24
|
+
id: 'SenseChat-Vision',
|
25
|
+
pricing: {
|
26
|
+
currency: 'CNY',
|
27
|
+
input: 100,
|
28
|
+
output: 100,
|
29
|
+
},
|
30
|
+
tokens: 16_384,
|
31
|
+
vision: true,
|
32
|
+
},
|
33
|
+
{
|
34
|
+
description: '适用于快速问答、模型微调场景',
|
35
|
+
displayName: 'SenseChat 5.0 Turbo',
|
36
|
+
enabled: true,
|
37
|
+
id: 'SenseChat-Turbo',
|
38
|
+
pricing: {
|
39
|
+
currency: 'CNY',
|
40
|
+
input: 2,
|
41
|
+
output: 5,
|
42
|
+
},
|
43
|
+
tokens: 32_768,
|
44
|
+
},
|
45
|
+
{
|
46
|
+
description: '32K上下文长度,在粤语的对话理解上超越了GPT-4,在知识、推理、数学及代码编写等多个领域均能与GPT-4 Turbo相媲美',
|
47
|
+
displayName: 'SenseChat 5.0 Cantonese',
|
48
|
+
id: 'SenseChat-5-Cantonese',
|
49
|
+
pricing: {
|
50
|
+
currency: 'CNY',
|
51
|
+
input: 27,
|
52
|
+
output: 27,
|
53
|
+
},
|
54
|
+
tokens: 32_768,
|
55
|
+
},
|
56
|
+
{
|
57
|
+
description: '基础版本模型 (V4),128K上下文长度,在长文本理解及生成等任务中表现出色',
|
58
|
+
displayName: 'SenseChat 4.0 128K',
|
59
|
+
enabled: true,
|
60
|
+
id: 'SenseChat-128K',
|
61
|
+
pricing: {
|
62
|
+
currency: 'CNY',
|
63
|
+
input: 60,
|
64
|
+
output: 60,
|
65
|
+
},
|
66
|
+
tokens: 131_072,
|
67
|
+
},
|
68
|
+
{
|
69
|
+
description: '基础版本模型 (V4),32K上下文长度,灵活应用于各类场景',
|
70
|
+
displayName: 'SenseChat 4.0 32K',
|
71
|
+
enabled: true,
|
72
|
+
id: 'SenseChat-32K',
|
73
|
+
pricing: {
|
74
|
+
currency: 'CNY',
|
75
|
+
input: 36,
|
76
|
+
output: 36,
|
77
|
+
},
|
78
|
+
tokens: 32_768,
|
79
|
+
},
|
80
|
+
{
|
81
|
+
description: '基础版本模型 (V4),4K上下文长度,通用能力强大',
|
82
|
+
displayName: 'SenseChat 4.0 4K',
|
83
|
+
enabled: true,
|
84
|
+
id: 'SenseChat',
|
85
|
+
pricing: {
|
86
|
+
currency: 'CNY',
|
87
|
+
input: 12,
|
88
|
+
output: 12,
|
89
|
+
},
|
90
|
+
tokens: 4096,
|
91
|
+
},
|
92
|
+
{
|
93
|
+
description: '标准版模型,8K上下文长度,高响应速度',
|
94
|
+
displayName: 'SenseChat Character',
|
95
|
+
id: 'SenseChat-Character',
|
96
|
+
pricing: {
|
97
|
+
currency: 'CNY',
|
98
|
+
input: 12,
|
99
|
+
output: 12,
|
100
|
+
},
|
101
|
+
tokens: 8192,
|
102
|
+
},
|
103
|
+
{
|
104
|
+
description: '高级版模型,32K上下文长度,能力全面提升,支持中/英文对话',
|
105
|
+
displayName: 'SenseChat Character Pro',
|
106
|
+
id: 'SenseChat-Character-Pro',
|
107
|
+
pricing: {
|
108
|
+
currency: 'CNY',
|
109
|
+
input: 15,
|
110
|
+
output: 15,
|
111
|
+
},
|
112
|
+
tokens: 32_768,
|
113
|
+
},
|
114
|
+
],
|
115
|
+
checkModel: 'SenseChat-Turbo',
|
116
|
+
disableBrowserRequest: true,
|
117
|
+
id: 'sensenova',
|
118
|
+
modelList: { showModelFetcher: true },
|
119
|
+
modelsUrl: 'https://platform.sensenova.cn/pricing',
|
120
|
+
name: 'SenseNova',
|
121
|
+
url: 'https://platform.sensenova.cn/home',
|
122
|
+
};
|
123
|
+
|
124
|
+
export default SenseNova;
|
package/src/const/auth.ts
CHANGED
@@ -8,8 +8,9 @@ export const CHAT_TEXTAREA_HEIGHT = 160;
|
|
8
8
|
export const CHAT_TEXTAREA_HEIGHT_MOBILE = 108;
|
9
9
|
export const CHAT_SIDEBAR_WIDTH = 280;
|
10
10
|
|
11
|
-
export const
|
12
|
-
export const
|
11
|
+
export const CHAT_PORTAL_WIDTH = 400;
|
12
|
+
export const CHAT_PORTAL_MAX_WIDTH = 1280;
|
13
|
+
export const CHAT_PORTAL_TOOL_UI_WIDTH = 600;
|
13
14
|
|
14
15
|
export const MARKET_SIDEBAR_WIDTH = 400;
|
15
16
|
export const FOLDER_WIDTH = 270;
|
@@ -20,6 +20,7 @@ import {
|
|
20
20
|
OpenRouterProviderCard,
|
21
21
|
PerplexityProviderCard,
|
22
22
|
QwenProviderCard,
|
23
|
+
SenseNovaProviderCard,
|
23
24
|
SiliconCloudProviderCard,
|
24
25
|
SparkProviderCard,
|
25
26
|
StepfunProviderCard,
|
@@ -123,6 +124,10 @@ export const DEFAULT_LLM_CONFIG: UserModelProviderConfig = {
|
|
123
124
|
enabled: false,
|
124
125
|
enabledModels: filterEnabledModels(QwenProviderCard),
|
125
126
|
},
|
127
|
+
sensenova: {
|
128
|
+
enabled: false,
|
129
|
+
enabledModels: filterEnabledModels(SenseNovaProviderCard),
|
130
|
+
},
|
126
131
|
siliconcloud: {
|
127
132
|
enabled: false,
|
128
133
|
enabledModels: filterEnabledModels(SiliconCloudProviderCard),
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import { SenseNova } from '@lobehub/icons';
|
2
|
+
import { Input } from 'antd';
|
3
|
+
import { memo } from 'react';
|
4
|
+
import { useTranslation } from 'react-i18next';
|
5
|
+
|
6
|
+
import { ModelProvider } from '@/libs/agent-runtime';
|
7
|
+
import { useUserStore } from '@/store/user';
|
8
|
+
import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
9
|
+
|
10
|
+
import { FormAction } from '../style';
|
11
|
+
|
12
|
+
const SenseNovaForm = memo(() => {
|
13
|
+
const { t } = useTranslation('modelProvider');
|
14
|
+
|
15
|
+
const [sensenovaAccessKeyID, sensenovaAccessKeySecret, setConfig] = useUserStore((s) => [
|
16
|
+
keyVaultsConfigSelectors.sensenovaConfig(s).sensenovaAccessKeyID,
|
17
|
+
keyVaultsConfigSelectors.sensenovaConfig(s).sensenovaAccessKeySecret,
|
18
|
+
s.updateKeyVaultConfig,
|
19
|
+
]);
|
20
|
+
|
21
|
+
return (
|
22
|
+
<FormAction
|
23
|
+
avatar={<SenseNova color={SenseNova.colorPrimary} size={56} />}
|
24
|
+
description={t('sensenova.unlock.description')}
|
25
|
+
title={t('sensenova.unlock.title')}
|
26
|
+
>
|
27
|
+
<Input.Password
|
28
|
+
autoComplete={'new-password'}
|
29
|
+
onChange={(e) => {
|
30
|
+
setConfig(ModelProvider.SenseNova, { sensenovaAccessKeyID: e.target.value });
|
31
|
+
}}
|
32
|
+
placeholder={t('sensenova.sensenovaAccessKeyID.placeholder')}
|
33
|
+
type={'block'}
|
34
|
+
value={sensenovaAccessKeyID}
|
35
|
+
/>
|
36
|
+
<Input.Password
|
37
|
+
autoComplete={'new-password'}
|
38
|
+
onChange={(e) => {
|
39
|
+
setConfig(ModelProvider.SenseNova, { sensenovaAccessKeySecret: e.target.value });
|
40
|
+
}}
|
41
|
+
placeholder={t('sensenova.sensenovaAccessKeySecret.placeholder')}
|
42
|
+
type={'block'}
|
43
|
+
value={sensenovaAccessKeySecret}
|
44
|
+
/>
|
45
|
+
</FormAction>
|
46
|
+
);
|
47
|
+
});
|
48
|
+
|
49
|
+
export default SenseNovaForm;
|
@@ -10,6 +10,7 @@ import { GlobalLLMProviderKey } from '@/types/user/settings';
|
|
10
10
|
|
11
11
|
import BedrockForm from './Bedrock';
|
12
12
|
import ProviderApiKeyForm from './ProviderApiKeyForm';
|
13
|
+
import SenseNovaForm from './SenseNova';
|
13
14
|
import WenxinForm from './Wenxin';
|
14
15
|
|
15
16
|
interface APIKeyFormProps {
|
@@ -66,6 +67,8 @@ const APIKeyForm = memo<APIKeyFormProps>(({ id, provider }) => {
|
|
66
67
|
<Center gap={16} style={{ maxWidth: 300 }}>
|
67
68
|
{provider === ModelProvider.Bedrock ? (
|
68
69
|
<BedrockForm />
|
70
|
+
) : provider === ModelProvider.SenseNova ? (
|
71
|
+
<SenseNovaForm />
|
69
72
|
) : provider === ModelProvider.Wenxin ? (
|
70
73
|
<WenxinForm />
|
71
74
|
) : (
|
@@ -25,6 +25,7 @@ import { LobeOpenAI } from './openai';
|
|
25
25
|
import { LobeOpenRouterAI } from './openrouter';
|
26
26
|
import { LobePerplexityAI } from './perplexity';
|
27
27
|
import { LobeQwenAI } from './qwen';
|
28
|
+
import { LobeSenseNovaAI } from './sensenova';
|
28
29
|
import { LobeSiliconCloudAI } from './siliconcloud';
|
29
30
|
import { LobeSparkAI } from './spark';
|
30
31
|
import { LobeStepfunAI } from './stepfun';
|
@@ -146,6 +147,7 @@ class AgentRuntime {
|
|
146
147
|
openrouter: Partial<ClientOptions>;
|
147
148
|
perplexity: Partial<ClientOptions>;
|
148
149
|
qwen: Partial<ClientOptions>;
|
150
|
+
sensenova: Partial<ClientOptions>;
|
149
151
|
siliconcloud: Partial<ClientOptions>;
|
150
152
|
spark: Partial<ClientOptions>;
|
151
153
|
stepfun: Partial<ClientOptions>;
|
@@ -314,6 +316,11 @@ class AgentRuntime {
|
|
314
316
|
runtimeModel = new LobeHunyuanAI(params.hunyuan);
|
315
317
|
break;
|
316
318
|
}
|
319
|
+
|
320
|
+
case ModelProvider.SenseNova: {
|
321
|
+
runtimeModel = await LobeSenseNovaAI.fromAPIKey(params.sensenova);
|
322
|
+
break;
|
323
|
+
}
|
317
324
|
}
|
318
325
|
|
319
326
|
return new AgentRuntime(runtimeModel);
|
@@ -1,6 +1,5 @@
|
|
1
1
|
// @vitest-environment edge-runtime
|
2
|
-
import {
|
3
|
-
import { JSONSchema7 } from 'json-schema';
|
2
|
+
import { FunctionDeclarationsTool } from '@google/generative-ai';
|
4
3
|
import OpenAI from 'openai';
|
5
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
6
5
|
|
@@ -479,10 +478,10 @@ describe('LobeGoogleAI', () => {
|
|
479
478
|
name: 'testTool',
|
480
479
|
description: 'A test tool',
|
481
480
|
parameters: {
|
482
|
-
type:
|
481
|
+
type: 'object',
|
483
482
|
properties: {
|
484
|
-
param1: { type:
|
485
|
-
param2: { type:
|
483
|
+
param1: { type: 'string' },
|
484
|
+
param2: { type: 'number' },
|
486
485
|
},
|
487
486
|
required: ['param1'],
|
488
487
|
},
|
@@ -490,92 +489,6 @@ describe('LobeGoogleAI', () => {
|
|
490
489
|
});
|
491
490
|
});
|
492
491
|
|
493
|
-
describe('convertSchemaObject', () => {
|
494
|
-
it('should correctly convert object schema', () => {
|
495
|
-
const schema: JSONSchema7 = {
|
496
|
-
type: 'object',
|
497
|
-
properties: {
|
498
|
-
prop1: { type: 'string' },
|
499
|
-
prop2: { type: 'number' },
|
500
|
-
},
|
501
|
-
};
|
502
|
-
|
503
|
-
const converted = instance['convertSchemaObject'](schema);
|
504
|
-
|
505
|
-
expect(converted).toEqual({
|
506
|
-
type: FunctionDeclarationSchemaType.OBJECT,
|
507
|
-
properties: {
|
508
|
-
prop1: { type: FunctionDeclarationSchemaType.STRING },
|
509
|
-
prop2: { type: FunctionDeclarationSchemaType.NUMBER },
|
510
|
-
},
|
511
|
-
});
|
512
|
-
});
|
513
|
-
|
514
|
-
it('should correctly convert nested schema', () => {
|
515
|
-
const schema: JSONSchema7 = {
|
516
|
-
type: 'object',
|
517
|
-
properties: {
|
518
|
-
nested: {
|
519
|
-
type: 'array',
|
520
|
-
items: {
|
521
|
-
type: 'object',
|
522
|
-
properties: {
|
523
|
-
prop: { type: 'string' },
|
524
|
-
},
|
525
|
-
},
|
526
|
-
},
|
527
|
-
},
|
528
|
-
};
|
529
|
-
|
530
|
-
const converted = instance['convertSchemaObject'](schema);
|
531
|
-
|
532
|
-
expect(converted).toEqual({
|
533
|
-
type: FunctionDeclarationSchemaType.OBJECT,
|
534
|
-
properties: {
|
535
|
-
nested: {
|
536
|
-
type: FunctionDeclarationSchemaType.ARRAY,
|
537
|
-
items: {
|
538
|
-
type: FunctionDeclarationSchemaType.OBJECT,
|
539
|
-
properties: {
|
540
|
-
prop: { type: FunctionDeclarationSchemaType.STRING },
|
541
|
-
},
|
542
|
-
},
|
543
|
-
},
|
544
|
-
},
|
545
|
-
});
|
546
|
-
});
|
547
|
-
|
548
|
-
it('should correctly convert array schema', () => {
|
549
|
-
const schema: JSONSchema7 = {
|
550
|
-
type: 'array',
|
551
|
-
items: { type: 'string' },
|
552
|
-
};
|
553
|
-
const converted = instance['convertSchemaObject'](schema);
|
554
|
-
expect(converted).toEqual({
|
555
|
-
type: FunctionDeclarationSchemaType.ARRAY,
|
556
|
-
items: { type: FunctionDeclarationSchemaType.STRING },
|
557
|
-
});
|
558
|
-
});
|
559
|
-
|
560
|
-
it('should correctly convert string schema', () => {
|
561
|
-
const schema: JSONSchema7 = { type: 'string' };
|
562
|
-
const converted = instance['convertSchemaObject'](schema);
|
563
|
-
expect(converted).toEqual({ type: FunctionDeclarationSchemaType.STRING });
|
564
|
-
});
|
565
|
-
|
566
|
-
it('should correctly convert number schema', () => {
|
567
|
-
const schema: JSONSchema7 = { type: 'number' };
|
568
|
-
const converted = instance['convertSchemaObject'](schema);
|
569
|
-
expect(converted).toEqual({ type: FunctionDeclarationSchemaType.NUMBER });
|
570
|
-
});
|
571
|
-
|
572
|
-
it('should correctly convert boolean schema', () => {
|
573
|
-
const schema: JSONSchema7 = { type: 'boolean' };
|
574
|
-
const converted = instance['convertSchemaObject'](schema);
|
575
|
-
expect(converted).toEqual({ type: FunctionDeclarationSchemaType.BOOLEAN });
|
576
|
-
});
|
577
|
-
});
|
578
|
-
|
579
492
|
describe('convertOAIMessagesToGoogleMessage', () => {
|
580
493
|
it('should correctly convert assistant message', async () => {
|
581
494
|
const message: OpenAIChatMessage = {
|
@@ -2,14 +2,11 @@ import {
|
|
2
2
|
Content,
|
3
3
|
FunctionCallPart,
|
4
4
|
FunctionDeclaration,
|
5
|
-
FunctionDeclarationSchemaProperty,
|
6
|
-
FunctionDeclarationSchemaType,
|
7
5
|
Tool as GoogleFunctionCallTool,
|
8
6
|
GoogleGenerativeAI,
|
9
7
|
Part,
|
8
|
+
SchemaType,
|
10
9
|
} from '@google/generative-ai';
|
11
|
-
import { JSONSchema7 } from 'json-schema';
|
12
|
-
import { transform } from 'lodash-es';
|
13
10
|
|
14
11
|
import { imageUrlToBase64 } from '@/utils/imageToBase64';
|
15
12
|
import { safeParseJSON } from '@/utils/safeParseJSON';
|
@@ -190,13 +187,12 @@ export class LobeGoogleAI implements LobeRuntimeAI {
|
|
190
187
|
};
|
191
188
|
};
|
192
189
|
|
193
|
-
// convert messages from the
|
194
|
-
// that is expected by the Google GenAI SDK
|
190
|
+
// convert messages from the OpenAI format to Google GenAI SDK
|
195
191
|
private buildGoogleMessages = async (
|
196
192
|
messages: OpenAIChatMessage[],
|
197
193
|
model: string,
|
198
194
|
): Promise<Content[]> => {
|
199
|
-
// if the model is gemini-1.0 we
|
195
|
+
// if the model is gemini-1.0 we need to pair messages
|
200
196
|
if (model.startsWith('gemini-1.0')) {
|
201
197
|
const contents: Content[] = [];
|
202
198
|
let lastRole = 'model';
|
@@ -298,52 +294,12 @@ export class LobeGoogleAI implements LobeRuntimeAI {
|
|
298
294
|
name: functionDeclaration.name,
|
299
295
|
parameters: {
|
300
296
|
description: parameters?.description,
|
301
|
-
properties:
|
302
|
-
result[key] = this.convertSchemaObject(value as JSONSchema7);
|
303
|
-
}),
|
297
|
+
properties: parameters?.properties,
|
304
298
|
required: parameters?.required,
|
305
|
-
type:
|
299
|
+
type: SchemaType.OBJECT,
|
306
300
|
},
|
307
301
|
};
|
308
302
|
};
|
309
|
-
|
310
|
-
private convertSchemaObject(schema: JSONSchema7): FunctionDeclarationSchemaProperty {
|
311
|
-
switch (schema.type) {
|
312
|
-
default:
|
313
|
-
case 'object': {
|
314
|
-
return {
|
315
|
-
...schema,
|
316
|
-
properties: Object.fromEntries(
|
317
|
-
Object.entries(schema.properties || {}).map(([key, value]) => [
|
318
|
-
key,
|
319
|
-
this.convertSchemaObject(value as JSONSchema7),
|
320
|
-
]),
|
321
|
-
),
|
322
|
-
type: FunctionDeclarationSchemaType.OBJECT,
|
323
|
-
} as any;
|
324
|
-
}
|
325
|
-
|
326
|
-
case 'array': {
|
327
|
-
return {
|
328
|
-
...schema,
|
329
|
-
items: this.convertSchemaObject(schema.items as JSONSchema7),
|
330
|
-
type: FunctionDeclarationSchemaType.ARRAY,
|
331
|
-
} as any;
|
332
|
-
}
|
333
|
-
|
334
|
-
case 'string': {
|
335
|
-
return { ...schema, type: FunctionDeclarationSchemaType.STRING } as any;
|
336
|
-
}
|
337
|
-
|
338
|
-
case 'number': {
|
339
|
-
return { ...schema, type: FunctionDeclarationSchemaType.NUMBER } as any;
|
340
|
-
}
|
341
|
-
|
342
|
-
case 'boolean': {
|
343
|
-
return { ...schema, type: FunctionDeclarationSchemaType.BOOLEAN } as any;
|
344
|
-
}
|
345
|
-
}
|
346
|
-
}
|
347
303
|
}
|
348
304
|
|
349
305
|
export default LobeGoogleAI;
|