diff --git a/CHANGELOG.md b/CHANGELOG.md
index 680ab982aa2c6..eefa610f8d71c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,31 @@
# Changelog
+### [Version 1.49.6](https://github.com/lobehub/lobe-chat/compare/v1.49.5...v1.49.6)
+
+Released on **2025-01-30**
+
+#### 🐛 Bug Fixes
+
+- **misc**: Support litellm reasoning streaming.
+
+
+
+
+Improvements and Fixes
+
+#### What's fixed
+
+- **misc**: Support litellm reasoning streaming, closes [#5632](https://github.com/lobehub/lobe-chat/issues/5632) ([9942fb3](https://github.com/lobehub/lobe-chat/commit/9942fb3))
+
+
+
+
+
+[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
+
+
+
### [Version 1.49.5](https://github.com/lobehub/lobe-chat/compare/v1.49.4...v1.49.5)
Released on **2025-01-28**
diff --git a/changelog/v1.json b/changelog/v1.json
index 5e32ba7b07ae7..5c93dc78e6af9 100644
--- a/changelog/v1.json
+++ b/changelog/v1.json
@@ -1,4 +1,11 @@
[
+ {
+ "children": {
+ "fixes": ["Support litellm reasoning streaming."]
+ },
+ "date": "2025-01-30",
+ "version": "1.49.6"
+ },
{
"children": {
"fixes": ["Pin @clerk/nextjs@6.10.2 to avoid build error."]
diff --git a/package.json b/package.json
index 2bb79ba7ff464..4f8043b77ba71 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@lobehub/chat",
- "version": "1.49.5",
+ "version": "1.49.6",
"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.",
"keywords": [
"framework",
diff --git a/src/libs/agent-runtime/utils/streams/openai.test.ts b/src/libs/agent-runtime/utils/streams/openai.test.ts
index a7625ce18764d..3a26ba3c3829a 100644
--- a/src/libs/agent-runtime/utils/streams/openai.test.ts
+++ b/src/libs/agent-runtime/utils/streams/openai.test.ts
@@ -554,7 +554,7 @@ describe('OpenAIStream', () => {
});
describe('Reasoning', () => {
- it('should handle reasoning event', async () => {
+ it('should handle reasoning event in official DeepSeek api', async () => {
const data = [
{
id: '1',
@@ -722,6 +722,206 @@ describe('OpenAIStream', () => {
chunks.push(decoder.decode(chunk, { stream: true }));
}
+ expect(chunks).toEqual(
+ [
+ 'id: 1',
+ 'event: reasoning',
+ `data: ""\n`,
+ 'id: 1',
+ 'event: reasoning',
+ `data: "您好"\n`,
+ 'id: 1',
+ 'event: reasoning',
+ `data: "!"\n`,
+ 'id: 1',
+ 'event: text',
+ `data: "你好"\n`,
+ 'id: 1',
+ 'event: text',
+ `data: "很高兴"\n`,
+ 'id: 1',
+ 'event: text',
+ `data: "为您"\n`,
+ 'id: 1',
+ 'event: text',
+ `data: "提供"\n`,
+ 'id: 1',
+ 'event: text',
+ `data: "帮助。"\n`,
+ 'id: 1',
+ 'event: stop',
+ `data: "stop"\n`,
+ ].map((i) => `${i}\n`),
+ );
+ });
+ it('should handle reasoning in litellm', async () => {
+ const data = [
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { role: 'assistant', reasoning_content: '' },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { reasoning_content: '您好' },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { reasoning_content: '!' },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '你好', reasoning_content: null },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '很高兴', reasoning_cont: null },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '为您', reasoning_content: null },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '提供', reasoning_content: null },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '帮助。', reasoning_content: null },
+ logprobs: null,
+ finish_reason: null,
+ },
+ ],
+ },
+ {
+ id: '1',
+ object: 'chat.completion.chunk',
+ created: 1737563070,
+ model: 'deepseek-reasoner',
+ system_fingerprint: 'fp_1c5d8833bc',
+ choices: [
+ {
+ index: 0,
+ delta: { content: '', reasoning_content: null },
+ logprobs: null,
+ finish_reason: 'stop',
+ },
+ ],
+ usage: {
+ prompt_tokens: 6,
+ completion_tokens: 104,
+ total_tokens: 110,
+ prompt_tokens_details: { cached_tokens: 0 },
+ completion_tokens_details: { reasoning_tokens: 70 },
+ prompt_cache_hit_tokens: 0,
+ prompt_cache_miss_tokens: 6,
+ },
+ },
+ ];
+
+ const mockOpenAIStream = new ReadableStream({
+ start(controller) {
+ data.forEach((chunk) => {
+ controller.enqueue(chunk);
+ });
+
+ controller.close();
+ },
+ });
+
+ const protocolStream = OpenAIStream(mockOpenAIStream);
+
+ const decoder = new TextDecoder();
+ const chunks = [];
+
+ // @ts-ignore
+ for await (const chunk of protocolStream) {
+ chunks.push(decoder.decode(chunk, { stream: true }));
+ }
+
expect(chunks).toEqual(
[
'id: 1',
diff --git a/src/libs/agent-runtime/utils/streams/openai.ts b/src/libs/agent-runtime/utils/streams/openai.ts
index 07d06ce653edc..4edcd3303112e 100644
--- a/src/libs/agent-runtime/utils/streams/openai.ts
+++ b/src/libs/agent-runtime/utils/streams/openai.ts
@@ -92,13 +92,18 @@ export const transformOpenAIStream = (
return { data: item.delta.content, id: chunk.id, type: 'text' };
}
+ // DeepSeek reasoner 会将 thinking 放在 reasoning_content 字段中
+ // litellm 处理 reasoning content 时 不会设定 content = null
+ if (
+ item.delta &&
+ 'reasoning_content' in item.delta &&
+ typeof item.delta.reasoning_content === 'string'
+ ) {
+ return { data: item.delta.reasoning_content, id: chunk.id, type: 'reasoning' };
+ }
+
// 无内容情况
if (item.delta && item.delta.content === null) {
- // deepseek reasoner 会将 thinking 放在 reasoning_content 字段中
- if ('reasoning_content' in item.delta && typeof item.delta.reasoning_content === 'string') {
- return { data: item.delta.reasoning_content, id: chunk.id, type: 'reasoning' };
- }
-
return { data: item.delta, id: chunk.id, type: 'data' };
}