@lobehub/chat 1.15.13 → 1.15.14
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
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.15.14](https://github.com/lobehub/lobe-chat/compare/v1.15.13...v1.15.14)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-09-06**</sup>
|
|
8
|
+
|
|
9
|
+
<br/>
|
|
10
|
+
|
|
11
|
+
<details>
|
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
13
|
+
|
|
14
|
+
</details>
|
|
15
|
+
|
|
16
|
+
<div align="right">
|
|
17
|
+
|
|
18
|
+
[](#readme-top)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
5
22
|
### [Version 1.15.13](https://github.com/lobehub/lobe-chat/compare/v1.15.12...v1.15.13)
|
|
6
23
|
|
|
7
24
|
<sup>Released on **2024-09-06**</sup>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.14",
|
|
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",
|
package/src/services/chat.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { produce } from 'immer';
|
|
|
3
3
|
import { merge } from 'lodash-es';
|
|
4
4
|
|
|
5
5
|
import { createErrorResponse } from '@/app/api/errorResponse';
|
|
6
|
+
import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
|
|
6
7
|
import { INBOX_GUIDE_SYSTEMROLE } from '@/const/guide';
|
|
7
8
|
import { INBOX_SESSION_ID } from '@/const/session';
|
|
8
9
|
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
@@ -304,6 +305,8 @@ class ChatService {
|
|
|
304
305
|
provider,
|
|
305
306
|
});
|
|
306
307
|
|
|
308
|
+
const providerConfig = DEFAULT_MODEL_PROVIDER_LIST.find((item) => item.id === provider);
|
|
309
|
+
|
|
307
310
|
return fetchSSE(API_ENDPOINTS.chat(provider), {
|
|
308
311
|
body: JSON.stringify(payload),
|
|
309
312
|
fetcher: fetcher,
|
|
@@ -314,6 +317,7 @@ class ChatService {
|
|
|
314
317
|
onFinish: options?.onFinish,
|
|
315
318
|
onMessageHandle: options?.onMessageHandle,
|
|
316
319
|
signal,
|
|
320
|
+
smoothing: providerConfig?.smoothing,
|
|
317
321
|
});
|
|
318
322
|
};
|
|
319
323
|
|
package/src/types/llm.ts
CHANGED
|
@@ -43,6 +43,12 @@ export interface ChatModelCard {
|
|
|
43
43
|
vision?: boolean;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
export interface SmoothingParams {
|
|
47
|
+
speed?: number;
|
|
48
|
+
text?: boolean;
|
|
49
|
+
toolsCalling?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
export interface ModelProviderCard {
|
|
47
53
|
chatModels: ChatModelCard[];
|
|
48
54
|
/**
|
|
@@ -89,6 +95,11 @@ export interface ModelProviderCard {
|
|
|
89
95
|
* so provider like ollama don't need api key field
|
|
90
96
|
*/
|
|
91
97
|
showApiKey?: boolean;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* whether to smoothing the output
|
|
101
|
+
*/
|
|
102
|
+
smoothing?: SmoothingParams;
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
// 语言模型的设置参数
|
|
@@ -139,6 +139,7 @@ describe('fetchSSE', () => {
|
|
|
139
139
|
await fetchSSE('/', {
|
|
140
140
|
onMessageHandle: mockOnMessageHandle,
|
|
141
141
|
onFinish: mockOnFinish,
|
|
142
|
+
smoothing: true,
|
|
142
143
|
});
|
|
143
144
|
|
|
144
145
|
expect(mockOnMessageHandle).toHaveBeenNthCalledWith(1, { text: 'Hell', type: 'text' });
|
|
@@ -183,6 +184,7 @@ describe('fetchSSE', () => {
|
|
|
183
184
|
await fetchSSE('/', {
|
|
184
185
|
onMessageHandle: mockOnMessageHandle,
|
|
185
186
|
onFinish: mockOnFinish,
|
|
187
|
+
smoothing: true,
|
|
186
188
|
});
|
|
187
189
|
|
|
188
190
|
// TODO: need to check whether the `aarg1` is correct
|
|
@@ -234,6 +236,7 @@ describe('fetchSSE', () => {
|
|
|
234
236
|
onMessageHandle: mockOnMessageHandle,
|
|
235
237
|
onFinish: mockOnFinish,
|
|
236
238
|
signal: abortController.signal,
|
|
239
|
+
smoothing: true,
|
|
237
240
|
});
|
|
238
241
|
|
|
239
242
|
expect(mockOnMessageHandle).toHaveBeenNthCalledWith(1, { text: 'Hell', type: 'text' });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { MESSAGE_CANCEL_FLAT } from '@/const/message';
|
|
2
2
|
import { LOBE_CHAT_OBSERVATION_ID, LOBE_CHAT_TRACE_ID } from '@/const/trace';
|
|
3
3
|
import { ChatErrorType } from '@/types/fetch';
|
|
4
|
+
import { SmoothingParams } from '@/types/llm';
|
|
4
5
|
import {
|
|
5
6
|
ChatMessageError,
|
|
6
7
|
MessageToolCall,
|
|
@@ -41,14 +42,19 @@ export interface FetchSSEOptions {
|
|
|
41
42
|
onErrorHandle?: (error: ChatMessageError) => void;
|
|
42
43
|
onFinish?: OnFinishHandler;
|
|
43
44
|
onMessageHandle?: (chunk: MessageTextChunk | MessageToolCallsChunk) => void;
|
|
44
|
-
smoothing?: boolean;
|
|
45
|
+
smoothing?: SmoothingParams | boolean;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
const START_ANIMATION_SPEED = 4;
|
|
48
49
|
|
|
49
50
|
const END_ANIMATION_SPEED = 15;
|
|
50
51
|
|
|
51
|
-
const createSmoothMessage = (params: {
|
|
52
|
+
const createSmoothMessage = (params: {
|
|
53
|
+
onTextUpdate: (delta: string, text: string) => void;
|
|
54
|
+
startSpeed?: number;
|
|
55
|
+
}) => {
|
|
56
|
+
const { startSpeed = START_ANIMATION_SPEED } = params;
|
|
57
|
+
|
|
52
58
|
let buffer = '';
|
|
53
59
|
// why use queue: https://shareg.pt/GLBrjpK
|
|
54
60
|
let outputQueue: string[] = [];
|
|
@@ -66,7 +72,7 @@ const createSmoothMessage = (params: { onTextUpdate: (delta: string, text: strin
|
|
|
66
72
|
|
|
67
73
|
// define startAnimation function to display the text in buffer smooth
|
|
68
74
|
// when you need to start the animation, call this function
|
|
69
|
-
const startAnimation = (speed =
|
|
75
|
+
const startAnimation = (speed = startSpeed) =>
|
|
70
76
|
new Promise<void>((resolve) => {
|
|
71
77
|
if (isAnimationActive) {
|
|
72
78
|
resolve();
|
|
@@ -122,7 +128,9 @@ const createSmoothMessage = (params: { onTextUpdate: (delta: string, text: strin
|
|
|
122
128
|
|
|
123
129
|
const createSmoothToolCalls = (params: {
|
|
124
130
|
onToolCallsUpdate: (toolCalls: MessageToolCall[], isAnimationActives: boolean[]) => void;
|
|
131
|
+
startSpeed?: number;
|
|
125
132
|
}) => {
|
|
133
|
+
const { startSpeed = START_ANIMATION_SPEED } = params;
|
|
126
134
|
let toolCallsBuffer: MessageToolCall[] = [];
|
|
127
135
|
|
|
128
136
|
// 为每个 tool_call 维护一个输出队列和动画控制器
|
|
@@ -139,7 +147,7 @@ const createSmoothToolCalls = (params: {
|
|
|
139
147
|
}
|
|
140
148
|
};
|
|
141
149
|
|
|
142
|
-
const startAnimation = (index: number, speed =
|
|
150
|
+
const startAnimation = (index: number, speed = startSpeed) =>
|
|
143
151
|
new Promise<void>((resolve) => {
|
|
144
152
|
if (isAnimationActives[index]) {
|
|
145
153
|
resolve();
|
|
@@ -194,7 +202,7 @@ const createSmoothToolCalls = (params: {
|
|
|
194
202
|
});
|
|
195
203
|
};
|
|
196
204
|
|
|
197
|
-
const startAnimations = async (speed =
|
|
205
|
+
const startAnimations = async (speed = startSpeed) => {
|
|
198
206
|
const pools = toolCallsBuffer.map(async (_, index) => {
|
|
199
207
|
if (outputQueues[index].length > 0 && !isAnimationActives[index]) {
|
|
200
208
|
await startAnimation(index, speed);
|
|
@@ -230,19 +238,26 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio
|
|
|
230
238
|
let finishedType: SSEFinishType = 'done';
|
|
231
239
|
let response!: Response;
|
|
232
240
|
|
|
233
|
-
const { smoothing
|
|
241
|
+
const { smoothing } = options;
|
|
242
|
+
|
|
243
|
+
const textSmoothing = typeof smoothing === 'boolean' ? smoothing : smoothing?.text;
|
|
244
|
+
const toolsCallingSmoothing =
|
|
245
|
+
typeof smoothing === 'boolean' ? smoothing : (smoothing?.toolsCalling ?? true);
|
|
246
|
+
const smoothingSpeed = typeof smoothing === 'object' ? smoothing.speed : undefined;
|
|
234
247
|
|
|
235
248
|
const textController = createSmoothMessage({
|
|
236
249
|
onTextUpdate: (delta, text) => {
|
|
237
250
|
output = text;
|
|
238
251
|
options.onMessageHandle?.({ text: delta, type: 'text' });
|
|
239
252
|
},
|
|
253
|
+
startSpeed: smoothingSpeed,
|
|
240
254
|
});
|
|
241
255
|
|
|
242
256
|
const toolCallsController = createSmoothToolCalls({
|
|
243
257
|
onToolCallsUpdate: (toolCalls, isAnimationActives) => {
|
|
244
258
|
options.onMessageHandle?.({ isAnimationActives, tool_calls: toolCalls, type: 'tool_calls' });
|
|
245
259
|
},
|
|
260
|
+
startSpeed: smoothingSpeed,
|
|
246
261
|
});
|
|
247
262
|
|
|
248
263
|
await fetchEventSource(url, {
|
|
@@ -305,7 +320,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio
|
|
|
305
320
|
}
|
|
306
321
|
|
|
307
322
|
case 'text': {
|
|
308
|
-
if (
|
|
323
|
+
if (textSmoothing) {
|
|
309
324
|
textController.pushToQueue(data);
|
|
310
325
|
|
|
311
326
|
if (!textController.isAnimationActive) textController.startAnimation();
|
|
@@ -323,7 +338,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio
|
|
|
323
338
|
if (!toolCalls) toolCalls = [];
|
|
324
339
|
toolCalls = parseToolCalls(toolCalls, data);
|
|
325
340
|
|
|
326
|
-
if (
|
|
341
|
+
if (toolsCallingSmoothing) {
|
|
327
342
|
// make the tool calls smooth
|
|
328
343
|
|
|
329
344
|
// push the tool calls to the smooth queue
|
|
@@ -333,10 +348,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio
|
|
|
333
348
|
toolCallsController.startAnimations();
|
|
334
349
|
}
|
|
335
350
|
} else {
|
|
336
|
-
options.onMessageHandle?.({
|
|
337
|
-
tool_calls: toolCalls,
|
|
338
|
-
type: 'tool_calls',
|
|
339
|
-
});
|
|
351
|
+
options.onMessageHandle?.({ tool_calls: toolCalls, type: 'tool_calls' });
|
|
340
352
|
}
|
|
341
353
|
}
|
|
342
354
|
}
|