@lobehub/chat 1.49.15 → 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.
Files changed (75) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/changelog/v1.json +21 -0
  3. package/docs/usage/agents/model.mdx +16 -0
  4. package/docs/usage/agents/model.zh-CN.mdx +16 -0
  5. package/locales/ar/discover.json +4 -0
  6. package/locales/ar/models.json +3 -0
  7. package/locales/ar/setting.json +12 -0
  8. package/locales/bg-BG/discover.json +4 -0
  9. package/locales/bg-BG/models.json +3 -0
  10. package/locales/bg-BG/setting.json +12 -0
  11. package/locales/de-DE/discover.json +4 -0
  12. package/locales/de-DE/models.json +3 -0
  13. package/locales/de-DE/setting.json +12 -0
  14. package/locales/en-US/discover.json +4 -0
  15. package/locales/en-US/models.json +3 -0
  16. package/locales/en-US/setting.json +12 -0
  17. package/locales/es-ES/discover.json +4 -0
  18. package/locales/es-ES/models.json +3 -0
  19. package/locales/es-ES/setting.json +12 -0
  20. package/locales/fa-IR/discover.json +4 -0
  21. package/locales/fa-IR/models.json +3 -0
  22. package/locales/fa-IR/setting.json +12 -0
  23. package/locales/fr-FR/discover.json +4 -0
  24. package/locales/fr-FR/models.json +3 -0
  25. package/locales/fr-FR/setting.json +12 -0
  26. package/locales/it-IT/discover.json +4 -0
  27. package/locales/it-IT/models.json +3 -0
  28. package/locales/it-IT/setting.json +12 -0
  29. package/locales/ja-JP/discover.json +4 -0
  30. package/locales/ja-JP/models.json +3 -0
  31. package/locales/ja-JP/setting.json +12 -0
  32. package/locales/ko-KR/discover.json +4 -0
  33. package/locales/ko-KR/models.json +15 -0
  34. package/locales/ko-KR/setting.json +12 -0
  35. package/locales/nl-NL/discover.json +4 -0
  36. package/locales/nl-NL/models.json +3 -0
  37. package/locales/nl-NL/setting.json +12 -0
  38. package/locales/pl-PL/discover.json +4 -0
  39. package/locales/pl-PL/models.json +3 -0
  40. package/locales/pl-PL/setting.json +12 -0
  41. package/locales/pt-BR/discover.json +4 -0
  42. package/locales/pt-BR/models.json +3 -0
  43. package/locales/pt-BR/setting.json +12 -0
  44. package/locales/ru-RU/discover.json +4 -0
  45. package/locales/ru-RU/models.json +3 -0
  46. package/locales/ru-RU/setting.json +12 -0
  47. package/locales/tr-TR/discover.json +4 -0
  48. package/locales/tr-TR/models.json +3 -0
  49. package/locales/tr-TR/setting.json +12 -0
  50. package/locales/vi-VN/discover.json +4 -0
  51. package/locales/vi-VN/models.json +3 -0
  52. package/locales/vi-VN/setting.json +12 -0
  53. package/locales/zh-CN/discover.json +4 -0
  54. package/locales/zh-CN/models.json +4 -1
  55. package/locales/zh-CN/setting.json +12 -0
  56. package/locales/zh-TW/discover.json +4 -0
  57. package/locales/zh-TW/models.json +3 -0
  58. package/locales/zh-TW/setting.json +12 -0
  59. package/package.json +1 -1
  60. package/src/app/(main)/discover/(detail)/model/[...slugs]/features/ParameterList/index.tsx +10 -0
  61. package/src/config/aiModels/github.ts +18 -7
  62. package/src/config/aiModels/openai.ts +35 -2
  63. package/src/config/aiModels/perplexity.ts +25 -32
  64. package/src/config/modelProviders/perplexity.ts +26 -32
  65. package/src/features/AgentSetting/AgentModal/index.tsx +27 -3
  66. package/src/libs/agent-runtime/github/index.ts +3 -3
  67. package/src/libs/agent-runtime/openai/index.ts +7 -5
  68. package/src/libs/agent-runtime/openrouter/__snapshots__/index.test.ts.snap +7 -7
  69. package/src/libs/agent-runtime/utils/streams/openai.test.ts +202 -0
  70. package/src/libs/agent-runtime/utils/streams/openai.ts +9 -8
  71. package/src/locales/default/discover.ts +4 -0
  72. package/src/locales/default/setting.ts +12 -0
  73. package/src/store/chat/slices/aiChat/actions/generateAIChat.ts +5 -0
  74. package/src/types/agent/index.ts +6 -0
  75. package/src/types/llm.ts +5 -0
