@lobehub/chat 1.15.13 → 1.15.15
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 +42 -0
- package/README.md +5 -3
- package/docs/self-hosting/server-database/repocloud.mdx +20 -4
- package/package.json +1 -1
- package/src/config/modelProviders/google.ts +4 -0
- package/src/config/modelProviders/groq.ts +8 -1
- package/src/services/chat.ts +4 -0
- package/src/types/llm.ts +11 -0
- package/src/utils/fetch/__tests__/fetchSSE.test.ts +3 -0
- package/src/utils/fetch/fetchSSE.ts +24 -12
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
### [Version 1.15.15](https://github.com/lobehub/lobe-chat/compare/v1.15.14...v1.15.15)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2024-09-06**</sup>
|
|
8
|
+
|
|
9
|
+
#### 💄 Styles
|
|
10
|
+
|
|
11
|
+
- **misc**: Add `LLaVA 1.5 7B` model in Groq.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Styles
|
|
19
|
+
|
|
20
|
+
- **misc**: Add `LLaVA 1.5 7B` model in Groq, closes [#3769](https://github.com/lobehub/lobe-chat/issues/3769) ([f78a0b1](https://github.com/lobehub/lobe-chat/commit/f78a0b1))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
### [Version 1.15.14](https://github.com/lobehub/lobe-chat/compare/v1.15.13...v1.15.14)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2024-09-06**</sup>
|
|
33
|
+
|
|
34
|
+
<br/>
|
|
35
|
+
|
|
36
|
+
<details>
|
|
37
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
38
|
+
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
<div align="right">
|
|
42
|
+
|
|
43
|
+
[](#readme-top)
|
|
44
|
+
|
|
45
|
+
</div>
|
|
46
|
+
|
|
5
47
|
### [Version 1.15.13](https://github.com/lobehub/lobe-chat/compare/v1.15.12...v1.15.13)
|
|
6
48
|
|
|
7
49
|
<sup>Released on **2024-09-06**</sup>
|
package/README.md
CHANGED
|
@@ -462,9 +462,9 @@ If you want to deploy this service yourself on either Vercel or Zeabur, you can
|
|
|
462
462
|
|
|
463
463
|
<div align="center">
|
|
464
464
|
|
|
465
|
-
| Deploy with Vercel | Deploy with Zeabur | Deploy with Sealos |
|
|
466
|
-
| :-------------------------------------: | :---------------------------------------------------------: | :---------------------------------------------------------: |
|
|
467
|
-
| [![][deploy-button-image]][deploy-link] | [![][deploy-on-zeabur-button-image]][deploy-on-zeabur-link] | [![][deploy-on-sealos-button-image]][deploy-on-sealos-link] |
|
|
465
|
+
| Deploy with Vercel | Deploy with Zeabur | Deploy with Sealos | Deploy with RepoCloud |
|
|
466
|
+
| :-------------------------------------: | :---------------------------------------------------------: | :---------------------------------------------------------: | :------------------------------------------------------------: |
|
|
467
|
+
| [![][deploy-button-image]][deploy-link] | [![][deploy-on-zeabur-button-image]][deploy-on-zeabur-link] | [![][deploy-on-sealos-button-image]][deploy-on-sealos-link] | [![][deploy-on-repocloud-button-image]][deploy-on-repocloud-link] |
|
|
468
468
|
|
|
469
469
|
</div>
|
|
470
470
|
|
|
@@ -715,6 +715,8 @@ This project is [Apache 2.0](./LICENSE) licensed.
|
|
|
715
715
|
[deploy-on-sealos-link]: https://cloud.sealos.io/?openapp=system-template%3FtemplateName%3Dlobe-chat
|
|
716
716
|
[deploy-on-zeabur-button-image]: https://zeabur.com/button.svg
|
|
717
717
|
[deploy-on-zeabur-link]: https://zeabur.com/templates/VZGGTI
|
|
718
|
+
[deploy-on-repocloud-button-image]: https://d16t0pc4846x52.cloudfront.net/deploylobe.svg
|
|
719
|
+
[deploy-on-repocloud-link]: https://repocloud.io/details/?app_id=248
|
|
718
720
|
[discord-link]: https://discord.gg/AYFPHvv2jT
|
|
719
721
|
[discord-shield]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=flat-square
|
|
720
722
|
[discord-shield-badge]: https://img.shields.io/discord/1127171173982154893?color=5865F2&label=discord&labelColor=black&logo=discord&logoColor=white&style=for-the-badge
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Deploy LobeChat with Database on RepoCloud
|
|
3
|
-
description:
|
|
4
|
-
Learn how to deploy LobeChat on RepoCloud with ease, including: database,
|
|
5
|
-
authentication and S3 storage service.
|
|
3
|
+
description: Learn how to deploy LobeChat on RepoCloud with ease, including: database, authentication and S3 storage service.
|
|
6
4
|
tags:
|
|
7
5
|
- Deploy LobeChat
|
|
8
6
|
- RepoCloud Deployment
|
|
@@ -12,5 +10,23 @@ tags:
|
|
|
12
10
|
|
|
13
11
|
# Deploying LobeChat Database Edition with RepoCloud
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
If you want to deploy LobeChat Database Edition on RepoCloud, you can follow the steps below:
|
|
16
14
|
|
|
15
|
+
## RepoCloud Deployment Process
|
|
16
|
+
|
|
17
|
+
<Steps>
|
|
18
|
+
### Prepare your OpenAI API Key
|
|
19
|
+
|
|
20
|
+
Go to [OpenAI API Key](https://platform.openai.com/account/api-keys) to get your OpenAI API Key.
|
|
21
|
+
|
|
22
|
+
### One-click to deploy
|
|
23
|
+
|
|
24
|
+
[](https://repocloud.io/details/?app_id=248)
|
|
25
|
+
|
|
26
|
+
### Once deployed, you can start using it
|
|
27
|
+
|
|
28
|
+
### Bind a custom domain (optional)
|
|
29
|
+
|
|
30
|
+
You can use the subdomain provided by RepoCloud, or choose to bind a custom domain. Currently, the domains provided by RepoCloud have not been contaminated, and most regions can connect directly.
|
|
31
|
+
|
|
32
|
+
</Steps>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.15",
|
|
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",
|
|
@@ -57,7 +57,7 @@ const Groq: ModelProviderCard = {
|
|
|
57
57
|
tokens: 8192,
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
displayName: '
|
|
60
|
+
displayName: 'Gemma 2 9B',
|
|
61
61
|
enabled: true,
|
|
62
62
|
functionCall: true,
|
|
63
63
|
id: 'gemma2-9b-it',
|
|
@@ -76,6 +76,13 @@ const Groq: ModelProviderCard = {
|
|
|
76
76
|
id: 'mixtral-8x7b-32768',
|
|
77
77
|
tokens: 32_768,
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'LLaVA 1.5 7B',
|
|
81
|
+
enabled: true,
|
|
82
|
+
id: 'llava-v1.5-7b-4096-preview',
|
|
83
|
+
tokens: 4096,
|
|
84
|
+
vision: true,
|
|
85
|
+
},
|
|
79
86
|
],
|
|
80
87
|
checkModel: 'gemma2-9b-it',
|
|
81
88
|
id: 'groq',
|
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
|
}
|