@lobehub/chat 0.149.3 → 0.149.4

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,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.149.4](https://github.com/lobehub/lobe-chat/compare/v0.149.3...v0.149.4)
6
+
7
+ <sup>Released on **2024-04-25**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix chat client request not support abort.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix chat client request not support abort, closes [#2193](https://github.com/lobehub/lobe-chat/issues/2193) ([d22ef2c](https://github.com/lobehub/lobe-chat/commit/d22ef2c))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ### [Version 0.149.3](https://github.com/lobehub/lobe-chat/compare/v0.149.2...v0.149.3)
6
31
 
7
32
  <sup>Released on **2024-04-25**</sup>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.149.3",
3
+ "version": "0.149.4",
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",
@@ -72,14 +72,17 @@ describe('LobeAnthropicAI', () => {
72
72
  });
73
73
 
74
74
  // Assert
75
- expect(instance['client'].messages.create).toHaveBeenCalledWith({
76
- max_tokens: 4096,
77
- messages: [{ content: 'Hello', role: 'user' }],
78
- model: 'claude-3-haiku-20240307',
79
- stream: true,
80
- temperature: 0,
81
- top_p: 1,
82
- });
75
+ expect(instance['client'].messages.create).toHaveBeenCalledWith(
76
+ {
77
+ max_tokens: 4096,
78
+ messages: [{ content: 'Hello', role: 'user' }],
79
+ model: 'claude-3-haiku-20240307',
80
+ stream: true,
81
+ temperature: 0,
82
+ top_p: 1,
83
+ },
84
+ {},
85
+ );
83
86
  expect(result).toBeInstanceOf(Response);
84
87
  });
85
88
 
@@ -105,14 +108,17 @@ describe('LobeAnthropicAI', () => {
105
108
  });
106
109
 
107
110
  // Assert
108
- expect(instance['client'].messages.create).toHaveBeenCalledWith({
109
- max_tokens: 4096,
110
- messages: [{ content: 'Hello', role: 'user' }],
111
- model: 'claude-3-haiku-20240307',
112
- stream: true,
113
- system: 'You are an awesome greeter',
114
- temperature: 0,
115
- });
111
+ expect(instance['client'].messages.create).toHaveBeenCalledWith(
112
+ {
113
+ max_tokens: 4096,
114
+ messages: [{ content: 'Hello', role: 'user' }],
115
+ model: 'claude-3-haiku-20240307',
116
+ stream: true,
117
+ system: 'You are an awesome greeter',
118
+ temperature: 0,
119
+ },
120
+ {},
121
+ );
116
122
  expect(result).toBeInstanceOf(Response);
117
123
  });
118
124
 
@@ -137,14 +143,17 @@ describe('LobeAnthropicAI', () => {
137
143
  });
138
144
 
139
145
  // Assert
140
- expect(instance['client'].messages.create).toHaveBeenCalledWith({
141
- max_tokens: 2048,
142
- messages: [{ content: 'Hello', role: 'user' }],
143
- model: 'claude-3-haiku-20240307',
144
- stream: true,
145
- temperature: 0.5,
146
- top_p: 1,
147
- });
146
+ expect(instance['client'].messages.create).toHaveBeenCalledWith(
147
+ {
148
+ max_tokens: 2048,
149
+ messages: [{ content: 'Hello', role: 'user' }],
150
+ model: 'claude-3-haiku-20240307',
151
+ stream: true,
152
+ temperature: 0.5,
153
+ top_p: 1,
154
+ },
155
+ {},
156
+ );
148
157
  expect(result).toBeInstanceOf(Response);
149
158
  });
150
159
 
@@ -171,14 +180,17 @@ describe('LobeAnthropicAI', () => {
171
180
  });
172
181
 
173
182
  // Assert
174
- expect(instance['client'].messages.create).toHaveBeenCalledWith({
175
- max_tokens: 2048,
176
- messages: [{ content: 'Hello', role: 'user' }],
177
- model: 'claude-3-haiku-20240307',
178
- stream: true,
179
- temperature: 0.5,
180
- top_p: 1,
181
- });
183
+ expect(instance['client'].messages.create).toHaveBeenCalledWith(
184
+ {
185
+ max_tokens: 2048,
186
+ messages: [{ content: 'Hello', role: 'user' }],
187
+ model: 'claude-3-haiku-20240307',
188
+ stream: true,
189
+ temperature: 0.5,
190
+ top_p: 1,
191
+ },
192
+ {},
193
+ );
182
194
  expect(result).toBeInstanceOf(Response);
183
195
  });
184
196
 