@@ -2,62 +2,55 @@ import { AIChatModelCard } from '@/types/aiModel';
2
2
 
3
3
  const perplexityChatModels: AIChatModelCard[] = [
4
4
  {
5
- contextWindowTokens: 128_000,
5
+ contextWindowTokens: 127_072,
6
6
  description:
7
- 'Llama 3.1 Sonar Small Online 模型,具备8B参数,支持约127,000个标记的上下文长度,专为在线聊天设计,能高效处理各种文本交互。',
8
- displayName: 'Llama 3.1 Sonar Small Online',
9
- enabled: true,
10
- id: 'llama-3.1-sonar-small-128k-online',
11
- type: 'chat',
12
- },
13
- {
14
- contextWindowTokens: 128_000,
15
- description:
16
- 'Llama 3.1 Sonar Large Online 模型,具备70B参数,支持约127,000个标记的上下文长度,适用于高容量和多样化聊天任务。',
17
- displayName: 'Llama 3.1 Sonar Large Online',
7
+ ' DeepSeek 推理模型提供支持的新 API 产品。',
8
+ displayName: 'Sonar Reasoning',
18
9
  enabled: true,
19
- id: 'llama-3.1-sonar-large-128k-online',
10
+ id: 'sonar-reasoning',
20
11
  type: 'chat',
21
12
  },
22
13
  {
23
- contextWindowTokens: 128_000,
14
+ contextWindowTokens: 200_000,
24
15
  description:
25
- 'Llama 3.1 Sonar Huge Online 模型,具备405B参数,支持约127,000个标记的上下文长度,设计用于复杂的在线聊天应用。',
26
- displayName: 'Llama 3.1 Sonar Huge Online',
16
+ '支持搜索上下文的高级搜索产品,支持高级查询和跟进。',
17
+ displayName: 'Sonar Pro',
27
18
  enabled: true,
28
- id: 'llama-3.1-sonar-huge-128k-online',
19
+ id: 'sonar-pro',
29
20
  type: 'chat',
30
21
  },
31
22
  {
32
- contextWindowTokens: 128_000,
23
+ contextWindowTokens: 127_072,
33
24
  description:
34
- 'Llama 3.1 Sonar Small Chat 模型,具备8B参数,专为离线聊天设计,支持约127,000个标记的上下文长度。',
35
- displayName: 'Llama 3.1 Sonar Small Chat',
25
+ '基于搜索上下文的轻量级搜索产品,比 Sonar Pro 更快、更便宜。',
26
+ displayName: 'Sonar',
36
27
  enabled: true,
37
- id: 'llama-3.1-sonar-small-128k-chat',
28
+ id: 'sonar',
38
29
  type: 'chat',
39
30
  },
31
+ // The following will be deprecated on 02-22
40
32
  {
41
- contextWindowTokens: 128_000,
33
+ contextWindowTokens: 127_072,
42
34
  description:
43
- 'Llama 3.1 Sonar Large Chat 模型,具备70B参数,支持约127,000个标记的上下文长度,适合于复杂的离线聊天任务。',
44
- displayName: 'Llama 3.1 Sonar Large Chat',
45
- enabled: true,
46
- id: 'llama-3.1-sonar-large-128k-chat',
35
+ 'Llama 3.1 Sonar Small Online 模型,具备8B参数,支持约127,000个标记的上下文长度,专为在线聊天设计,能高效处理各种文本交互。',
36
+ displayName: 'Llama 3.1 Sonar Small Online',
37
+ id: 'llama-3.1-sonar-small-128k-online',
47
38
  type: 'chat',
48
39
  },
49
40
  {
50
- contextWindowTokens: 128_000,
41
+ contextWindowTokens: 127_072,
51
42
  description:
52
- 'Llama 3.1 8B Instruct 模型,具备8B参数,支持画面指示任务的高效执行,提供优质的文本生成能力。',
53
- id: 'llama-3.1-8b-instruct',
43
+ 'Llama 3.1 Sonar Large Online 模型,具备70B参数,支持约127,000个标记的上下文长度,适用于高容量和多样化聊天任务。',
44
+ displayName: 'Llama 3.1 Sonar Large Online',
45
+ id: 'llama-3.1-sonar-large-128k-online',
54
46
  type: 'chat',
55
47
  },
56
48
  {
57
- contextWindowTokens: 128_000,
49
+ contextWindowTokens: 127_072,
58
50
  description:
59
- 'Llama 3.1 70B Instruct 模型,具备70B参数,能在大型文本生成和指示任务中提供卓越性能。',
60
- id: 'llama-3.1-70b-instruct',
51
+ 'Llama 3.1 Sonar Huge Online 模型,具备405B参数,支持约127,000个标记的上下文长度,设计用于复杂的在线聊天应用。',
52
+ displayName: 'Llama 3.1 Sonar Huge Online',
53
+ id: 'llama-3.1-sonar-huge-128k-online',
61
54
  type: 'chat',
62
55
  },
63
56
  ];
