@lobehub/lobehub 2.0.0-next.155 → 2.0.0-next.157
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/changelog/v1.json +18 -0
- package/package.json +4 -4
- package/packages/model-bank/src/aiModels/cerebras.ts +22 -48
- package/packages/model-bank/src/aiModels/infiniai.ts +62 -0
- package/packages/model-bank/src/aiModels/minimax.ts +23 -11
- package/packages/model-bank/src/aiModels/moonshot.ts +3 -24
- package/packages/model-bank/src/aiModels/openai.ts +0 -23
- package/packages/model-bank/src/aiModels/qwen.ts +26 -27
- package/packages/model-bank/src/aiModels/siliconcloud.ts +46 -0
- package/packages/model-bank/src/aiModels/spark.ts +17 -16
- package/packages/model-bank/src/aiModels/volcengine.ts +53 -0
- package/packages/model-bank/src/aiModels/wenxin.ts +49 -1
- package/packages/model-runtime/src/core/RouterRuntime/createRuntime.ts +2 -2
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +44 -2
- package/packages/model-runtime/src/providers/minimax/index.ts +1 -11
- package/packages/model-runtime/src/providers/spark/index.test.ts +12 -11
- package/packages/model-runtime/src/providers/spark/index.ts +19 -4
- package/packages/model-runtime/src/providers/volcengine/index.test.ts +0 -14
- package/packages/model-runtime/src/providers/volcengine/index.ts +1 -24
- package/packages/types/src/tool/builtin.ts +6 -6
- package/scripts/migrateServerDB/index.ts +10 -3
- package/src/config/modelProviders/spark.ts +0 -3
- package/src/config/modelProviders/volcengine.ts +2 -1
- package/src/store/aiInfra/store.ts +2 -2
- package/src/store/chat/store.ts +2 -2
- package/src/store/discover/store.ts +2 -2
- package/src/store/electron/store.ts +2 -2
- package/src/store/file/store.ts +2 -2
- package/src/store/global/store.ts +2 -2
- package/src/store/knowledgeBase/store.ts +2 -2
- package/src/store/serverConfig/store.ts +2 -2
- package/src/store/session/store.ts +2 -2
- package/src/store/tool/store.ts +2 -2
- package/src/store/user/store.ts +2 -2
|
@@ -3,22 +3,25 @@ import { AIChatModelCard } from '../types/aiModel';
|
|
|
3
3
|
const sparkChatModels: AIChatModelCard[] = [
|
|
4
4
|
{
|
|
5
5
|
abilities: {
|
|
6
|
+
functionCall: true,
|
|
6
7
|
reasoning: true,
|
|
7
8
|
search: true,
|
|
8
9
|
},
|
|
9
|
-
contextWindowTokens:
|
|
10
|
+
contextWindowTokens: 65_535,
|
|
10
11
|
description:
|
|
11
|
-
'
|
|
12
|
-
displayName: 'Spark X1',
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
'X1.5能力介绍:(1)新增动态调整思考模式,通过thinking 字段控制;(2)上下文长度增大:输入、输出各64K;(3)支持FunctionCall功能。',
|
|
13
|
+
displayName: 'Spark X1.5',
|
|
14
|
+
enabled: true,
|
|
15
|
+
id: 'spark-x',
|
|
16
|
+
maxOutput: 65_535,
|
|
15
17
|
settings: {
|
|
18
|
+
extendParams: ['thinking'],
|
|
16
19
|
searchImpl: 'params',
|
|
17
20
|
},
|
|
18
21
|
type: 'chat',
|
|
19
22
|
},
|
|
20
23
|
{
|
|
21
|
-
contextWindowTokens: 8192,
|
|
24
|
+
contextWindowTokens: 8192 + 4096,
|
|
22
25
|
description:
|
|
23
26
|
'Spark Lite 是一款轻量级大语言模型,具备极低的延迟与高效的处理能力,完全免费开放,支持实时在线搜索功能。其快速响应的特性使其在低算力设备上的推理应用和模型微调中表现出色,为用户带来出色的成本效益和智能体验,尤其在知识问答、内容生成及搜索场景下表现不俗。',
|
|
24
27
|
displayName: 'Spark Lite',
|
|
@@ -31,11 +34,10 @@ const sparkChatModels: AIChatModelCard[] = [
|
|
|
31
34
|
abilities: {
|
|
32
35
|
search: true,
|
|
33
36
|
},
|
|
34
|
-
contextWindowTokens: 8192,
|
|
37
|
+
contextWindowTokens: 8192 + 8192,
|
|
35
38
|
description:
|
|
36
39
|
'Spark Pro 是一款为专业领域优化的高性能大语言模型,专注数学、编程、医疗、教育等多个领域,并支持联网搜索及内置天气、日期等插件。其优化后模型在复杂知识问答、语言理解及高层次文本创作中展现出色表现和高效性能,是适合专业应用场景的理想选择。',
|
|
37
40
|
displayName: 'Spark Pro',
|
|
38
|
-
enabled: true,
|
|
39
41
|
id: 'generalv3',
|
|
40
42
|
maxOutput: 8192,
|
|
41
43
|
settings: {
|
|
@@ -49,7 +51,7 @@ const sparkChatModels: AIChatModelCard[] = [
|
|
|
49
51
|
'Spark Pro 128K 配置了特大上下文处理能力,能够处理多达128K的上下文信息,特别适合需通篇分析和长期逻辑关联处理的长文内容,可在复杂文本沟通中提供流畅一致的逻辑与多样的引用支持。',
|
|
50
52
|
displayName: 'Spark Pro 128K',
|
|
51
53
|
id: 'pro-128k',
|
|
52
|
-
maxOutput:
|
|
54
|
+
maxOutput: 131_072,
|
|
53
55
|
type: 'chat',
|
|
54
56
|
},
|
|
55
57
|
{
|
|
@@ -57,11 +59,10 @@ const sparkChatModels: AIChatModelCard[] = [
|
|
|
57
59
|
functionCall: true,
|
|
58
60
|
search: true,
|
|
59
61
|
},
|
|
60
|
-
contextWindowTokens: 8192,
|
|
62
|
+
contextWindowTokens: 8192 + 8192,
|
|
61
63
|
description:
|
|
62
64
|
'Spark Max 为功能最为全面的版本,支持联网搜索及众多内置插件。其全面优化的核心能力以及系统角色设定和函数调用功能,使其在各种复杂应用场景中的表现极为优异和出色。',
|
|
63
65
|
displayName: 'Spark Max',
|
|
64
|
-
enabled: true,
|
|
65
66
|
id: 'generalv3.5',
|
|
66
67
|
maxOutput: 8192,
|
|
67
68
|
settings: {
|
|
@@ -74,12 +75,12 @@ const sparkChatModels: AIChatModelCard[] = [
|
|
|
74
75
|
functionCall: true,
|
|
75
76
|
search: true,
|
|
76
77
|
},
|
|
77
|
-
contextWindowTokens: 32_768,
|
|
78
|
+
contextWindowTokens: 32_768 + 32_768,
|
|
78
79
|
description:
|
|
79
80
|
'Spark Max 32K 配置了大上下文处理能力,更强的上下文理解和逻辑推理能力,支持32K tokens的文本输入,适用于长文档阅读、私有知识问答等场景',
|
|
80
81
|
displayName: 'Spark Max 32K',
|
|
81
82
|
id: 'max-32k',
|
|
82
|
-
maxOutput:
|
|
83
|
+
maxOutput: 32_768,
|
|
83
84
|
settings: {
|
|
84
85
|
searchImpl: 'internal',
|
|
85
86
|
},
|
|
@@ -88,15 +89,15 @@ const sparkChatModels: AIChatModelCard[] = [
|
|
|
88
89
|
{
|
|
89
90
|
abilities: {
|
|
90
91
|
functionCall: true,
|
|
92
|
+
reasoning: true,
|
|
91
93
|
search: true,
|
|
92
94
|
},
|
|
93
|
-
contextWindowTokens:
|
|
95
|
+
contextWindowTokens: 32_768 + 32_768,
|
|
94
96
|
description:
|
|
95
97
|
'Spark Ultra 是星火大模型系列中最为强大的版本,在升级联网搜索链路同时,提升对文本内容的理解和总结能力。它是用于提升办公生产力和准确响应需求的全方位解决方案,是引领行业的智能产品。',
|
|
96
98
|
displayName: 'Spark 4.0 Ultra',
|
|
97
|
-
enabled: true,
|
|
98
99
|
id: '4.0Ultra',
|
|
99
|
-
maxOutput:
|
|
100
|
+
maxOutput: 32_768,
|
|
100
101
|
settings: {
|
|
101
102
|
searchImpl: 'params',
|
|
102
103
|
},
|
|
@@ -3,6 +3,59 @@ import { AIChatModelCard, AIImageModelCard } from '../types/aiModel';
|
|
|
3
3
|
// https://www.volcengine.com/docs/82379/1330310
|
|
4
4
|
|
|
5
5
|
const doubaoChatModels: AIChatModelCard[] = [
|
|
6
|
+
{
|
|
7
|
+
abilities: {
|
|
8
|
+
functionCall: true,
|
|
9
|
+
reasoning: true,
|
|
10
|
+
vision: true,
|
|
11
|
+
},
|
|
12
|
+
config: {
|
|
13
|
+
deploymentName: 'doubao-seed-code-preview-251028',
|
|
14
|
+
},
|
|
15
|
+
contextWindowTokens: 256_000,
|
|
16
|
+
description:
|
|
17
|
+
'Doubao-Seed-Code 面向 Agentic 编程任务进行了深度优化,支持多模态(文字/图片/视频)与 256k 长上下文,兼容 Anthropic API,适用于编程、视觉理解与 Agent 场景。',
|
|
18
|
+
displayName: 'Doubao Seed Code',
|
|
19
|
+
id: 'doubao-seed-code',
|
|
20
|
+
maxOutput: 32_000,
|
|
21
|
+
pricing: {
|
|
22
|
+
currency: 'CNY',
|
|
23
|
+
units: [
|
|
24
|
+
{
|
|
25
|
+
lookup: {
|
|
26
|
+
prices: {
|
|
27
|
+
'[0, 0.032]': 1.2,
|
|
28
|
+
'[0.032, 0.128]': 1.4,
|
|
29
|
+
'[0.128, 0.256]': 2.8,
|
|
30
|
+
},
|
|
31
|
+
pricingParams: ['textInputRange'],
|
|
32
|
+
},
|
|
33
|
+
name: 'textInput',
|
|
34
|
+
strategy: 'lookup',
|
|
35
|
+
unit: 'millionTokens',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
lookup: {
|
|
39
|
+
prices: {
|
|
40
|
+
'[0, 0.032]': 8,
|
|
41
|
+
'[0.032, 0.128]': 12,
|
|
42
|
+
'[0.128, 0.256]': 16,
|
|
43
|
+
},
|
|
44
|
+
pricingParams: ['textInputRange'],
|
|
45
|
+
},
|
|
46
|
+
name: 'textOutput',
|
|
47
|
+
strategy: 'lookup',
|
|
48
|
+
unit: 'millionTokens',
|
|
49
|
+
},
|
|
50
|
+
{ name: 'textInput_cacheRead', rate: 0.24, strategy: 'fixed', unit: 'millionTokens' },
|
|
51
|
+
{ name: 'textInput_cacheWrite', rate: 0.017, strategy: 'fixed', unit: 'millionTokens' },
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
settings: {
|
|
55
|
+
extendParams: ['enableReasoning'],
|
|
56
|
+
},
|
|
57
|
+
type: 'chat',
|
|
58
|
+
},
|
|
6
59
|
{
|
|
7
60
|
abilities: {
|
|
8
61
|
functionCall: true,
|
|
@@ -3,6 +3,55 @@ import { AIChatModelCard, AIImageModelCard } from '../types/aiModel';
|
|
|
3
3
|
// https://cloud.baidu.com/doc/qianfan/s/rmh4stp0j
|
|
4
4
|
|
|
5
5
|
const wenxinChatModels: AIChatModelCard[] = [
|
|
6
|
+
{
|
|
7
|
+
abilities: {
|
|
8
|
+
functionCall: true,
|
|
9
|
+
reasoning: true,
|
|
10
|
+
search: true,
|
|
11
|
+
vision: true,
|
|
12
|
+
},
|
|
13
|
+
contextWindowTokens: 131_072,
|
|
14
|
+
description:
|
|
15
|
+
'文心5.0 Thinking,原生全模态旗舰模型,支持文本、图像、音频、视频统一建模,综合能力全面升级,适用于复杂问答、创作与智能体场景。',
|
|
16
|
+
displayName: 'ERNIE 5.0 Thinking',
|
|
17
|
+
enabled: true,
|
|
18
|
+
id: 'ernie-5.0-thinking-latest',
|
|
19
|
+
maxOutput: 65_536,
|
|
20
|
+
pricing: {
|
|
21
|
+
currency: 'CNY',
|
|
22
|
+
units: [
|
|
23
|
+
{
|
|
24
|
+
lookup: {
|
|
25
|
+
prices: {
|
|
26
|
+
'[0, 0.032]': 6,
|
|
27
|
+
'[0.032, 0.128]': 10,
|
|
28
|
+
},
|
|
29
|
+
pricingParams: ['textInput'],
|
|
30
|
+
},
|
|
31
|
+
name: 'textInput',
|
|
32
|
+
strategy: 'lookup',
|
|
33
|
+
unit: 'millionTokens',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
lookup: {
|
|
37
|
+
prices: {
|
|
38
|
+
'[0, 0.032]': 24,
|
|
39
|
+
'[0.032, 0.128]': 40,
|
|
40
|
+
},
|
|
41
|
+
pricingParams: ['textInput'],
|
|
42
|
+
},
|
|
43
|
+
name: 'textOutput',
|
|
44
|
+
strategy: 'lookup',
|
|
45
|
+
unit: 'millionTokens',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
releasedAt: '2025-11-12',
|
|
50
|
+
settings: {
|
|
51
|
+
searchImpl: 'params',
|
|
52
|
+
},
|
|
53
|
+
type: 'chat',
|
|
54
|
+
},
|
|
6
55
|
{
|
|
7
56
|
abilities: {
|
|
8
57
|
functionCall: true,
|
|
@@ -14,7 +63,6 @@ const wenxinChatModels: AIChatModelCard[] = [
|
|
|
14
63
|
description:
|
|
15
64
|
'文心5.0 Thinking 预览版,原生全模态旗舰模型,支持文本、图像、音频、视频统一建模,综合能力全面升级,适用于复杂问答、创作与智能体场景。',
|
|
16
65
|
displayName: 'ERNIE 5.0 Thinking Preview',
|
|
17
|
-
enabled: true,
|
|
18
66
|
id: 'ernie-5.0-thinking-preview',
|
|
19
67
|
maxOutput: 65_536,
|
|
20
68
|
pricing: {
|
|
@@ -124,7 +124,7 @@ export interface CreateRouterRuntimeOptions<T extends Record<string, any> = any>
|
|
|
124
124
|
export const createRouterRuntime = ({
|
|
125
125
|
id,
|
|
126
126
|
routers,
|
|
127
|
-
apiKey:
|
|
127
|
+
apiKey: DEFAULT_API_KEY,
|
|
128
128
|
models: modelsOption,
|
|
129
129
|
...params
|
|
130
130
|
}: CreateRouterRuntimeOptions) => {
|
|
@@ -137,7 +137,7 @@ export const createRouterRuntime = ({
|
|
|
137
137
|
constructor(options: ClientOptions & Record<string, any> = {}) {
|
|
138
138
|
this._options = {
|
|
139
139
|
...options,
|
|
140
|
-
apiKey: options.apiKey?.trim() ||
|
|
140
|
+
apiKey: options.apiKey?.trim() || DEFAULT_API_KEY,
|
|
141
141
|
baseURL: options.baseURL?.trim(),
|
|
142
142
|
};
|
|
143
143
|
|
|
@@ -154,7 +154,7 @@ export interface OpenAICompatibleFactoryOptions<T extends Record<string, any> =
|
|
|
154
154
|
export const createOpenAICompatibleRuntime = <T extends Record<string, any> = any>({
|
|
155
155
|
provider,
|
|
156
156
|
baseURL: DEFAULT_BASE_URL,
|
|
157
|
-
apiKey:
|
|
157
|
+
apiKey: DEFAULT_API_KEY,
|
|
158
158
|
errorType,
|
|
159
159
|
debug: debugParams,
|
|
160
160
|
constructorOptions,
|
|
@@ -182,7 +182,7 @@ export const createOpenAICompatibleRuntime = <T extends Record<string, any> = an
|
|
|
182
182
|
constructor(options: ClientOptions & Record<string, any> = {}) {
|
|
183
183
|
const _options = {
|
|
184
184
|
...options,
|
|
185
|
-
apiKey: options.apiKey?.trim() ||
|
|
185
|
+
apiKey: options.apiKey?.trim() || DEFAULT_API_KEY,
|
|
186
186
|
baseURL: options.baseURL?.trim() || DEFAULT_BASE_URL,
|
|
187
187
|
};
|
|
188
188
|
const { apiKey, baseURL = DEFAULT_BASE_URL, ...res } = _options;
|
|
@@ -346,6 +346,48 @@ export const createOpenAICompatibleRuntime = <T extends Record<string, any> = an
|
|
|
346
346
|
return this.handleResponseAPIMode(processedPayload, options);
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
+
const computedBaseURL =
|
|
350
|
+
typeof this._options.baseURL === 'string' && this._options.baseURL
|
|
351
|
+
? this._options.baseURL.trim()
|
|
352
|
+
: typeof DEFAULT_BASE_URL === 'string'
|
|
353
|
+
? DEFAULT_BASE_URL
|
|
354
|
+
: undefined;
|
|
355
|
+
const targetBaseURL = computedBaseURL || this.baseURL;
|
|
356
|
+
|
|
357
|
+
if (targetBaseURL !== this.baseURL) {
|
|
358
|
+
const restOptions = {
|
|
359
|
+
...(this._options as ConstructorOptions<T> & Record<string, any>),
|
|
360
|
+
} as Record<string, any>;
|
|
361
|
+
const optionApiKey = restOptions.apiKey;
|
|
362
|
+
delete restOptions.apiKey;
|
|
363
|
+
delete restOptions.baseURL;
|
|
364
|
+
|
|
365
|
+
const sanitizedApiKey = optionApiKey?.toString().trim() || DEFAULT_API_KEY;
|
|
366
|
+
|
|
367
|
+
const nextOptions = {
|
|
368
|
+
...restOptions,
|
|
369
|
+
apiKey: sanitizedApiKey,
|
|
370
|
+
baseURL: targetBaseURL,
|
|
371
|
+
} as ConstructorOptions<T>;
|
|
372
|
+
|
|
373
|
+
const initOptions = {
|
|
374
|
+
apiKey: sanitizedApiKey,
|
|
375
|
+
baseURL: targetBaseURL,
|
|
376
|
+
...constructorOptions,
|
|
377
|
+
...restOptions,
|
|
378
|
+
} as ConstructorOptions<T> & Record<string, any>;
|
|
379
|
+
|
|
380
|
+
this._options = nextOptions;
|
|
381
|
+
|
|
382
|
+
if (customClient?.createClient) {
|
|
383
|
+
this.client = customClient.createClient(initOptions);
|
|
384
|
+
} else {
|
|
385
|
+
this.client = new OpenAI(initOptions);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
this.baseURL = targetBaseURL;
|
|
389
|
+
}
|
|
390
|
+
|
|
349
391
|
const messages = await convertOpenAIMessages(postPayload.messages);
|
|
350
392
|
|
|
351
393
|
let response: Stream<OpenAI.Chat.Completions.ChatCompletionChunk>;
|
|
@@ -13,16 +13,7 @@ export const LobeMinimaxAI = createOpenAICompatibleRuntime({
|
|
|
13
13
|
baseURL: 'https://api.minimaxi.com/v1',
|
|
14
14
|
chatCompletion: {
|
|
15
15
|
handlePayload: (payload) => {
|
|
16
|
-
const { enabledSearch, max_tokens, messages, temperature,
|
|
17
|
-
|
|
18
|
-
const minimaxTools = enabledSearch
|
|
19
|
-
? [
|
|
20
|
-
...(tools || []),
|
|
21
|
-
{
|
|
22
|
-
type: 'web_search',
|
|
23
|
-
},
|
|
24
|
-
]
|
|
25
|
-
: tools;
|
|
16
|
+
const { enabledSearch, max_tokens, messages, temperature, top_p, ...params } = payload;
|
|
26
17
|
|
|
27
18
|
// Interleaved thinking
|
|
28
19
|
const processedMessages = messages.map((message: any) => {
|
|
@@ -77,7 +68,6 @@ export const LobeMinimaxAI = createOpenAICompatibleRuntime({
|
|
|
77
68
|
messages: processedMessages,
|
|
78
69
|
reasoning_split: true,
|
|
79
70
|
temperature: finalTemperature,
|
|
80
|
-
tools: minimaxTools,
|
|
81
71
|
top_p: resolvedParams.top_p,
|
|
82
72
|
} as any;
|
|
83
73
|
},
|
|
@@ -16,6 +16,7 @@ testProvider({
|
|
|
16
16
|
chatModel: 'spark',
|
|
17
17
|
test: {
|
|
18
18
|
skipAPICall: true,
|
|
19
|
+
skipErrorHandle: true,
|
|
19
20
|
},
|
|
20
21
|
});
|
|
21
22
|
|
|
@@ -69,7 +70,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
69
70
|
enabledSearch: false,
|
|
70
71
|
};
|
|
71
72
|
|
|
72
|
-
const result = handlePayload(payload);
|
|
73
|
+
const result = handlePayload(payload, {});
|
|
73
74
|
|
|
74
75
|
expect(result.tools).toBeUndefined();
|
|
75
76
|
expect(result.enabledSearch).toBeUndefined();
|
|
@@ -81,7 +82,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
81
82
|
messages: [{ role: 'user' as const, content: 'Hello' }],
|
|
82
83
|
};
|
|
83
84
|
|
|
84
|
-
const result = handlePayload(payload);
|
|
85
|
+
const result = handlePayload(payload, {});
|
|
85
86
|
|
|
86
87
|
expect(result.tools).toBeUndefined();
|
|
87
88
|
});
|
|
@@ -93,7 +94,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
93
94
|
enabledSearch: true,
|
|
94
95
|
};
|
|
95
96
|
|
|
96
|
-
const result = handlePayload(payload);
|
|
97
|
+
const result = handlePayload(payload, {});
|
|
97
98
|
|
|
98
99
|
expect(result.tools).toBeDefined();
|
|
99
100
|
expect(result.tools).toHaveLength(1);
|
|
@@ -115,7 +116,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
115
116
|
enabledSearch: true,
|
|
116
117
|
};
|
|
117
118
|
|
|
118
|
-
const result = handlePayload(payload);
|
|
119
|
+
const result = handlePayload(payload, {});
|
|
119
120
|
|
|
120
121
|
expect(result.tools[0].web_search.search_mode).toBe('normal');
|
|
121
122
|
});
|
|
@@ -129,7 +130,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
129
130
|
enabledSearch: true,
|
|
130
131
|
};
|
|
131
132
|
|
|
132
|
-
const result = handlePayload(payload);
|
|
133
|
+
const result = handlePayload(payload, {});
|
|
133
134
|
|
|
134
135
|
expect(result.tools[0].web_search.search_mode).toBe('deep');
|
|
135
136
|
delete process.env.SPARK_SEARCH_MODE;
|
|
@@ -154,7 +155,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
154
155
|
tools: existingTools,
|
|
155
156
|
};
|
|
156
157
|
|
|
157
|
-
const result = handlePayload(payload);
|
|
158
|
+
const result = handlePayload(payload, {});
|
|
158
159
|
|
|
159
160
|
expect(result.tools).toHaveLength(2);
|
|
160
161
|
expect(result.tools[0]).toEqual(existingTools[0]);
|
|
@@ -180,7 +181,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
180
181
|
tools: existingTools,
|
|
181
182
|
};
|
|
182
183
|
|
|
183
|
-
const result = handlePayload(payload);
|
|
184
|
+
const result = handlePayload(payload, {});
|
|
184
185
|
|
|
185
186
|
expect(result.tools).toEqual(existingTools);
|
|
186
187
|
});
|
|
@@ -192,7 +193,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
192
193
|
enabledSearch: true,
|
|
193
194
|
};
|
|
194
195
|
|
|
195
|
-
const result = handlePayload(payload);
|
|
196
|
+
const result = handlePayload(payload, {});
|
|
196
197
|
|
|
197
198
|
expect(result.enabledSearch).toBeUndefined();
|
|
198
199
|
});
|
|
@@ -207,7 +208,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
207
208
|
enabledSearch: true,
|
|
208
209
|
};
|
|
209
210
|
|
|
210
|
-
const result = handlePayload(payload);
|
|
211
|
+
const result = handlePayload(payload, {});
|
|
211
212
|
|
|
212
213
|
expect(result.model).toBe('spark');
|
|
213
214
|
expect(result.messages).toEqual(payload.messages);
|
|
@@ -224,7 +225,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
224
225
|
tools: [],
|
|
225
226
|
};
|
|
226
227
|
|
|
227
|
-
const result = handlePayload(payload);
|
|
228
|
+
const result = handlePayload(payload, {});
|
|
228
229
|
|
|
229
230
|
expect(result.tools).toHaveLength(1);
|
|
230
231
|
expect(result.tools[0].type).toBe('web_search');
|
|
@@ -257,7 +258,7 @@ describe('LobeSparkAI - custom features', () => {
|
|
|
257
258
|
tools: existingTools,
|
|
258
259
|
};
|
|
259
260
|
|
|
260
|
-
const result = handlePayload(payload);
|
|
261
|
+
const result = handlePayload(payload, {});
|
|
261
262
|
|
|
262
263
|
expect(result.tools).toHaveLength(3);
|
|
263
264
|
expect(result.tools[0]).toEqual(existingTools[0]);
|
|
@@ -7,11 +7,25 @@ import {
|
|
|
7
7
|
import { SparkAIStream, transformSparkResponseToStream } from '../../core/streams';
|
|
8
8
|
import { ChatStreamPayload } from '../../types';
|
|
9
9
|
|
|
10
|
+
const getBaseURLByModel = (model: string): string => {
|
|
11
|
+
if (model.includes('x1-preview')) {
|
|
12
|
+
return 'https://spark-api-open-preview.xf-yun.com/v2';
|
|
13
|
+
}
|
|
14
|
+
if (model.includes('spark-x')) {
|
|
15
|
+
return 'https://spark-api-open.xf-yun.com/v2';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return 'https://spark-api-open.xf-yun.com/v1';
|
|
19
|
+
};
|
|
20
|
+
|
|
10
21
|
export const params = {
|
|
11
22
|
baseURL: 'https://spark-api-open.xf-yun.com/v1',
|
|
12
23
|
chatCompletion: {
|
|
13
|
-
handlePayload: (payload: ChatStreamPayload) => {
|
|
14
|
-
const { enabledSearch, tools, ...rest } = payload;
|
|
24
|
+
handlePayload: (payload: ChatStreamPayload, options) => {
|
|
25
|
+
const { enabledSearch, thinking, tools, ...rest } = payload;
|
|
26
|
+
|
|
27
|
+
const baseURL = getBaseURLByModel(payload.model);
|
|
28
|
+
if (options) options.baseURL = baseURL;
|
|
15
29
|
|
|
16
30
|
const sparkTools = enabledSearch
|
|
17
31
|
? [
|
|
@@ -22,8 +36,8 @@ export const params = {
|
|
|
22
36
|
enable: true,
|
|
23
37
|
search_mode: process.env.SPARK_SEARCH_MODE || 'normal', // normal or deep
|
|
24
38
|
/*
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
show_ref_label: true,
|
|
40
|
+
*/
|
|
27
41
|
},
|
|
28
42
|
},
|
|
29
43
|
]
|
|
@@ -31,6 +45,7 @@ export const params = {
|
|
|
31
45
|
|
|
32
46
|
return {
|
|
33
47
|
...rest,
|
|
48
|
+
thinking: { type: thinking?.type },
|
|
34
49
|
tools: sparkTools,
|
|
35
50
|
} as any;
|
|
36
51
|
},
|
|
@@ -57,19 +57,5 @@ describe('LobeVolcengineAI - custom features', () => {
|
|
|
57
57
|
const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];
|
|
58
58
|
expect(calledPayload.thinking).toEqual({ type: 'enabled' });
|
|
59
59
|
});
|
|
60
|
-
|
|
61
|
-
it('should not add thinking for non-thinking models', async () => {
|
|
62
|
-
await instance.chat({
|
|
63
|
-
messages: [{ content: 'Hello', role: 'user' }],
|
|
64
|
-
model: 'doubao-pro-32k',
|
|
65
|
-
thinking: {
|
|
66
|
-
type: 'enabled',
|
|
67
|
-
budget_tokens: 1000,
|
|
68
|
-
},
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const calledPayload = (instance['client'].chat.completions.create as any).mock.calls[0][0];
|
|
72
|
-
expect(calledPayload.thinking).toBeUndefined();
|
|
73
|
-
});
|
|
74
60
|
});
|
|
75
61
|
});
|
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
import { ModelProvider } from 'model-bank';
|
|
2
2
|
|
|
3
3
|
import { createOpenAICompatibleRuntime } from '../../core/openaiCompatibleFactory';
|
|
4
|
-
import { MODEL_LIST_CONFIGS, processModelList } from '../../utils/modelParse';
|
|
5
4
|
import { createVolcengineImage } from './createImage';
|
|
6
5
|
|
|
7
|
-
const THINKING_MODELS = [
|
|
8
|
-
'thinking-vision-pro',
|
|
9
|
-
'thinking-pro-m',
|
|
10
|
-
'doubao-seed-1-6',
|
|
11
|
-
'doubao-1-5-ui-tars',
|
|
12
|
-
'deepseek-v3-1',
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
export interface VolcengineModelCard {
|
|
16
|
-
id: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
6
|
export const LobeVolcengineAI = createOpenAICompatibleRuntime({
|
|
20
7
|
baseURL: 'https://ark.cn-beijing.volces.com/api/v3',
|
|
21
8
|
chatCompletion: {
|
|
@@ -25,11 +12,7 @@ export const LobeVolcengineAI = createOpenAICompatibleRuntime({
|
|
|
25
12
|
return {
|
|
26
13
|
...rest,
|
|
27
14
|
model,
|
|
28
|
-
...(
|
|
29
|
-
? {
|
|
30
|
-
thinking: { type: thinking?.type },
|
|
31
|
-
}
|
|
32
|
-
: {}),
|
|
15
|
+
...(thinking?.type && { thinking: { type: thinking.type } }),
|
|
33
16
|
} as any;
|
|
34
17
|
},
|
|
35
18
|
},
|
|
@@ -37,11 +20,5 @@ export const LobeVolcengineAI = createOpenAICompatibleRuntime({
|
|
|
37
20
|
debug: {
|
|
38
21
|
chatCompletion: () => process.env.DEBUG_VOLCENGINE_CHAT_COMPLETION === '1',
|
|
39
22
|
},
|
|
40
|
-
models: async ({ client }) => {
|
|
41
|
-
const modelsPage = (await client.models.list()) as any;
|
|
42
|
-
const modelList: VolcengineModelCard[] = modelsPage.data;
|
|
43
|
-
|
|
44
|
-
return processModelList(modelList, MODEL_LIST_CONFIGS.volcengine, 'volcengine');
|
|
45
|
-
},
|
|
46
23
|
provider: ModelProvider.Volcengine,
|
|
47
24
|
});
|
|
@@ -8,22 +8,22 @@ interface Meta {
|
|
|
8
8
|
/**
|
|
9
9
|
* avatar
|
|
10
10
|
* @desc Avatar of the plugin
|
|
11
|
-
* @
|
|
12
|
-
* @
|
|
11
|
+
* @nameEN Avatar
|
|
12
|
+
* @descEN Plugin avatar
|
|
13
13
|
*/
|
|
14
14
|
avatar?: string;
|
|
15
15
|
/**
|
|
16
16
|
* description
|
|
17
17
|
* @desc Description of the plugin
|
|
18
|
-
* @
|
|
19
|
-
* @
|
|
18
|
+
* @nameEN Description
|
|
19
|
+
* @descEN Plugin description
|
|
20
20
|
*/
|
|
21
21
|
description?: string;
|
|
22
22
|
/**
|
|
23
23
|
* tags
|
|
24
24
|
* @desc Tags of the plugin
|
|
25
|
-
* @
|
|
26
|
-
* @
|
|
25
|
+
* @nameEN Tags
|
|
26
|
+
* @descEN Plugin tags
|
|
27
27
|
*/
|
|
28
28
|
tags?: string[];
|
|
29
29
|
title: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as dotenv from 'dotenv';
|
|
2
|
+
import dotenvExpand from 'dotenv-expand';
|
|
2
3
|
import { migrate as neonMigrate } from 'drizzle-orm/neon-serverless/migrator';
|
|
3
4
|
import { migrate as nodeMigrate } from 'drizzle-orm/node-postgres/migrator';
|
|
4
5
|
import { join } from 'node:path';
|
|
@@ -6,9 +7,15 @@ import { join } from 'node:path';
|
|
|
6
7
|
// @ts-ignore tsgo handle esm import cjs and compatibility issues
|
|
7
8
|
import { DB_FAIL_INIT_HINT, DUPLICATE_EMAIL_HINT, PGVECTOR_HINT } from './errorHint';
|
|
8
9
|
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
|
|
10
|
+
// Load environment variables in priority order:
|
|
11
|
+
// 1. .env (lowest priority)
|
|
12
|
+
// 2. .env.[env] (medium priority, overrides .env)
|
|
13
|
+
// 3. .env.[env].local (highest priority, overrides previous)
|
|
14
|
+
// Use dotenv-expand to support ${var} variable expansion
|
|
15
|
+
const env = process.env.NODE_ENV || 'development';
|
|
16
|
+
dotenvExpand.expand(dotenv.config()); // Load .env
|
|
17
|
+
dotenvExpand.expand(dotenv.config({ override: true, path: `.env.${env}` })); // Load .env.[env] and override
|
|
18
|
+
dotenvExpand.expand(dotenv.config({ override: true, path: `.env.${env}.local` })); // Load .env.[env].local and override
|
|
12
19
|
|
|
13
20
|
const migrationsFolder = join(__dirname, '../../packages/database/migrations');
|
|
14
21
|
|
|
@@ -3,7 +3,7 @@ import { ModelProviderCard } from '@/types/llm';
|
|
|
3
3
|
// ref https://www.volcengine.com/docs/82379/1330310
|
|
4
4
|
const Doubao: ModelProviderCard = {
|
|
5
5
|
chatModels: [],
|
|
6
|
-
checkModel: 'doubao-1-
|
|
6
|
+
checkModel: 'doubao-seed-1-6-flash-250828',
|
|
7
7
|
description:
|
|
8
8
|
'字节跳动推出的大模型服务的开发平台,提供功能丰富、安全以及具备价格竞争力的模型调用服务,同时提供模型数据、精调、推理、评测等端到端功能,全方位保障您的 AI 应用开发落地。',
|
|
9
9
|
id: 'volcengine',
|
|
@@ -20,6 +20,7 @@ const Doubao: ModelProviderCard = {
|
|
|
20
20
|
},
|
|
21
21
|
sdkType: 'openai',
|
|
22
22
|
showDeployName: true,
|
|
23
|
+
showModelFetcher: false,
|
|
23
24
|
},
|
|
24
25
|
url: 'https://www.volcengine.com/product/ark',
|
|
25
26
|
};
|
|
@@ -7,7 +7,7 @@ import { AIProviderStoreState, initialState } from './initialState';
|
|
|
7
7
|
import { AiModelAction, createAiModelSlice } from './slices/aiModel';
|
|
8
8
|
import { AiProviderAction, createAiProviderSlice } from './slices/aiProvider';
|
|
9
9
|
|
|
10
|
-
// ===============
|
|
10
|
+
// =============== Aggregate createStoreFn ============ //
|
|
11
11
|
|
|
12
12
|
export interface AiInfraStore extends AIProviderStoreState, AiProviderAction, AiModelAction {
|
|
13
13
|
/* empty */
|
|
@@ -19,7 +19,7 @@ const createStore: StateCreator<AiInfraStore, [['zustand/devtools', never]]> = (
|
|
|
19
19
|
...createAiProviderSlice(...parameters),
|
|
20
20
|
});
|
|
21
21
|
|
|
22
|
-
// ===============
|
|
22
|
+
// =============== Implement useStore ============ //
|
|
23
23
|
const devtools = createDevtools('aiInfra');
|
|
24
24
|
|
|
25
25
|
export const useAiInfraStore = createWithEqualityFn<AiInfraStore>()(devtools(createStore), shallow);
|
package/src/store/chat/store.ts
CHANGED
|
@@ -33,7 +33,7 @@ export interface ChatStoreAction
|
|
|
33
33
|
|
|
34
34
|
export type ChatStore = ChatStoreAction & ChatStoreState;
|
|
35
35
|
|
|
36
|
-
// ===============
|
|
36
|
+
// =============== Aggregate createStoreFn ============ //
|
|
37
37
|
|
|
38
38
|
const createStore: StateCreator<ChatStore, [['zustand/devtools', never]]> = (...params) => ({
|
|
39
39
|
...initialState,
|
|
@@ -53,7 +53,7 @@ const createStore: StateCreator<ChatStore, [['zustand/devtools', never]]> = (...
|
|
|
53
53
|
// cloud
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
// ===============
|
|
56
|
+
// =============== Implement useStore ============ //
|
|
57
57
|
const devtools = createDevtools('chat');
|
|
58
58
|
|
|
59
59
|
export const useChatStore = createWithEqualityFn<ChatStore>()(
|