@@ -32,15 +32,18 @@ export class LobeAnthropicAI implements LobeRuntimeAI {
32
32
  const user_messages = messages.filter((m) => m.role !== 'system');
33
33
 
34
34
  try {
35
- const response = await this.client.messages.create({
36
- max_tokens: max_tokens || 4096,
37
- messages: buildAnthropicMessages(user_messages),
38
- model: model,
39
- stream: true,
40
- system: system_message?.content as string,
41
- temperature: temperature,
42
- top_p: top_p,
43
- });
35
+ const response = await this.client.messages.create(
36
+ {
37
+ max_tokens: max_tokens || 4096,
38
+ messages: buildAnthropicMessages(user_messages),
39
+ model: model,
40
+ stream: true,
41
+ system: system_message?.content as string,
42
+ temperature: temperature,
43
+ top_p: top_p,
44
+ },
45
+ { signal: options?.signal },
46
+ );
44
47
 
45
48
  const [prod, debug] = response.tee();
46
49
 
@@ -8,7 +8,7 @@ import { OpenAIStream, StreamingTextResponse } from 'ai';
8
8
 
9
9
  import { LobeRuntimeAI } from '../BaseAI';
10
10
  import { AgentRuntimeErrorType } from '../error';
11
- import { ChatStreamPayload, ModelProvider } from '../types';
11
+ import { ChatCompetitionOptions, ChatStreamPayload, ModelProvider } from '../types';
12
12
  import { AgentRuntimeError } from '../utils/createError';
13
13
  import { debugStream } from '../utils/debugStream';
14
14
 
@@ -26,7 +26,7 @@ export class LobeAzureOpenAI implements LobeRuntimeAI {
26
26
 
27
27
  baseURL: string;
28
28
 
29
- async chat(payload: ChatStreamPayload) {
29
+ async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
30
30
  // ============ 1. preprocess messages ============ //
31
31
  const { messages, model, ...params } = payload;
32
32
 
@@ -36,10 +36,9 @@ export class LobeAzureOpenAI implements LobeRuntimeAI {
36
36
  const response = await this.client.streamChatCompletions(
37
37
  model,
38
38
  messages as ChatRequestMessage[],
39
- params as GetChatCompletionsOptions,
39
+ { ...params, abortSignal: options?.signal } as GetChatCompletionsOptions,
40
40
  );
41
41
 
42
- // TODO: we need to refactor this part in the future
43
42
  const stream = OpenAIStream(response as any);
44
43
 
45
44
  const [debug, prod] = stream.tee();
@@ -68,7 +68,7 @@ export class LobeBedrockAI implements LobeRuntimeAI {
68
68
 
69
69
  try {
70
70
  // Ask Claude for a streaming chat completion given the prompt
71
- const bedrockResponse = await this.client.send(command);
71
+ const bedrockResponse = await this.client.send(command, { abortSignal: options?.signal });
72
72
 
73
73
  // Convert the response into a friendly text-stream
74
74
  const stream = AWSBedrockStream(
@@ -31,6 +31,13 @@ export class LobeOllamaAI implements LobeRuntimeAI {
31
31
 
32
32
  async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
33
33
  try {
34
+ const abort = () => {
35
+ this.client.abort();
36
+ options?.signal?.removeEventListener('abort', abort);
37
+ };
38
+
39
+ options?.signal?.addEventListener('abort', abort);
40
+
34
41
  const response = await this.client.chat({
35
42
  messages: this.buildOllamaMessages(payload.messages),
36
43
  model: payload.model,
@@ -33,6 +33,7 @@ export class LobePerplexityAI implements LobeRuntimeAI {
33
33
  };
34
34
  const response = await this.client.chat.completions.create(
35
35
  chatPayload as unknown as OpenAI.ChatCompletionCreateParamsStreaming,
36
+ { signal: options?.signal },
36
37
  );
37
38
  const [prod, debug] = response.tee();
38
39
 
@@ -90,8 +90,9 @@ export interface ChatStreamPayload {
90
90
  }
91
91
 
92
92
  export interface ChatCompetitionOptions {
93
- callback: ChatStreamCallbacks;
93
+ callback?: ChatStreamCallbacks;
94
94
  headers?: Record<string, any>;
95
+ signal?: AbortSignal;
95
96
  }
96
97
 
97
98
  export interface ChatCompletionFunctions {
@@ -76,6 +76,7 @@ export const LobeOpenAICompatibleFactory = ({
76
76
  const response = await this.client.chat.completions.create(postPayload, {
77
77
  // https://github.com/lobehub/lobe-chat/pull/318
78
78
  headers: { Accept: '*/*' },
79
+ signal: options?.signal,
79
80
  });
80
81
 
81
82
  const [prod, useForDebug] = response.tee();
@@ -168,18 +168,6 @@ export function initializeWithClientStore(provider: string, payload: any) {
168
168
  });
169
169
  }
170
170
 
171
- /**
172
- * Fetch chat completion on the client side.
173
- * @param provider - The provider name.
174
- * @param payload - The payload data for the chat stream.
175
- * @returns A promise that resolves to the chat response.
176
- */
177
- export async function fetchOnClient(provider: string, payload: Partial<ChatStreamPayload>) {
178
- const agentRuntime = await initializeWithClientStore(provider, payload);
179
- const data = payload as ChatStreamPayload;
180
- return await agentRuntime.chat(data);
181
- }
182
-
183
171
  class ChatService {
184
172
  createAssistantMessage = async (
185
173
  { plugins: enabledPlugins, messages, ...params }: GetChatCompletionPayload,
@@ -279,7 +267,7 @@ class ChatService {
279
267
  */
280
268
  if (enableFetchOnClient) {
281
269
  try {
282
- return await fetchOnClient(provider, payload);
270
+ return this.fetchOnClient({ payload, provider, signal });
283
271
  } catch (e) {
284
272
  const {
285
273
  errorType = ChatErrorType.BadRequest,
@@ -472,6 +460,21 @@ class ChatService {
472
460
  userId: commonSelectors.userId(useGlobalStore.getState()),
473
461
  };
474
462
  }
463
+
464
+ /**
465
+ * Fetch chat completion on the client side.
466
+
467
+ */
468
+ private fetchOnClient = async (params: {
469
+ payload: Partial<ChatStreamPayload>;
470
+ provider: string;
471
+ signal?: AbortSignal;
472
+ }) => {
473
+ const agentRuntime = await initializeWithClientStore(params.provider, params.payload);
474
+ const data = params.payload as ChatStreamPayload;
475
+
476
+ return agentRuntime.chat(data, { signal: params.signal });
477
+ };
475
478
  }
476
479
 
477
480
  export const chatService = new ChatService();