@@ -4,59 +4,53 @@ import { ModelProviderCard } from '@/types/llm';
4
4
  const Perplexity: ModelProviderCard = {
5
5
  chatModels: [
6
6
  {
7
- contextWindowTokens: 128_000,
7
+ contextWindowTokens: 127_072,
8
8
  description:
9
- 'Llama 3.1 Sonar Small Online 模型,具备8B参数,支持约127,000个标记的上下文长度,专为在线聊天设计,能高效处理各种文本交互。',
10
- displayName: 'Llama 3.1 Sonar Small Online',
9
+ ' DeepSeek 推理模型提供支持的新 API 产品。',
10
+ displayName: 'Sonar Reasoning',
11
11
  enabled: true,
12
- id: 'llama-3.1-sonar-small-128k-online',
12
+ id: 'sonar-reasoning',
13
13
  },
14
14
  {
15
- contextWindowTokens: 128_000,
15
+ contextWindowTokens: 200_000,
16
16
  description:
17
- 'Llama 3.1 Sonar Large Online 模型,具备70B参数,支持约127,000个标记的上下文长度,适用于高容量和多样化聊天任务。',
18
- displayName: 'Llama 3.1 Sonar Large Online',
17
+ '支持搜索上下文的高级搜索产品,支持高级查询和跟进。',
18
+ displayName: 'Sonar Pro',
19
19
  enabled: true,
20
- id: 'llama-3.1-sonar-large-128k-online',
20
+ id: 'sonar-pro',
21
21
  },
22
22
  {
23
- contextWindowTokens: 128_000,
23
+ contextWindowTokens: 127_072,
24
24
  description:
25
- 'Llama 3.1 Sonar Huge Online 模型,具备405B参数,支持约127,000个标记的上下文长度,设计用于复杂的在线聊天应用。',
26
- displayName: 'Llama 3.1 Sonar Huge Online',
25
+ '基于搜索上下文的轻量级搜索产品,比 Sonar Pro 更快、更便宜。',
26
+ displayName: 'Sonar',
27
27
  enabled: true,
28
- id: 'llama-3.1-sonar-huge-128k-online',
28
+ id: 'sonar',
29
29
  },
30
+ // The following will be deprecated on 02-22
30
31
  {
31
- contextWindowTokens: 128_000,
32
+ contextWindowTokens: 127_072,
32
33
  description:
33
- 'Llama 3.1 Sonar Small Chat 模型,具备8B参数,专为离线聊天设计,支持约127,000个标记的上下文长度。',
34
- displayName: 'Llama 3.1 Sonar Small Chat',
35
- enabled: true,
36
- id: 'llama-3.1-sonar-small-128k-chat',
37
- },
38
- {
39
- contextWindowTokens: 128_000,
40
- description:
41
- 'Llama 3.1 Sonar Large Chat 模型,具备70B参数,支持约127,000个标记的上下文长度,适合于复杂的离线聊天任务。',
42
- displayName: 'Llama 3.1 Sonar Large Chat',
43
- enabled: true,
44
- id: 'llama-3.1-sonar-large-128k-chat',
34
+ 'Llama 3.1 Sonar Small Online 模型,具备8B参数,支持约127,000个标记的上下文长度,专为在线聊天设计,能高效处理各种文本交互。',
35
+ displayName: 'Llama 3.1 Sonar Small Online',
36
+ id: 'llama-3.1-sonar-small-128k-online',
45
37
  },
46
38
  {
47
- contextWindowTokens: 128_000,
39
+ contextWindowTokens: 127_072,
48
40
  description:
49
- 'Llama 3.1 8B Instruct 模型,具备8B参数,支持画面指示任务的高效执行,提供优质的文本生成能力。',
50
- id: 'llama-3.1-8b-instruct',
41
+ 'Llama 3.1 Sonar Large Online 模型,具备70B参数,支持约127,000个标记的上下文长度,适用于高容量和多样化聊天任务。',
42
+ displayName: 'Llama 3.1 Sonar Large Online',
43
+ id: 'llama-3.1-sonar-large-128k-online',
51
44
  },
52
45
  {
53
- contextWindowTokens: 128_000,
46
+ contextWindowTokens: 127_072,
54
47
  description:
55
- 'Llama 3.1 70B Instruct 模型,具备70B参数,能在大型文本生成和指示任务中提供卓越性能。',
56
- id: 'llama-3.1-70b-instruct',
48
+ 'Llama 3.1 Sonar Huge Online 模型,具备405B参数,支持约127,000个标记的上下文长度,设计用于复杂的在线聊天应用。',
49
+ displayName: 'Llama 3.1 Sonar Huge Online',
50
+ id: 'llama-3.1-sonar-huge-128k-online',
57
51
  },
58
52
  ],
59
- checkModel: 'llama-3.1-8b-instruct',
53
+ checkModel: 'sonar',
60
54
  description:
61
55
  'Perplexity 是一家领先的对话生成模型提供商,提供多种先进的Llama 3.1模型,支持在线和离线应用,特别适用于复杂的自然语言处理任务。',
62
56
  id: 'perplexity',
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { Form, ItemGroup, SliderWithInput } from '@lobehub/ui';
4
- import { Switch } from 'antd';
4
+ import { Select, Switch } from 'antd';
5
5
  import { memo } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
@@ -17,9 +17,9 @@ const AgentModal = memo(() => {
17
17
  const { t } = useTranslation('setting');
18
18
  const [form] = Form.useForm();
19
19
 
20
- const [enableMaxTokens, updateConfig] = useStore((s) => {
20
+ const [enableMaxTokens, enableReasoningEffort, updateConfig] = useStore((s) => {
21
21
  const config = selectors.chatConfig(s);
22
- return [config.enableMaxTokens, s.setAgentConfig];
22
+ return [config.enableMaxTokens, config.enableReasoningEffort, s.setAgentConfig];
23
23
  });
24
24
 
25
25
  const providerName = useProviderName(useStore((s) => s.config.provider) as string);
@@ -79,6 +79,30 @@ const AgentModal = memo(() => {
79
79
  name: ['params', 'max_tokens'],
80
80
  tag: 'max_tokens',
81
81
  },
82
+ {
83
+ children: <Switch />,
84
+ label: t('settingModel.enableReasoningEffort.title'),
85
+ minWidth: undefined,
86
+ name: ['chatConfig', 'enableReasoningEffort'],
87
+ valuePropName: 'checked',
88
+ },
89
+ {
90
+ children: (
91
+ <Select
92
+ defaultValue='medium'
93
+ options={[
94
+ { label: t('settingModel.reasoningEffort.options.low'), value: 'low' },
95
+ { label: t('settingModel.reasoningEffort.options.medium'), value: 'medium' },
96
+ { label: t('settingModel.reasoningEffort.options.high'), value: 'high' },
97
+ ]}
98
+ />
99
+ ),
100
+ desc: t('settingModel.reasoningEffort.desc'),
101
+ hidden: !enableReasoningEffort,
102
+ label: t('settingModel.reasoningEffort.title'),
103
+ name: ['params', 'reasoning_effort'],
104
+ tag: 'reasoning_effort',
105
+ },
82
106
  ],
83
107
  title: t('settingModel.title'),
84
108
  };
@@ -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 { o1Models, pruneO1Payload } from '../openai';
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 (o1Models.has(model)) {
41
- return { ...pruneO1Payload(payload), stream: false } as any;
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 o1Models = new Set([
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 pruneO1Payload = (payload: ChatStreamPayload) => ({
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' ? 'user' : message.role,
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 (o1Models.has(model)) {
33
- return pruneO1Payload(payload) as any;
34
+ if (reasoningModels.has(model)) {
35
+ return pruneReasoningPayload(payload) as any;
34
36
  }
35
37
 
36
38
  return { ...payload, stream: payload.stream ?? true };
@@ -196,7 +196,7 @@ _These are extended-context endpoints for [Hermes 3 405B Instruct](/models/nousr
196
196
  "contextWindowTokens": 127072,
197
197
  "description": "Llama 3.1 Sonar is Perplexity's latest model family. It surpasses their earlier Sonar models in cost-efficiency, speed, and performance. The model is built upon the Llama 3.1 405B and has internet access.",
198
198
  "displayName": "Perplexity: Llama 3.1 Sonar 405B Online",
199
- "enabled": true,
199
+ "enabled": false,
200
200
  "functionCall": false,
201
201
  "id": "perplexity/llama-3.1-sonar-huge-128k-online",
202
202
  "maxTokens": undefined,
@@ -304,7 +304,7 @@ Note: This model is experimental and not suited for production use-cases. It may
304
304
 
305
305
  This is the online version of the [offline chat model](/models/perplexity/llama-3.1-sonar-large-128k-chat). It is focused on delivering helpful, up-to-date, and factual responses. #online",
306
306
  "displayName": "Perplexity: Llama 3.1 Sonar 70B Online",
307
- "enabled": true,
307
+ "enabled": false,
308
308
  "functionCall": false,
309
309
  "id": "perplexity/llama-3.1-sonar-large-128k-online",
310
310
  "maxTokens": undefined,
@@ -316,7 +316,7 @@ This is the online version of the [offline chat model](/models/perplexity/llama-
316
316
 
317
317
  This is a normal offline LLM, but the [online version](/models/perplexity/llama-3.1-sonar-large-128k-online) of this model has Internet access.",
318
318
  "displayName": "Perplexity: Llama 3.1 Sonar 70B",
319
- "enabled": true,
319
+ "enabled": false,
320
320
  "functionCall": false,
321
321
  "id": "perplexity/llama-3.1-sonar-large-128k-chat",
322
322
  "maxTokens": undefined,
@@ -328,7 +328,7 @@ This is a normal offline LLM, but the [online version](/models/perplexity/llama-
328
328
 
329
329
  This is the online version of the [offline chat model](/models/perplexity/llama-3.1-sonar-small-128k-chat). It is focused on delivering helpful, up-to-date, and factual responses. #online",
330
330
  "displayName": "Perplexity: Llama 3.1 Sonar 8B Online",
331
- "enabled": true,
331
+ "enabled": false,
332
332
  "functionCall": false,
333
333
  "id": "perplexity/llama-3.1-sonar-small-128k-online",
334
334
  "maxTokens": undefined,
@@ -340,7 +340,7 @@ This is the online version of the [offline chat model](/models/perplexity/llama-
340
340
 
341
341
  This is a normal offline LLM, but the [online version](/models/perplexity/llama-3.1-sonar-small-128k-online) of this model has Internet access.",
342
342
  "displayName": "Perplexity: Llama 3.1 Sonar 8B",
343
- "enabled": true,
343
+ "enabled": false,
344
344
  "functionCall": false,
345
345
  "id": "perplexity/llama-3.1-sonar-small-128k-chat",
346
346
  "maxTokens": undefined,
@@ -354,7 +354,7 @@ It has demonstrated strong performance compared to leading closed-source models
354
354
 
355
355
  To read more about the model release, [click here](https://ai.meta.com/blog/meta-llama-3/). Usage of this model is subject to [Meta's Acceptable Use Policy](https://llama.meta.com/llama3/use-policy/).",
356
356
  "displayName": "Meta: Llama 3.1 70B Instruct",
357
- "enabled": false,
357
+ "enabled": true,
358
358
  "functionCall": false,
359
359
  "id": "meta-llama/llama-3.1-70b-instruct",
360
360
  "maxTokens": undefined,
@@ -384,7 +384,7 @@ It has demonstrated strong performance compared to leading closed-source models
384
384
 
385
385
  To read more about the model release, [click here](https://ai.meta.com/blog/meta-llama-3/). Usage of this model is subject to [Meta's Acceptable Use Policy](https://llama.meta.com/llama3/use-policy/).",
386
386
  "displayName": "Meta: Llama 3.1 8B Instruct",
387
- "enabled": false,
387
+ "enabled": true,
388
388
  "functionCall": false,
389
389
  "id": "meta-llama/llama-3.1-8b-instruct",
390
390
  "maxTokens": undefined,
@@ -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
- if (typeof item.delta?.content === 'string') {
92
- return { data: item.delta.content, id: chunk.id, type: 'text' };
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 = '';