@lobehub/chat 1.49.16 → 1.50.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.
- package/CHANGELOG.md +33 -0
- package/changelog/v1.json +12 -0
- package/docs/usage/agents/model.mdx +16 -0
- package/docs/usage/agents/model.zh-CN.mdx +16 -0
- package/locales/ar/discover.json +4 -0
- package/locales/ar/models.json +3 -0
- package/locales/ar/setting.json +12 -0
- package/locales/bg-BG/discover.json +4 -0
- package/locales/bg-BG/models.json +3 -0
- package/locales/bg-BG/setting.json +12 -0
- package/locales/de-DE/discover.json +4 -0
- package/locales/de-DE/models.json +3 -0
- package/locales/de-DE/setting.json +12 -0
- package/locales/en-US/discover.json +4 -0
- package/locales/en-US/models.json +3 -0
- package/locales/en-US/setting.json +12 -0
- package/locales/es-ES/discover.json +4 -0
- package/locales/es-ES/models.json +3 -0
- package/locales/es-ES/setting.json +12 -0
- package/locales/fa-IR/discover.json +4 -0
- package/locales/fa-IR/models.json +3 -0
- package/locales/fa-IR/setting.json +12 -0
- package/locales/fr-FR/discover.json +4 -0
- package/locales/fr-FR/models.json +3 -0
- package/locales/fr-FR/setting.json +12 -0
- package/locales/it-IT/discover.json +4 -0
- package/locales/it-IT/models.json +3 -0
- package/locales/it-IT/setting.json +12 -0
- package/locales/ja-JP/discover.json +4 -0
- package/locales/ja-JP/models.json +3 -0
- package/locales/ja-JP/setting.json +12 -0
- package/locales/ko-KR/discover.json +4 -0
- package/locales/ko-KR/models.json +15 -0
- package/locales/ko-KR/setting.json +12 -0
- package/locales/nl-NL/discover.json +4 -0
- package/locales/nl-NL/models.json +3 -0
- package/locales/nl-NL/setting.json +12 -0
- package/locales/pl-PL/discover.json +4 -0
- package/locales/pl-PL/models.json +3 -0
- package/locales/pl-PL/setting.json +12 -0
- package/locales/pt-BR/discover.json +4 -0
- package/locales/pt-BR/models.json +3 -0
- package/locales/pt-BR/setting.json +12 -0
- package/locales/ru-RU/discover.json +4 -0
- package/locales/ru-RU/models.json +3 -0
- package/locales/ru-RU/setting.json +12 -0
- package/locales/tr-TR/discover.json +4 -0
- package/locales/tr-TR/models.json +3 -0
- package/locales/tr-TR/setting.json +12 -0
- package/locales/vi-VN/discover.json +4 -0
- package/locales/vi-VN/models.json +3 -0
- package/locales/vi-VN/setting.json +12 -0
- package/locales/zh-CN/discover.json +4 -0
- package/locales/zh-CN/models.json +4 -1
- package/locales/zh-CN/setting.json +12 -0
- package/locales/zh-TW/discover.json +4 -0
- package/locales/zh-TW/models.json +3 -0
- package/locales/zh-TW/setting.json +12 -0
- package/package.json +1 -1
- package/src/app/(main)/discover/(detail)/model/[...slugs]/features/ParameterList/index.tsx +10 -0
- package/src/config/aiModels/github.ts +18 -7
- package/src/config/aiModels/openai.ts +35 -2
- package/src/features/AgentSetting/AgentModal/index.tsx +27 -3
- package/src/libs/agent-runtime/github/index.ts +3 -3
- package/src/libs/agent-runtime/openai/index.ts +7 -5
- package/src/libs/agent-runtime/utils/streams/openai.test.ts +202 -0
- package/src/libs/agent-runtime/utils/streams/openai.ts +9 -8
- package/src/locales/default/discover.ts +4 -0
- package/src/locales/default/setting.ts +12 -0
- package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +5 -0
- package/src/types/agent/index.ts +6 -0
- package/src/types/llm.ts +5 -0
@@ -2,7 +2,7 @@ import { LOBE_DEFAULT_MODEL_LIST } from '@/config/modelProviders';
|
|
2
2
|
import type { ChatModelCard } from '@/types/llm';
|
3
3
|
|
4
4
|
import { AgentRuntimeErrorType } from '../error';
|
5
|
-
import {
|
5
|
+
import { pruneReasoningPayload, reasoningModels } from '../openai';
|
6
6
|
import { ModelProvider } from '../types';
|
7
7
|
import {
|
8
8
|
CHAT_MODELS_BLOCK_LIST,
|
@@ -37,8 +37,8 @@ export const LobeGithubAI = LobeOpenAICompatibleFactory({
|
|
37
37
|
handlePayload: (payload) => {
|
38
38
|
const { model } = payload;
|
39
39
|
|
40
|
-
if (
|
41
|
-
return { ...
|
40
|
+
if (reasoningModels.has(model)) {
|
41
|
+
return { ...pruneReasoningPayload(payload), stream: false } as any;
|
42
42
|
}
|
43
43
|
|
44
44
|
return { ...payload, stream: payload.stream ?? true };
|
@@ -2,21 +2,23 @@ import { ChatStreamPayload, ModelProvider, OpenAIChatMessage } from '../types';
|
|
2
2
|
import { LobeOpenAICompatibleFactory } from '../utils/openaiCompatibleFactory';
|
3
3
|
|
4
4
|
// TODO: 临时写法,后续要重构成 model card 展示配置
|
5
|
-
export const
|
5
|
+
export const reasoningModels = new Set([
|
6
6
|
'o1-preview',
|
7
7
|
'o1-preview-2024-09-12',
|
8
8
|
'o1-mini',
|
9
9
|
'o1-mini-2024-09-12',
|
10
10
|
'o1',
|
11
11
|
'o1-2024-12-17',
|
12
|
+
'o3-mini',
|
13
|
+
'o3-mini-2025-01-31',
|
12
14
|
]);
|
13
15
|
|
14
|
-
export const
|
16
|
+
export const pruneReasoningPayload = (payload: ChatStreamPayload) => ({
|
15
17
|
...payload,
|
16
18
|
frequency_penalty: 0,
|
17
19
|
messages: payload.messages.map((message: OpenAIChatMessage) => ({
|
18
20
|
...message,
|
19
|
-
role: message.role === 'system' ? '
|
21
|
+
role: message.role === 'system' ? 'developer' : message.role,
|
20
22
|
})),
|
21
23
|
presence_penalty: 0,
|
22
24
|
temperature: 1,
|
@@ -29,8 +31,8 @@ export const LobeOpenAI = LobeOpenAICompatibleFactory({
|
|
29
31
|
handlePayload: (payload) => {
|
30
32
|
const { model } = payload;
|
31
33
|
|
32
|
-
if (
|
33
|
-
return
|
34
|
+
if (reasoningModels.has(model)) {
|
35
|
+
return pruneReasoningPayload(payload) as any;
|
34
36
|
}
|
35
37
|
|
36
38
|
return { ...payload, stream: payload.stream ?? true };
|
@@ -754,6 +754,7 @@ describe('OpenAIStream', () => {
|
|
754
754
|
].map((i) => `${i}\n`),
|
755
755
|
);
|
756
756
|
});
|
757
|
+
|
757
758
|
it('should handle reasoning in litellm', async () => {
|
758
759
|
const data = [
|
759
760
|
{
|
@@ -954,5 +955,206 @@ describe('OpenAIStream', () => {
|
|
954
955
|
].map((i) => `${i}\n`),
|
955
956
|
);
|
956
957
|
});
|
958
|
+
|
959
|
+
it('should handle reasoning in siliconflow', async () => {
|
960
|
+
const data = [
|
961
|
+
{
|
962
|
+
id: '1',
|
963
|
+
object: 'chat.completion.chunk',
|
964
|
+
created: 1737563070,
|
965
|
+
model: 'deepseek-reasoner',
|
966
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
967
|
+
choices: [
|
968
|
+
{
|
969
|
+
index: 0,
|
970
|
+
delta: { role: 'assistant', reasoning_content: '', content: '' },
|
971
|
+
logprobs: null,
|
972
|
+
finish_reason: null,
|
973
|
+
},
|
974
|
+
],
|
975
|
+
},
|
976
|
+
{
|
977
|
+
id: '1',
|
978
|
+
object: 'chat.completion.chunk',
|
979
|
+
created: 1737563070,
|
980
|
+
model: 'deepseek-reasoner',
|
981
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
982
|
+
choices: [
|
983
|
+
{
|
984
|
+
index: 0,
|
985
|
+
delta: { reasoning_content: '您好', content: '' },
|
986
|
+
logprobs: null,
|
987
|
+
finish_reason: null,
|
988
|
+
},
|
989
|
+
],
|
990
|
+
},
|
991
|
+
{
|
992
|
+
id: '1',
|
993
|
+
object: 'chat.completion.chunk',
|
994
|
+
created: 1737563070,
|
995
|
+
model: 'deepseek-reasoner',
|
996
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
997
|
+
choices: [
|
998
|
+
{
|
999
|
+
index: 0,
|
1000
|
+
delta: { reasoning_content: '!', content: '' },
|
1001
|
+
logprobs: null,
|
1002
|
+
finish_reason: null,
|
1003
|
+
},
|
1004
|
+
],
|
1005
|
+
},
|
1006
|
+
{
|
1007
|
+
id: '1',
|
1008
|
+
object: 'chat.completion.chunk',
|
1009
|
+
created: 1737563070,
|
1010
|
+
model: 'deepseek-reasoner',
|
1011
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1012
|
+
choices: [
|
1013
|
+
{
|
1014
|
+
index: 0,
|
1015
|
+
delta: { content: '你好', reasoning_content: null },
|
1016
|
+
logprobs: null,
|
1017
|
+
finish_reason: null,
|
1018
|
+
},
|
1019
|
+
],
|
1020
|
+
},
|
1021
|
+
{
|
1022
|
+
id: '1',
|
1023
|
+
object: 'chat.completion.chunk',
|
1024
|
+
created: 1737563070,
|
1025
|
+
model: 'deepseek-reasoner',
|
1026
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1027
|
+
choices: [
|
1028
|
+
{
|
1029
|
+
index: 0,
|
1030
|
+
delta: { content: '很高兴', reasoning_cont: null },
|
1031
|
+
logprobs: null,
|
1032
|
+
finish_reason: null,
|
1033
|
+
},
|
1034
|
+
],
|
1035
|
+
},
|
1036
|
+
{
|
1037
|
+
id: '1',
|
1038
|
+
object: 'chat.completion.chunk',
|
1039
|
+
created: 1737563070,
|
1040
|
+
model: 'deepseek-reasoner',
|
1041
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1042
|
+
choices: [
|
1043
|
+
{
|
1044
|
+
index: 0,
|
1045
|
+
delta: { content: '为您', reasoning_content: null },
|
1046
|
+
logprobs: null,
|
1047
|
+
finish_reason: null,
|
1048
|
+
},
|
1049
|
+
],
|
1050
|
+
},
|
1051
|
+
{
|
1052
|
+
id: '1',
|
1053
|
+
object: 'chat.completion.chunk',
|
1054
|
+
created: 1737563070,
|
1055
|
+
model: 'deepseek-reasoner',
|
1056
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1057
|
+
choices: [
|
1058
|
+
{
|
1059
|
+
index: 0,
|
1060
|
+
delta: { content: '提供', reasoning_content: null },
|
1061
|
+
logprobs: null,
|
1062
|
+
finish_reason: null,
|
1063
|
+
},
|
1064
|
+
],
|
1065
|
+
},
|
1066
|
+
{
|
1067
|
+
id: '1',
|
1068
|
+
object: 'chat.completion.chunk',
|
1069
|
+
created: 1737563070,
|
1070
|
+
model: 'deepseek-reasoner',
|
1071
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1072
|
+
choices: [
|
1073
|
+
{
|
1074
|
+
index: 0,
|
1075
|
+
delta: { content: '帮助。', reasoning_content: null },
|
1076
|
+
logprobs: null,
|
1077
|
+
finish_reason: null,
|
1078
|
+
},
|
1079
|
+
],
|
1080
|
+
},
|
1081
|
+
{
|
1082
|
+
id: '1',
|
1083
|
+
object: 'chat.completion.chunk',
|
1084
|
+
created: 1737563070,
|
1085
|
+
model: 'deepseek-reasoner',
|
1086
|
+
system_fingerprint: 'fp_1c5d8833bc',
|
1087
|
+
choices: [
|
1088
|
+
{
|
1089
|
+
index: 0,
|
1090
|
+
delta: { content: '', reasoning_content: null },
|
1091
|
+
logprobs: null,
|
1092
|
+
finish_reason: 'stop',
|
1093
|
+
},
|
1094
|
+
],
|
1095
|
+
usage: {
|
1096
|
+
prompt_tokens: 6,
|
1097
|
+
completion_tokens: 104,
|
1098
|
+
total_tokens: 110,
|
1099
|
+
prompt_tokens_details: { cached_tokens: 0 },
|
1100
|
+
completion_tokens_details: { reasoning_tokens: 70 },
|
1101
|
+
prompt_cache_hit_tokens: 0,
|
1102
|
+
prompt_cache_miss_tokens: 6,
|
1103
|
+
},
|
1104
|
+
},
|
1105
|
+
];
|
1106
|
+
|
1107
|
+
const mockOpenAIStream = new ReadableStream({
|
1108
|
+
start(controller) {
|
1109
|
+
data.forEach((chunk) => {
|
1110
|
+
controller.enqueue(chunk);
|
1111
|
+
});
|
1112
|
+
|
1113
|
+
controller.close();
|
1114
|
+
},
|
1115
|
+
});
|
1116
|
+
|
1117
|
+
const protocolStream = OpenAIStream(mockOpenAIStream);
|
1118
|
+
|
1119
|
+
const decoder = new TextDecoder();
|
1120
|
+
const chunks = [];
|
1121
|
+
|
1122
|
+
// @ts-ignore
|
1123
|
+
for await (const chunk of protocolStream) {
|
1124
|
+
chunks.push(decoder.decode(chunk, { stream: true }));
|
1125
|
+
}
|
1126
|
+
|
1127
|
+
expect(chunks).toEqual(
|
1128
|
+
[
|
1129
|
+
'id: 1',
|
1130
|
+
'event: reasoning',
|
1131
|
+
`data: ""\n`,
|
1132
|
+
'id: 1',
|
1133
|
+
'event: reasoning',
|
1134
|
+
`data: "您好"\n`,
|
1135
|
+
'id: 1',
|
1136
|
+
'event: reasoning',
|
1137
|
+
`data: "!"\n`,
|
1138
|
+
'id: 1',
|
1139
|
+
'event: text',
|
1140
|
+
`data: "你好"\n`,
|
1141
|
+
'id: 1',
|
1142
|
+
'event: text',
|
1143
|
+
`data: "很高兴"\n`,
|
1144
|
+
'id: 1',
|
1145
|
+
'event: text',
|
1146
|
+
`data: "为您"\n`,
|
1147
|
+
'id: 1',
|
1148
|
+
'event: text',
|
1149
|
+
`data: "提供"\n`,
|
1150
|
+
'id: 1',
|
1151
|
+
'event: text',
|
1152
|
+
`data: "帮助。"\n`,
|
1153
|
+
'id: 1',
|
1154
|
+
'event: stop',
|
1155
|
+
`data: "stop"\n`,
|
1156
|
+
].map((i) => `${i}\n`),
|
1157
|
+
);
|
1158
|
+
});
|
957
1159
|
});
|
958
1160
|
});
|
@@ -37,9 +37,8 @@ export const transformOpenAIStream = (
|
|
37
37
|
return { data: errorData, id: 'first_chunk_error', type: 'error' };
|
38
38
|
}
|
39
39
|
|
40
|
-
// maybe need another structure to add support for multiple choices
|
41
|
-
|
42
40
|
try {
|
41
|
+
// maybe need another structure to add support for multiple choices
|
43
42
|
const item = chunk.choices[0];
|
44
43
|
if (!item) {
|
45
44
|
return { data: chunk, id: chunk.id, type: 'data' };
|
@@ -88,12 +87,10 @@ export const transformOpenAIStream = (
|
|
88
87
|
return { data: item.finish_reason, id: chunk.id, type: 'stop' };
|
89
88
|
}
|
90
89
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
// DeepSeek reasoner 会将 thinking 放在 reasoning_content 字段中
|
96
|
-
// litellm 处理 reasoning content 时 不会设定 content = null
|
90
|
+
// DeepSeek reasoner will put thinking in the reasoning_content field
|
91
|
+
// litellm will not set content = null when processing reasoning content
|
92
|
+
// en: siliconflow has encountered a situation where both content and reasoning_content are present, so the parsing order go ahead
|
93
|
+
// refs: https://github.com/lobehub/lobe-chat/issues/5681
|
97
94
|
if (
|
98
95
|
item.delta &&
|
99
96
|
'reasoning_content' in item.delta &&
|
@@ -102,6 +99,10 @@ export const transformOpenAIStream = (
|
|
102
99
|
return { data: item.delta.reasoning_content, id: chunk.id, type: 'reasoning' };
|
103
100
|
}
|
104
101
|
|
102
|
+
if (typeof item.delta?.content === 'string') {
|
103
|
+
return { data: item.delta.content, id: chunk.id, type: 'text' };
|
104
|
+
}
|
105
|
+
|
105
106
|
// 无内容情况
|
106
107
|
if (item.delta && item.delta.content === null) {
|
107
108
|
return { data: item.delta, id: chunk.id, type: 'data' };
|
@@ -127,6 +127,10 @@ export default {
|
|
127
127
|
title: '话题新鲜度',
|
128
128
|
},
|
129
129
|
range: '范围',
|
130
|
+
reasoning_effort: {
|
131
|
+
desc: '此设置用于控制模型在生成回答前的推理强度。低强度优先响应速度并节省 Token,高强度提供更完整的推理,但会消耗更多 Token 并降低响应速度。默认值为中,平衡推理准确性与响应速度。',
|
132
|
+
title: '推理强度',
|
133
|
+
},
|
130
134
|
temperature: {
|
131
135
|
desc: '此设置影响模型回应的多样性。较低的值会导致更可预测和典型的回应,而较高的值则鼓励更多样化和不常见的回应。当值设为0时,模型对于给定的输入总是给出相同的回应。',
|
132
136
|
title: '随机性',
|
@@ -202,6 +202,9 @@ export default {
|
|
202
202
|
enableMaxTokens: {
|
203
203
|
title: '开启单次回复限制',
|
204
204
|
},
|
205
|
+
enableReasoningEffort: {
|
206
|
+
title: '开启推理强度调整',
|
207
|
+
},
|
205
208
|
frequencyPenalty: {
|
206
209
|
desc: '值越大,越有可能降低重复字词',
|
207
210
|
title: '频率惩罚度',
|
@@ -218,6 +221,15 @@ export default {
|
|
218
221
|
desc: '值越大,越有可能扩展到新话题',
|
219
222
|
title: '话题新鲜度',
|
220
223
|
},
|
224
|
+
reasoningEffort: {
|
225
|
+
desc: '值越大,推理能力越强,但可能会增加响应时间和 Token 消耗',
|
226
|
+
options: {
|
227
|
+
high: '高',
|
228
|
+
low: '低',
|
229
|
+
medium: '中',
|
230
|
+
},
|
231
|
+
title: '推理强度',
|
232
|
+
},
|
221
233
|
temperature: {
|
222
234
|
desc: '值越大,回复越随机',
|
223
235
|
title: '随机性',
|
@@ -421,6 +421,11 @@ export const generateAIChat: StateCreator<
|
|
421
421
|
? agentConfig.params.max_tokens
|
422
422
|
: undefined;
|
423
423
|
|
424
|
+
// 5. handle reasoning_effort
|
425
|
+
agentConfig.params.reasoning_effort = chatConfig.enableReasoningEffort
|
426
|
+
? agentConfig.params.reasoning_effort
|
427
|
+
: undefined;
|
428
|
+
|
424
429
|
let isFunctionCall = false;
|
425
430
|
let msgTraceId: string | undefined;
|
426
431
|
let output = '';
|
package/src/types/agent/index.ts
CHANGED
@@ -68,6 +68,11 @@ export interface LobeAgentChatConfig {
|
|
68
68
|
enableHistoryCount?: boolean;
|
69
69
|
enableMaxTokens?: boolean;
|
70
70
|
|
71
|
+
/**
|
72
|
+
* 自定义推理强度
|
73
|
+
*/
|
74
|
+
enableReasoningEffort?: boolean;
|
75
|
+
|
71
76
|
/**
|
72
77
|
* 历史消息条数
|
73
78
|
*/
|
@@ -82,6 +87,7 @@ export const AgentChatConfigSchema = z.object({
|
|
82
87
|
enableCompressHistory: z.boolean().optional(),
|
83
88
|
enableHistoryCount: z.boolean().optional(),
|
84
89
|
enableMaxTokens: z.boolean().optional(),
|
90
|
+
enableReasoningEffort: z.boolean().optional(),
|
85
91
|
historyCount: z.number().optional(),
|
86
92
|
});
|
87
93
|
|
package/src/types/llm.ts
CHANGED