@lobehub/chat 1.19.5 → 1.19.6
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.
Potentially problematic release.
This version of @lobehub/chat might be problematic. Click here for more details.
- package/CHANGELOG.md +25 -0
- package/package.json +1 -1
- package/src/app/api/openai/createBizOpenAI/index.ts +1 -0
- package/src/app/{api/openai/tts → webapi/tts/openai}/route.ts +1 -0
- package/src/const/fetch.ts +3 -1
- package/src/libs/agent-runtime/AgentRuntime.ts +4 -0
- package/src/libs/agent-runtime/BaseAI.ts +8 -1
- package/src/libs/agent-runtime/types/index.ts +1 -0
- package/src/libs/agent-runtime/types/tts.ts +14 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +16 -1
- package/src/services/_header.ts +10 -3
- package/src/services/_url.ts +8 -6
- package/src/store/file/slices/tts/action.ts +1 -1
- package/src/store/file/slices/upload/action.ts +11 -5
- /package/src/app/{api/openai/stt → webapi/stt/openai}/route.ts +0 -0
- /package/src/app/{api/tts/edge-speech → webapi/tts/edge}/route.ts +0 -0
- /package/src/app/{api/tts/microsoft-speech → webapi/tts/microsoft}/route.ts +0 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.19.6](https://github.com/lobehub/lobe-chat/compare/v1.19.5...v1.19.6)
|
6
|
+
|
7
|
+
<sup>Released on **2024-09-19**</sup>
|
8
|
+
|
9
|
+
#### ♻ Code Refactoring
|
10
|
+
|
11
|
+
- **misc**: Refactor the tts route url.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### Code refactoring
|
19
|
+
|
20
|
+
- **misc**: Refactor the tts route url, closes [#4030](https://github.com/lobehub/lobe-chat/issues/4030) ([60dcf19](https://github.com/lobehub/lobe-chat/commit/60dcf19))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.19.5](https://github.com/lobehub/lobe-chat/compare/v1.19.4...v1.19.5)
|
6
31
|
|
7
32
|
<sup>Released on **2024-09-19**</sup>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.19.
|
3
|
+
"version": "1.19.6",
|
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",
|
@@ -28,6 +28,7 @@ export const preferredRegion = [
|
|
28
28
|
export const POST = async (req: Request) => {
|
29
29
|
const payload = (await req.json()) as OpenAITTSPayload;
|
30
30
|
|
31
|
+
// need to be refactored with jwt auth mode
|
31
32
|
const openaiOrErrResponse = createBizOpenAI(req);
|
32
33
|
|
33
34
|
// if resOrOpenAI is a Response, it means there is an error,just return it
|
package/src/const/fetch.ts
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
export const OPENAI_END_POINT = 'X-openai-end-point';
|
2
2
|
export const OPENAI_API_KEY_HEADER_KEY = 'X-openai-api-key';
|
3
|
+
export const LOBE_USER_ID = 'X-lobe-user-id';
|
3
4
|
|
4
5
|
export const USE_AZURE_OPENAI = 'X-use-azure-openai';
|
5
6
|
|
@@ -19,9 +20,10 @@ export const getOpenAIAuthFromRequest = (req: Request) => {
|
|
19
20
|
const useAzureStr = req.headers.get(USE_AZURE_OPENAI);
|
20
21
|
const apiVersion = req.headers.get(AZURE_OPENAI_API_VERSION);
|
21
22
|
const oauthAuthorizedStr = req.headers.get(OAUTH_AUTHORIZED);
|
23
|
+
const userId = req.headers.get(LOBE_USER_ID);
|
22
24
|
|
23
25
|
const oauthAuthorized = !!oauthAuthorizedStr;
|
24
26
|
const useAzure = !!useAzureStr;
|
25
27
|
|
26
|
-
return { accessCode, apiKey, apiVersion, endpoint, oauthAuthorized, useAzure };
|
28
|
+
return { accessCode, apiKey, apiVersion, endpoint, oauthAuthorized, useAzure, userId };
|
27
29
|
};
|
@@ -35,6 +35,7 @@ import {
|
|
35
35
|
EmbeddingsPayload,
|
36
36
|
ModelProvider,
|
37
37
|
TextToImagePayload,
|
38
|
+
TextToSpeechPayload,
|
38
39
|
} from './types';
|
39
40
|
import { LobeUpstageAI } from './upstage';
|
40
41
|
import { LobeZeroOneAI } from './zeroone';
|
@@ -97,6 +98,9 @@ class AgentRuntime {
|
|
97
98
|
async embeddings(payload: EmbeddingsPayload, options?: EmbeddingsOptions) {
|
98
99
|
return this._runtime.embeddings?.(payload, options);
|
99
100
|
}
|
101
|
+
async textToSpeech(payload: TextToSpeechPayload, options?: EmbeddingsOptions) {
|
102
|
+
return this._runtime.textToSpeech?.(payload, options);
|
103
|
+
}
|
100
104
|
|
101
105
|
/**
|
102
106
|
* @description Initialize the runtime with the provider and the options
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import OpenAI from 'openai';
|
2
2
|
|
3
|
-
import { TextToImagePayload } from '@/libs/agent-runtime/types/textToImage';
|
4
3
|
import { ChatModelCard } from '@/types/llm';
|
5
4
|
|
6
5
|
import {
|
@@ -9,6 +8,9 @@ import {
|
|
9
8
|
EmbeddingItem,
|
10
9
|
EmbeddingsOptions,
|
11
10
|
EmbeddingsPayload,
|
11
|
+
TextToImagePayload,
|
12
|
+
TextToSpeechOptions,
|
13
|
+
TextToSpeechPayload,
|
12
14
|
} from './types';
|
13
15
|
|
14
16
|
export interface LobeRuntimeAI {
|
@@ -20,6 +22,11 @@ export interface LobeRuntimeAI {
|
|
20
22
|
models?(): Promise<any>;
|
21
23
|
|
22
24
|
textToImage?: (payload: TextToImagePayload) => Promise<string[]>;
|
25
|
+
|
26
|
+
textToSpeech?: (
|
27
|
+
payload: TextToSpeechPayload,
|
28
|
+
options?: TextToSpeechOptions,
|
29
|
+
) => Promise<ArrayBuffer>;
|
23
30
|
}
|
24
31
|
|
25
32
|
export abstract class LobeOpenAICompatibleRuntime {
|
@@ -0,0 +1,14 @@
|
|
1
|
+
export interface TextToSpeechPayload {
|
2
|
+
input: string;
|
3
|
+
model: string;
|
4
|
+
voice: string;
|
5
|
+
}
|
6
|
+
|
7
|
+
export interface TextToSpeechOptions {
|
8
|
+
headers?: Record<string, any>;
|
9
|
+
signal?: AbortSignal;
|
10
|
+
/**
|
11
|
+
* userId for the embeddings
|
12
|
+
*/
|
13
|
+
user?: string;
|
14
|
+
}
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import OpenAI, { ClientOptions } from 'openai';
|
2
2
|
|
3
3
|
import { LOBE_DEFAULT_MODEL_LIST } from '@/config/modelProviders';
|
4
|
-
import { TextToImagePayload } from '@/libs/agent-runtime/types/textToImage';
|
5
4
|
import { ChatModelCard } from '@/types/llm';
|
6
5
|
|
7
6
|
import { LobeRuntimeAI } from '../../BaseAI';
|
@@ -13,6 +12,9 @@ import {
|
|
13
12
|
EmbeddingItem,
|
14
13
|
EmbeddingsOptions,
|
15
14
|
EmbeddingsPayload,
|
15
|
+
TextToImagePayload,
|
16
|
+
TextToSpeechOptions,
|
17
|
+
TextToSpeechPayload,
|
16
18
|
} from '../../types';
|
17
19
|
import { AgentRuntimeError } from '../createError';
|
18
20
|
import { debugResponse, debugStream } from '../debugStream';
|
@@ -253,6 +255,19 @@ export const LobeOpenAICompatibleFactory = <T extends Record<string, any> = any>
|
|
253
255
|
}
|
254
256
|
}
|
255
257
|
|
258
|
+
async textToSpeech(payload: TextToSpeechPayload, options?: TextToSpeechOptions) {
|
259
|
+
try {
|
260
|
+
const mp3 = await this.client.audio.speech.create(payload as any, {
|
261
|
+
headers: options?.headers,
|
262
|
+
signal: options?.signal,
|
263
|
+
});
|
264
|
+
|
265
|
+
return mp3.arrayBuffer();
|
266
|
+
} catch (error) {
|
267
|
+
throw this.handleError(error);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
|
256
271
|
private handleError(error: any): ChatCompletionErrorPayload {
|
257
272
|
let desensitizedEndpoint = this.baseURL;
|
258
273
|
|
package/src/services/_header.ts
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
LOBE_CHAT_ACCESS_CODE,
|
3
|
+
LOBE_USER_ID,
|
4
|
+
OPENAI_API_KEY_HEADER_KEY,
|
5
|
+
OPENAI_END_POINT,
|
6
|
+
} from '@/const/fetch';
|
2
7
|
import { useUserStore } from '@/store/user';
|
3
8
|
import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
4
9
|
|
@@ -8,12 +13,14 @@ import { keyVaultsConfigSelectors } from '@/store/user/selectors';
|
|
8
13
|
*/
|
9
14
|
// eslint-disable-next-line no-undef
|
10
15
|
export const createHeaderWithOpenAI = (header?: HeadersInit): HeadersInit => {
|
11
|
-
const
|
16
|
+
const state = useUserStore.getState();
|
17
|
+
const openAIConfig = keyVaultsConfigSelectors.openAIConfig(state);
|
12
18
|
|
13
19
|
// eslint-disable-next-line no-undef
|
14
20
|
return {
|
15
21
|
...header,
|
16
|
-
[LOBE_CHAT_ACCESS_CODE]: keyVaultsConfigSelectors.password(
|
22
|
+
[LOBE_CHAT_ACCESS_CODE]: keyVaultsConfigSelectors.password(state),
|
23
|
+
[LOBE_USER_ID]: state.user?.id || '',
|
17
24
|
[OPENAI_API_KEY_HEADER_KEY]: openAIConfig.apiKey || '',
|
18
25
|
[OPENAI_END_POINT]: openAIConfig.baseURL || '',
|
19
26
|
};
|
package/src/services/_url.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// TODO:
|
1
|
+
// TODO: 未来路由需要迁移到 trpc or /webapi
|
2
2
|
|
3
3
|
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
4
4
|
import { transform } from 'lodash-es';
|
@@ -38,9 +38,11 @@ export const API_ENDPOINTS = mapWithBasePath({
|
|
38
38
|
// image
|
39
39
|
images: '/api/text-to-image/openai',
|
40
40
|
|
41
|
-
//
|
42
|
-
stt: '/
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
// STT
|
42
|
+
stt: '/webapi/stt/openai',
|
43
|
+
|
44
|
+
// TTS
|
45
|
+
tts: '/webapi/tts/openai',
|
46
|
+
edge: '/webapi/tts/edge',
|
47
|
+
microsoft: '/webapi/tts/microsoft',
|
46
48
|
});
|
@@ -39,7 +39,7 @@ export const createTTSFileSlice: StateCreator<
|
|
39
39
|
};
|
40
40
|
const file = new File([blob], fileName, fileOptions);
|
41
41
|
|
42
|
-
const res = await get().uploadWithProgress({ file });
|
42
|
+
const res = await get().uploadWithProgress({ file, skipCheckFileType: true });
|
43
43
|
|
44
44
|
return res?.id;
|
45
45
|
},
|
@@ -29,6 +29,12 @@ interface UploadWithProgressParams {
|
|
29
29
|
type: 'removeFile';
|
30
30
|
},
|
31
31
|
) => void;
|
32
|
+
/**
|
33
|
+
* Optional flag to indicate whether to skip the file type check.
|
34
|
+
* When set to `true`, any file type checks will be bypassed.
|
35
|
+
* Default is `false`, which means file type checks will be performed.
|
36
|
+
*/
|
37
|
+
skipCheckFileType?: boolean;
|
32
38
|
}
|
33
39
|
|
34
40
|
interface UploadWithProgressResult {
|
@@ -52,8 +58,8 @@ export const createFileUploadSlice: StateCreator<
|
|
52
58
|
[],
|
53
59
|
FileUploadAction
|
54
60
|
> = (set, get) => ({
|
55
|
-
internal_uploadToClientDB: async ({ file, onStatusUpdate }) => {
|
56
|
-
if (!file.type.startsWith('image')) {
|
61
|
+
internal_uploadToClientDB: async ({ file, onStatusUpdate, skipCheckFileType }) => {
|
62
|
+
if (!skipCheckFileType && !file.type.startsWith('image')) {
|
57
63
|
onStatusUpdate?.({ id: file.name, type: 'removeFile' });
|
58
64
|
message.info({
|
59
65
|
content: t('upload.fileOnlySupportInServerMode', {
|
@@ -158,11 +164,11 @@ export const createFileUploadSlice: StateCreator<
|
|
158
164
|
return data;
|
159
165
|
},
|
160
166
|
|
161
|
-
uploadWithProgress: async (
|
167
|
+
uploadWithProgress: async (payload) => {
|
162
168
|
const { internal_uploadToServer, internal_uploadToClientDB } = get();
|
163
169
|
|
164
|
-
if (isServerMode) return internal_uploadToServer(
|
170
|
+
if (isServerMode) return internal_uploadToServer(payload);
|
165
171
|
|
166
|
-
return internal_uploadToClientDB(
|
172
|
+
return internal_uploadToClientDB(payload);
|
167
173
|
},
|
168
174
|
});
|
File without changes
|
File without changes
|
File without changes
|